mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-11-23 18:20:04 +00:00
Optimize JSON Parse builtin
Change-Id: I5f8afddf7faead9b9d5121f3c4ed6684531918f4 Signed-off-by: Panferov Ivan <panferov.ivan@huawei-partners.com>
This commit is contained in:
parent
35b7f88217
commit
a5e918efd2
@ -87,6 +87,8 @@ protected:
|
||||
}
|
||||
end_ = end - 1;
|
||||
current_ = begin;
|
||||
SkipEndWhiteSpace();
|
||||
range_ = end_;
|
||||
|
||||
auto vm = thread_->GetEcmaVM();
|
||||
factory_ = vm->GetFactory();
|
||||
@ -101,8 +103,6 @@ protected:
|
||||
initialJSObjectClass_ =
|
||||
JSHandle<JSHClass>(thread_, JSFunction::GetOrCreateInitialJSHClass(thread_, objectFunc));
|
||||
|
||||
SkipEndWhiteSpace();
|
||||
range_ = end_;
|
||||
JSTaggedValue result = ParseJSONText();
|
||||
RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread_);
|
||||
return JSHandle<JSTaggedValue>(thread_, result);
|
||||
@ -282,24 +282,43 @@ protected:
|
||||
}
|
||||
|
||||
JSHandle<JSTaggedValue> CreateJsonObject(JsonContinuation continuation,
|
||||
std::vector<JSHandle<JSTaggedValue>> &propertyList)
|
||||
std::vector<JSHandle<JSTaggedValue>> &propertyList)
|
||||
{
|
||||
size_t start = continuation.index_;
|
||||
size_t size = propertyList.size() - start;
|
||||
JSHandle<JSObject> obj = factory_->NewJSObject(initialJSObjectClass_);
|
||||
auto obj = JSHandle<JSTaggedValue>(factory_->NewJSObject(initialJSObjectClass_));
|
||||
for (size_t i = 0; i < size; i += 2) { // 2: prop name and value
|
||||
JSHandle<JSTaggedValue> keyHandle = propertyList[start + i];
|
||||
JSHandle<JSTaggedValue> valueHandle = propertyList[start + i + 1];
|
||||
JSTaggedValue res = ObjectFastOperator::SetPropertyByValue<ObjectFastOperator::Status::UseOwn>
|
||||
(thread_, obj.GetTaggedValue(), keyHandle.GetTaggedValue(), valueHandle.GetTaggedValue());
|
||||
auto &keyHandle = propertyList[start + i];
|
||||
auto &valueHandle = propertyList[start + i + 1];
|
||||
auto res = SetPropertyByValue(obj, keyHandle, valueHandle);
|
||||
RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread_);
|
||||
if (res.IsHole()) {
|
||||
// slow path
|
||||
JSTaggedValue::SetProperty(thread_, JSHandle<JSTaggedValue>(obj), keyHandle, valueHandle, true);
|
||||
JSTaggedValue::SetProperty(thread_, obj, keyHandle, valueHandle, true);
|
||||
RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread_);
|
||||
}
|
||||
}
|
||||
return JSHandle<JSTaggedValue>(obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
JSTaggedValue SetPropertyByValue(const JSHandle<JSTaggedValue> &receiver, const JSHandle<JSTaggedValue> &key,
|
||||
const JSHandle<JSTaggedValue> &value)
|
||||
{
|
||||
ASSERT(key->IsString());
|
||||
auto newKey = key.GetTaggedValue();
|
||||
auto stringAccessor = EcmaStringAccessor(newKey);
|
||||
if (!stringAccessor.IsLineString() || IsNumberCharacter(*stringAccessor.GetDataUtf8())) {
|
||||
uint32_t index = 0;
|
||||
if (stringAccessor.ToElementIndex(&index)) {
|
||||
return ObjectFastOperator::SetPropertyByIndex<ObjectFastOperator::Status::UseOwn>(thread_,
|
||||
receiver.GetTaggedValue(), index, value.GetTaggedValue());
|
||||
}
|
||||
}
|
||||
if (!stringAccessor.IsInternString()) {
|
||||
newKey = JSTaggedValue(thread_->GetEcmaVM()->GetFactory()->InternString(key));
|
||||
}
|
||||
return ObjectFastOperator::SetPropertyByName<ObjectFastOperator::Status::UseOwn>(thread_,
|
||||
receiver.GetTaggedValue(), newKey, value.GetTaggedValue());
|
||||
}
|
||||
|
||||
JSTaggedValue ParseNumber(bool inObjorArr = false)
|
||||
@ -781,16 +800,31 @@ public:
|
||||
NO_COPY_SEMANTIC(Utf8JsonParser);
|
||||
NO_MOVE_SEMANTIC(Utf8JsonParser);
|
||||
|
||||
JSHandle<JSTaggedValue> Parse(EcmaString *str)
|
||||
JSHandle<JSTaggedValue> Parse(const JSHandle<EcmaString> &strHandle)
|
||||
{
|
||||
ASSERT(str != nullptr);
|
||||
auto stringAccessor = EcmaStringAccessor(str);
|
||||
ASSERT(*strHandle != nullptr);
|
||||
auto stringAccessor = EcmaStringAccessor(strHandle);
|
||||
uint32_t len = stringAccessor.GetLength();
|
||||
ASSERT(len != UINT32_MAX);
|
||||
CVector<uint8_t> buf(len + 1);
|
||||
stringAccessor.WriteToFlatUtf8(buf.data(), len);
|
||||
Text begin = buf.data();
|
||||
return Launch(begin, begin + len);
|
||||
|
||||
uint32_t slicedOffset = 0;
|
||||
if (LIKELY(stringAccessor.IsLineOrConstantString())) {
|
||||
sourceString_ = strHandle;
|
||||
begin_ = stringAccessor.GetDataUtf8();
|
||||
} else if (stringAccessor.IsSlicedString()) {
|
||||
auto *sliced = static_cast<SlicedString *>(*strHandle);
|
||||
slicedOffset = sliced->GetStartIndex();
|
||||
sourceString_ = JSHandle<EcmaString>(thread_, EcmaString::Cast(sliced->GetParent()));
|
||||
} else {
|
||||
auto *flatten = EcmaStringAccessor::Flatten(thread_->GetEcmaVM(), strHandle);
|
||||
sourceString_ = JSHandle<EcmaString>(thread_, flatten);
|
||||
}
|
||||
begin_ = EcmaStringAccessor(sourceString_).GetDataUtf8();
|
||||
auto *heap = const_cast<Heap *>(thread_->GetEcmaVM()->GetHeap());
|
||||
auto listenerId = heap->AddGCListener(UpdatePointersListener, this);
|
||||
auto res = Launch(begin_ + slicedOffset, begin_ + slicedOffset + len);
|
||||
heap->RemoveGCListener(listenerId);
|
||||
return res;
|
||||
}
|
||||
|
||||
private:
|
||||
@ -799,6 +833,21 @@ private:
|
||||
str += std::string_view(reinterpret_cast<const char *>(current), nextCurrent - current);
|
||||
}
|
||||
|
||||
static void UpdatePointersListener(void *utf8Parser)
|
||||
{
|
||||
auto *parser = reinterpret_cast<Utf8JsonParser *>(utf8Parser);
|
||||
auto *begin = EcmaStringAccessor(parser->sourceString_).GetDataUtf8();
|
||||
if (parser->begin_ != begin) {
|
||||
uint32_t currentOffset = parser->current_ - parser->begin_;
|
||||
uint32_t endOffset = parser->end_ - parser->begin_;
|
||||
uint32_t rangeOffset = parser->range_ - parser->begin_;
|
||||
parser->current_ = reinterpret_cast<uint8_t *>(ToUintPtr(begin) + currentOffset);
|
||||
parser->end_ = reinterpret_cast<uint8_t *>(ToUintPtr(begin) + endOffset);
|
||||
parser->range_ = reinterpret_cast<uint8_t *>(ToUintPtr(begin) + rangeOffset);
|
||||
parser->begin_ = begin;
|
||||
}
|
||||
}
|
||||
|
||||
JSTaggedValue ParseString(bool inObjorArr = false) override
|
||||
{
|
||||
bool isFastString = true;
|
||||
@ -809,12 +858,11 @@ private:
|
||||
THROW_SYNTAX_ERROR_AND_RETURN(thread_, "Unexpected end Text in JSON", JSTaggedValue::Exception());
|
||||
}
|
||||
if (isFastString) {
|
||||
size_t strLength = end_ - current_;
|
||||
uint32_t offset = current_ - begin_;
|
||||
uint32_t strLength = end_ - current_;
|
||||
ASSERT(strLength <= static_cast<size_t>(UINT32_MAX));
|
||||
JSTaggedValue res = factory_->NewCompressedUtf8(
|
||||
reinterpret_cast<const uint8_t *>(current_), strLength).GetTaggedValue();
|
||||
current_ = end_ + 1;
|
||||
return res;
|
||||
return factory_->NewCompressedUtf8SubString(sourceString_, offset, strLength).GetTaggedValue();
|
||||
}
|
||||
} else {
|
||||
if (*end_ != '"' || current_ == end_) {
|
||||
@ -825,11 +873,12 @@ private:
|
||||
THROW_SYNTAX_ERROR_AND_RETURN(thread_, "Unexpected end Text in JSON", JSTaggedValue::Exception());
|
||||
}
|
||||
if (LIKELY(isFastString)) {
|
||||
std::string_view value(reinterpret_cast<const char *>(current_), end_ - current_);
|
||||
uint32_t offset = current_ - begin_;
|
||||
uint32_t strLength = end_ - current_;
|
||||
ASSERT(strLength <= static_cast<size_t>(UINT32_MAX));
|
||||
current_ = end_ + 1;
|
||||
ASSERT(value.size() <= static_cast<size_t>(UINT32_MAX));
|
||||
return factory_->NewFromUtf8LiteralCompress(
|
||||
reinterpret_cast<const uint8_t *>(value.data()), value.size()).GetTaggedValue();
|
||||
return factory_->NewFromUtf8LiteralCompressSubString(
|
||||
sourceString_, offset, strLength).GetTaggedValue();
|
||||
}
|
||||
}
|
||||
return SlowParseString();
|
||||
@ -867,6 +916,9 @@ private:
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const uint8_t *begin_;
|
||||
JSHandle<EcmaString> sourceString_;
|
||||
};
|
||||
|
||||
class Utf16JsonParser : public JsonParser<uint16_t> {
|
||||
|
@ -61,17 +61,17 @@ HWTEST_F_L0(JsonParserTest, Parser_001)
|
||||
// JSON Number
|
||||
JSHandle<JSTaggedValue> handleMsg2(factory->NewFromASCII("1234"));
|
||||
JSHandle<EcmaString> handleStr2(JSTaggedValue::ToString(thread, handleMsg2));
|
||||
JSHandle<JSTaggedValue> result2 = parser.Parse(*handleStr2);
|
||||
JSHandle<JSTaggedValue> result2 = parser.Parse(handleStr2);
|
||||
EXPECT_EQ(result2->GetNumber(), 1234);
|
||||
// JSON Literal
|
||||
JSHandle<JSTaggedValue> handleMsg3(factory->NewFromASCII("true"));
|
||||
JSHandle<EcmaString> handleStr3(JSTaggedValue::ToString(thread, handleMsg3));
|
||||
JSHandle<JSTaggedValue> result3 = parser.Parse(*handleStr3);
|
||||
JSHandle<JSTaggedValue> result3 = parser.Parse(handleStr3);
|
||||
EXPECT_EQ(result3.GetTaggedValue(), JSTaggedValue::True());
|
||||
// JSON Unexpected
|
||||
JSHandle<JSTaggedValue> handleMsg4(factory->NewFromASCII("trus"));
|
||||
JSHandle<EcmaString> handleStr4(JSTaggedValue::ToString(thread, handleMsg4));
|
||||
JSHandle<JSTaggedValue> result4 = parser.Parse(*handleStr4);
|
||||
JSHandle<JSTaggedValue> result4 = parser.Parse(handleStr4);
|
||||
EXPECT_EQ(result4.GetTaggedValue(), JSTaggedValue::Exception());
|
||||
}
|
||||
|
||||
@ -127,7 +127,7 @@ HWTEST_F_L0(JsonParserTest, Parser_003)
|
||||
"\t\r \n{\t\r \n \"json\"\t\r\n:\t\r \n{\t\r \n}\t\r \n,\t\r \n \"prop2\"\t\r \n:\t\r \n [\t\r \nfalse\t\r"
|
||||
"\n,\t\r \nnull\t\r, \ntrue\t\r,123.456\t\r \n]\t\r \n}\t\r \n"));
|
||||
JSHandle<EcmaString> handleStr(JSTaggedValue::ToString(thread, handleMsg)); // JSON Object
|
||||
JSHandle<JSTaggedValue> result = parser.Parse(*handleStr);
|
||||
JSHandle<JSTaggedValue> result = parser.Parse(handleStr);
|
||||
EXPECT_TRUE(result->IsECMAObject());
|
||||
}
|
||||
|
||||
@ -146,7 +146,7 @@ HWTEST_F_L0(JsonParserTest, Parser_004)
|
||||
|
||||
JSHandle<JSTaggedValue> handleMsg(factory->NewFromASCII("[100,2.5,\"abc\"]"));
|
||||
JSHandle<EcmaString> handleStr(JSTaggedValue::ToString(thread, handleMsg)); // JSON Array
|
||||
JSHandle<JSTaggedValue> result = parser.Parse(*handleStr);
|
||||
JSHandle<JSTaggedValue> result = parser.Parse(handleStr);
|
||||
|
||||
JSTaggedValue resultValue(static_cast<JSTaggedType>(result->GetRawData()));
|
||||
EXPECT_TRUE(resultValue.IsECMAObject());
|
||||
@ -173,7 +173,7 @@ HWTEST_F_L0(JsonParserTest, Parser_005)
|
||||
JSHandle<JSTaggedValue> handleMsg(factory->NewFromASCII("{\"epf\":100,\"key1\":400}"));
|
||||
JSHandle<EcmaString> handleStr(JSTaggedValue::ToString(thread, handleMsg)); // JSON Object
|
||||
|
||||
JSHandle<JSTaggedValue> result = parser.Parse(*handleStr);
|
||||
JSHandle<JSTaggedValue> result = parser.Parse(handleStr);
|
||||
JSTaggedValue resultValue(static_cast<JSTaggedType>(result->GetRawData()));
|
||||
EXPECT_TRUE(resultValue.IsECMAObject());
|
||||
|
||||
@ -198,7 +198,7 @@ HWTEST_F_L0(JsonParserTest, Parser_006)
|
||||
{
|
||||
Utf8JsonParser parser(thread);
|
||||
JSHandle<EcmaString> emptyString(thread->GlobalConstants()->GetHandledEmptyString());
|
||||
JSHandle<JSTaggedValue> result = parser.Parse(*emptyString);
|
||||
JSHandle<JSTaggedValue> result = parser.Parse(emptyString);
|
||||
EXPECT_TRUE(result->IsException());
|
||||
}
|
||||
} // namespace panda::test
|
||||
|
@ -49,7 +49,7 @@ JSTaggedValue BuiltinsJson::Parse(EcmaRuntimeCallInfo *argv)
|
||||
JSHandle<JSTaggedValue> result;
|
||||
if (EcmaStringAccessor(parseString).IsUtf8()) {
|
||||
panda::ecmascript::base::Utf8JsonParser parser(thread);
|
||||
result = parser.Parse(*parseString);
|
||||
result = parser.Parse(parseString);
|
||||
} else {
|
||||
panda::ecmascript::base::Utf16JsonParser parser(thread);
|
||||
result = parser.Parse(*parseString);
|
||||
|
@ -48,11 +48,7 @@ inline EcmaString *EcmaString::CreateFromUtf8(const EcmaVM *vm, const uint8_t *u
|
||||
} else {
|
||||
string = CreateLineStringWithSpaceType(vm, utf8Len, true, type);
|
||||
ASSERT(string != nullptr);
|
||||
|
||||
if (memcpy_s(string->GetDataUtf8Writable(), utf8Len, utf8Data, utf8Len) != EOK) {
|
||||
LOG_FULL(FATAL) << "memcpy_s failed";
|
||||
UNREACHABLE();
|
||||
}
|
||||
std::copy(utf8Data, utf8Data + utf8Len, string->GetDataUtf8Writable());
|
||||
}
|
||||
} else {
|
||||
auto utf16Len = base::utf_helper::Utf8ToUtf16Size(utf8Data, utf8Len);
|
||||
@ -68,6 +64,20 @@ inline EcmaString *EcmaString::CreateFromUtf8(const EcmaVM *vm, const uint8_t *u
|
||||
return string;
|
||||
}
|
||||
|
||||
/* static */
|
||||
inline EcmaString *EcmaString::CreateFromUtf8CompressedSubString(const EcmaVM *vm, const JSHandle<EcmaString> &string,
|
||||
uint32_t offset, uint32_t utf8Len, MemSpaceType type)
|
||||
{
|
||||
ASSERT(utf8Len != 0);
|
||||
EcmaString *subString = CreateLineStringWithSpaceType(vm, utf8Len, true, type);
|
||||
ASSERT(subString != nullptr);
|
||||
|
||||
auto *utf8Data = string->GetDataUtf8() + offset;
|
||||
std::copy(utf8Data, utf8Data + utf8Len, subString->GetDataUtf8Writable());
|
||||
ASSERT_PRINT(CanBeCompressed(subString), "String cannot be compressed!");
|
||||
return subString;
|
||||
}
|
||||
|
||||
inline EcmaString *EcmaString::CreateUtf16StringFromUtf8(const EcmaVM *vm, const uint8_t *utf8Data, uint32_t utf16Len,
|
||||
MemSpaceType type)
|
||||
{
|
||||
|
@ -112,6 +112,8 @@ private:
|
||||
static EcmaString *CreateFromUtf8(const EcmaVM *vm, const uint8_t *utf8Data, uint32_t utf8Len,
|
||||
bool canBeCompress, MemSpaceType type = MemSpaceType::SEMI_SPACE, bool isConstantString = false,
|
||||
uint32_t idOffset = 0);
|
||||
static EcmaString *CreateFromUtf8CompressedSubString(const EcmaVM *vm, const JSHandle<EcmaString> &string,
|
||||
uint32_t offset, uint32_t utf8Len, MemSpaceType type = MemSpaceType::SEMI_SPACE);
|
||||
static EcmaString *CreateUtf16StringFromUtf8(const EcmaVM *vm, const uint8_t *utf8Data, uint32_t utf8Len,
|
||||
MemSpaceType type = MemSpaceType::SEMI_SPACE);
|
||||
static EcmaString *CreateFromUtf16(const EcmaVM *vm, const uint16_t *utf16Data, uint32_t utf16Len,
|
||||
@ -482,22 +484,12 @@ private:
|
||||
LOG_FULL(FATAL) << " length is higher than half of size_t::max";
|
||||
UNREACHABLE();
|
||||
}
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
||||
// Only memcpy_s maxLength number of chars into buffer if length > maxLength
|
||||
CVector<uint8_t> tmpBuf;
|
||||
const uint8_t *data = GetUtf8DataFlat(this, tmpBuf);
|
||||
if (length > maxLength) {
|
||||
if (memcpy_s(buf, maxLength, data + start, maxLength) != EOK) {
|
||||
LOG_FULL(FATAL) << "memcpy_s failed when length > maxlength";
|
||||
UNREACHABLE();
|
||||
}
|
||||
return maxLength;
|
||||
}
|
||||
if (memcpy_s(buf, maxLength, data + start, length) != EOK) {
|
||||
LOG_FULL(FATAL) << "memcpy_s failed when length <= maxlength";
|
||||
UNREACHABLE();
|
||||
}
|
||||
return length;
|
||||
const uint8_t *data = GetUtf8DataFlat(this, tmpBuf) + start;
|
||||
// Only copy maxLength number of chars into buffer if length > maxLength
|
||||
auto dataLen = std::min(length, maxLength);
|
||||
std::copy(data, data + dataLen, buf);
|
||||
return dataLen;
|
||||
}
|
||||
CVector<uint16_t> tmpBuf;
|
||||
const uint16_t *data = GetUtf16DataFlat(this, tmpBuf);
|
||||
@ -1074,6 +1066,13 @@ public:
|
||||
return EcmaString::CreateFromUtf8(vm, utf8Data, utf8Len, canBeCompress, type, isConstantString, idOffset);
|
||||
}
|
||||
|
||||
static EcmaString *CreateFromUtf8CompressedSubString(const EcmaVM *vm, const JSHandle<EcmaString> &string,
|
||||
uint32_t offset, uint32_t utf8Len,
|
||||
MemSpaceType type = MemSpaceType::SEMI_SPACE)
|
||||
{
|
||||
return EcmaString::CreateFromUtf8CompressedSubString(vm, string, offset, utf8Len, type);
|
||||
}
|
||||
|
||||
static EcmaString *CreateConstantString(const EcmaVM *vm, const uint8_t *utf8Data, size_t length,
|
||||
bool compressed, MemSpaceType type = MemSpaceType::SEMI_SPACE, uint32_t idOffset = 0)
|
||||
{
|
||||
@ -1450,6 +1449,11 @@ public:
|
||||
return string_->IsConstantString();
|
||||
}
|
||||
|
||||
bool IsSlicedString() const
|
||||
{
|
||||
return string_->IsSlicedString();
|
||||
}
|
||||
|
||||
bool IsLineOrConstantString() const
|
||||
{
|
||||
return string_->IsLineOrConstantString();
|
||||
|
@ -133,6 +133,22 @@ EcmaString *EcmaStringTable::GetOrInternString(const uint8_t *utf8Data, uint32_t
|
||||
return str;
|
||||
}
|
||||
|
||||
EcmaString *EcmaStringTable::GetOrInternCompressedSubString(const JSHandle<EcmaString> &string,
|
||||
uint32_t offset, uint32_t utf8Len)
|
||||
{
|
||||
auto *utf8Data = EcmaStringAccessor(string).GetDataUtf8() + offset;
|
||||
std::pair<EcmaString *, uint32_t> result = GetString(utf8Data, utf8Len, true);
|
||||
if (result.first != nullptr) {
|
||||
return result.first;
|
||||
}
|
||||
|
||||
EcmaString *str = EcmaStringAccessor::CreateFromUtf8CompressedSubString(
|
||||
vm_, string, offset, utf8Len, MemSpaceType::OLD_SPACE);
|
||||
str->SetMixHashcode(result.second);
|
||||
InternString(str);
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
This function is used to create global constant strings from non-movable sapce only.
|
||||
It only inserts string into string-table and provides no string-table validity check.
|
||||
|
@ -40,6 +40,7 @@ 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 *GetOrInternCompressedSubString(const JSHandle<EcmaString> &string, uint32_t offset, uint32_t utf8Len);
|
||||
EcmaString *GetOrInternStringWithSpaceType(const uint8_t *utf8Data, uint32_t utf8Len, bool canBeCompress,
|
||||
MemSpaceType type, bool isConstantString, uint32_t idOffset);
|
||||
EcmaString *GetOrInternStringWithSpaceType(const uint8_t *utf8Data, uint32_t utf16Len,
|
||||
|
@ -137,6 +137,7 @@ void Heap::Initialize()
|
||||
compressGCMarker_ = new CompressGCMarker(this);
|
||||
evacuator_ = new ParallelEvacuator(this);
|
||||
incrementalMarker_ = new IncrementalMarker(this);
|
||||
gcListeners_.reserve(16U);
|
||||
}
|
||||
|
||||
void Heap::Destroy()
|
||||
@ -365,6 +366,7 @@ void Heap::CollectGarbage(TriggerGCType gcType, GCReason reason)
|
||||
{
|
||||
RecursionScope recurScope(this);
|
||||
if (thread_->IsCrossThreadExecutionEnable() || (InSensitiveStatus() && !ObjectExceedMaxHeapSize())) {
|
||||
ProcessGCListeners();
|
||||
return;
|
||||
}
|
||||
#if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
|
||||
@ -433,6 +435,7 @@ void Heap::CollectGarbage(TriggerGCType gcType, GCReason reason)
|
||||
oldSpace_->SetOvershootSize(GetEcmaVM()->GetEcmaParamConfiguration().GetOldSpaceOvershootSize());
|
||||
TriggerConcurrentMarking();
|
||||
oldGCRequested_ = true;
|
||||
ProcessGCListeners();
|
||||
return;
|
||||
}
|
||||
partialGC_->RunPhases();
|
||||
@ -513,6 +516,7 @@ void Heap::CollectGarbage(TriggerGCType gcType, GCReason reason)
|
||||
}
|
||||
#endif
|
||||
ASSERT(thread_->IsPropertyCacheCleared());
|
||||
ProcessGCListeners();
|
||||
}
|
||||
|
||||
void Heap::ThrowOutOfMemoryError(size_t size, std::string functionName, bool NonMovableObjNearOOM)
|
||||
@ -1643,4 +1647,23 @@ std::tuple<uint64_t, uint8_t *, int, kungfu::CalleeRegAndOffsetVec> Heap::CalCal
|
||||
}
|
||||
return code->CalCallSiteInfo(retAddr);
|
||||
};
|
||||
|
||||
GCListenerId Heap::AddGCListener(FinishGCListener listener, void *data)
|
||||
{
|
||||
gcListeners_.emplace_back(std::make_pair(listener, data));
|
||||
return std::prev(gcListeners_.cend());
|
||||
}
|
||||
|
||||
void Heap::ProcessGCListeners()
|
||||
{
|
||||
for (auto &&[listener, data] : gcListeners_) {
|
||||
listener(data);
|
||||
}
|
||||
}
|
||||
|
||||
void Heap::RemoveGCListener(GCListenerId listenerId)
|
||||
{
|
||||
gcListeners_.erase(listenerId);
|
||||
}
|
||||
|
||||
} // namespace panda::ecmascript
|
||||
|
@ -46,6 +46,8 @@ class PartialGC;
|
||||
class STWYoungGC;
|
||||
|
||||
using IdleNotifyStatusCallback = std::function<void(bool)>;
|
||||
using FinishGCListener = void (*)(void *);
|
||||
using GCListenerId = std::vector<std::pair<FinishGCListener, void *>>::const_iterator;
|
||||
|
||||
enum class IdleTaskType : uint8_t {
|
||||
NO_TASK,
|
||||
@ -653,6 +655,8 @@ public:
|
||||
void CheckNonMovableSpaceOOM();
|
||||
std::tuple<uint64_t, uint8_t *, int, kungfu::CalleeRegAndOffsetVec> CalCallSiteInfo(uintptr_t retAddr) const;
|
||||
|
||||
GCListenerId AddGCListener(FinishGCListener listener, void *data);
|
||||
void RemoveGCListener(GCListenerId listenerId);
|
||||
private:
|
||||
static constexpr int IDLE_TIME_LIMIT = 10; // if idle time over 10ms we can do something
|
||||
static constexpr int ALLOCATE_SIZE_LIMIT = 100_KB;
|
||||
@ -672,6 +676,7 @@ private:
|
||||
void DumpHeapSnapshotBeforeOOM(bool isFullGC = true);
|
||||
inline void ReclaimRegions(TriggerGCType gcType);
|
||||
inline size_t CalculateCommittedCacheSize();
|
||||
void ProcessGCListeners();
|
||||
class ParallelGCTask : public Task {
|
||||
public:
|
||||
ParallelGCTask(int32_t id, Heap *heap, ParallelGCTaskPhase taskPhase)
|
||||
@ -860,6 +865,11 @@ private:
|
||||
// ONLY used for heap verification.
|
||||
bool shouldVerifyHeap_ {false};
|
||||
bool isVerifying_ {false};
|
||||
|
||||
/*
|
||||
* The listeners which are called at the end of GC
|
||||
*/
|
||||
std::vector<std::pair<FinishGCListener, void *>> gcListeners_;
|
||||
};
|
||||
} // namespace panda::ecmascript
|
||||
|
||||
|
@ -229,7 +229,8 @@ Local<JSValueRef> JSON::Parse(const EcmaVM *vm, Local<StringRef> string)
|
||||
JSHandle<JSTaggedValue> result;
|
||||
if (EcmaStringAccessor(ecmaStr).IsUtf8()) {
|
||||
Utf8JsonParser parser(thread);
|
||||
result = parser.Parse(EcmaString::Cast(JSNApiHelper::ToJSTaggedValue(*string).GetTaggedObject()));
|
||||
JSHandle<EcmaString> str(thread, JSNApiHelper::ToJSTaggedValue(*string));
|
||||
result = parser.Parse(str);
|
||||
} else {
|
||||
Utf16JsonParser parser(thread);
|
||||
result = parser.Parse(EcmaString::Cast(JSNApiHelper::ToJSTaggedValue(*string).GetTaggedObject()));
|
||||
|
@ -25,6 +25,8 @@
|
||||
#include "ecmascript/compiler/builtins/builtins_call_signature.h"
|
||||
#include "ecmascript/ecma_macros.h"
|
||||
#include "ecmascript/ecma_string_table.h"
|
||||
#include "ecmascript/ecma_string.h"
|
||||
#include "ecmascript/ecma_string-inl.h"
|
||||
#include "ecmascript/ecma_vm.h"
|
||||
#include "ecmascript/element_accessor.h"
|
||||
#include "ecmascript/element_accessor-inl.h"
|
||||
@ -3016,6 +3018,15 @@ JSHandle<EcmaString> ObjectFactory::GetStringFromStringTable(const uint8_t *utf8
|
||||
return JSHandle<EcmaString>(thread_, stringTable->GetOrInternString(utf8Data, utf8Len, canBeCompress));
|
||||
}
|
||||
|
||||
JSHandle<EcmaString> ObjectFactory::GetCompressedSubStringFromStringTable(const JSHandle<EcmaString> &string,
|
||||
uint32_t offset, uint32_t utf8Len) const
|
||||
{
|
||||
NewObjectHook();
|
||||
ASSERT(utf8Len != 0);
|
||||
auto *stringTable = vm_->GetEcmaStringTable();
|
||||
return JSHandle<EcmaString>(thread_, stringTable->GetOrInternCompressedSubString(string, offset, utf8Len));
|
||||
}
|
||||
|
||||
JSHandle<EcmaString> ObjectFactory::GetStringFromStringTableNonMovable(const uint8_t *utf8Data, uint32_t utf8Len) const
|
||||
{
|
||||
NewObjectHook();
|
||||
@ -4015,6 +4026,15 @@ JSHandle<EcmaString> ObjectFactory::NewFromUtf8LiteralCompress(const uint8_t *ut
|
||||
return JSHandle<EcmaString>(thread_, EcmaStringAccessor::CreateFromUtf8(vm_, utf8Data, utf8Len, true));
|
||||
}
|
||||
|
||||
JSHandle<EcmaString> ObjectFactory::NewFromUtf8LiteralCompressSubString(const JSHandle<EcmaString> &string,
|
||||
uint32_t offset, uint32_t utf8Len)
|
||||
{
|
||||
NewObjectHook();
|
||||
ASSERT(EcmaStringAccessor::CanBeCompressed(EcmaStringAccessor(string).GetDataUtf8() + offset, utf8Len));
|
||||
return JSHandle<EcmaString>(thread_, EcmaStringAccessor::CreateFromUtf8CompressedSubString(vm_, string,
|
||||
offset, utf8Len));
|
||||
}
|
||||
|
||||
JSHandle<EcmaString> ObjectFactory::NewCompressedUtf8(const uint8_t *utf8Data, uint32_t utf8Len)
|
||||
{
|
||||
NewObjectHook();
|
||||
@ -4022,6 +4042,14 @@ JSHandle<EcmaString> ObjectFactory::NewCompressedUtf8(const uint8_t *utf8Data, u
|
||||
return GetStringFromStringTable(utf8Data, utf8Len, true);
|
||||
}
|
||||
|
||||
JSHandle<EcmaString> ObjectFactory::NewCompressedUtf8SubString(const JSHandle<EcmaString> &string,
|
||||
uint32_t offset, uint32_t utf8Len)
|
||||
{
|
||||
NewObjectHook();
|
||||
ASSERT(EcmaStringAccessor::CanBeCompressed(EcmaStringAccessor(string).GetDataUtf8() + offset, utf8Len));
|
||||
return GetCompressedSubStringFromStringTable(string, offset, utf8Len);
|
||||
}
|
||||
|
||||
JSHandle<EcmaString> ObjectFactory::NewFromUtf16Literal(const uint16_t *utf16Data, uint32_t utf16Len)
|
||||
{
|
||||
NewObjectHook();
|
||||
|
@ -569,8 +569,11 @@ public:
|
||||
|
||||
JSHandle<EcmaString> NewFromUtf8Literal(const uint8_t *utf8Data, uint32_t utf8Len);
|
||||
JSHandle<EcmaString> PUBLIC_API NewFromUtf8LiteralCompress(const uint8_t *utf8Data, uint32_t utf8Len);
|
||||
JSHandle<EcmaString> PUBLIC_API NewFromUtf8LiteralCompressSubString(const JSHandle<EcmaString> &string,
|
||||
uint32_t offset, uint32_t utf8Len);
|
||||
JSHandle<EcmaString> PUBLIC_API NewCompressedUtf8(const uint8_t *utf8Data, uint32_t utf8Len);
|
||||
|
||||
JSHandle<EcmaString> PUBLIC_API NewCompressedUtf8SubString(const JSHandle<EcmaString> &string,
|
||||
uint32_t offset, uint32_t utf8Len);
|
||||
JSHandle<EcmaString> NewFromUtf16Literal(const uint16_t *utf16Data, uint32_t utf16Len);
|
||||
JSHandle<EcmaString> NewFromUtf16LiteralCompress(const uint16_t *utf16Data, uint32_t utf16Len);
|
||||
JSHandle<EcmaString> PUBLIC_API NewFromUtf16LiteralNotCompress(const uint16_t *utf16Data, uint32_t utf16Len);
|
||||
@ -739,6 +742,8 @@ private:
|
||||
const JSHandle<JSTaggedValue> &object);
|
||||
|
||||
JSHandle<EcmaString> GetStringFromStringTable(const uint8_t *utf8Data, uint32_t utf8Len, bool canBeCompress) const;
|
||||
JSHandle<EcmaString> GetCompressedSubStringFromStringTable(const JSHandle<EcmaString> &string, uint32_t offset,
|
||||
uint32_t utf8Len) const;
|
||||
JSHandle<EcmaString> GetStringFromStringTableNonMovable(const uint8_t *utf8Data, uint32_t utf8Len) const;
|
||||
// For MUtf-8 string data
|
||||
EcmaString* PUBLIC_API GetRawStringFromStringTable(StringData sd, MemSpaceType type = MemSpaceType::SEMI_SPACE,
|
||||
|
@ -168,7 +168,7 @@ public:
|
||||
ecmascript::base::Utf8JsonParser parser(jsThread);
|
||||
|
||||
JSHandle<EcmaString> handleStr = factory->NewFromASCII(jsonInfo.c_str()); // JSON Object
|
||||
JSHandle<JSTaggedValue> result = parser.Parse(*handleStr);
|
||||
JSHandle<JSTaggedValue> result = parser.Parse(handleStr);
|
||||
JSTaggedValue resultValue(static_cast<JSTaggedType>(result->GetRawData()));
|
||||
if (!resultValue.IsArray(jsThread)) {
|
||||
LOG_COMPILER(ERROR) << "Pkg list info parse failed. result is not an array. jsonData: " << jsonInfo.c_str();
|
||||
@ -203,7 +203,7 @@ public:
|
||||
ecmascript::base::Utf8JsonParser parser(jsThread);
|
||||
|
||||
JSHandle<EcmaString> handleStr(factory->NewFromASCII(jsonInfo.c_str())); // JSON Object
|
||||
JSHandle<JSTaggedValue> result = parser.Parse(*handleStr);
|
||||
JSHandle<JSTaggedValue> result = parser.Parse(handleStr);
|
||||
JSTaggedValue resultValue(static_cast<JSTaggedType>(result->GetRawData()));
|
||||
if (!resultValue.IsECMAObject()) {
|
||||
LOG_COMPILER(ERROR) << "Pkg info parse failed. result is not an object. jsonData: " << jsonInfo.c_str();
|
||||
|
Loading…
Reference in New Issue
Block a user