Optimize JSON Parse builtin

Change-Id: I5f8afddf7faead9b9d5121f3c4ed6684531918f4
Signed-off-by: Panferov Ivan <panferov.ivan@huawei-partners.com>
This commit is contained in:
Panferov Ivan 2024-02-12 20:04:52 +08:00
parent 35b7f88217
commit a5e918efd2
13 changed files with 207 additions and 57 deletions

View File

@ -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> {

View File

@ -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

View File

@ -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);

View File

@ -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)
{

View File

@ -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();

View File

@ -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.

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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()));

View File

@ -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();

View File

@ -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,

View File

@ -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();