Constpool object moved to old age

Description
  1.GC is frequent during constpool parsing
  2.Constpool object moved to old age allocation
Issue:
  https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I5H2ZN

Signed-off-by: xliu <liuxin259@huawei.com>
Change-Id: Ie4b54e205c5673705992a370f2af8f9b46e412e3
This commit is contained in:
xliu 2022-07-14 16:29:43 +08:00
parent f1a031481d
commit 203136be24
19 changed files with 274 additions and 86 deletions

View File

@ -1139,6 +1139,12 @@ JSTaggedValue BuiltinsArray::IndexOf(EcmaRuntimeCallInfo *argv)
// b. If k < 0, let k be 0.
double from = (fromIndex >= 0) ? fromIndex : ((len + fromIndex) >= 0 ? len + fromIndex : 0);
// if it is stable array, we can go to fast path
if (thisObjVal->IsStableJSArray(thread)) {
return JSStableArray::IndexOf(thread, thisObjVal, searchElement, static_cast<uint32_t>(from),
static_cast<uint32_t>(len));
}
// 11. Repeat, while k<len
// a. Let kPresent be HasProperty(O, ToString(k)).
// b. ReturnIfAbrupt(kPresent).

View File

@ -868,7 +868,7 @@ HWTEST_F_L0(BuiltinsArrayTest, IndexOf)
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1);
JSTaggedValue result = Array::IndexOf(ecmaRuntimeCallInfo1);
TestHelper::TearDownFrame(thread, prev);
ASSERT_EQ(result.GetRawData(), JSTaggedValue(static_cast<double>(2)).GetRawData());
ASSERT_EQ(result.GetRawData(), JSTaggedValue(2).GetRawData());
auto ecmaRuntimeCallInfo2 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
ecmaRuntimeCallInfo2->SetFunction(JSTaggedValue::Undefined());
@ -879,7 +879,7 @@ HWTEST_F_L0(BuiltinsArrayTest, IndexOf)
prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo2);
result = Array::IndexOf(ecmaRuntimeCallInfo2);
TestHelper::TearDownFrame(thread, prev);
ASSERT_EQ(result.GetRawData(), JSTaggedValue(static_cast<double>(4)).GetRawData());
ASSERT_EQ(result.GetRawData(), JSTaggedValue(4).GetRawData());
auto ecmaRuntimeCallInfo3 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
ecmaRuntimeCallInfo3->SetFunction(JSTaggedValue::Undefined());
@ -900,7 +900,7 @@ HWTEST_F_L0(BuiltinsArrayTest, IndexOf)
prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo4);
result = Array::IndexOf(ecmaRuntimeCallInfo4);
TestHelper::TearDownFrame(thread, prev);
ASSERT_EQ(result.GetRawData(), JSTaggedValue(static_cast<double>(2)).GetRawData());
ASSERT_EQ(result.GetRawData(), JSTaggedValue(2).GetRawData());
}
// 22.1.3.14 new Array(1,2,3,4,3).LastIndexOf(searchElement [ , fromIndex ])

View File

@ -46,16 +46,40 @@ inline EcmaString *EcmaString::CreateEmptyString(const EcmaVM *vm)
return string;
}
/* static */
inline EcmaString *EcmaString::AllocStringObjectWithSpaceType(size_t length, bool compressed, const EcmaVM *vm,
MemSpaceType type)
{
size_t size = compressed ? ComputeSizeUtf8(length) : ComputeSizeUtf16(length);
EcmaString *string = nullptr;
switch (type) {
case MemSpaceType::SEMI_SPACE:
string = vm->GetFactory()->AllocStringObject(size);
break;
case MemSpaceType::OLD_SPACE:
string = vm->GetFactory()->AllocOldSpaceStringObject(size);
break;
case MemSpaceType::NON_MOVABLE:
string = vm->GetFactory()->AllocNonMovableStringObject(size);
break;
default:
UNREACHABLE();
}
string->SetLength(length, compressed);
string->SetRawHashcode(0);
return string;
}
/* static */
inline EcmaString *EcmaString::CreateFromUtf8(const uint8_t *utf8Data, uint32_t utf8Len, const EcmaVM *vm,
bool canBeCompress)
bool canBeCompress, MemSpaceType type)
{
if (utf8Len == 0) {
return vm->GetFactory()->GetEmptyString().GetObject<EcmaString>();
}
EcmaString *string = nullptr;
if (canBeCompress) {
string = AllocStringObject(utf8Len, true, vm);
string = AllocStringObjectWithSpaceType(utf8Len, true, vm, type);
ASSERT(string != nullptr);
if (memcpy_s(string->GetDataUtf8Writable(), utf8Len, utf8Data, utf8Len) != EOK) {
@ -64,7 +88,7 @@ inline EcmaString *EcmaString::CreateFromUtf8(const uint8_t *utf8Data, uint32_t
}
} else {
auto utf16Len = base::utf_helper::Utf8ToUtf16Size(utf8Data, utf8Len);
string = AllocStringObject(utf16Len, false, vm);
string = AllocStringObjectWithSpaceType(utf16Len, false, vm, type);
ASSERT(string != nullptr);
[[maybe_unused]] auto len =
@ -82,7 +106,7 @@ inline EcmaString *EcmaString::CreateFromUtf8NonMovable(const EcmaVM *vm, const
if (utf8Len == 0) {
return vm->GetFactory()->GetEmptyString().GetObject<EcmaString>();
}
EcmaString *string = AllocStringObjectNonMovable(vm, utf8Len);
EcmaString *string = AllocStringObjectWithSpaceType(utf8Len, true, vm, MemSpaceType::NON_MOVABLE);
ASSERT(string != nullptr);
if (memcpy_s(string->GetDataUtf8Writable(), utf8Len, utf8Data, utf8Len) != EOK) {
LOG_FULL(FATAL) << "memcpy_s failed";
@ -93,12 +117,12 @@ inline EcmaString *EcmaString::CreateFromUtf8NonMovable(const EcmaVM *vm, const
}
inline EcmaString *EcmaString::CreateFromUtf16(const uint16_t *utf16Data, uint32_t utf16Len, const EcmaVM *vm,
bool canBeCompress)
bool canBeCompress, MemSpaceType type)
{
if (utf16Len == 0) {
return vm->GetFactory()->GetEmptyString().GetObject<EcmaString>();
}
auto string = AllocStringObject(utf16Len, canBeCompress, vm);
auto string = AllocStringObjectWithSpaceType(utf16Len, canBeCompress, vm, type);
ASSERT(string != nullptr);
if (canBeCompress) {
@ -142,17 +166,6 @@ inline EcmaString *EcmaString::AllocStringObject(size_t length, bool compressed,
return string;
}
/* static */
inline EcmaString *EcmaString::AllocStringObjectNonMovable(const EcmaVM *vm, size_t length)
{
// we only consider compressable string which is utf8 strings
size_t size = ComputeSizeUtf8(length);
auto string = reinterpret_cast<EcmaString *>(vm->GetFactory()->AllocNonMovableStringObject(size));
string->SetLength(length, true);
string->SetRawHashcode(0);
return string;
}
void EcmaString::WriteData(EcmaString *src, uint32_t start, uint32_t destSize, uint32_t length)
{
if (IsUtf8()) {

View File

@ -23,8 +23,9 @@
#include "ecmascript/base/utf_helper.h"
#include "ecmascript/ecma_macros.h"
#include "ecmascript/js_tagged_value.h"
#include "ecmascript/mem/tagged_object.h"
#include "ecmascript/mem/barriers.h"
#include "ecmascript/mem/space.h"
#include "ecmascript/mem/tagged_object.h"
#include "macros.h"
#include "securec.h"
@ -40,10 +41,11 @@ public:
static const EcmaString *ConstCast(const TaggedObject *object);
static EcmaString *CreateEmptyString(const EcmaVM *vm);
static EcmaString *CreateFromUtf8(const uint8_t *utf8Data, uint32_t utf8Len, const EcmaVM *vm, bool canBeCompress);
static EcmaString *CreateFromUtf8(const uint8_t *utf8Data, uint32_t utf8Len, const EcmaVM *vm, bool canBeCompress,
MemSpaceType type = MemSpaceType::SEMI_SPACE);
static EcmaString *CreateFromUtf8NonMovable(const EcmaVM *vm, const uint8_t *utf8Data, uint32_t utf8Len);
static EcmaString *CreateFromUtf16(const uint16_t *utf16Data, uint32_t utf16Len, const EcmaVM *vm,
bool canBeCompress);
bool canBeCompress, MemSpaceType type = MemSpaceType::SEMI_SPACE);
static EcmaString *Concat(const JSHandle<EcmaString> &str1Handle, const JSHandle<EcmaString> &str2Handle,
const EcmaVM *vm);
static EcmaString *FastSubString(const JSHandle<EcmaString> &src, uint32_t start, uint32_t utf16Len,
@ -302,7 +304,8 @@ public:
}
static EcmaString *AllocStringObject(size_t length, bool compressed, const EcmaVM *vm);
static EcmaString *AllocStringObjectNonMovable(const EcmaVM *vm, size_t length);
static EcmaString *AllocStringObjectWithSpaceType(size_t length, bool compressed, const EcmaVM *vm,
MemSpaceType type);
static bool CanBeCompressed(const uint8_t *utf8Data, uint32_t utf8Len);
static bool CanBeCompressed(const uint16_t *utf16Data, uint32_t utf16Len);

View File

@ -157,6 +157,32 @@ EcmaString *EcmaStringTable::GetOrInternString(EcmaString *string)
return string;
}
EcmaString *EcmaStringTable::GetOrInternStringWithSpaceType(const uint8_t *utf8Data, uint32_t utf8Len,
bool canBeCompress, MemSpaceType type)
{
EcmaString *result = GetString(utf8Data, utf8Len, canBeCompress);
if (result != nullptr) {
return result;
}
result = EcmaString::CreateFromUtf8(utf8Data, utf8Len, vm_, canBeCompress, type);
InternString(result);
return result;
}
EcmaString *EcmaStringTable::GetOrInternStringWithSpaceType(const uint16_t *utf16Data, uint32_t utf16Len,
bool canBeCompress, MemSpaceType type)
{
EcmaString *result = GetString(utf16Data, utf16Len);
if (result != nullptr) {
return result;
}
result = EcmaString::CreateFromUtf16(utf16Data, utf16Len, vm_, canBeCompress, type);
InternString(result);
return result;
}
void EcmaStringTable::SweepWeakReference(const WeakRootVisitor &visitor)
{
for (auto it = table_.begin(); it != table_.end();) {

View File

@ -17,6 +17,7 @@
#define ECMASCRIPT_STRING_TABLE_H
#include "ecmascript/mem/c_containers.h"
#include "ecmascript/mem/space.h"
#include "ecmascript/mem/visitor.h"
namespace panda::ecmascript {
@ -37,6 +38,10 @@ public:
EcmaString *CreateAndInternStringNonMovable(const uint8_t *utf8Data, uint32_t utf8Len);
EcmaString *GetOrInternString(const uint16_t *utf16Data, uint32_t utf16Len, bool canBeCompress);
EcmaString *GetOrInternString(EcmaString *string);
EcmaString *GetOrInternStringWithSpaceType(const uint8_t *utf8Data, uint32_t utf8Len, bool canBeCompress,
MemSpaceType type);
EcmaString *GetOrInternStringWithSpaceType(const uint16_t *utf16Data, uint32_t utf16Len, bool canBeCompress,
MemSpaceType type);
void SweepWeakReference(const WeakRootVisitor &visitor);
bool CheckStringTableValidity();

View File

@ -1905,7 +1905,7 @@ JSHandle<JSObject> JSObject::CreateObjectFromProperties(const JSThread *thread,
propsLen++;
}
if (propsLen <= PropertyAttributes::MAX_CAPACITY_OF_PROPERTIES) {
JSHandle<JSObject> obj = factory->GetObjectLiteralByHClass(properties, propsLen);
JSHandle<JSObject> obj = factory->NewOldSpaceObjLiteralByHClass(properties, propsLen);
ASSERT_PRINT(obj->IsECMAObject(), "Obj is not a valid object");
for (size_t i = 0; i < propsLen; i++) {
// 2: literal contains a pair of key-value

View File

@ -269,4 +269,30 @@ JSTaggedValue JSStableArray::Join(JSHandle<JSArray> receiver, EcmaRuntimeCallInf
ASSERT_PRINT(isOneByte == EcmaString::CanBeCompressed(newString), "isOneByte does not match the real value!");
return JSTaggedValue(newString);
}
JSTaggedValue JSStableArray::IndexOf(JSThread *thread, JSHandle<JSTaggedValue> receiver,
JSHandle<JSTaggedValue> searchElement, uint32_t from, uint32_t len)
{
JSHandle<TaggedArray> elements(thread, JSHandle<JSObject>::Cast(receiver)->GetElements());
while (from < len) {
JSTaggedValue value = elements->Get(from);
if (!value.IsUndefined() && !value.IsHole()) {
if (JSTaggedValue::StrictEqual(searchElement.GetTaggedValue(), value)) {
return JSTaggedValue(from);
}
} else {
bool exist = JSTaggedValue::HasProperty(thread, receiver, from);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
if (exist) {
JSHandle<JSTaggedValue> kValueHandle = JSArray::FastGetPropertyByValue(thread, receiver, from);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
if (JSTaggedValue::StrictEqual(thread, searchElement, kValueHandle)) {
return JSTaggedValue(from);
}
}
}
from++;
}
return JSTaggedValue(-1);
}
} // namespace panda::ecmascript

View File

@ -30,6 +30,8 @@ public:
double start, double insertCount, double actualDeleteCount);
static JSTaggedValue Shift(JSHandle<JSArray> receiver, EcmaRuntimeCallInfo *argv);
static JSTaggedValue Join(JSHandle<JSArray> receiver, EcmaRuntimeCallInfo *argv);
static JSTaggedValue IndexOf(JSThread *thread, JSHandle<JSTaggedValue> receiver,
JSHandle<JSTaggedValue> searchElement, uint32_t from, uint32_t len);
};
} // namespace panda::ecmascript
#endif // ECMASCRIPT_JS_STABLE_ARRAY_H
#endif // ECMASCRIPT_JS_STABLE_ARRAY_H

View File

@ -330,8 +330,7 @@ inline bool JSTaggedValue::SameValue(const JSTaggedValue &x, const JSTaggedValue
return SameValueNumberic(x, y);
}
if (x.IsString() && y.IsString()) {
return EcmaString::StringsAreEqual(static_cast<EcmaString *>(x.GetTaggedObject()),
static_cast<EcmaString *>(y.GetTaggedObject()));
return StringCompare(EcmaString::Cast(x.GetTaggedObject()), EcmaString::Cast(y.GetTaggedObject()));
}
if (x.IsBigInt() && y.IsBigInt()) {
return BigInt::SameValue(x, y);
@ -397,18 +396,25 @@ inline bool JSTaggedValue::StrictNumberEquals(double x, double y)
inline bool JSTaggedValue::StrictEqual([[maybe_unused]] const JSThread *thread, const JSHandle<JSTaggedValue> &x,
const JSHandle<JSTaggedValue> &y)
{
if (x->IsNumber() && y->IsNumber()) {
return StrictNumberEquals(x->ExtractNumber(), y->ExtractNumber());
return StrictEqual(x.GetTaggedValue(), y.GetTaggedValue());
}
inline bool JSTaggedValue::StrictEqual(const JSTaggedValue &x, const JSTaggedValue &y)
{
if (x.IsNumber() && y.IsNumber()) {
return StrictNumberEquals(x.ExtractNumber(), y.ExtractNumber());
}
if (x.GetTaggedValue() == y.GetTaggedValue()) {
if (x == y) {
return true;
}
if (x->IsString() && y->IsString()) {
return EcmaString::StringsAreEqual(x.GetObject<EcmaString>(), y.GetObject<EcmaString>());
if (x.IsString() && y.IsString()) {
return StringCompare(EcmaString::Cast(x.GetTaggedObject()), EcmaString::Cast(y.GetTaggedObject()));
}
if (x->IsBigInt() && y->IsBigInt()) {
return BigInt::Equal(x.GetTaggedValue(), y.GetTaggedValue());
if (x.IsBigInt() && y.IsBigInt()) {
return BigInt::Equal(x, y);
}
return false;
}
@ -1319,5 +1325,13 @@ inline JSTaggedNumber JSTaggedValue::StringToDouble(JSTaggedValue tagged)
base::ALLOW_BINARY + base::ALLOW_OCTAL + base::ALLOW_HEX);
return JSTaggedNumber(d);
}
inline bool JSTaggedValue::StringCompare(EcmaString *xStr, EcmaString *yStr)
{
if (xStr->IsInternString() && yStr->IsInternString()) {
return xStr == yStr;
}
return EcmaString::StringsAreEqual(xStr, yStr);
}
} // namespace panda::ecmascript
#endif // ECMASCRIPT_TAGGED_VALUE_INL_H

View File

@ -417,6 +417,7 @@ public:
static bool Less(JSThread *thread, const JSHandle<JSTaggedValue> &x, const JSHandle<JSTaggedValue> &y);
static bool Equal(JSThread *thread, const JSHandle<JSTaggedValue> &x, const JSHandle<JSTaggedValue> &y);
static bool StrictEqual(const JSThread *thread, const JSHandle<JSTaggedValue> &x, const JSHandle<JSTaggedValue> &y);
static bool StrictEqual(const JSTaggedValue &x, const JSTaggedValue &y);
static bool SameValueNumberic(const JSTaggedValue &x, const JSTaggedValue &y);
// ES6 7.4 Operations on Iterator Objects
@ -620,6 +621,7 @@ public:
const JSHandle<JSTaggedValue> &y);
static ComparisonResult StrictNumberCompare(double x, double y);
static bool StrictNumberEquals(double x, double y);
static bool StringCompare(EcmaString *xStr, EcmaString *yStr);
static JSHandle<JSTaggedValue> ToPrototypeOrObj(JSThread *thread, const JSHandle<JSTaggedValue> &obj);
inline uint32_t GetKeyHashCode() const;

View File

@ -32,8 +32,9 @@ void ClassInfoExtractor::BuildClassInfoExtractorFromLiteral(JSThread *thread, JS
uint32_t nonStaticNum = static_cast<uint32_t>(literal->Get(thread, literalBufferLength - 1).GetInt());
// Reserve sufficient length to prevent frequent creation.
JSHandle<TaggedArray> nonStaticKeys = factory->NewTaggedArray(nonStaticNum + NON_STATIC_RESERVED_LENGTH);
JSHandle<TaggedArray> nonStaticProperties = factory->NewTaggedArray(nonStaticNum + NON_STATIC_RESERVED_LENGTH);
JSHandle<TaggedArray> nonStaticKeys = factory->NewOldSpaceTaggedArray(nonStaticNum + NON_STATIC_RESERVED_LENGTH);
JSHandle<TaggedArray> nonStaticProperties =
factory->NewOldSpaceTaggedArray(nonStaticNum + NON_STATIC_RESERVED_LENGTH);
nonStaticKeys->Set(thread, CONSTRUCTOR_INDEX, globalConst->GetConstructorString());
@ -58,8 +59,8 @@ void ClassInfoExtractor::BuildClassInfoExtractorFromLiteral(JSThread *thread, JS
uint32_t staticNum = (literalBufferLength - 1) / 2 - nonStaticNum;
// Reserve sufficient length to prevent frequent creation.
JSHandle<TaggedArray> staticKeys = factory->NewTaggedArray(staticNum + STATIC_RESERVED_LENGTH);
JSHandle<TaggedArray> staticProperties = factory->NewTaggedArray(staticNum + STATIC_RESERVED_LENGTH);
JSHandle<TaggedArray> staticKeys = factory->NewOldSpaceTaggedArray(staticNum + STATIC_RESERVED_LENGTH);
JSHandle<TaggedArray> staticProperties = factory->NewOldSpaceTaggedArray(staticNum + STATIC_RESERVED_LENGTH);
staticKeys->Set(thread, LENGTH_INDEX, globalConst->GetLengthString());
staticKeys->Set(thread, NAME_INDEX, globalConst->GetNameString());
@ -133,7 +134,8 @@ bool ClassInfoExtractor::ExtractAndReturnWhetherWithElements(JSThread *thread, c
if (JSTaggedValue::StringToElementIndex(firstValue.GetTaggedValue(), &elementIndex)) {
ASSERT(elementIndex < JSObject::MAX_ELEMENT_INDEX);
uint32_t elementsLength = elements->GetLength();
elements = TaggedArray::SetCapacity(thread, elements, elementsLength + 2); // 2: key-value pair
elements =
TaggedArray::SetCapacityInOldSpace(thread, elements, elementsLength + 2); // 2: key-value pair
elements->Set(thread, elementsLength, firstValue);
elements->Set(thread, elementsLength + 1, secondValue);
withElementsFlag = true;
@ -179,7 +181,7 @@ JSHandle<JSHClass> ClassInfoExtractor::CreatePrototypeHClass(JSThread *thread, J
JSHandle<JSHClass> hclass;
if (LIKELY(length <= PropertyAttributes::MAX_CAPACITY_OF_PROPERTIES)) {
JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
JSHandle<LayoutInfo> layout = factory->CreateLayoutInfo(length);
JSHandle<LayoutInfo> layout = factory->CreateLayoutInfo(length, MemSpaceType::OLD_SPACE);
for (uint32_t index = 0; index < length; ++index) {
key.Update(keys->Get(index));
ASSERT_PRINT(JSTaggedValue::IsPropertyKey(key), "Key is not a property key");
@ -220,7 +222,7 @@ JSHandle<JSHClass> ClassInfoExtractor::CreateConstructorHClass(JSThread *thread,
JSHandle<JSHClass> hclass;
if (LIKELY(length <= PropertyAttributes::MAX_CAPACITY_OF_PROPERTIES)) {
JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
JSHandle<LayoutInfo> layout = factory->CreateLayoutInfo(length);
JSHandle<LayoutInfo> layout = factory->CreateLayoutInfo(length, MemSpaceType::OLD_SPACE);
for (uint32_t index = 0; index < length; ++index) {
key.Update(keys->Get(index));
ASSERT_PRINT(JSTaggedValue::IsPropertyKey(key), "Key is not a property key");
@ -278,12 +280,12 @@ JSHandle<JSFunction> ClassHelper::DefineClassTemplate(JSThread *thread, JSHandle
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<JSHClass> prototypeHClass(thread, extractor->GetPrototypeHClass());
JSHandle<JSObject> prototype = factory->NewJSObject(prototypeHClass);
JSHandle<JSObject> prototype = factory->NewOldSpaceJSObject(prototypeHClass);
JSHandle<JSHClass> constructorHClass(thread, extractor->GetConstructorHClass());
JSHandle<JSFunction> constructor = factory->NewJSFunctionByDynClass(extractor->GetConstructorMethod(),
constructorHClass,
FunctionKind::CLASS_CONSTRUCTOR);
JSHandle<JSFunction> constructor =
factory->NewJSFunctionByDynClass(extractor->GetConstructorMethod(), constructorHClass,
FunctionKind::CLASS_CONSTRUCTOR, MemSpaceType::OLD_SPACE);
// non-static
JSHandle<TaggedArray> nonStaticProperties(thread, extractor->GetNonStaticProperties());

View File

@ -41,8 +41,8 @@ void LiteralDataExtractor::ExtractObjectDatas(JSThread *thread, const JSPandaFil
panda_file::LiteralDataAccessor lda(*pf, literalArraysId);
uint32_t num = lda.GetLiteralValsNum(index) / 2; // 2: half
elements.Update(factory->NewTaggedArray(num).GetTaggedValue());
properties.Update(factory->NewTaggedArray(num).GetTaggedValue());
elements.Update(factory->NewOldSpaceTaggedArray(num).GetTaggedValue());
properties.Update(factory->NewOldSpaceTaggedArray(num).GetTaggedValue());
uint32_t epos = 0;
uint32_t ppos = 0;
const uint8_t pairSize = 2;
@ -68,7 +68,8 @@ void LiteralDataExtractor::ExtractObjectDatas(JSThread *thread, const JSPandaFil
}
case LiteralTag::STRING: {
StringData sd = pf->GetStringData(panda_file::File::EntityId(std::get<uint32_t>(value)));
EcmaString *str = factory->GetRawStringFromStringTable(sd.data, sd.utf16_length, sd.is_ascii);
EcmaString *str = factory->GetRawStringFromStringTable(sd.data, sd.utf16_length, sd.is_ascii,
MemSpaceType::OLD_SPACE);
jt = JSTaggedValue(str);
uint32_t index = 0;
if (JSTaggedValue::ToElementIndex(jt, &index) && ppos % pairSize == 0) {
@ -127,7 +128,7 @@ JSHandle<TaggedArray> LiteralDataExtractor::GetDatasIgnoreType(JSThread *thread,
panda_file::LiteralDataAccessor lda(*pf, literalArraysId);
uint32_t num = lda.GetLiteralValsNum(index) / 2; // 2: half
JSHandle<TaggedArray> literals = factory->NewTaggedArray(num);
JSHandle<TaggedArray> literals = factory->NewOldSpaceTaggedArray(num);
uint32_t pos = 0;
uint32_t methodId;
FunctionKind kind;
@ -151,7 +152,8 @@ JSHandle<TaggedArray> LiteralDataExtractor::GetDatasIgnoreType(JSThread *thread,
case LiteralTag::STRING: {
const panda_file::File *pf = jsPandaFile->GetPandaFile();
StringData sd = pf->GetStringData(panda_file::File::EntityId(std::get<uint32_t>(value)));
EcmaString *str = factory->GetRawStringFromStringTable(sd.data, sd.utf16_length, sd.is_ascii);
EcmaString *str = factory->GetRawStringFromStringTable(sd.data, sd.utf16_length, sd.is_ascii,
MemSpaceType::OLD_SPACE);
jt = JSTaggedValue(str);
break;
}
@ -208,7 +210,8 @@ JSHandle<JSFunction> LiteralDataExtractor::DefineMethodInLiteral(JSThread *threa
} else {
functionClass = JSHandle<JSHClass>::Cast(env->GetGeneratorFunctionClass());
}
JSHandle<JSFunction> jsFunc = factory->NewJSFunctionByDynClass(method, functionClass, kind);
JSHandle<JSFunction> jsFunc =
factory->NewJSFunctionByDynClass(method, functionClass, kind, MemSpaceType::OLD_SPACE);
if (kind == FunctionKind::GENERATOR_FUNCTION) {
JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();

View File

@ -143,16 +143,16 @@ JSTaggedValue PandaFileTranslator::ParseConstPool(EcmaVM *vm, const JSPandaFile
if (value.GetConstpoolType() == ConstPoolType::STRING) {
panda_file::File::EntityId id(it.first);
auto foundStr = pf->GetStringData(id);
auto string = factory->GetRawStringFromStringTable(foundStr.data,
foundStr.utf16_length, foundStr.is_ascii);
auto string = factory->GetRawStringFromStringTable(foundStr.data, foundStr.utf16_length, foundStr.is_ascii,
MemSpaceType::OLD_SPACE);
constpool->Set(thread, value.GetConstpoolIndex(), JSTaggedValue(string));
} else if (value.GetConstpoolType() == ConstPoolType::BASE_FUNCTION) {
panda_file::File::EntityId id(it.first);
auto method = jsPandaFile->FindMethods(it.first);
ASSERT(method != nullptr);
JSHandle<JSFunction> jsFunc =
factory->NewJSFunctionByDynClass(method, dynclass, FunctionKind::BASE_CONSTRUCTOR);
JSHandle<JSFunction> jsFunc = factory->NewJSFunctionByDynClass(
method, dynclass, FunctionKind::BASE_CONSTRUCTOR, MemSpaceType::OLD_SPACE);
if (isLoadedAOT) {
fileLoader->SetAOTFuncEntry(jsPandaFile, jsFunc);
}
@ -163,8 +163,8 @@ JSTaggedValue PandaFileTranslator::ParseConstPool(EcmaVM *vm, const JSPandaFile
auto method = jsPandaFile->FindMethods(it.first);
ASSERT(method != nullptr);
JSHandle<JSFunction> jsFunc =
factory->NewJSFunctionByDynClass(method, normalDynclass, FunctionKind::NORMAL_FUNCTION);
JSHandle<JSFunction> jsFunc = factory->NewJSFunctionByDynClass(
method, normalDynclass, FunctionKind::NORMAL_FUNCTION, MemSpaceType::OLD_SPACE);
if (isLoadedAOT) {
fileLoader->SetAOTFuncEntry(jsPandaFile, jsFunc);
}
@ -214,8 +214,8 @@ JSTaggedValue PandaFileTranslator::ParseConstPool(EcmaVM *vm, const JSPandaFile
auto method = jsPandaFile->FindMethods(it.first);
ASSERT(method != nullptr);
JSHandle<JSFunction> jsFunc =
factory->NewJSFunctionByDynClass(method, normalDynclass, FunctionKind::NORMAL_FUNCTION);
JSHandle<JSFunction> jsFunc = factory->NewJSFunctionByDynClass(
method, normalDynclass, FunctionKind::NORMAL_FUNCTION, MemSpaceType::OLD_SPACE);
if (isLoadedAOT) {
fileLoader->SetAOTFuncEntry(jsPandaFile, jsFunc);
}
@ -268,7 +268,7 @@ JSTaggedValue PandaFileTranslator::ParseConstPool(EcmaVM *vm, const JSPandaFile
// link JSPandaFile
JSHandle<JSNativePointer> jsPandaFilePointer = factory->NewJSNativePointer(
const_cast<JSPandaFile *>(jsPandaFile), JSPandaFileManager::RemoveJSPandaFile,
JSPandaFileManager::GetInstance());
JSPandaFileManager::GetInstance(), true);
constpool->Set(thread, constpoolIndex, jsPandaFilePointer.GetTaggedValue());
DefineClassesInConstPool(thread, constpool, jsPandaFile);

View File

@ -40,6 +40,13 @@ EcmaString *ObjectFactory::AllocStringObject(size_t size)
JSHClass::Cast(thread_->GlobalConstants()->GetStringClass().GetTaggedObject()), size));
}
EcmaString *ObjectFactory::AllocOldSpaceStringObject(size_t size)
{
NewObjectHook();
return reinterpret_cast<EcmaString *>(heap_->AllocateOldOrHugeObject(
JSHClass::Cast(thread_->GlobalConstants()->GetStringClass().GetTaggedObject()), size));
}
JSHandle<JSNativePointer> ObjectFactory::NewJSNativePointer(void *externalPointer,
const DeleteEntryPoint &callBack,
void *data,
@ -92,5 +99,19 @@ void ObjectFactory::NewJSIntlIcuData(const JSHandle<T> &obj, const S &icu, const
JSHandle<JSNativePointer> pointer = NewJSNativePointer(icuPoint, callback);
obj->SetIcuField(thread_, pointer.GetTaggedValue());
}
TaggedObject *ObjectFactory::AllocObjectWithSpaceType(size_t size, JSHClass *cls, MemSpaceType type)
{
switch (type) {
case MemSpaceType::SEMI_SPACE:
return heap_->AllocateYoungOrHugeObject(cls, size);
case MemSpaceType::OLD_SPACE:
return heap_->AllocateOldOrHugeObject(cls, size);
case MemSpaceType::NON_MOVABLE:
return heap_->AllocateNonMovableOrHugeObject(cls, size);
default:
UNREACHABLE();
}
}
} // namespace panda::ecmascript
#endif // ECMASCRIPT_OBJECT_FACTORY_INL_H

View File

@ -1437,9 +1437,22 @@ JSHandle<JSHClass> ObjectFactory::CreateFunctionClass(FunctionKind kind, uint32_
}
JSHandle<JSFunction> ObjectFactory::NewJSFunctionByDynClass(JSMethod *method, const JSHandle<JSHClass> &clazz,
FunctionKind kind)
FunctionKind kind, MemSpaceType type)
{
JSHandle<JSFunction> function = JSHandle<JSFunction>::Cast(NewJSObject(clazz));
JSHandle<JSFunction> function;
switch (type) {
case MemSpaceType::SEMI_SPACE:
function = JSHandle<JSFunction>::Cast(NewJSObject(clazz));
break;
case MemSpaceType::OLD_SPACE:
function = JSHandle<JSFunction>::Cast(NewOldSpaceJSObject(clazz));
break;
case MemSpaceType::NON_MOVABLE:
function = JSHandle<JSFunction>::Cast(NewNonMovableJSObject(clazz));
break;
default:
UNREACHABLE();
}
clazz->SetCallable(true);
clazz->SetExtensible(true);
JSFunction::InitializeJSFunction(thread_, function, kind);
@ -2036,13 +2049,13 @@ JSHandle<TaggedArray> ObjectFactory::NewDictionaryArray(uint32_t length)
}
JSHandle<TaggedArray> ObjectFactory::ExtendArray(const JSHandle<TaggedArray> &old, uint32_t length,
JSTaggedValue initVal)
JSTaggedValue initVal, MemSpaceType type)
{
ASSERT(length > old->GetLength());
NewObjectHook();
size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), length);
auto header = heap_->AllocateYoungOrHugeObject(
JSHClass::Cast(thread_->GlobalConstants()->GetArrayClass().GetTaggedObject()), size);
JSHClass *arrayClass = JSHClass::Cast(thread_->GlobalConstants()->GetArrayClass().GetTaggedObject());
TaggedObject *header = AllocObjectWithSpaceType(size, arrayClass, type);
JSHandle<TaggedArray> newArray(thread_, header);
newArray->SetLength(length);
@ -2088,21 +2101,20 @@ JSHandle<TaggedArray> ObjectFactory::CopyPartArray(const JSHandle<TaggedArray> &
return newArray;
}
JSHandle<TaggedArray> ObjectFactory::CopyArray(const JSHandle<TaggedArray> &old,
[[maybe_unused]] uint32_t oldLength, uint32_t newLength,
JSTaggedValue initVal)
JSHandle<TaggedArray> ObjectFactory::CopyArray(const JSHandle<TaggedArray> &old, uint32_t oldLength, uint32_t newLength,
JSTaggedValue initVal, MemSpaceType type)
{
if (newLength == 0) {
return EmptyArray();
}
if (newLength > oldLength) {
return ExtendArray(old, newLength, initVal);
return ExtendArray(old, newLength, initVal, type);
}
NewObjectHook();
size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), newLength);
auto header = heap_->AllocateYoungOrHugeObject(
JSHClass::Cast(thread_->GlobalConstants()->GetArrayClass().GetTaggedObject()), size);
JSHClass *arrayClass = JSHClass::Cast(thread_->GlobalConstants()->GetArrayClass().GetTaggedObject());
TaggedObject *header = AllocObjectWithSpaceType(size, arrayClass, type);
JSHandle<TaggedArray> newArray(thread_, header);
newArray->InitializeWithSpecialValue(JSTaggedValue::Hole(), newLength);
newArray->SetLength(newLength);
@ -2115,10 +2127,10 @@ JSHandle<TaggedArray> ObjectFactory::CopyArray(const JSHandle<TaggedArray> &old,
return newArray;
}
JSHandle<LayoutInfo> ObjectFactory::CreateLayoutInfo(int properties, JSTaggedValue initVal)
JSHandle<LayoutInfo> ObjectFactory::CreateLayoutInfo(int properties, MemSpaceType type, JSTaggedValue initVal)
{
uint32_t arrayLength = LayoutInfo::ComputeArrayLength(LayoutInfo::ComputeGrowCapacity(properties));
JSHandle<LayoutInfo> layoutInfoHandle = JSHandle<LayoutInfo>::Cast(NewTaggedArray(arrayLength, initVal));
JSHandle<LayoutInfo> layoutInfoHandle = JSHandle<LayoutInfo>::Cast(NewTaggedArray(arrayLength, initVal, type));
layoutInfoHandle->SetNumberOfElements(thread_, 0);
return layoutInfoHandle;
}
@ -2274,8 +2286,8 @@ JSHandle<EcmaString> ObjectFactory::GetStringFromStringTable(EcmaString *string)
}
// NB! don't do special case for C0 80, it means '\u0000', so don't convert to UTF-8
EcmaString *ObjectFactory::GetRawStringFromStringTable(const uint8_t *mutf8Data,
uint32_t utf16Len, bool canBeCompressed) const
EcmaString *ObjectFactory::GetRawStringFromStringTable(const uint8_t *mutf8Data, uint32_t utf16Len,
bool canBeCompressed, MemSpaceType type) const
{
NewObjectHook();
if (UNLIKELY(utf16Len == 0)) {
@ -2283,12 +2295,12 @@ EcmaString *ObjectFactory::GetRawStringFromStringTable(const uint8_t *mutf8Data,
}
if (canBeCompressed) {
return EcmaString::Cast(vm_->GetEcmaStringTable()->GetOrInternString(mutf8Data, utf16Len, true));
return vm_->GetEcmaStringTable()->GetOrInternStringWithSpaceType(mutf8Data, utf16Len, true, type);
}
CVector<uint16_t> utf16Data(utf16Len);
auto len = utf::ConvertRegionMUtf8ToUtf16(mutf8Data, utf16Data.data(), utf::Mutf8Size(mutf8Data), utf16Len, 0);
return EcmaString::Cast(vm_->GetEcmaStringTable()->GetOrInternString(utf16Data.data(), len, false));
return vm_->GetEcmaStringTable()->GetOrInternStringWithSpaceType(utf16Data.data(), len, false, type);
}
JSHandle<PropertyBox> ObjectFactory::NewPropertyBox(const JSHandle<JSTaggedValue> &value)
@ -2744,10 +2756,11 @@ JSHandle<JSHClass> ObjectFactory::GetObjectLiteralHClass(const JSHandle<TaggedAr
return SetLayoutInObjHClass(properties, length, JSHandle<JSHClass>(thread_, maybeHClass));
}
JSHandle<JSObject> ObjectFactory::GetObjectLiteralByHClass(const JSHandle<TaggedArray> &properties, size_t length)
JSHandle<JSObject> ObjectFactory::NewOldSpaceObjLiteralByHClass(const JSHandle<TaggedArray> &properties, size_t length)
{
JSHandle<JSHClass> dynclass = GetObjectLiteralHClass(properties, length);
JSHandle<JSObject> obj = NewJSObjectWithInit(dynclass);
JSHandle<JSObject> obj = NewOldSpaceJSObject(dynclass);
InitializeJSObject(obj, dynclass);
return obj;
}
@ -3500,4 +3513,30 @@ JSHandle<JSHClass> ObjectFactory::CreateIteratorResultInstanceClass()
}
return iterResultClass;
}
TaggedObject *ObjectFactory::NewOldSpaceDynObject(const JSHandle<JSHClass> &dynclass)
{
NewObjectHook();
TaggedObject *header = heap_->AllocateOldOrHugeObject(*dynclass);
uint32_t inobjPropCount = dynclass->GetInlinedProperties();
if (inobjPropCount > 0) {
InitializeExtraProperties(dynclass, header, inobjPropCount);
}
return header;
}
JSHandle<JSObject> ObjectFactory::NewOldSpaceJSObject(const JSHandle<JSHClass> &jshclass)
{
JSHandle<JSObject> obj(thread_, JSObject::Cast(NewOldSpaceDynObject(jshclass)));
JSHandle<TaggedArray> emptyArray = EmptyArray();
obj->InitializeHash();
obj->SetElements(thread_, emptyArray);
obj->SetProperties(thread_, emptyArray);
return obj;
}
JSHandle<TaggedArray> ObjectFactory::NewOldSpaceTaggedArray(uint32_t length, JSTaggedValue initVal)
{
return NewTaggedArray(length, initVal, MemSpaceType::OLD_SPACE);
}
} // namespace panda::ecmascript

View File

@ -316,15 +316,18 @@ public:
JSHandle<BigInt> NewBigInt(uint32_t length);
// use for copy properties keys's array to another array
JSHandle<TaggedArray> ExtendArray(const JSHandle<TaggedArray> &old, uint32_t length,
JSTaggedValue initVal = JSTaggedValue::Hole());
JSTaggedValue initVal = JSTaggedValue::Hole(),
MemSpaceType type = MemSpaceType::SEMI_SPACE);
JSHandle<TaggedArray> CopyPartArray(const JSHandle<TaggedArray> &old, uint32_t start, uint32_t end);
JSHandle<TaggedArray> CopyArray(const JSHandle<TaggedArray> &old, uint32_t oldLength, uint32_t newLength,
JSTaggedValue initVal = JSTaggedValue::Hole());
JSTaggedValue initVal = JSTaggedValue::Hole(),
MemSpaceType type = MemSpaceType::SEMI_SPACE);
JSHandle<TaggedArray> CloneProperties(const JSHandle<TaggedArray> &old);
JSHandle<TaggedArray> CloneProperties(const JSHandle<TaggedArray> &old, const JSHandle<JSTaggedValue> &env,
const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &constpool);
JSHandle<LayoutInfo> CreateLayoutInfo(int properties, JSTaggedValue initVal = JSTaggedValue::Hole());
JSHandle<LayoutInfo> CreateLayoutInfo(int properties, MemSpaceType type = MemSpaceType::SEMI_SPACE,
JSTaggedValue initVal = JSTaggedValue::Hole());
JSHandle<LayoutInfo> ExtendLayoutInfo(const JSHandle<LayoutInfo> &old, int properties,
JSTaggedValue initVal = JSTaggedValue::Hole());
@ -418,13 +421,14 @@ public:
void *data = nullptr,
bool nonMovable = false);
JSHandle<JSObject> GetObjectLiteralByHClass(const JSHandle<TaggedArray> &properties, size_t length);
JSHandle<JSObject> NewOldSpaceObjLiteralByHClass(const JSHandle<TaggedArray> &properties, size_t length);
JSHandle<JSHClass> SetLayoutInObjHClass(const JSHandle<TaggedArray> &properties, size_t length,
const JSHandle<JSHClass> &objClass);
JSHandle<JSHClass> GetObjectLiteralHClass(const JSHandle<TaggedArray> &properties, size_t length);
// only use for creating Function.prototype and Function
JSHandle<JSFunction> NewJSFunctionByDynClass(JSMethod *method, const JSHandle<JSHClass> &clazz,
FunctionKind kind = FunctionKind::NORMAL_FUNCTION);
FunctionKind kind = FunctionKind::NORMAL_FUNCTION,
MemSpaceType type = MemSpaceType::SEMI_SPACE);
JSHandle<JSFunction> NewJSFunctionByDynClass(const void *func, const JSHandle<JSHClass> &clazz,
FunctionKind kind = FunctionKind::NORMAL_FUNCTION);
@ -528,6 +532,11 @@ public:
JSHandle<JSHClass> CreateIteratorResultInstanceClass();
// --------------------------------------old space object--------------------------------------------
JSHandle<JSObject> NewOldSpaceJSObject(const JSHandle<JSHClass> &jshclass);
TaggedObject *NewOldSpaceDynObject(const JSHandle<JSHClass> &dynclass);
JSHandle<TaggedArray> NewOldSpaceTaggedArray(uint32_t length, JSTaggedValue initVal = JSTaggedValue::Hole());
private:
friend class GlobalEnv;
friend class GlobalEnvConstants;
@ -583,7 +592,8 @@ private:
JSHandle<EcmaString> GetStringFromStringTable(const uint8_t *utf8Data, uint32_t utf8Len, bool canBeCompress) const;
JSHandle<EcmaString> GetStringFromStringTableNonMovable(const uint8_t *utf8Data, uint32_t utf8Len) const;
// For MUtf-8 string data
EcmaString *GetRawStringFromStringTable(const uint8_t *mutf8Data, uint32_t utf16Len, bool canBeCompressed) const;
EcmaString *GetRawStringFromStringTable(const uint8_t *mutf8Data, uint32_t utf16Len, bool canBeCompressed,
MemSpaceType type = MemSpaceType::SEMI_SPACE) const;
JSHandle<EcmaString> GetStringFromStringTable(const uint16_t *utf16Data, uint32_t utf16Len,
bool canBeCompress) const;
@ -594,6 +604,7 @@ private:
const JSHandle<EcmaString> &secondString);
inline EcmaString *AllocStringObject(size_t size);
inline EcmaString *AllocOldSpaceStringObject(size_t size);
inline EcmaString *AllocNonMovableStringObject(size_t size);
JSHandle<TaggedArray> NewEmptyArray(); // only used for EcmaVM.
@ -601,6 +612,8 @@ private:
JSHandle<JSHClass> CreateJSArrayInstanceClass(JSHandle<JSTaggedValue> proto);
JSHandle<JSHClass> CreateJSRegExpInstanceClass(JSHandle<JSTaggedValue> proto);
inline TaggedObject *AllocObjectWithSpaceType(size_t size, JSHClass *cls, MemSpaceType type);
friend class Builtins; // create builtins object need dynclass
friend class JSFunction; // create prototype_or_dynclass need dynclass
friend class JSHClass; // HC transition need dynclass

View File

@ -155,6 +155,16 @@ inline JSHandle<TaggedArray> TaggedArray::SetCapacity(const JSThread *thread, co
return newArray;
}
inline JSHandle<TaggedArray> TaggedArray::SetCapacityInOldSpace(const JSThread *thread,
const JSHandle<TaggedArray> &array, uint32_t capa)
{
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
uint32_t oldLength = array->GetLength();
JSHandle<TaggedArray> newArray =
factory->CopyArray(array, oldLength, capa, JSTaggedValue::Hole(), MemSpaceType::OLD_SPACE);
return newArray;
}
inline bool TaggedArray::IsDictionaryMode() const
{
return GetClass()->IsDictionary();

View File

@ -75,6 +75,9 @@ public:
static JSHandle<TaggedArray> SetCapacity(const JSThread *thread, const JSHandle<TaggedArray> &array,
uint32_t capa);
static JSHandle<TaggedArray> SetCapacityInOldSpace(const JSThread *thread, const JSHandle<TaggedArray> &array,
uint32_t capa);
inline void InitializeWithSpecialValue(JSTaggedValue initValue, uint32_t length);
static inline bool ShouldTrim(uint32_t oldLength, uint32_t newLength)