Merge branch 'master' of gitee.com:openharmony/arkcompiler_ets_runtime into master

Signed-off-by: zhaozhibo <zhaozhibo3@huawei.com>
This commit is contained in:
zhaozhibo 2022-11-28 02:01:20 +00:00 committed by Gitee
commit 5e4853b54b
192 changed files with 3888 additions and 2048 deletions

View File

@ -437,7 +437,6 @@ ecma_source = [
"ecmascript/builtins/builtins_weak_ref.cpp",
"ecmascript/builtins/builtins_weak_set.cpp",
"ecmascript/byte_array.cpp",
"ecmascript/calleeReg.cpp",
"ecmascript/containers/containers_arraylist.cpp",
"ecmascript/containers/containers_deque.cpp",
"ecmascript/containers/containers_errors.cpp",
@ -454,15 +453,16 @@ ecma_source = [
"ecmascript/containers/containers_treemap.cpp",
"ecmascript/containers/containers_treeset.cpp",
"ecmascript/containers/containers_vector.cpp",
"ecmascript/deoptimizer/calleeReg.cpp",
"ecmascript/deoptimizer/deoptimizer.cpp",
"ecmascript/deoptimizer/relocator.cpp",
"ecmascript/dfx/pgo_profiler/pgo_profiler_loader.cpp",
"ecmascript/dfx/pgo_profiler/pgo_profiler_manager.cpp",
"ecmascript/dfx/stackinfo/js_stackinfo.cpp",
"ecmascript/deoptimizer.cpp",
"ecmascript/dfx/vmstat/caller_stat.cpp",
"ecmascript/dfx/vmstat/runtime_stat.cpp",
"ecmascript/dfx/vm_thread_control.cpp",
"ecmascript/dump.cpp",
"ecmascript/relocator.cpp",
"ecmascript/ecma_string.cpp",
"ecmascript/ecma_string_table.cpp",
"ecmascript/ecma_vm.cpp",

View File

@ -22,8 +22,8 @@
#include "ecmascript/base/config.h"
#include "ecmascript/compiler/bc_call_signature.h"
#include "ecmascript/compiler/common_stubs.h"
#include "ecmascript/deoptimizer.h"
#include "ecmascript/relocator.h"
#include "ecmascript/deoptimizer/deoptimizer.h"
#include "ecmascript/deoptimizer/relocator.h"
#include "ecmascript/llvm_stackmap_parser.h"
#include "ecmascript/ecma_vm.h"
#include "ecmascript/message_string.h"
@ -208,6 +208,113 @@ bool StubFileInfo::Load(EcmaVM *vm)
return true;
}
AnFileDataManager *AnFileDataManager::GetInstance()
{
static AnFileDataManager anFileDataManager;
return &anFileDataManager;
}
AnFileDataManager::~AnFileDataManager()
{
os::memory::LockHolder lock(lock_);
auto iter = loadedData_.begin();
while (iter != loadedData_.end()) {
void *poolAddr = iter->second->poolAddr;
size_t poolSize = iter->second->poolSize;
MemMapAllocator::GetInstance()->Free(poolAddr, poolSize, false);
iter = loadedData_.erase(iter);
}
}
bool AnFileDataManager::SafeLoad(const std::string &filename)
{
if (!AOTFileInfo::VerifyFilePath(filename)) {
LOG_COMPILER(ERROR) << "Can not load aot file from path [ " << filename << " ], "
<< "please execute ark_aot_compiler with options --aot-file.";
UNREACHABLE();
return false;
}
os::memory::LockHolder lock(lock_);
const CString &cstrFileName = ConvertToString(filename);
const std::shared_ptr<AnFileData const> anFileData = UnsafeFind(cstrFileName);
if (anFileData != nullptr) {
return true;
}
if (!UnsafeLoadData(cstrFileName)) {
return false;
}
return true;
}
std::shared_ptr<const AnFileDataManager::AnFileData> AnFileDataManager::UnsafeFind(const CString &filename) const
{
// note: This method is not thread-safe
// need to ensure that the instance of AnFileDataManager has been locked before use
const auto iter = loadedData_.find(filename);
if (iter == loadedData_.end()) {
return nullptr;
}
return iter->second;
}
std::shared_ptr<const AnFileDataManager::AnFileData> AnFileDataManager::SafeGetAnFileData(const CString &filename)
{
os::memory::LockHolder lock(lock_);
return UnsafeFind(filename);
}
bool AnFileDataManager::UnsafeLoadData(const CString &filename)
{
std::ifstream file(filename.c_str(), std::ofstream::binary);
if (!file.good()) {
LOG_COMPILER(ERROR) << "Fail to load an file: " << filename.c_str();
file.close();
return false;
}
std::array<uint8_t, AOTFileManager::AOT_VERSION_SIZE> anVersion;
file.read(reinterpret_cast<char *>(anVersion.data()), sizeof(uint8_t) * AOTFileManager::AOT_VERSION_SIZE);
if (anVersion != AOTFileManager::AOT_VERSION) {
auto convToStr = [] (std::array<uint8_t, AOTFileManager::AOT_VERSION_SIZE> version) -> std::string {
std::string ret = "";
for (size_t i = 0; i < AOTFileManager::AOT_VERSION_SIZE; ++i) {
if (i) {
ret += ".";
}
ret += std::to_string(version[i]);
}
return ret;
};
LOG_COMPILER(ERROR) << "Load an file failed, an file version is incorrect, "
<< "expected version is " << convToStr(AOTFileManager::AOT_VERSION)
<< ", but got " << convToStr(anVersion);
file.close();
return false;
}
std::shared_ptr<AnFileData> data = std::make_shared<AnFileData>(AnFileData());
loadedData_[filename] = data;
file.read(reinterpret_cast<char *>(&data->entryNum), sizeof(data->entryNum));
data->entries.resize(data->entryNum);
file.read(reinterpret_cast<char *>(data->entries.data()), sizeof(AOTFileInfo::FuncEntryDes) * data->entryNum);
file.read(reinterpret_cast<char *>(&data->moduleNum), sizeof(data->moduleNum));
data->des.resize(data->moduleNum);
file.read(reinterpret_cast<char *>(&data->totalCodeSize), sizeof(data->totalCodeSize));
int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
auto pool = MemMapAllocator::GetInstance()->Allocate(AlignUp(data->totalCodeSize, 256_KB), 0, false, prot);
data->poolAddr = pool.GetMem();
data->poolSize = pool.GetSize();
uint64_t codeAddress = reinterpret_cast<uint64_t>(pool.GetMem());
uint32_t curUnitOffset = 0;
for (size_t i = 0; i < data->moduleNum; i++) {
data->des[i].LoadSectionsInfo(file, curUnitOffset, codeAddress);
}
return true;
}
void AnFileInfo::Iterate(const RootVisitor &v)
{
v(Root::ROOT_VM, ObjectSlot(reinterpret_cast<uintptr_t>(&snapshotConstantPool_)));
@ -268,43 +375,19 @@ void AnFileInfo::RewriteRelcateTextSection([[maybe_unused]] const char* symbol,
#endif
}
bool AnFileInfo::Load(EcmaVM *vm, const std::string &filename)
bool AnFileInfo::Load(const std::string &filename)
{
if (!VerifyFilePath(filename)) {
LOG_COMPILER(ERROR) << "Can not load aot file from path [ " << filename << " ], "
<< "please execute ark_aot_compiler with options --aot-file.";
UNREACHABLE();
AnFileDataManager *anFileDataManager = AnFileDataManager::GetInstance();
if (!anFileDataManager->SafeLoad(filename)) {
return false;
}
std::ifstream file(filename.c_str(), std::ofstream::binary);
if (!file.good()) {
LOG_COMPILER(ERROR) << "Fail to load aot file: " << filename.c_str();
file.close();
return false;
}
std::array<uint8_t, AOTFileManager::AOT_VERSION_SIZE> anVersion;
file.read(reinterpret_cast<char *>(anVersion.data()), sizeof(uint8_t) * AOTFileManager::AOT_VERSION_SIZE);
if (anVersion != vm->GetAOTFileManager()->AOT_VERSION) {
LOG_COMPILER(ERROR) << "Load aot file failed";
file.close();
return false;
}
file.read(reinterpret_cast<char *>(&entryNum_), sizeof(entryNum_));
entries_.resize(entryNum_);
file.read(reinterpret_cast<char *>(entries_.data()), sizeof(FuncEntryDes) * entryNum_);
file.read(reinterpret_cast<char *>(&moduleNum_), sizeof(moduleNum_));
des_.resize(moduleNum_);
uint32_t totalCodeSize = 0;
file.read(reinterpret_cast<char *>(&totalCodeSize), sizeof(totalCodeSize_));
[[maybe_unused]] EcmaHandleScope handleScope(vm->GetAssociatedJSThread());
int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
auto pool = MemMapAllocator::GetInstance()->Allocate(AlignUp(totalCodeSize, 256_KB), 0, false, prot);
vm->GetAOTFileManager()->SetAOTmmap(pool.GetMem(), pool.GetSize());
uint64_t codeAddress = reinterpret_cast<uint64_t>(pool.GetMem());
uint32_t curUnitOffset = 0;
for (size_t i = 0; i < moduleNum_; i++) {
des_[i].LoadSectionsInfo(file, curUnitOffset, codeAddress);
}
data_ = anFileDataManager->SafeGetAnFileData(ConvertToString(filename));
entryNum_ = data_->entryNum;
entries_ = data_->entries;
moduleNum_ = data_->moduleNum;
totalCodeSize_ = data_->totalCodeSize;
des_ = data_->des;
for (size_t i = 0; i < entries_.size(); i++) {
FuncEntryDes& funcDes = entries_[i];
auto moduleDes = des_[funcDes.moduleIndex_];
@ -313,7 +396,7 @@ bool AnFileInfo::Load(EcmaVM *vm, const std::string &filename)
mainEntryMap_[funcDes.indexInKindOrMethodId_] = funcDes.codeAddr_;
}
}
file.close();
LOG_COMPILER(INFO) << "loaded aot file: " << filename.c_str();
isLoad_ = true;
return true;
@ -329,14 +412,13 @@ bool AnFileInfo::IsLoadMain(const JSPandaFile *jsPandaFile, const CString &entry
return true;
}
void AOTFileInfo::Iterate(const RootVisitor &v)
{
v(Root::ROOT_VM, ObjectSlot(reinterpret_cast<uintptr_t>(&machineCodeObj_)));
}
bool AOTFileInfo::VerifyFilePath([[maybe_unused]] const std::string &filePath,
[[maybe_unused]] bool toGenerate) const
[[maybe_unused]] bool toGenerate)
{
#ifndef PANDA_TARGET_WINDOWS
if (filePath.size() > PATH_MAX) {
@ -369,7 +451,7 @@ void AOTFileManager::LoadStubFile()
void AOTFileManager::LoadAnFile(const std::string &fileName)
{
AnFileInfo anFileInfo_;
if (!anFileInfo_.Load(vm_, fileName)) {
if (!anFileInfo_.Load(fileName)) {
return;
}
AddAnFileInfo(anFileInfo_);
@ -600,6 +682,12 @@ void AOTFileManager::AddSnapshotConstantPool(JSTaggedValue snapshotConstantPool)
JSHandle<JSTaggedValue> AOTFileManager::GetSnapshotConstantPool(const JSPandaFile *jsPandaFile)
{
// In some appilication, only the main vm will load '.an' file currently
// return the constantpool with HOLE value when other worker try to obtain the
// snapshot constantpool from aot_file_manager.
if (anFileInfos_.size() == 0) {
return JSHandle<JSTaggedValue>(vm_->GetJSThread(), JSTaggedValue::Hole());
}
uint32_t anFileInfoIndex = jsPandaFile->GetAOTFileInfoIndex();
const AnFileInfo &anFileInfo = anFileInfos_[anFileInfoIndex];
return anFileInfo.GetSnapshotConstantPool();
@ -611,9 +699,6 @@ AOTFileManager::~AOTFileManager()
delete arkStackMapParser_;
arkStackMapParser_ = nullptr;
}
for (size_t i = 0; i < aotAddrs_.size(); i++) {
MemMapAllocator::GetInstance()->Free(aotAddrs_[i].first, aotAddrs_[i].second, false);
}
for (size_t i = 0; i < stubAddrs_.size(); i++) {
MemMapAllocator::GetInstance()->Free(stubAddrs_[i].first, stubAddrs_[i].second, false);
}
@ -657,19 +742,14 @@ bool AOTFileManager::GetAbsolutePath(const std::string &relativePath, std::strin
char buffer[PATH_MAX] = {0};
#ifndef PANDA_TARGET_WINDOWS
auto path = realpath(relativePath.c_str(), buffer);
if (path == nullptr) {
return false;
}
absPath = std::string(path);
return true;
#else
auto path = _fullpath(buffer, relativePath.c_str(), sizeof(buffer) - 1);
#endif
if (path == nullptr) {
return false;
}
absPath = std::string(buffer);
return true;
#endif
}
void BinaryBufferParser::ParseBuffer(void *dst, uint32_t count)

View File

@ -16,7 +16,7 @@
#define ECMASCRIPT_AOT_FILE_MANAGER_H
#include "ecmascript/ark_stackmap.h"
#include "ecmascript/calleeReg.h"
#include "ecmascript/deoptimizer/calleeReg.h"
#include "ecmascript/js_function.h"
#include "ecmascript/js_runtime_options.h"
#include "ecmascript/compiler/binary_section.h"
@ -144,7 +144,8 @@ public:
using CallSignature = kungfu::CallSignature;
AOTFileInfo() = default;
virtual ~AOTFileInfo() = default;
bool VerifyFilePath([[maybe_unused]] const std::string &filePath, [[maybe_unused]] bool toGenerate = false) const;
static bool VerifyFilePath([[maybe_unused]] const std::string &filePath,
[[maybe_unused]] bool toGenerate = false);
struct FuncEntryDes {
uint64_t codeAddr_;
@ -241,7 +242,7 @@ public:
{
FuncEntryDes des;
if (memset_s(&des, sizeof(des), 0, sizeof(des)) != EOK) {
LOG_FULL(FATAL) << "memset failed";
LOG_FULL(FATAL) << "memset_s failed";
return;
}
des.kind_ = kind;
@ -292,13 +293,41 @@ protected:
JSTaggedValue machineCodeObj_ {JSTaggedValue::Hole()};
};
class AnFileDataManager {
public:
static AnFileDataManager *GetInstance();
~AnFileDataManager();
struct AnFileData {
uint32_t entryNum {0};
uint32_t moduleNum {0};
uint32_t totalCodeSize {0};
std::vector<AOTFileInfo::FuncEntryDes> entries {};
std::vector<ModuleSectionDes> des {};
void *poolAddr {nullptr};
size_t poolSize {0};
};
bool SafeLoad(const std::string &filename);
std::shared_ptr<const AnFileData> SafeGetAnFileData(const CString &filename);
private:
AnFileDataManager() = default;
std::shared_ptr<const AnFileData> UnsafeFind(const CString &filename) const;
bool UnsafeLoadData(const CString &filename);
os::memory::RecursiveMutex lock_;
std::unordered_map<const CString, std::shared_ptr<AnFileData>, CStringHash> loadedData_;
};
class PUBLIC_API AnFileInfo : public AOTFileInfo {
public:
AnFileInfo() = default;
~AnFileInfo() override = default;
void Iterate(const RootVisitor &v);
void Save(const std::string &filename);
bool Load(EcmaVM *vm, const std::string &filename);
bool Load(const std::string &filename);
void AddModuleDes(ModuleSectionDes &moduleDes)
{
des_.emplace_back(moduleDes);
@ -343,6 +372,7 @@ private:
void RewriteRelcateTextSection(const char* symbol, uintptr_t patchAddr);
std::unordered_map<uint32_t, uint64_t> mainEntryMap_ {};
JSTaggedValue snapshotConstantPool_ {JSTaggedValue::Hole()};
std::shared_ptr<const AnFileDataManager::AnFileData> data_;
bool isLoad_ {false};
};
@ -458,11 +488,6 @@ public:
JSHandle<JSTaggedValue> GetSnapshotConstantPool(const JSPandaFile *jsPandaFile);
private:
void SetAOTmmap(void *addr, size_t totalCodeSize)
{
aotAddrs_.emplace_back(std::make_pair(addr, totalCodeSize));
}
void SetStubmmap(void *addr, size_t totalCodeSize)
{
stubAddrs_.emplace_back(std::make_pair(addr, totalCodeSize));
@ -488,7 +513,6 @@ private:
void AdjustBCStubAndDebuggerStubEntries(JSThread *thread, const std::vector<AOTFileInfo::FuncEntryDes> &stubs,
const AsmInterParsedOption &asmInterOpt);
std::vector<std::pair<void *, size_t>> aotAddrs_;
std::vector<std::pair<void *, size_t>> stubAddrs_;
EcmaVM *vm_ {nullptr};
ObjectFactory *factory_ {nullptr};

View File

@ -15,7 +15,7 @@
#include "ecmascript/ark_stackmap_parser.h"
#include "ecmascript/ark_stackmap_builder.h"
#include "ecmascript/compiler/assembler/assembler.h"
#include "ecmascript/deoptimizer.h"
#include "ecmascript/deoptimizer/deoptimizer.h"
#include "ecmascript/aot_file_manager.h"
namespace panda::ecmascript::kungfu {

View File

@ -19,13 +19,8 @@
#include <cstdint>
#include <cstring>
#include <limits>
#include <macros.h>
#include <securec.h>
#include <type_traits>
#include "ecmascript/log_wrapper.h"
#include "ecmascript/log.h"
namespace panda::ecmascript::base {
template <typename T>
inline constexpr uint32_t CountLeadingZeros(T value)
@ -129,11 +124,9 @@ inline To bit_cast(const From &src) noexcept // NOLINT(readability-identifier-n
{
static_assert(sizeof(To) == sizeof(From), "size of the types must be equal");
To dst;
errno_t res = memcpy_s(&dst, sizeof(To), &src, sizeof(To));
if (res != EOK) {
LOG_FULL(FATAL) << "memcpy_s failed";
UNREACHABLE();
}
// The use of security functions 'memccpy_s' here will have a greater impact on performance
// todo use union instance of memcpy
memcpy(&dst, &src, sizeof(To));
return dst;
}

View File

@ -27,7 +27,6 @@ namespace panda::ecmascript::base {
bool FilePathHelper::RealPath(const std::string &path, std::string &realPath, [[maybe_unused]] bool readOnly)
{
realPath = "";
if (path.empty() || path.size() > PATH_MAX) {
LOG_ECMA(WARN) << "File path is illeage";
return false;

View File

@ -366,8 +366,12 @@ JSTaggedValue JsonStringifier::SerializeJSONProperty(const JSHandle<JSTaggedValu
return tagValue;
}
// If Type(value) is String, return QuoteJSONString(value).
case JSType::STRING: {
CString str = ConvertToString(*JSHandle<EcmaString>(valHandle), StringConvertedUsage::LOGICOPERATION);
case JSType::LINE_STRING:
case JSType::TREE_STRING: {
JSHandle<EcmaString> strHandle = JSHandle<EcmaString>(valHandle);
auto string = JSHandle<EcmaString>(thread_,
EcmaStringAccessor::Flatten(thread_->GetEcmaVM(), strHandle));
CString str = ConvertToString(*string, StringConvertedUsage::LOGICOPERATION);
str = ValueToQuotedString(str);
result_ += str;
return tagValue;

View File

@ -687,7 +687,7 @@ JSTaggedValue NumberHelper::StringToBigInt(JSThread *thread, JSHandle<JSTaggedVa
if (strLen == 0) {
return BigInt::Int32ToBigInt(thread, 0).GetTaggedValue();
}
[[maybe_unused]] CVector<uint8_t> buf;
CVector<uint8_t> buf;
Span<const uint8_t> str = EcmaStringAccessor(strObj).ToUtf8Span(buf);
auto p = const_cast<uint8_t *>(str.begin());

View File

@ -261,30 +261,30 @@ public:
if (srcStr.find('\n') == std::string::npos) {
escape = false;
}
int prePos = 0;
size_t prePos = 0;
int findPrePos = lineNumber - 1;
for (int i = 0; i < findPrePos; i++) {
if (escape) {
prePos = srcStr.find('\n', prePos);
if (prePos == -1) {
if (prePos == std::string::npos) {
return "";
}
prePos += 1;
} else {
prePos = srcStr.find("\\n", prePos);
if (prePos == -1) {
if (prePos == std::string::npos) {
return "";
}
prePos += 2; // 2 : add the two characters found to start searching again
}
}
int findEndPos = 0;
size_t findEndPos = 0;
if (escape) {
findEndPos = srcStr.find('\n', prePos);
} else {
findEndPos = srcStr.find("\\n", prePos);
}
if (findEndPos == -1) {
if (findEndPos == std::string::npos) {
return srcStr.substr(prePos, srcStr.length() - prePos);
}
ASSERT(findEndPos > prePos);

View File

@ -23,11 +23,14 @@ host_unittest_action("BaseTest") {
# test file
"array_helper_test.cpp",
"atomic_helper_test.cpp",
"bit_helper_test.cpp",
"builtins_base_test.cpp",
"error_helper_test.cpp",
"file_path_helper_test.cpp",
"gc_ring_buffer_test.cpp",
"json_parser_test.cpp",
"json_stringifier_test.cpp",
"math_helper_test.cpp",
"number_helper_test.cpp",
"string_helper_test.cpp",
"typed_array_helper_test.cpp",

View File

@ -0,0 +1,112 @@
/*
* 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.
*/
#include "ecmascript/base/bit_helper.h"
#include "ecmascript/tests/test_helper.h"
using namespace panda::ecmascript;
using namespace panda::ecmascript::base;
namespace panda::test {
class BitHelperTest : public testing::Test {
public:
static void SetUpTestCase()
{
GTEST_LOG_(INFO) << "SetUpTestCase";
}
static void TearDownTestCase()
{
GTEST_LOG_(INFO) << "TearDownCase";
}
void SetUp() override
{
TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
}
void TearDown() override
{
TestHelper::DestroyEcmaVMWithScope(instance, scope);
}
EcmaVM *instance {nullptr};
EcmaHandleScope *scope {nullptr};
JSThread *thread {nullptr};
};
HWTEST_F_L0(BitHelperTest, CountLeadingZeros_CountTrailingZeros)
{
uint8_t uint8MaxValue = std::numeric_limits<uint8_t>::max();
uint8_t uint8MinValue = std::numeric_limits<uint8_t>::min();
EXPECT_EQ(CountLeadingZeros<uint8_t>(uint8MaxValue), 0U);
EXPECT_EQ(CountLeadingZeros<uint8_t>(uint8MinValue), 8U);
EXPECT_EQ(CountTrailingZeros<uint8_t>(uint8MaxValue), 0U);
EXPECT_EQ(CountTrailingZeros<uint8_t>(uint8MinValue), 8U);
uint16_t uint16MaxValue = std::numeric_limits<uint16_t>::max();
uint16_t uint16MinValue = std::numeric_limits<uint16_t>::min();
EXPECT_EQ(CountLeadingZeros<uint16_t>(uint16MaxValue), 0U);
EXPECT_EQ(CountLeadingZeros<uint16_t>(uint16MinValue), 16U);
EXPECT_EQ(CountTrailingZeros<uint16_t>(uint16MaxValue), 0U);
EXPECT_EQ(CountTrailingZeros<uint16_t>(uint16MinValue), 16U);
uint32_t uint32MaxValue = std::numeric_limits<uint32_t>::max();
uint32_t uint32MinValue = std::numeric_limits<uint32_t>::min();
EXPECT_EQ(CountLeadingZeros<uint32_t>(uint32MaxValue), 0U);
EXPECT_EQ(CountLeadingZeros<uint32_t>(uint32MinValue), 32U);
EXPECT_EQ(CountTrailingZeros<uint32_t>(uint32MaxValue), 0U);
EXPECT_EQ(CountTrailingZeros<uint32_t>(uint32MinValue), 32U);
uint64_t uint64MaxValue = std::numeric_limits<uint64_t>::max();
uint64_t uint64MinValue = std::numeric_limits<uint64_t>::min();
EXPECT_EQ(CountLeadingZeros<uint64_t>(uint64MaxValue), 0U);
EXPECT_EQ(CountLeadingZeros<uint64_t>(uint64MinValue), 64U);
EXPECT_EQ(CountTrailingZeros<uint64_t>(uint64MaxValue), 0U);
EXPECT_EQ(CountTrailingZeros<uint64_t>(uint64MinValue), 64U);
}
HWTEST_F_L0(BitHelperTest, CountLeadingZeros32_CountLeadingOnes32)
{
uint32_t uint32MaxValue = std::numeric_limits<uint32_t>::max();
uint32_t uint32CommonValue1 = std::numeric_limits<uint32_t>::max() >> 1;
uint32_t uint32CommonValue2 = std::numeric_limits<uint32_t>::max() >> 31; // 31 : right shift digit
uint32_t uint32MinValue = std::numeric_limits<uint32_t>::min();
EXPECT_EQ(CountLeadingZeros32(uint32MaxValue), 0U);
EXPECT_EQ(CountLeadingZeros32(uint32CommonValue1), 1U);
EXPECT_EQ(CountLeadingZeros32(uint32CommonValue2), 31U);
EXPECT_EQ(CountLeadingZeros32(uint32MinValue), 32U);
EXPECT_EQ(CountLeadingOnes32(uint32MaxValue), 32U);
EXPECT_EQ(CountLeadingOnes32(uint32CommonValue1), 0U);
EXPECT_EQ(CountLeadingOnes32(uint32CommonValue2), 0U);
EXPECT_EQ(CountLeadingOnes32(uint32MinValue), 0U);
}
HWTEST_F_L0(BitHelperTest, CountLeadingZeros64_CountLeadingOnes64)
{
uint64_t uint64MaxValue = std::numeric_limits<uint64_t>::max();
uint64_t uint64CommonValue1 = std::numeric_limits<uint64_t>::max() >> 1;
uint64_t uint64CommonValue2 = std::numeric_limits<uint64_t>::max() >> 63; // 63 : right shift digit
uint64_t uint64MinValue = std::numeric_limits<uint64_t>::min();
EXPECT_EQ(CountLeadingZeros64(uint64MaxValue), 0U);
EXPECT_EQ(CountLeadingZeros64(uint64CommonValue1), 1U);
EXPECT_EQ(CountLeadingZeros64(uint64CommonValue2), 63U);
EXPECT_EQ(CountLeadingZeros64(uint64MinValue), 64U);
EXPECT_EQ(CountLeadingOnes64(uint64MaxValue), 64U);
EXPECT_EQ(CountLeadingOnes64(uint64CommonValue1), 0U);
EXPECT_EQ(CountLeadingOnes64(uint64CommonValue2), 0U);
EXPECT_EQ(CountLeadingOnes64(uint64MinValue), 0U);
}
} // namespace panda::test

View File

@ -0,0 +1,69 @@
/*
* 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.
*/
#include "ecmascript/base/file_path_helper.h"
#include "ecmascript/tests/test_helper.h"
using namespace panda::ecmascript;
using namespace panda::ecmascript::base;
namespace panda::test {
class FilePathHelperTest : public testing::Test {
public:
static void SetUpTestCase()
{
GTEST_LOG_(INFO) << "SetUpTestCase";
}
static void TearDownTestCase()
{
GTEST_LOG_(INFO) << "TearDownCase";
}
void SetUp() override
{
TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
}
void TearDown() override
{
TestHelper::DestroyEcmaVMWithScope(instance, scope);
}
EcmaVM *instance {nullptr};
EcmaHandleScope *scope {nullptr};
JSThread *thread {nullptr};
};
HWTEST_F_L0(FilePathHelperTest, RealPath)
{
std::string filePath = "__FilePathHelperTest.test";
EXPECT_TRUE(std::fopen(filePath.c_str(), "r") == nullptr);
std::string realPath;
bool result = FilePathHelper::RealPath(filePath, realPath, false);
EXPECT_EQ(result, true);
std::fstream stream {};
stream.open(realPath, std::ios::out);
EXPECT_EQ(stream.good(), true);
EXPECT_TRUE(std::fopen(realPath.c_str(), "r") != nullptr);
stream.close();
stream.clear();
std::remove(filePath.c_str());
std::remove(realPath.c_str());
}
} // namespace panda::test

View File

@ -171,7 +171,7 @@ HWTEST_F_L0(JsonStringifierTest, Stringify_003)
EXPECT_TRUE(resultString->IsString());
JSHandle<EcmaString> resultStr =
factory->NewFromASCII("{\ntttt\"z\": 1,\ntttt\"x\": 3.6,\ntttt\"y\": \"abc\"\n}");
EXPECT_EQ(EcmaStringAccessor::Compare(*resultStr, reinterpret_cast<EcmaString *>(resultString->GetRawData())), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, resultStr, JSHandle<EcmaString>(resultString)), 0);
}
/**

View File

@ -0,0 +1,88 @@
/*
* 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.
*/
#include "ecmascript/base/math_helper.h"
#include "ecmascript/tests/test_helper.h"
using namespace panda::ecmascript;
using namespace panda::ecmascript::base;
namespace panda::test {
class MathHelperTest : public testing::Test {
public:
static void SetUpTestCase()
{
GTEST_LOG_(INFO) << "SetUpTestCase";
}
static void TearDownTestCase()
{
GTEST_LOG_(INFO) << "TearDownCase";
}
void SetUp() override
{
TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
}
void TearDown() override
{
TestHelper::DestroyEcmaVMWithScope(instance, scope);
}
EcmaVM *instance {nullptr};
EcmaHandleScope *scope {nullptr};
JSThread *thread {nullptr};
};
HWTEST_F_L0(MathHelperTest, GetIntLog2_001)
{
const uint32_t commonInput = static_cast<uint32_t>(0b111111111) << 13; // 13 : left shift digit
const uint32_t maxInput = std::numeric_limits<uint32_t>::max();
EXPECT_EQ(MathHelper::GetIntLog2(commonInput), 13U);
EXPECT_EQ(MathHelper::GetIntLog2(maxInput), 0U);
}
HWTEST_F_L0(MathHelperTest, GetIntLog2_002)
{
const uint64_t commonInput = static_cast<uint64_t>(0b111111111) << 53; // 53 : left shift digit
const uint64_t maxInput = std::numeric_limits<uint64_t>::max();
EXPECT_EQ(MathHelper::GetIntLog2(commonInput), 53U);
EXPECT_EQ(MathHelper::GetIntLog2(maxInput), 0U);
}
HWTEST_F_L0(MathHelperTest, Asinh)
{
EXPECT_EQ(MathHelper::Asinh(1), 0.88137358701954302523260932497979);
EXPECT_EQ(MathHelper::Asinh(+0), +0.0);
EXPECT_EQ(MathHelper::Asinh(-0), -0.0);
EXPECT_EQ(MathHelper::Asinh(-1), -0.88137358701954302523260932497979);
double nanResult = MathHelper::Asinh(std::numeric_limits<double>::signaling_NaN());
EXPECT_TRUE(std::isnan(nanResult));
}
HWTEST_F_L0(MathHelperTest, Atanh)
{
EXPECT_EQ(MathHelper::Atanh(0), 0);
EXPECT_EQ(MathHelper::Atanh(0.5), std::atanh(0.5));
double infResult = MathHelper::Atanh(-1); // limit value
EXPECT_TRUE(std::isinf(infResult));
double nanResult = MathHelper::Atanh(2); // out of input range
EXPECT_TRUE(std::isnan(nanResult));
}
} // namespace panda::test

View File

@ -86,37 +86,37 @@ HWTEST_F_L0(NumberHelperTest, DoubleToString_001)
radix = 2;
JSHandle<EcmaString> resultStr = factory->NewFromASCII("100101");
JSHandle<EcmaString> handleEcmaStr1(thread, NumberHelper::DoubleToString(thread, 37, radix));
EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr1, *resultStr), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr1, resultStr), 0);
radix = 3;
resultStr = factory->NewFromASCII("-1101");
JSHandle<EcmaString> handleEcmaStr2(thread, NumberHelper::DoubleToString(thread, -37, radix));
EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr2, *resultStr), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr2, resultStr), 0);
radix = 4;
resultStr = factory->NewFromASCII("211");
JSHandle<EcmaString> handleEcmaStr3(thread, NumberHelper::DoubleToString(thread, 37, radix));
EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr3, *resultStr), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr3, resultStr), 0);
radix = 5;
resultStr = factory->NewFromASCII("122");
JSHandle<EcmaString> handleEcmaStr4(thread, NumberHelper::DoubleToString(thread, 37, radix));
EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr4, *resultStr), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr4, resultStr), 0);
radix = 6;
resultStr = factory->NewFromASCII("101");
JSHandle<EcmaString> handleEcmaStr6(thread, NumberHelper::DoubleToString(thread, 37, radix));
EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr6, *resultStr), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr6, resultStr), 0);
radix = 7;
resultStr = factory->NewFromASCII("52");
JSHandle<EcmaString> handleEcmaStr7(thread, NumberHelper::DoubleToString(thread, 37, radix));
EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr7, *resultStr), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr7, resultStr), 0);
radix = 36;
resultStr = factory->NewFromASCII("11");
JSHandle<EcmaString> handleEcmaStr5(thread, NumberHelper::DoubleToString(thread, 37, radix));
EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr5, *resultStr), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr5, resultStr), 0);
}
HWTEST_F_L0(NumberHelperTest, DoubleToString_002)
@ -127,28 +127,28 @@ HWTEST_F_L0(NumberHelperTest, DoubleToString_002)
JSHandle<EcmaString> resultStr =
factory->NewFromASCII("10.111111011011000110000101010010001010100110111101");
JSHandle<EcmaString> handleEcmaStr1(thread, NumberHelper::DoubleToString(thread, 2.99099, radix));
EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr1, *resultStr), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr1, resultStr), 0);
resultStr = factory->NewFromASCII("10.000000101001000000000011111011101010001000001001101");
JSHandle<EcmaString> handleEcmaStr2(thread, NumberHelper::DoubleToString(thread, 2.01001, radix));
EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr2, *resultStr), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr2, resultStr), 0);
resultStr = factory->NewFromASCII("10.100000000000011010001101101110001011101011000111001");
JSHandle<EcmaString> handleEcmaStr3(thread, NumberHelper::DoubleToString(thread, 2.5001, radix));
EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr3, *resultStr), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr3, resultStr), 0);
radix = 36;
resultStr = factory->NewFromASCII("0.i04nym8equ");
JSHandle<EcmaString> handleEcmaStr4(thread, NumberHelper::DoubleToString(thread, 0.5001, radix));
EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr4, *resultStr), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr4, resultStr), 0);
resultStr = factory->NewFromASCII("0.wej2d0mt58f");
JSHandle<EcmaString> handleEcmaStr5(thread, NumberHelper::DoubleToString(thread, 0.9001, radix));
EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr5, *resultStr), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr5, resultStr), 0);
resultStr = factory->NewFromASCII("0.0d384dldb02");
JSHandle<EcmaString> handleEcmaStr6(thread, NumberHelper::DoubleToString(thread, 0.0101, radix));
EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr6, *resultStr), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr6, resultStr), 0);
}
/**
@ -313,32 +313,32 @@ HWTEST_F_L0(NumberHelperTest, DoubleToExponential)
radix = -4;
JSHandle<EcmaString> resultStr = factory->NewFromASCII("1.239876e+2");
JSHandle<EcmaString> handleEcmaStr1(thread, NumberHelper::DoubleToExponential(thread, 123.9876, radix));
EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr1, *resultStr), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr1, resultStr), 0);
radix = -6;
resultStr = factory->NewFromASCII("1.239876e+2");
JSHandle<EcmaString> handleEcmaStr2(thread, NumberHelper::DoubleToExponential(thread, 123.9876, radix));
EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr2, *resultStr), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr2, resultStr), 0);
radix = 2;
resultStr = factory->NewFromASCII("1.24e+2");
JSHandle<EcmaString> handleEcmaStr3(thread, NumberHelper::DoubleToExponential(thread, 123.567, radix));
EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr3, *resultStr), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr3, resultStr), 0);
radix = 6;
resultStr = factory->NewFromASCII("1.234567e+2");
JSHandle<EcmaString> handleEcmaStr4(thread, NumberHelper::DoubleToExponential(thread, 123.4567, radix));
EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr4, *resultStr), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr4, resultStr), 0);
radix = 7;
resultStr = factory->NewFromASCII("1.2345670e+2");
JSHandle<EcmaString> handleEcmaStr5(thread, NumberHelper::DoubleToExponential(thread, 123.45670, radix));
EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr5, *resultStr), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr5, resultStr), 0);
radix = 3;
resultStr = factory->NewFromASCII("1.230e+2");
JSHandle<EcmaString> handleEcmaStr6(thread, NumberHelper::DoubleToExponential(thread, 123.0123, radix));
EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr6, *resultStr), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr6, resultStr), 0);
}
HWTEST_F_L0(NumberHelperTest, DoubleToFixed)
@ -349,27 +349,27 @@ HWTEST_F_L0(NumberHelperTest, DoubleToFixed)
radix = 1;
JSHandle<EcmaString> resultStr = factory->NewFromASCII("123.5");
JSHandle<EcmaString> handleEcmaStr1(thread, NumberHelper::DoubleToFixed(thread, 123.456, radix));
EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr1, *resultStr), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr1, resultStr), 0);
radix = 2;
resultStr = factory->NewFromASCII("123.46");
JSHandle<EcmaString> handleEcmaStr2(thread, NumberHelper::DoubleToFixed(thread, 123.456, radix));
EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr2, *resultStr), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr2, resultStr), 0);
radix = 3;
resultStr = factory->NewFromASCII("123.456");
JSHandle<EcmaString> handleEcmaStr3(thread, NumberHelper::DoubleToFixed(thread, 123.456, radix));
EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr3, *resultStr), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr3, resultStr), 0);
radix = 4;
resultStr = factory->NewFromASCII("123.4560");
JSHandle<EcmaString> handleEcmaStr4(thread, NumberHelper::DoubleToFixed(thread, 123.456, radix));
EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr4, *resultStr), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr4, resultStr), 0);
radix = 0;
resultStr = factory->NewFromASCII("123");
JSHandle<EcmaString> handleEcmaStr5(thread, NumberHelper::DoubleToFixed(thread, 123.456, radix));
EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr5, *resultStr), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr5, resultStr), 0);
}
/**
@ -389,24 +389,24 @@ HWTEST_F_L0(NumberHelperTest, DoubleToPrecision)
radix = 1;
JSHandle<EcmaString> resultStr = factory->NewFromASCII("0");
JSHandle<EcmaString> handleEcmaStr1(thread, NumberHelper::DoubleToPrecision(thread, 0.0, radix));
EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr1, *resultStr), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr1, resultStr), 0);
resultStr = factory->NewFromASCII("0.0001");
JSHandle<EcmaString> handleEcmaStr2(thread, NumberHelper::DoubleToPrecision(thread, 0.0001, radix));
EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr2, *resultStr), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr2, resultStr), 0);
resultStr = factory->NewFromASCII("1e-7");
JSHandle<EcmaString> handleEcmaStr3(thread, NumberHelper::DoubleToPrecision(thread, 0.0000001, radix));
EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr3, *resultStr), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr3, resultStr), 0);
resultStr = factory->NewFromASCII("1e+3");
JSHandle<EcmaString> handleEcmaStr5(thread, NumberHelper::DoubleToPrecision(thread, 1000.1234, radix));
EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr5, *resultStr), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr5, resultStr), 0);
radix = 6;
resultStr = factory->NewFromASCII("1000.12");
JSHandle<EcmaString> handleEcmaStr6(thread, NumberHelper::DoubleToPrecision(thread, 1000.1234, radix));
EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr6, *resultStr), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr6, resultStr), 0);
}
/**
@ -423,7 +423,7 @@ HWTEST_F_L0(NumberHelperTest, StringToDoubleWithRadix)
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
int radix;
Span<const uint8_t> sp;
[[maybe_unused]] CVector<uint8_t> buf;
CVector<uint8_t> buf;
JSHandle<EcmaString> resultStr;
radix = 3;
@ -530,11 +530,11 @@ HWTEST_F_L0(NumberHelperTest, NumberToString)
double d = 8.1999999999999993;
JSHandle<EcmaString> result = NumberHelper::NumberToString(thread, JSTaggedValue(d));
JSHandle<EcmaString> target = factory->NewFromASCII("8.2");
EXPECT_EQ(EcmaStringAccessor::Compare(*result, *target), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, result, target), 0);
double d2 = 0.30000000000000004;
JSHandle<EcmaString> result1 = NumberHelper::NumberToString(thread, JSTaggedValue(d2));
JSHandle<EcmaString> target1 = factory->NewFromASCII("0.30000000000000004");
EXPECT_EQ(EcmaStringAccessor::Compare(*result1, *target1), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, result1, target1), 0);
}
} // namespace panda::ecmascript

View File

@ -425,7 +425,7 @@ JSHandle<JSObject> TypedArrayHelper::AllocateTypedArrayBuffer(JSThread *thread,
uint32_t elementSize = TypedArrayHelper::GetSizeFromType(arrayType);
// 6. Let byteLength be elementSize × length.
uint32_t arrayLength = static_cast<uint32_t>(length);
uint64_t byteLength = elementSize * arrayLength;
uint64_t byteLength = static_cast<uint64_t>(elementSize) * length;
// 7. Let data be ? AllocateArrayBuffer(%ArrayBuffer%, byteLength).
JSTaggedValue data;
if (byteLength > JSTypedArray::MAX_ONHEAP_LENGTH) {

View File

@ -1597,16 +1597,13 @@ void Builtins::InitializeString(const JSHandle<GlobalEnv> &env, const JSHandle<J
stringFunction.GetObject<JSFunction>()->SetFunctionPrototype(thread_, stringFuncInstanceHClass.GetTaggedValue());
// String.prototype method
SetFunction(env, stringFuncPrototype, "charAt", BuiltinsString::CharAt, FunctionLength::ONE,
static_cast<uint8_t>(BUILTINS_STUB_ID(CharAt)));
SetFunction(env, stringFuncPrototype, "charCodeAt", BuiltinsString::CharCodeAt, FunctionLength::ONE,
static_cast<uint8_t>(BUILTINS_STUB_ID(CharCodeAt)));
SetFunction(env, stringFuncPrototype, "charAt", BuiltinsString::CharAt, FunctionLength::ONE);
SetFunction(env, stringFuncPrototype, "charCodeAt", BuiltinsString::CharCodeAt, FunctionLength::ONE);
SetFunction(env, stringFuncPrototype, "codePointAt", BuiltinsString::CodePointAt, FunctionLength::ONE);
SetFunction(env, stringFuncPrototype, "concat", BuiltinsString::Concat, FunctionLength::ONE);
SetFunction(env, stringFuncPrototype, "endsWith", BuiltinsString::EndsWith, FunctionLength::ONE);
SetFunction(env, stringFuncPrototype, "includes", BuiltinsString::Includes, FunctionLength::ONE);
SetFunction(env, stringFuncPrototype, "indexOf", BuiltinsString::IndexOf, FunctionLength::ONE,
static_cast<uint8_t>(BUILTINS_STUB_ID(IndexOf)));
SetFunction(env, stringFuncPrototype, "indexOf", BuiltinsString::IndexOf, FunctionLength::ONE);
SetFunction(env, stringFuncPrototype, "lastIndexOf", BuiltinsString::LastIndexOf, FunctionLength::ONE);
SetFunction(env, stringFuncPrototype, "localeCompare", BuiltinsString::LocaleCompare, FunctionLength::ONE);
SetFunction(env, stringFuncPrototype, "match", BuiltinsString::Match, FunctionLength::ONE);
@ -1621,8 +1618,7 @@ void Builtins::InitializeString(const JSHandle<GlobalEnv> &env, const JSHandle<J
SetFunction(env, stringFuncPrototype, "slice", BuiltinsString::Slice, FunctionLength::TWO);
SetFunction(env, stringFuncPrototype, "split", BuiltinsString::Split, FunctionLength::TWO);
SetFunction(env, stringFuncPrototype, "startsWith", BuiltinsString::StartsWith, FunctionLength::ONE);
SetFunction(env, stringFuncPrototype, "substring", BuiltinsString::Substring, FunctionLength::TWO,
static_cast<uint8_t>(BUILTINS_STUB_ID(Substring)));
SetFunction(env, stringFuncPrototype, "substring", BuiltinsString::Substring, FunctionLength::TWO);
SetFunction(env, stringFuncPrototype, "substr", BuiltinsString::SubStr, FunctionLength::TWO);
SetFunction(env, stringFuncPrototype, "toLocaleLowerCase", BuiltinsString::ToLocaleLowerCase, FunctionLength::ZERO);
SetFunction(env, stringFuncPrototype, "toLocaleUpperCase", BuiltinsString::ToLocaleUpperCase, FunctionLength::ZERO);

View File

@ -163,6 +163,7 @@ bool BuiltinsArkTools::CreateFile(std::string &fileName)
LOG_ECMA(ERROR) << "file create failed, errno = "<< errno;
return false;
}
close(fd);
return true;
} else {
fileName = path;

View File

@ -203,6 +203,7 @@ JSTaggedValue BuiltinsDate::ToPrimitive(EcmaRuntimeCallInfo *argv)
ASSERT(argv);
BUILTINS_API_TRACE(argv->GetThread(), Date, ToPrimitive);
JSThread *thread = argv->GetThread();
auto vm = thread->GetEcmaVM();
[[maybe_unused]] EcmaHandleScope handleScope(thread);
JSHandle<JSTaggedValue> object = GetThis(argv);
@ -214,13 +215,13 @@ JSTaggedValue BuiltinsDate::ToPrimitive(EcmaRuntimeCallInfo *argv)
const GlobalEnvConstants *globalConst = thread->GlobalConstants();
if (hint->IsString()) {
JSHandle<EcmaString> numberStrHandle = JSHandle<EcmaString>::Cast(globalConst->GetHandledNumberString());
if (EcmaStringAccessor::StringsAreEqual(hint.GetObject<EcmaString>(), *numberStrHandle)) {
if (EcmaStringAccessor::StringsAreEqual(vm, JSHandle<EcmaString>(hint), numberStrHandle)) {
tryFirst = PREFER_NUMBER;
} else {
JSHandle<EcmaString> stringStrHandle = JSHandle<EcmaString>::Cast(globalConst->GetHandledStringString());
JSHandle<EcmaString> defaultStrHandle = JSHandle<EcmaString>::Cast(globalConst->GetHandledDefaultString());
if (EcmaStringAccessor::StringsAreEqual(hint.GetObject<EcmaString>(), *stringStrHandle) ||
EcmaStringAccessor::StringsAreEqual(hint.GetObject<EcmaString>(), *defaultStrHandle)) {
if (EcmaStringAccessor::StringsAreEqual(vm, JSHandle<EcmaString>(hint), stringStrHandle) ||
EcmaStringAccessor::StringsAreEqual(vm, JSHandle<EcmaString>(hint), defaultStrHandle)) {
tryFirst = PREFER_STRING;
} else {
THROW_TYPE_ERROR_AND_RETURN(thread, "This is not a primitiveType.", JSTaggedValue::Exception());
@ -259,6 +260,16 @@ JSTaggedValue BuiltinsDate::ToLocaleString(EcmaRuntimeCallInfo *argv)
// Let options be ? ToDateTimeOptions(options, "any", "all").
JSHandle<JSTaggedValue> locales = GetCallArg(argv, 0);
JSHandle<JSTaggedValue> options = GetCallArg(argv, 1);
bool cacheable = (locales->IsUndefined() || locales->IsString()) && options->IsUndefined();
if (cacheable) {
auto simpleDateFormat = JSDateTimeFormat::GetCachedIcuSimpleDateFormat(thread, locales,
IcuFormatterType::SimpleDateFormatDefault);
if (simpleDateFormat != nullptr) {
JSHandle<EcmaString> result = JSDateTimeFormat::FormatDateTime(thread, simpleDateFormat, x);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
return result.GetTaggedValue();
}
}
JSHandle<JSObject> dateTimeOptions =
JSDateTimeFormat::ToDateTimeOptions(thread, options, RequiredOption::ANY, DefaultsOption::ALL);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
@ -269,9 +280,17 @@ JSTaggedValue BuiltinsDate::ToLocaleString(EcmaRuntimeCallInfo *argv)
JSHandle<JSDateTimeFormat> dtf = JSDateTimeFormat::InitializeDateTimeFormat(
thread, JSHandle<JSDateTimeFormat>::Cast(obj), locales, JSHandle<JSTaggedValue>::Cast(dateTimeOptions));
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
if (cacheable) {
auto icuSimpleDateFormat = dtf->GetIcuSimpleDateFormat();
std::string cacheEntry =
locales->IsUndefined() ? "" : EcmaStringAccessor(locales.GetTaggedValue()).ToStdString();
ecmaVm->SetIcuFormatterToCache(IcuFormatterType::SimpleDateFormatDefault, cacheEntry,
std::make_shared<icu::SimpleDateFormat>(*icuSimpleDateFormat));
}
// Return ? FormatDateTime(dateFormat, x).
JSHandle<EcmaString> result = JSDateTimeFormat::FormatDateTime(thread, dtf, x);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
return result.GetTaggedValue();
}
@ -302,6 +321,16 @@ JSTaggedValue BuiltinsDate::ToLocaleDateString(EcmaRuntimeCallInfo *argv)
// Let options be ? ToDateTimeOptions(options, "any", "all").
JSHandle<JSTaggedValue> locales = GetCallArg(argv, 0);
JSHandle<JSTaggedValue> options = GetCallArg(argv, 1);
bool cacheable = (locales->IsUndefined() || locales->IsString()) && options->IsUndefined();
if (cacheable) {
auto simpleDateFormat = JSDateTimeFormat::GetCachedIcuSimpleDateFormat(thread, locales,
IcuFormatterType::SimpleDateFormatDate);
if (simpleDateFormat != nullptr) {
JSHandle<EcmaString> result = JSDateTimeFormat::FormatDateTime(thread, simpleDateFormat, x);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
return result.GetTaggedValue();
}
}
JSHandle<JSObject> dateTimeOptions =
JSDateTimeFormat::ToDateTimeOptions(thread, options, RequiredOption::DATE, DefaultsOption::DATE);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
@ -312,9 +341,17 @@ JSTaggedValue BuiltinsDate::ToLocaleDateString(EcmaRuntimeCallInfo *argv)
JSHandle<JSDateTimeFormat> dtf = JSDateTimeFormat::InitializeDateTimeFormat(
thread, JSHandle<JSDateTimeFormat>::Cast(obj), locales, JSHandle<JSTaggedValue>::Cast(dateTimeOptions));
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
if (cacheable) {
auto icuSimpleDateFormat = dtf->GetIcuSimpleDateFormat();
std::string cacheEntry =
locales->IsUndefined() ? "" : EcmaStringAccessor(locales.GetTaggedValue()).ToStdString();
ecmaVm->SetIcuFormatterToCache(IcuFormatterType::SimpleDateFormatDate, cacheEntry,
std::make_shared<icu::SimpleDateFormat>(*icuSimpleDateFormat));
}
// Return ? FormatDateTime(dateFormat, x).
JSHandle<EcmaString> result = JSDateTimeFormat::FormatDateTime(thread, dtf, x);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
return result.GetTaggedValue();
}
@ -345,6 +382,16 @@ JSTaggedValue BuiltinsDate::ToLocaleTimeString(EcmaRuntimeCallInfo *argv)
// Let options be ? ToDateTimeOptions(options, "any", "all").
JSHandle<JSTaggedValue> locales = GetCallArg(argv, 0);
JSHandle<JSTaggedValue> options = GetCallArg(argv, 1);
bool cacheable = (locales->IsUndefined() || locales->IsString()) && options->IsUndefined();
if (cacheable) {
auto simpleDateFormat = JSDateTimeFormat::GetCachedIcuSimpleDateFormat(thread, locales,
IcuFormatterType::SimpleDateFormatTime);
if (simpleDateFormat != nullptr) {
JSHandle<EcmaString> result = JSDateTimeFormat::FormatDateTime(thread, simpleDateFormat, x);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
return result.GetTaggedValue();
}
}
JSHandle<JSObject> dateTimeOptions =
JSDateTimeFormat::ToDateTimeOptions(thread, options, RequiredOption::TIME, DefaultsOption::TIME);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
@ -355,9 +402,17 @@ JSTaggedValue BuiltinsDate::ToLocaleTimeString(EcmaRuntimeCallInfo *argv)
JSHandle<JSDateTimeFormat> dtf = JSDateTimeFormat::InitializeDateTimeFormat(
thread, JSHandle<JSDateTimeFormat>::Cast(obj), locales, JSHandle<JSTaggedValue>::Cast(dateTimeOptions));
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
if (cacheable) {
auto icuSimpleDateFormat = dtf->GetIcuSimpleDateFormat();
std::string cacheEntry =
locales->IsUndefined() ? "" : EcmaStringAccessor(locales.GetTaggedValue()).ToStdString();
ecmaVm->SetIcuFormatterToCache(IcuFormatterType::SimpleDateFormatTime, cacheEntry,
std::make_shared<icu::SimpleDateFormat>(*icuSimpleDateFormat));
}
// Return ? FormatDateTime(dateFormat, x).
JSHandle<EcmaString> result = JSDateTimeFormat::FormatDateTime(thread, dtf, x);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
return result.GetTaggedValue();
}
} // namespace panda::ecmascript::builtins

View File

@ -159,7 +159,7 @@ JSTaggedValue BuiltinsNumber::ParseFloat(EcmaRuntimeCallInfo *argv)
JSHandle<EcmaString> numberString = JSTaggedValue::ToString(thread, msg);
// 2. ReturnIfAbrupt(inputString).
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
[[maybe_unused]] CVector<uint8_t> buf;
CVector<uint8_t> buf;
Span<const uint8_t> str = EcmaStringAccessor(numberString).ToUtf8Span(buf);
// 4. If neither trimmedString nor any prefix of trimmedString satisfies the syntax of a StrDecimalLiteral
// (see 7.1.3.1), return NaN.
@ -190,7 +190,7 @@ JSTaggedValue BuiltinsNumber::ParseInt(EcmaRuntimeCallInfo *argv)
// 1. Let inputString be ToString(string).
JSHandle<EcmaString> numberString = JSTaggedValue::ToString(thread, msg);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
[[maybe_unused]] CVector<uint8_t> buf;
CVector<uint8_t> buf;
Span<const uint8_t> str = EcmaStringAccessor(numberString).ToUtf8Span(buf);
JSTaggedValue result = NumberHelper::StringToDoubleWithRadix(str.begin(), str.end(), radix);

View File

@ -54,8 +54,8 @@ JSTaggedValue BuiltinsPromiseJob::PromiseReactionJob(EcmaRuntimeCallInfo *argv)
// 5. Else if handler is "Thrower", let handlerResult be Completion{[[type]]: throw, [[value]]: argument,
// [[target]]: empty}.
if (EcmaStringAccessor::StringsAreEqual(handler.GetObject<EcmaString>(),
globalConst->GetHandledThrowerString().GetObject<EcmaString>())) {
if (EcmaStringAccessor::StringsAreEqual(thread->GetEcmaVM(),
JSHandle<EcmaString>(handler), JSHandle<EcmaString>(globalConst->GetHandledThrowerString()))) {
call.Update(capability->GetReject());
}
} else {

View File

@ -553,7 +553,7 @@ JSTaggedValue BuiltinsRegExp::MatchAll(EcmaRuntimeCallInfo *argv)
// 10. Else, let global be false.
JSHandle<EcmaString> gString(globalConstants->GetHandledGString());
bool global = false;
if (EcmaStringAccessor::IndexOf(*flagsStrHandle, *gString) != -1) {
if (EcmaStringAccessor::IndexOf(ecmaVm, flagsStrHandle, gString) != -1) {
global = true;
}
@ -561,7 +561,7 @@ JSTaggedValue BuiltinsRegExp::MatchAll(EcmaRuntimeCallInfo *argv)
// 12. Else, let fullUnicode be false.
JSHandle<EcmaString> uString(globalConstants->GetHandledUString());
bool fullUnicode = false;
if (EcmaStringAccessor::IndexOf(*flagsStrHandle, *uString) != -1) {
if (EcmaStringAccessor::IndexOf(ecmaVm, flagsStrHandle, uString) != -1) {
fullUnicode = true;
}
@ -1106,11 +1106,11 @@ JSTaggedValue BuiltinsRegExp::Split(EcmaRuntimeCallInfo *argv)
// 9. If flags contains "u", let unicodeMatching be true.
// 10. Else, let unicodeMatching be false.
JSHandle<EcmaString> uStringHandle(globalConstants->GetHandledUString());
bool unicodeMatching = (EcmaStringAccessor::IndexOf(*flags, *uStringHandle) != -1);
bool unicodeMatching = (EcmaStringAccessor::IndexOf(ecmaVm, flags, uStringHandle) != -1);
// 11. If flags contains "y", let newFlags be flags.
JSHandle<EcmaString> newFlagsHandle;
JSHandle<EcmaString> yStringHandle = JSHandle<EcmaString>::Cast(globalConstants->GetHandledYString());
if (EcmaStringAccessor::IndexOf(*flags, *yStringHandle) != -1) {
if (EcmaStringAccessor::IndexOf(ecmaVm, flags, yStringHandle) != -1) {
newFlagsHandle = flags;
} else {
// 12. Else, let newFlags be the string that is the concatenation of flags and "y".

View File

@ -242,7 +242,9 @@ JSTaggedValue BuiltinsString::CharAt(EcmaRuntimeCallInfo *argv)
JSHandle<JSTaggedValue> thisTag(JSTaggedValue::RequireObjectCoercible(thread, GetThis(argv)));
JSHandle<EcmaString> thisHandle = JSTaggedValue::ToString(thread, thisTag);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
int32_t thisLen = static_cast<int32_t>(EcmaStringAccessor(thisHandle).GetLength());
JSHandle<EcmaString> thisFlat = JSHandle<EcmaString>(thread,
EcmaStringAccessor::Flatten(thread->GetEcmaVM(), thisHandle));
int32_t thisLen = static_cast<int32_t>(EcmaStringAccessor(thisFlat).GetLength());
JSHandle<JSTaggedValue> posTag = BuiltinsString::GetCallArg(argv, 0);
int32_t pos;
if (posTag->IsInt()) {
@ -257,7 +259,7 @@ JSTaggedValue BuiltinsString::CharAt(EcmaRuntimeCallInfo *argv)
if (pos < 0 || pos >= thisLen) {
return factory->GetEmptyString().GetTaggedValue();
}
uint16_t res = EcmaStringAccessor(thisHandle).Get<false>(pos);
uint16_t res = EcmaStringAccessor(thisFlat).Get<false>(pos);
return factory->NewFromUtf16Literal(&res, 1).GetTaggedValue();
}
@ -271,7 +273,9 @@ JSTaggedValue BuiltinsString::CharCodeAt(EcmaRuntimeCallInfo *argv)
JSHandle<JSTaggedValue> thisTag(JSTaggedValue::RequireObjectCoercible(thread, GetThis(argv)));
JSHandle<EcmaString> thisHandle = JSTaggedValue::ToString(thread, thisTag);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
int32_t thisLen = static_cast<int32_t>(EcmaStringAccessor(thisHandle).GetLength());
JSHandle<EcmaString> thisFlat = JSHandle<EcmaString>(thread,
EcmaStringAccessor::Flatten(thread->GetEcmaVM(), thisHandle));
int32_t thisLen = static_cast<int32_t>(EcmaStringAccessor(thisFlat).GetLength());
JSHandle<JSTaggedValue> posTag = BuiltinsString::GetCallArg(argv, 0);
int32_t pos;
if (posTag->IsInt()) {
@ -286,7 +290,7 @@ JSTaggedValue BuiltinsString::CharCodeAt(EcmaRuntimeCallInfo *argv)
if (pos < 0 || pos >= thisLen) {
return GetTaggedDouble(base::NAN_VALUE);
}
uint16_t ret = EcmaStringAccessor(thisHandle).Get<false>(pos);
uint16_t ret = EcmaStringAccessor(thisFlat).Get<false>(pos);
return GetTaggedInt(ret);
}
@ -300,20 +304,22 @@ JSTaggedValue BuiltinsString::CodePointAt(EcmaRuntimeCallInfo *argv)
JSHandle<JSTaggedValue> thisTag(JSTaggedValue::RequireObjectCoercible(thread, GetThis(argv)));
JSHandle<EcmaString> thisHandle = JSTaggedValue::ToString(thread, thisTag);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
JSHandle<EcmaString> thisFlat = JSHandle<EcmaString>(thread,
EcmaStringAccessor::Flatten(thread->GetEcmaVM(), thisHandle));
JSHandle<JSTaggedValue> posTag = BuiltinsString::GetCallArg(argv, 0);
JSTaggedNumber posVal = JSTaggedValue::ToNumber(thread, posTag);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
int32_t pos = base::NumberHelper::DoubleInRangeInt32(posVal.GetNumber());
int32_t thisLen = static_cast<int32_t>(EcmaStringAccessor(thisHandle).GetLength());
int32_t thisLen = static_cast<int32_t>(EcmaStringAccessor(thisFlat).GetLength());
if (pos < 0 || pos >= thisLen) {
return JSTaggedValue::Undefined();
}
uint16_t first = EcmaStringAccessor(thisHandle).Get<false>(pos);
uint16_t first = EcmaStringAccessor(thisFlat).Get<false>(pos);
if (first < base::utf_helper::DECODE_LEAD_LOW || first > base::utf_helper::DECODE_LEAD_HIGH || pos + 1 == thisLen) {
return GetTaggedInt(first);
}
uint16_t second = EcmaStringAccessor(thisHandle).Get<false>(pos + 1);
uint16_t second = EcmaStringAccessor(thisFlat).Get<false>(pos + 1);
if (second < base::utf_helper::DECODE_TRAIL_LOW || second > base::utf_helper::DECODE_TRAIL_HIGH) {
return GetTaggedInt(first);
}
@ -395,7 +401,7 @@ JSTaggedValue BuiltinsString::EndsWith(EcmaRuntimeCallInfo *argv)
return BuiltinsString::GetTaggedBoolean(false);
}
int32_t idx = EcmaStringAccessor::IndexOf(*thisHandle, *searchHandle, start);
int32_t idx = EcmaStringAccessor::IndexOf(thread->GetEcmaVM(), thisHandle, searchHandle, start);
if (idx == start) {
return BuiltinsString::GetTaggedBoolean(true);
}
@ -430,7 +436,7 @@ JSTaggedValue BuiltinsString::Includes(EcmaRuntimeCallInfo *argv)
pos = base::NumberHelper::DoubleInRangeInt32(posVal.GetNumber());
}
int32_t start = std::min(std::max(pos, 0), static_cast<int32_t>(thisLen));
int32_t idx = EcmaStringAccessor::IndexOf(*thisHandle, *searchHandle, start);
int32_t idx = EcmaStringAccessor::IndexOf(thread->GetEcmaVM(), thisHandle, searchHandle, start);
if (idx < 0 || idx > static_cast<int32_t>(thisLen)) {
return BuiltinsString::GetTaggedBoolean(false);
}
@ -463,7 +469,7 @@ JSTaggedValue BuiltinsString::IndexOf(EcmaRuntimeCallInfo *argv)
pos = posVal.ToInt32();
}
pos = std::min(std::max(pos, 0), static_cast<int32_t>(thisLen));
int32_t res = EcmaStringAccessor::IndexOf(*thisHandle, *searchHandle, pos);
int32_t res = EcmaStringAccessor::IndexOf(thread->GetEcmaVM(), thisHandle, searchHandle, pos);
if (res >= 0 && res < static_cast<int32_t>(thisLen)) {
return GetTaggedInt(res);
}
@ -498,7 +504,7 @@ JSTaggedValue BuiltinsString::LastIndexOf(EcmaRuntimeCallInfo *argv)
}
}
pos = std::min(std::max(pos, 0), thisLen);
int32_t res = EcmaStringAccessor::LastIndexOf(*thisHandle, *searchHandle, pos);
int32_t res = EcmaStringAccessor::LastIndexOf(thread->GetEcmaVM(), thisHandle, searchHandle, pos);
if (res >= 0 && res < thisLen) {
return GetTaggedInt(res);
}
@ -541,7 +547,7 @@ JSTaggedValue BuiltinsString::LocaleCompare(EcmaRuntimeCallInfo *argv)
JSTaggedValue result = JSCollator::CompareStrings(icuCollator, thisHandle, thatHandle);
return result;
}
int32_t res = EcmaStringAccessor::Compare(*thisHandle, *thatHandle);
int32_t res = EcmaStringAccessor::Compare(thread->GetEcmaVM(), thisHandle, thatHandle);
return GetTaggedInt(res);
}
@ -626,8 +632,8 @@ JSTaggedValue BuiltinsString::MatchAll(EcmaRuntimeCallInfo *argv)
// iii. If ? ToString(flags) does not contain "g", throw a TypeError exception.
JSHandle<EcmaString> flagString = JSTaggedValue::ToString(thread, flags);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
int32_t pos = EcmaStringAccessor::IndexOf(
*flagString, static_cast<EcmaString *>(gvalue->GetTaggedObject()));
int32_t pos = EcmaStringAccessor::IndexOf(ecmaVm,
flagString, JSHandle<EcmaString>(gvalue));
if (pos == -1) {
THROW_TYPE_ERROR_AND_RETURN(thread,
"matchAll called with a non-global RegExp argument",
@ -670,7 +676,8 @@ JSTaggedValue BuiltinsString::Normalize(EcmaRuntimeCallInfo *argv)
BUILTINS_API_TRACE(argv->GetThread(), String, Normalize);
JSThread *thread = argv->GetThread();
[[maybe_unused]] EcmaHandleScope handleScope(thread);
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
auto vm = thread->GetEcmaVM();
ObjectFactory *factory = vm->GetFactory();
JSHandle<JSTaggedValue> thisTag(JSTaggedValue::RequireObjectCoercible(thread, GetThis(argv)));
JSHandle<EcmaString> thisHandle = JSTaggedValue::ToString(thread, thisTag);
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception());
@ -691,13 +698,13 @@ JSTaggedValue BuiltinsString::Normalize(EcmaRuntimeCallInfo *argv)
JSHandle<EcmaString> nfkc = factory->NewFromASCII("NFKC");
JSHandle<EcmaString> nfkd = factory->NewFromASCII("NFKD");
UNormalizationMode uForm;
if (EcmaStringAccessor::StringsAreEqual(*formValue, *nfc)) {
if (EcmaStringAccessor::StringsAreEqual(vm, formValue, nfc)) {
uForm = UNORM_NFC;
} else if (EcmaStringAccessor::StringsAreEqual(*formValue, *nfd)) {
} else if (EcmaStringAccessor::StringsAreEqual(vm, formValue, nfd)) {
uForm = UNORM_NFD;
} else if (EcmaStringAccessor::StringsAreEqual(*formValue, *nfkc)) {
} else if (EcmaStringAccessor::StringsAreEqual(vm, formValue, nfkc)) {
uForm = UNORM_NFKC;
} else if (EcmaStringAccessor::StringsAreEqual(*formValue, *nfkd)) {
} else if (EcmaStringAccessor::StringsAreEqual(vm, formValue, nfkd)) {
uForm = UNORM_NFKD;
} else {
THROW_RANGE_ERROR_AND_RETURN(thread, "compare not equal", JSTaggedValue::Exception());
@ -765,7 +772,7 @@ JSTaggedValue BuiltinsString::Repeat(EcmaRuntimeCallInfo *argv)
}
bool isUtf8 = EcmaStringAccessor(thisHandle).IsUtf8();
EcmaString *result = EcmaStringAccessor::AllocStringObject(thread->GetEcmaVM(), thisLen * count, isUtf8);
EcmaString *result = EcmaStringAccessor::CreateLineString(thread->GetEcmaVM(), thisLen * count, isUtf8);
for (uint32_t index = 0; index < static_cast<uint32_t>(count); ++index) {
EcmaStringAccessor::ReadData(result, *thisHandle, index * thisLen, (count - index) * thisLen, thisLen);
}
@ -842,7 +849,7 @@ JSTaggedValue BuiltinsString::Replace(EcmaRuntimeCallInfo *argv)
// Search string for the first occurrence of searchString and let pos be the index within string of the first code
// unit of the matched substring and let matched be searchString. If no occurrences of searchString were found,
// return string.
int32_t pos = EcmaStringAccessor::IndexOf(*thisString, *searchString);
int32_t pos = EcmaStringAccessor::IndexOf(ecmaVm, thisString, searchString);
if (pos == -1) {
return thisString.GetTaggedValue();
}
@ -917,7 +924,7 @@ JSTaggedValue BuiltinsString::ReplaceAll(EcmaRuntimeCallInfo *argv)
JSHandle<EcmaString> flagString = JSTaggedValue::ToString(thread, flags);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
JSHandle<EcmaString> gString(globalConst->GetHandledGString());
int32_t pos = EcmaStringAccessor::IndexOf(*flagString, *gString);
int32_t pos = EcmaStringAccessor::IndexOf(ecmaVm, flagString, gString);
if (pos == -1) {
THROW_TYPE_ERROR_AND_RETURN(thread,
"string.prototype.replaceAll called with a non-global RegExp argument",
@ -964,7 +971,7 @@ JSTaggedValue BuiltinsString::ReplaceAll(EcmaRuntimeCallInfo *argv)
std::u16string stringRealReplaceStr;
std::u16string stringSuffixString;
// 10. Let position be ! StringIndexOf(string, searchString, 0).
int32_t pos = EcmaStringAccessor::IndexOf(*thisString, *searchString);
int32_t pos = EcmaStringAccessor::IndexOf(ecmaVm, thisString, searchString);
int32_t endOfLastMatch = 0;
bool canBeCompress = true;
JSHandle<JSTaggedValue> undefined = globalConst->GetHandledUndefined();
@ -1008,7 +1015,7 @@ JSTaggedValue BuiltinsString::ReplaceAll(EcmaRuntimeCallInfo *argv)
}
stringBuilder = stringBuilder + stringPrefixString + stringRealReplaceStr;
endOfLastMatch = pos + searchLength;
pos = EcmaStringAccessor::IndexOf(*thisString, *searchString, pos + advanceBy);
pos = EcmaStringAccessor::IndexOf(ecmaVm, thisString, searchString, pos + advanceBy);
}
if (endOfLastMatch < static_cast<int32_t>(EcmaStringAccessor(thisString).GetLength())) {
@ -1039,18 +1046,20 @@ JSTaggedValue BuiltinsString::GetSubstitution(JSThread *thread, const JSHandle<E
auto ecmaVm = thread->GetEcmaVM();
ObjectFactory *factory = ecmaVm->GetFactory();
JSHandle<EcmaString> dollarString = JSHandle<EcmaString>::Cast(thread->GlobalConstants()->GetHandledDollarString());
int32_t replaceLength = static_cast<int32_t>(EcmaStringAccessor(replacement).GetLength());
JSHandle<EcmaString> replacementFlat = JSHandle<EcmaString>(
thread, EcmaStringAccessor::Flatten(ecmaVm, replacement));
int32_t replaceLength = static_cast<int32_t>(EcmaStringAccessor(replacementFlat).GetLength());
int32_t tailPos = position + static_cast<int32_t>(EcmaStringAccessor(matched).GetLength());
int32_t nextDollarIndex = EcmaStringAccessor::IndexOf(*replacement, *dollarString);
int32_t nextDollarIndex = EcmaStringAccessor::IndexOf(ecmaVm, replacementFlat, dollarString);
if (nextDollarIndex < 0) {
return replacement.GetTaggedValue();
return replacementFlat.GetTaggedValue();
}
std::u16string stringBuilder;
bool canBeCompress = true;
if (nextDollarIndex > 0) {
stringBuilder = EcmaStringAccessor(replacement).ToU16String(nextDollarIndex);
if (EcmaStringAccessor(replacement).IsUtf16()) {
stringBuilder = EcmaStringAccessor(replacementFlat).ToU16String(nextDollarIndex);
if (EcmaStringAccessor(replacementFlat).IsUtf16()) {
canBeCompress = false;
}
}
@ -1066,7 +1075,7 @@ JSTaggedValue BuiltinsString::GetSubstitution(JSThread *thread, const JSHandle<E
factory->NewFromUtf16LiteralNotCompress(uint16tData, stringBuilder.length()).GetTaggedValue();
}
int continueFromIndex = -1;
uint16_t peek = EcmaStringAccessor(replacement).Get(peekIndex);
uint16_t peek = EcmaStringAccessor(replacementFlat).Get(peekIndex);
switch (peek) {
case '$': // $$
stringBuilder += '$';
@ -1118,7 +1127,7 @@ JSTaggedValue BuiltinsString::GetSubstitution(JSThread *thread, const JSHandle<E
uint32_t scaledIndex = peek - '0';
int32_t advance = 1;
if (peekIndex + 1 < replaceLength) {
uint16_t nextPeek = EcmaStringAccessor(replacement).Get(peekIndex + 1);
uint16_t nextPeek = EcmaStringAccessor(replacementFlat).Get(peekIndex + 1);
if (nextPeek >= '0' && nextPeek <= '9') {
constexpr uint32_t TEN_BASE = 10;
uint32_t newScaledIndex = scaledIndex * TEN_BASE + (nextPeek - '0');
@ -1153,14 +1162,14 @@ JSTaggedValue BuiltinsString::GetSubstitution(JSThread *thread, const JSHandle<E
break;
}
JSHandle<EcmaString> greaterSymString = factory->NewFromASCII(">");
int32_t pos = EcmaStringAccessor::IndexOf(*replacement, *greaterSymString, peekIndex);
int32_t pos = EcmaStringAccessor::IndexOf(ecmaVm, replacementFlat, greaterSymString, peekIndex);
if (pos == -1) {
stringBuilder += '$';
continueFromIndex = peekIndex;
break;
}
JSHandle<EcmaString> groupName(thread,
EcmaStringAccessor::FastSubString(ecmaVm, replacement,
EcmaStringAccessor::FastSubString(ecmaVm, replacementFlat,
peekIndex + 1, pos - peekIndex - 1));
JSHandle<JSTaggedValue> names(groupName);
JSHandle<JSTaggedValue> capture = JSObject::GetProperty(thread, namedCaptures, names).GetValue();
@ -1182,10 +1191,10 @@ JSTaggedValue BuiltinsString::GetSubstitution(JSThread *thread, const JSHandle<E
break;
}
// Go the the next $ in the replacement.
nextDollarIndex = EcmaStringAccessor::IndexOf(*replacement, *dollarString, continueFromIndex);
nextDollarIndex = EcmaStringAccessor::IndexOf(ecmaVm, replacementFlat, dollarString, continueFromIndex);
if (nextDollarIndex < 0) {
if (continueFromIndex < replaceLength) {
EcmaString *nextAppend = EcmaStringAccessor::FastSubString(ecmaVm, replacement, continueFromIndex,
EcmaString *nextAppend = EcmaStringAccessor::FastSubString(ecmaVm, replacementFlat, continueFromIndex,
replaceLength - continueFromIndex);
stringBuilder += EcmaStringAccessor(nextAppend).ToU16String();
if (EcmaStringAccessor(nextAppend).IsUtf16()) {
@ -1201,7 +1210,7 @@ JSTaggedValue BuiltinsString::GetSubstitution(JSThread *thread, const JSHandle<E
// Append substring between the previous and the next $ character.
if (nextDollarIndex > continueFromIndex) {
EcmaString *nextAppend = EcmaStringAccessor::FastSubString(
ecmaVm, replacement, continueFromIndex, nextDollarIndex - continueFromIndex);
ecmaVm, replacementFlat, continueFromIndex, nextDollarIndex - continueFromIndex);
stringBuilder += EcmaStringAccessor(nextAppend).ToU16String();
if (EcmaStringAccessor(nextAppend).IsUtf16()) {
canBeCompress = false;
@ -1353,7 +1362,7 @@ JSTaggedValue BuiltinsString::Split(EcmaRuntimeCallInfo *argv)
}
// If S.length = 0, then
if (thisLength == 0) {
if (EcmaStringAccessor::IndexOf(*thisString, *seperatorString) != -1) {
if (EcmaStringAccessor::IndexOf(ecmaVm, thisString, seperatorString) != -1) {
return resultArray.GetTaggedValue();
}
JSObject::CreateDataProperty(thread, resultArray, 0, JSHandle<JSTaggedValue>(thisString));
@ -1376,7 +1385,7 @@ JSTaggedValue BuiltinsString::Split(EcmaRuntimeCallInfo *argv)
return resultArray.GetTaggedValue();
}
int32_t index = 0;
int32_t pos = EcmaStringAccessor::IndexOf(*thisString, *seperatorString);
int32_t pos = EcmaStringAccessor::IndexOf(ecmaVm, thisString, seperatorString);
while (pos != -1) {
EcmaString *elementString = EcmaStringAccessor::FastSubString(ecmaVm, thisString, index, pos - index);
JSHandle<JSTaggedValue> elementTag(thread, elementString);
@ -1387,7 +1396,7 @@ JSTaggedValue BuiltinsString::Split(EcmaRuntimeCallInfo *argv)
return resultArray.GetTaggedValue();
}
index = pos + seperatorLength;
pos = EcmaStringAccessor::IndexOf(*thisString, *seperatorString, index);
pos = EcmaStringAccessor::IndexOf(ecmaVm, thisString, seperatorString, index);
}
EcmaString *elementString = EcmaStringAccessor::FastSubString(ecmaVm, thisString, index, thisLength - index);
JSHandle<JSTaggedValue> elementTag(thread, elementString);
@ -1432,7 +1441,7 @@ JSTaggedValue BuiltinsString::StartsWith(EcmaRuntimeCallInfo *argv)
if (static_cast<uint32_t>(pos) + searchLen > thisLen) {
return BuiltinsString::GetTaggedBoolean(false);
}
int32_t res = EcmaStringAccessor::IndexOf(*thisHandle, *searchHandle, pos);
int32_t res = EcmaStringAccessor::IndexOf(thread->GetEcmaVM(), thisHandle, searchHandle, pos);
if (res == pos) {
return BuiltinsString::GetTaggedBoolean(true);
}

View File

@ -788,7 +788,7 @@ JSTaggedValue BuiltinsTypedArray::Join(EcmaRuntimeCallInfo *argv)
}
}
allocateLength += sepLength * (length - 1);
auto newString = EcmaStringAccessor::AllocStringObject(thread->GetEcmaVM(), allocateLength, isOneByte);
auto newString = EcmaStringAccessor::CreateLineString(thread->GetEcmaVM(), allocateLength, isOneByte);
int current = 0;
DISALLOW_GARBAGE_COLLECTION;
for (uint32_t k = 0; k < length; k++) {

View File

@ -1426,9 +1426,8 @@ HWTEST_F_L0(BuiltinsArrayTest, Join)
JSTaggedValue result = Array::Join(ecmaRuntimeCallInfo1);
TestHelper::TearDownFrame(thread, prev);
JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
[[maybe_unused]] auto *res = EcmaString::Cast(resultHandle.GetTaggedValue().GetTaggedObject());
ASSERT_EQ(EcmaStringAccessor::Compare(res, *str), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, str), 0);
}
HWTEST_F_L0(BuiltinsArrayTest, ToString)
@ -1458,9 +1457,8 @@ HWTEST_F_L0(BuiltinsArrayTest, ToString)
JSTaggedValue result = Array::ToString(ecmaRuntimeCallInfo1);
TestHelper::TearDownFrame(thread, prev);
JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
[[maybe_unused]] auto *res = EcmaString::Cast(resultHandle.GetTaggedValue().GetTaggedObject());
ASSERT_EQ(EcmaStringAccessor::Compare(res, *str), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, str), 0);
}
HWTEST_F_L0(BuiltinsArrayTest, Includes)

View File

@ -117,7 +117,7 @@ HWTEST_F_L0(BuiltinsBigIntTest, AsIntN_001)
JSHandle<BigInt> bigIntHandle(thread, result);
JSHandle<EcmaString> resultStr = BigInt::ToString(thread, bigIntHandle);
JSHandle<EcmaString> str = factory->NewFromASCII("9223372036854775807");
EXPECT_EQ(EcmaStringAccessor::Compare(*resultStr, *str), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, resultStr, str), 0);
}
// AsIntN(64, (2 ^ 63))
@ -141,7 +141,7 @@ HWTEST_F_L0(BuiltinsBigIntTest, AsIntN_002)
JSHandle<BigInt> bigIntHandle(thread, result);
JSHandle<EcmaString> resultStr = BigInt::ToString(thread, bigIntHandle);
JSHandle<EcmaString> str = factory->NewFromASCII("-9223372036854775808");
EXPECT_EQ(EcmaStringAccessor::Compare(*resultStr, *str), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, resultStr, str), 0);
}
// AsUintN(64, (2 ^ 64 - 1))
@ -165,7 +165,7 @@ HWTEST_F_L0(BuiltinsBigIntTest, AsUintN_001)
JSHandle<BigInt> bigIntHandle(thread, result);
JSHandle<EcmaString> resultStr = BigInt::ToString(thread, bigIntHandle);
JSHandle<EcmaString> str = factory->NewFromASCII("18446744073709551615");
EXPECT_EQ(EcmaStringAccessor::Compare(*resultStr, *str), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, resultStr, str), 0);
}
// AsUintN(64, (2 ^ 64))
@ -189,7 +189,7 @@ HWTEST_F_L0(BuiltinsBigIntTest, AsUintN_002)
JSHandle<BigInt> bigIntHandle(thread, result);
JSHandle<EcmaString> resultStr = BigInt::ToString(thread, bigIntHandle);
JSHandle<EcmaString> str = factory->NewFromASCII("0");
EXPECT_EQ(EcmaStringAccessor::Compare(*resultStr, *str), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, resultStr, str), 0);
}
// using locale
@ -223,7 +223,7 @@ HWTEST_F_L0(BuiltinsBigIntTest, ToLocaleString_001)
EXPECT_TRUE(result2.IsString());
JSHandle<EcmaString> ecmaStrHandle(thread, result2);
JSHandle<EcmaString> resultStr(factory->NewFromASCII("123.456.789.123.456.789"));
EXPECT_EQ(EcmaStringAccessor::Compare(*ecmaStrHandle, *resultStr), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, ecmaStrHandle, resultStr), 0);
}
// using locale and options
@ -546,14 +546,14 @@ HWTEST_F_L0(BuiltinsBigIntTest, StringToBigInt)
ASSERT_TRUE(bigint->IsBigInt());
str = BigInt::ToString(thread, JSHandle<BigInt>::Cast(bigint), BigInt::HEXADECIMAL);
parma = JSHandle<JSTaggedValue>(factory->NewFromASCII("ffff"));
ASSERT_EQ(EcmaStringAccessor::Compare(*str, reinterpret_cast<EcmaString *>(parma->GetRawData())), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance, str, JSHandle<EcmaString>(parma)), 0);
parma = JSHandle<JSTaggedValue>(factory->NewFromASCII("0XFFFF"));
bigint = JSHandle<JSTaggedValue>(thread, base::NumberHelper::StringToBigInt(thread, parma));
ASSERT_TRUE(bigint->IsBigInt());
str = BigInt::ToString(thread, JSHandle<BigInt>::Cast(bigint), BigInt::HEXADECIMAL);
parma = JSHandle<JSTaggedValue>(factory->NewFromASCII("ffff"));
ASSERT_EQ(EcmaStringAccessor::Compare(*str, reinterpret_cast<EcmaString *>(parma->GetRawData())), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance, str, JSHandle<EcmaString>(parma)), 0);
// binary string
parma = JSHandle<JSTaggedValue>(factory->NewFromASCII("0b11111111"));
@ -561,14 +561,14 @@ HWTEST_F_L0(BuiltinsBigIntTest, StringToBigInt)
ASSERT_TRUE(bigint->IsBigInt());
str = BigInt::ToString(thread, JSHandle<BigInt>::Cast(bigint), BigInt::BINARY);
parma = JSHandle<JSTaggedValue>(factory->NewFromASCII("11111111"));
ASSERT_EQ(EcmaStringAccessor::Compare(*str, reinterpret_cast<EcmaString *>(parma->GetRawData())), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance, str, JSHandle<EcmaString>(parma)), 0);
parma = JSHandle<JSTaggedValue>(factory->NewFromASCII("0B11111111"));
bigint = JSHandle<JSTaggedValue>(thread, base::NumberHelper::StringToBigInt(thread, parma));
ASSERT_TRUE(bigint->IsBigInt());
str = BigInt::ToString(thread, JSHandle<BigInt>::Cast(bigint), BigInt::BINARY);
parma = JSHandle<JSTaggedValue>(factory->NewFromASCII("11111111"));
ASSERT_EQ(EcmaStringAccessor::Compare(*str, reinterpret_cast<EcmaString *>(parma->GetRawData())), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance, str, JSHandle<EcmaString>(parma)), 0);
// octal string
parma = JSHandle<JSTaggedValue>(factory->NewFromASCII("0o123456"));
@ -576,21 +576,21 @@ HWTEST_F_L0(BuiltinsBigIntTest, StringToBigInt)
ASSERT_TRUE(bigint->IsBigInt());
str = BigInt::ToString(thread, JSHandle<BigInt>::Cast(bigint), BigInt::OCTAL);
parma = JSHandle<JSTaggedValue>(factory->NewFromASCII("123456"));
ASSERT_EQ(EcmaStringAccessor::Compare(*str, reinterpret_cast<EcmaString *>(parma->GetRawData())), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance, str, JSHandle<EcmaString>(parma)), 0);
parma = JSHandle<JSTaggedValue>(factory->NewFromASCII("0O123456"));
bigint = JSHandle<JSTaggedValue>(thread, base::NumberHelper::StringToBigInt(thread, parma));
ASSERT_TRUE(bigint->IsBigInt());
str = BigInt::ToString(thread, JSHandle<BigInt>::Cast(bigint), BigInt::OCTAL);
parma = JSHandle<JSTaggedValue>(factory->NewFromASCII("123456"));
ASSERT_EQ(EcmaStringAccessor::Compare(*str, reinterpret_cast<EcmaString *>(parma->GetRawData())), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance, str, JSHandle<EcmaString>(parma)), 0);
// decimal string
parma = JSHandle<JSTaggedValue>(factory->NewFromASCII("999999999"));
bigint = JSHandle<JSTaggedValue>(thread, base::NumberHelper::StringToBigInt(thread, parma));
ASSERT_TRUE(bigint->IsBigInt());
str = BigInt::ToString(thread, JSHandle<BigInt>::Cast(bigint));
ASSERT_EQ(EcmaStringAccessor::Compare(*str, reinterpret_cast<EcmaString *>(parma->GetRawData())), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance, str, JSHandle<EcmaString>(parma)), 0);
// string has space
parma = JSHandle<JSTaggedValue>(factory->NewFromASCII(" 123 "));

View File

@ -130,7 +130,7 @@ HWTEST_F_L0(BuiltinsBooleanTest, BooleanPrototypeToString)
ASSERT_TRUE(result.IsString());
JSHandle<EcmaString> res(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
auto ruler = thread->GetEcmaVM()->GetFactory()->NewFromASCII("false");
ASSERT_EQ(EcmaStringAccessor::Compare(*res, *ruler), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance, res, ruler), 0);
}
// (new Boolean(true)).toString()
@ -152,7 +152,7 @@ HWTEST_F_L0(BuiltinsBooleanTest, BooleanPrototypeToString1)
ASSERT_TRUE(result.IsString());
JSHandle<EcmaString> res(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
auto ruler = thread->GetEcmaVM()->GetFactory()->NewFromASCII("true");
ASSERT_EQ(EcmaStringAccessor::Compare(*res, *ruler), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance, res, ruler), 0);
}
// true.valueOf()

View File

@ -256,7 +256,7 @@ HWTEST_F_L0(BuiltinsCollatorTest, Compare_002)
JSTaggedValue result = BuiltinsArray::Join(ecmaRuntimeCallInfo3);
TestHelper::TearDownFrame(thread, prev);
JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
EXPECT_EQ(EcmaStringAccessor::Compare(*resultHandle, *str), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, str), 0);
}
// compare with options("search")

View File

@ -279,7 +279,7 @@ HWTEST_F_L0(BuiltinsDateTimeFormatTest, FormatRange_001)
JSHandle<EcmaString> handleStr(thread, result);
JSHandle<EcmaString> resultStr = factory->NewFromUtf8("2020/11/1周日 24:00:00 2021/7/1周四 24:00:00");
EXPECT_EQ(EcmaStringAccessor::Compare(*handleStr, *resultStr), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleStr, resultStr), 0);
}
// FormatRange(en)
@ -304,7 +304,7 @@ HWTEST_F_L0(BuiltinsDateTimeFormatTest, FormatRange_002)
JSHandle<EcmaString> handleStr(thread, result);
JSHandle<EcmaString> resultStr = factory->NewFromUtf8("Fri, 1/1/2021, 24:00:00 Mon, 3/1/2021, 24:00:00");
EXPECT_EQ(EcmaStringAccessor::Compare(*handleStr, *resultStr), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleStr, resultStr), 0);
}
HWTEST_F_L0(BuiltinsDateTimeFormatTest, FormatRangeToParts)

View File

@ -90,16 +90,12 @@ HWTEST_F_L0(BuiltinsErrorsTest, GetJSErrorObject)
*/
JSHandle<JSTaggedValue> msgValue(
JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(handleObj), msgKey).GetValue());
EXPECT_EQ(EcmaStringAccessor::Compare(reinterpret_cast<EcmaString *>(msgValue->GetRawData()),
reinterpret_cast<EcmaString *>(
ecmascript::JSTaggedValue(*factory->NewFromASCII("")).GetRawData())),
0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance,
JSHandle<EcmaString>(msgValue), factory->NewFromASCII("")), 0);
JSHandle<JSTaggedValue> nameValue(
JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(handleObj), nameKey).GetValue());
ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast<EcmaString *>(
ecmascript::JSTaggedValue(*factory->NewFromASCII("TypeError")).GetRawData()),
reinterpret_cast<EcmaString *>(nameValue->GetRawData())),
0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
factory->NewFromASCII("TypeError"), JSHandle<EcmaString>(nameValue)), 0);
}
/*
@ -116,16 +112,12 @@ HWTEST_F_L0(BuiltinsErrorsTest, GetJSErrorWithMessage)
JSHandle<JSTaggedValue> nameKey = thread->GlobalConstants()->GetHandledNameString();
JSHandle<JSTaggedValue> msgValue(
JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(handleObj), msgKey).GetValue());
ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast<EcmaString *>(
ecmascript::JSTaggedValue(*factory->NewFromASCII("I am type error")).GetRawData()),
reinterpret_cast<EcmaString *>(msgValue->GetRawData())),
0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
factory->NewFromASCII("I am type error"), JSHandle<EcmaString>(msgValue)), 0);
JSHandle<JSTaggedValue> nameValue(
JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(handleObj), nameKey).GetValue());
ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast<EcmaString *>(
ecmascript::JSTaggedValue(*factory->NewFromASCII("TypeError")).GetRawData()),
reinterpret_cast<EcmaString *>(nameValue->GetRawData())),
0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
factory->NewFromASCII("TypeError"), JSHandle<EcmaString>(nameValue)), 0);
}
/*
@ -154,16 +146,12 @@ HWTEST_F_L0(BuiltinsErrorsTest, ErrorNoParameterConstructor)
JSHandle<JSTaggedValue> nameKey = thread->GlobalConstants()->GetHandledNameString();
JSHandle<JSTaggedValue> msgValue(JSObject::GetProperty(thread, errorObject, msgKey).GetValue());
ASSERT_EQ(EcmaStringAccessor::Compare(
reinterpret_cast<EcmaString *>(ecmascript::JSTaggedValue(*factory->NewFromASCII("")).GetRawData()),
reinterpret_cast<EcmaString *>(msgValue->GetRawData())),
0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
factory->NewFromASCII(""), JSHandle<EcmaString>(msgValue)), 0);
JSHandle<JSTaggedValue> nameValue(JSObject::GetProperty(thread, errorObject, nameKey).GetValue());
ASSERT_EQ(EcmaStringAccessor::Compare(
reinterpret_cast<EcmaString *>(ecmascript::JSTaggedValue(*factory->NewFromASCII("Error")).GetRawData()),
reinterpret_cast<EcmaString *>(nameValue->GetRawData())),
0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
factory->NewFromASCII("Error"), JSHandle<EcmaString>(nameValue)), 0);
}
/*
@ -194,16 +182,12 @@ HWTEST_F_L0(BuiltinsErrorsTest, ErrorParameterConstructor)
JSHandle<JSTaggedValue> nameKey = thread->GlobalConstants()->GetHandledNameString();
JSHandle<JSTaggedValue> msgValue(JSObject::GetProperty(thread, errorObject, msgKey).GetValue());
ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast<EcmaString *>(
ecmascript::JSTaggedValue(*factory->NewFromASCII("Hello Error!")).GetRawData()),
reinterpret_cast<EcmaString *>(msgValue->GetRawData())),
0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
factory->NewFromASCII("Hello Error!"), JSHandle<EcmaString>(msgValue)), 0);
JSHandle<JSTaggedValue> nameValue(JSObject::GetProperty(thread, errorObject, nameKey).GetValue());
ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast<EcmaString *>(
ecmascript::JSTaggedValue(*factory->NewFromASCII("Error")).GetRawData()),
reinterpret_cast<EcmaString *>(nameValue->GetRawData())),
0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
factory->NewFromASCII("Error"), JSHandle<EcmaString>(nameValue)), 0);
}
/*
@ -228,10 +212,7 @@ HWTEST_F_L0(BuiltinsErrorsTest, ErrorNoParameterToString)
JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
EXPECT_TRUE(result.IsString());
EXPECT_EQ(EcmaStringAccessor::Compare(reinterpret_cast<EcmaString *>(
ecmascript::JSTaggedValue(*factory->NewFromASCII("Error")).GetRawData()),
reinterpret_cast<EcmaString *>(*resultHandle)),
0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, factory->NewFromASCII("Error"), resultHandle), 0);
}
/*
@ -261,10 +242,7 @@ HWTEST_F_L0(BuiltinsErrorsTest, ErrorToString)
JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
EXPECT_TRUE(result.IsString());
EXPECT_EQ(EcmaStringAccessor::Compare(reinterpret_cast<EcmaString *>(
ecmascript::JSTaggedValue(*factory->NewFromASCII("Error: This is Error!")).GetRawData()),
*resultHandle),
0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, factory->NewFromASCII("Error: This is Error!"), resultHandle), 0);
}
/*
@ -293,15 +271,11 @@ HWTEST_F_L0(BuiltinsErrorsTest, RangeErrorNoParameterConstructor)
JSHandle<JSTaggedValue> nameKey = thread->GlobalConstants()->GetHandledNameString();
JSHandle<JSTaggedValue> msgValue(JSObject::GetProperty(thread, errorObject, msgKey).GetValue());
ASSERT_EQ(EcmaStringAccessor::Compare(
reinterpret_cast<EcmaString *>(ecmascript::JSTaggedValue(*factory->NewFromASCII("")).GetRawData()),
reinterpret_cast<EcmaString *>(JSTaggedValue(msgValue.GetTaggedValue()).GetRawData())),
0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
factory->NewFromASCII(""), JSHandle<EcmaString>(msgValue)), 0);
JSHandle<JSTaggedValue> nameValue(JSObject::GetProperty(thread, errorObject, nameKey).GetValue());
ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast<EcmaString *>(
ecmascript::JSTaggedValue(*factory->NewFromASCII("RangeError")).GetRawData()),
reinterpret_cast<EcmaString *>(JSTaggedValue(nameValue.GetTaggedValue()).GetRawData())),
0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
factory->NewFromASCII("RangeError"), JSHandle<EcmaString>(nameValue)), 0);
}
/*
@ -332,16 +306,12 @@ HWTEST_F_L0(BuiltinsErrorsTest, RangeErrorParameterConstructor)
JSHandle<JSTaggedValue> nameKey = thread->GlobalConstants()->GetHandledNameString();
JSHandle<JSTaggedValue> msgValue(JSObject::GetProperty(thread, errorObject, msgKey).GetValue());
ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast<EcmaString *>(
ecmascript::JSTaggedValue(*factory->NewFromASCII("Hello RangeError!")).GetRawData()),
reinterpret_cast<EcmaString *>(msgValue->GetRawData())),
0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
factory->NewFromASCII("Hello RangeError!"), JSHandle<EcmaString>(msgValue)), 0);
JSHandle<JSTaggedValue> nameValue(JSObject::GetProperty(thread, errorObject, nameKey).GetValue());
ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast<EcmaString *>(
ecmascript::JSTaggedValue(*factory->NewFromASCII("RangeError")).GetRawData()),
reinterpret_cast<EcmaString *>(nameValue->GetRawData())),
0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
factory->NewFromASCII("RangeError"), JSHandle<EcmaString>(nameValue)), 0);
}
/*
@ -367,10 +337,8 @@ HWTEST_F_L0(BuiltinsErrorsTest, RangeErrorNoParameterToString)
EXPECT_TRUE(result.IsString());
EXPECT_EQ(EcmaStringAccessor::Compare(reinterpret_cast<EcmaString *>(
ecmascript::JSTaggedValue(*factory->NewFromASCII("RangeError")).GetRawData()),
reinterpret_cast<EcmaString *>(resultHandle->GetRawData())),
0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance,
factory->NewFromASCII("RangeError"), JSHandle<EcmaString>(resultHandle)), 0);
}
/*
@ -399,7 +367,8 @@ HWTEST_F_L0(BuiltinsErrorsTest, RangeErrorToString)
JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
EXPECT_TRUE(result.IsString());
EXPECT_EQ(EcmaStringAccessor::Compare(*factory->NewFromASCII("RangeError: This is RangeError!"), *resultHandle), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance,
factory->NewFromASCII("RangeError: This is RangeError!"), resultHandle), 0);
}
// new ReferenceError()
@ -428,16 +397,12 @@ HWTEST_F_L0(BuiltinsErrorsTest, ReferenceErrorNoParameterConstructor)
JSHandle<JSTaggedValue> nameKey = thread->GlobalConstants()->GetHandledNameString();
JSHandle<JSTaggedValue> msgValue(JSObject::GetProperty(thread, errorObject, msgKey).GetValue());
ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast<EcmaString *>(
ecmascript::JSTaggedValue(*factory->NewFromASCII("")).GetRawData()),
reinterpret_cast<EcmaString *>(msgValue->GetRawData())),
0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
factory->NewFromASCII(""), JSHandle<EcmaString>(msgValue)), 0);
JSHandle<JSTaggedValue> nameValue(JSObject::GetProperty(thread, errorObject, nameKey).GetValue());
ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast<EcmaString *>(
ecmascript::JSTaggedValue(*factory->NewFromASCII("ReferenceError")).GetRawData()),
reinterpret_cast<EcmaString *>(nameValue->GetRawData())),
0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
factory->NewFromASCII("ReferenceError"), JSHandle<EcmaString>(nameValue)), 0);
}
/*
@ -466,16 +431,12 @@ HWTEST_F_L0(BuiltinsErrorsTest, ReferenceErrorParameterConstructor)
JSHandle<JSTaggedValue> msgKey(factory->NewFromASCII("message"));
JSHandle<JSTaggedValue> nameKey = thread->GlobalConstants()->GetHandledNameString();
JSHandle<JSTaggedValue> msgValue(JSObject::GetProperty(thread, errorObject, msgKey).GetValue());
ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast<EcmaString *>(
ecmascript::JSTaggedValue(*factory->NewFromASCII("Hello ReferenceError!")).GetRawData()),
reinterpret_cast<EcmaString *>(msgValue->GetRawData())),
0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
factory->NewFromASCII("Hello ReferenceError!"), JSHandle<EcmaString>(msgValue)), 0);
JSHandle<JSTaggedValue> nameValue(JSObject::GetProperty(thread, errorObject, nameKey).GetValue());
ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast<EcmaString *>(
ecmascript::JSTaggedValue(*factory->NewFromASCII("ReferenceError")).GetRawData()),
reinterpret_cast<EcmaString *>(nameValue->GetRawData())),
0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
factory->NewFromASCII("ReferenceError"), JSHandle<EcmaString>(nameValue)), 0);
}
/*
@ -499,10 +460,7 @@ HWTEST_F_L0(BuiltinsErrorsTest, ReferenceErrorNoParameterToString)
JSTaggedValue result = ReferenceError::ToString(ecmaRuntimeCallInfo);
JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
EXPECT_TRUE(result.IsString());
EXPECT_EQ(EcmaStringAccessor::Compare(reinterpret_cast<EcmaString *>(
ecmascript::JSTaggedValue(*factory->NewFromASCII("ReferenceError")).GetRawData()),
*resultHandle),
0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, factory->NewFromASCII("ReferenceError"), resultHandle), 0);
}
/*
@ -530,10 +488,8 @@ HWTEST_F_L0(BuiltinsErrorsTest, ReferenceErrorToString)
JSTaggedValue result = ReferenceError::ToString(ecmaRuntimeCallInfo);
JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
EXPECT_TRUE(result.IsString());
EXPECT_EQ(EcmaStringAccessor::Compare(
*factory->NewFromASCII("ReferenceError: This is ReferenceError!"),
*resultHandle),
0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance,
factory->NewFromASCII("ReferenceError: This is ReferenceError!"), resultHandle), 0);
}
/*
@ -561,16 +517,12 @@ HWTEST_F_L0(BuiltinsErrorsTest, TypeErrorNoParameterConstructor)
JSHandle<JSTaggedValue> nameKey = thread->GlobalConstants()->GetHandledNameString();
JSHandle<JSTaggedValue> msgValue(JSObject::GetProperty(thread, errorObject, msgKey).GetValue());
ASSERT_EQ(EcmaStringAccessor::Compare(
reinterpret_cast<EcmaString *>(ecmascript::JSTaggedValue(*factory->NewFromASCII("")).GetRawData()),
reinterpret_cast<EcmaString *>(msgValue->GetRawData())),
0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
factory->NewFromASCII(""), JSHandle<EcmaString>(msgValue)), 0);
JSHandle<JSTaggedValue> nameValue(JSObject::GetProperty(thread, errorObject, nameKey).GetValue());
EXPECT_EQ(EcmaStringAccessor::Compare(
reinterpret_cast<EcmaString *>(JSTaggedValue(nameValue.GetTaggedValue()).GetRawData()),
reinterpret_cast<EcmaString *>(JSTaggedValue(nameValue.GetTaggedValue()).GetRawData())),
0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance,
JSHandle<EcmaString>(nameValue), JSHandle<EcmaString>(nameValue)), 0);
}
/*
@ -600,16 +552,12 @@ HWTEST_F_L0(BuiltinsErrorsTest, TypeErrorParameterConstructor)
JSHandle<JSTaggedValue> nameKey = thread->GlobalConstants()->GetHandledNameString();
JSHandle<JSTaggedValue> msgValue(JSObject::GetProperty(thread, errorObject, msgKey).GetValue());
ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast<EcmaString *>(
ecmascript::JSTaggedValue(*factory->NewFromASCII("Hello TypeError!")).GetRawData()),
reinterpret_cast<EcmaString *>(msgValue->GetRawData())),
0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
factory->NewFromASCII("Hello TypeError!"), JSHandle<EcmaString>(msgValue)), 0);
JSHandle<JSTaggedValue> nameValue(JSObject::GetProperty(thread, errorObject, nameKey).GetValue());
ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast<EcmaString *>(
ecmascript::JSTaggedValue(*factory->NewFromASCII("TypeError")).GetRawData()),
reinterpret_cast<EcmaString *>(nameValue->GetRawData())),
0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
factory->NewFromASCII("TypeError"), JSHandle<EcmaString>(nameValue)), 0);
}
/*
@ -633,10 +581,7 @@ HWTEST_F_L0(BuiltinsErrorsTest, TypeErrorNoParameterToString)
JSTaggedValue result = TypeError::ToString(ecmaRuntimeCallInfo);
JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
EXPECT_TRUE(result.IsString());
EXPECT_EQ(EcmaStringAccessor::Compare(reinterpret_cast<EcmaString *>(
ecmascript::JSTaggedValue(*factory->NewFromASCII("TypeError")).GetRawData()),
*resultHandle),
0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, factory->NewFromASCII("TypeError"), resultHandle), 0);
}
/*
@ -664,8 +609,8 @@ HWTEST_F_L0(BuiltinsErrorsTest, TypeErrorToString)
JSTaggedValue result = TypeError::ToString(ecmaRuntimeCallInfo);
JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
EXPECT_TRUE(result.IsString());
EXPECT_EQ(EcmaStringAccessor::Compare(
*factory->NewFromASCII("TypeError: This is TypeError!"), *resultHandle), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance,
factory->NewFromASCII("TypeError: This is TypeError!"), resultHandle), 0);
}
/*
@ -693,16 +638,12 @@ HWTEST_F_L0(BuiltinsErrorsTest, URIErrorNoParameterConstructor)
JSHandle<JSTaggedValue> nameKey = thread->GlobalConstants()->GetHandledNameString();
JSHandle<JSTaggedValue> msgValue(JSObject::GetProperty(thread, errorObject, msgKey).GetValue());
ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast<EcmaString *>(
ecmascript::JSTaggedValue(*factory->NewFromASCII("")).GetRawData()),
reinterpret_cast<EcmaString *>(msgValue->GetRawData())),
0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
factory->NewFromASCII(""), JSHandle<EcmaString>(msgValue)), 0);
JSHandle<JSTaggedValue> nameValue(JSObject::GetProperty(thread, errorObject, nameKey).GetValue());
ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast<EcmaString *>(
ecmascript::JSTaggedValue(*factory->NewFromASCII("URIError")).GetRawData()),
reinterpret_cast<EcmaString *>(nameValue->GetRawData())),
0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
factory->NewFromASCII("URIError"), JSHandle<EcmaString>(nameValue)), 0);
}
/*
@ -732,16 +673,12 @@ HWTEST_F_L0(BuiltinsErrorsTest, URIErrorParameterConstructor)
JSHandle<JSTaggedValue> nameKey = thread->GlobalConstants()->GetHandledNameString();
JSHandle<JSTaggedValue> msgValue(JSObject::GetProperty(thread, errorObject, msgKey).GetValue());
ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast<EcmaString *>(
ecmascript::JSTaggedValue(*factory->NewFromASCII("Hello URIError!")).GetRawData()),
reinterpret_cast<EcmaString *>(msgValue->GetRawData())),
0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
factory->NewFromASCII("Hello URIError!"), JSHandle<EcmaString>(msgValue)), 0);
JSHandle<JSTaggedValue> nameValue(JSObject::GetProperty(thread, errorObject, nameKey).GetValue());
ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast<EcmaString *>(
ecmascript::JSTaggedValue(*factory->NewFromASCII("URIError")).GetRawData()),
reinterpret_cast<EcmaString *>(nameValue->GetRawData())),
0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
factory->NewFromASCII("URIError"), JSHandle<EcmaString>(nameValue)), 0);
}
/*
@ -766,10 +703,7 @@ HWTEST_F_L0(BuiltinsErrorsTest, URIErrorNoParameterToString)
JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
EXPECT_TRUE(result.IsString());
EXPECT_EQ(EcmaStringAccessor::Compare(reinterpret_cast<EcmaString *>(
ecmascript::JSTaggedValue(*factory->NewFromASCII("URIError")).GetRawData()),
*resultHandle),
0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, factory->NewFromASCII("URIError"), resultHandle), 0);
}
/*
@ -799,10 +733,8 @@ HWTEST_F_L0(BuiltinsErrorsTest, URIErrorToString)
JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
EXPECT_TRUE(result.IsString());
EXPECT_EQ(EcmaStringAccessor::Compare(reinterpret_cast<EcmaString *>(
ecmascript::JSTaggedValue(*factory->NewFromASCII("URIError: This is URIError!")).GetRawData()),
*resultHandle),
0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance,
factory->NewFromASCII("URIError: This is URIError!"), resultHandle), 0);
}
/*
@ -830,16 +762,12 @@ HWTEST_F_L0(BuiltinsErrorsTest, SyntaxErrorNoParameterConstructor)
JSHandle<JSTaggedValue> nameKey = thread->GlobalConstants()->GetHandledNameString();
JSHandle<JSTaggedValue> msgValue(JSObject::GetProperty(thread, errorObject, msgKey).GetValue());
ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast<EcmaString *>(
ecmascript::JSTaggedValue(*factory->NewFromASCII("")).GetRawData()),
reinterpret_cast<EcmaString *>(msgValue->GetRawData())),
0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
factory->NewFromASCII(""), JSHandle<EcmaString>(msgValue)), 0);
JSHandle<JSTaggedValue> nameValue(JSObject::GetProperty(thread, errorObject, nameKey).GetValue());
ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast<EcmaString *>(
ecmascript::JSTaggedValue(*factory->NewFromASCII("SyntaxError")).GetRawData()),
reinterpret_cast<EcmaString *>(nameValue->GetRawData())),
0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
factory->NewFromASCII("SyntaxError"), JSHandle<EcmaString>(nameValue)), 0);
}
/*
@ -869,16 +797,12 @@ HWTEST_F_L0(BuiltinsErrorsTest, SyntaxErrorParameterConstructor)
JSHandle<JSTaggedValue> nameKey = thread->GlobalConstants()->GetHandledNameString();
JSHandle<JSTaggedValue> msgValue(JSObject::GetProperty(thread, errorObject, msgKey).GetValue());
ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast<EcmaString *>(
ecmascript::JSTaggedValue(*factory->NewFromASCII("Hello SyntaxError!")).GetRawData()),
reinterpret_cast<EcmaString *>(msgValue->GetRawData())),
0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
factory->NewFromASCII("Hello SyntaxError!"), JSHandle<EcmaString>(msgValue)), 0);
JSHandle<JSTaggedValue> nameValue(JSObject::GetProperty(thread, errorObject, nameKey).GetValue());
ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast<EcmaString *>(
ecmascript::JSTaggedValue(*factory->NewFromASCII("SyntaxError")).GetRawData()),
reinterpret_cast<EcmaString *>(nameValue->GetRawData())),
0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
factory->NewFromASCII("SyntaxError"), JSHandle<EcmaString>(nameValue)), 0);
}
/*
@ -903,10 +827,7 @@ HWTEST_F_L0(BuiltinsErrorsTest, SyntaxErrorNoParameterToString)
JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
EXPECT_TRUE(result.IsString());
EXPECT_EQ(EcmaStringAccessor::Compare(reinterpret_cast<EcmaString *>(
ecmascript::JSTaggedValue(*factory->NewFromASCII("SyntaxError")).GetRawData()),
*resultHandle),
0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, factory->NewFromASCII("SyntaxError"), resultHandle), 0);
}
/*
@ -935,8 +856,8 @@ HWTEST_F_L0(BuiltinsErrorsTest, SyntaxErrorToString)
JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
EXPECT_TRUE(result.IsString());
EXPECT_EQ(EcmaStringAccessor::Compare(
*factory->NewFromASCII("SyntaxError: This is SyntaxError!"), *resultHandle), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance,
factory->NewFromASCII("SyntaxError: This is SyntaxError!"), resultHandle), 0);
}
/*
@ -964,16 +885,12 @@ HWTEST_F_L0(BuiltinsErrorsTest, EvalErrorNoParameterConstructor)
JSHandle<JSTaggedValue> nameKey = thread->GlobalConstants()->GetHandledNameString();
JSHandle<JSTaggedValue> msgValue(JSObject::GetProperty(thread, errorObject, msgKey).GetValue());
ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast<EcmaString *>(
ecmascript::JSTaggedValue(*factory->NewFromASCII("")).GetRawData()),
reinterpret_cast<EcmaString *>(msgValue->GetRawData())),
0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
factory->NewFromASCII(""), JSHandle<EcmaString>(msgValue)), 0);
JSHandle<JSTaggedValue> nameValue(JSObject::GetProperty(thread, errorObject, nameKey).GetValue());
ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast<EcmaString *>(
ecmascript::JSTaggedValue(*factory->NewFromASCII("EvalError")).GetRawData()),
reinterpret_cast<EcmaString *>(nameValue->GetRawData())),
0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
factory->NewFromASCII("EvalError"), JSHandle<EcmaString>(nameValue)), 0);
}
/*
@ -1003,16 +920,12 @@ HWTEST_F_L0(BuiltinsErrorsTest, EvalErrorParameterConstructor)
JSHandle<JSTaggedValue> nameKey = thread->GlobalConstants()->GetHandledNameString();
JSHandle<JSTaggedValue> msgValue(JSObject::GetProperty(thread, errorObject, msgKey).GetValue());
ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast<EcmaString *>(
ecmascript::JSTaggedValue(*factory->NewFromASCII("Hello EvalError!")).GetRawData()),
reinterpret_cast<EcmaString *>(msgValue->GetRawData())),
0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
factory->NewFromASCII("Hello EvalError!"), JSHandle<EcmaString>(msgValue)), 0);
JSHandle<JSTaggedValue> nameValue(JSObject::GetProperty(thread, errorObject, nameKey).GetValue());
ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast<EcmaString *>(
ecmascript::JSTaggedValue(*factory->NewFromASCII("EvalError")).GetRawData()),
reinterpret_cast<EcmaString *>(nameValue->GetRawData())),
0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
factory->NewFromASCII("EvalError"), JSHandle<EcmaString>(nameValue)), 0);
}
/*
@ -1035,10 +948,7 @@ HWTEST_F_L0(BuiltinsErrorsTest, EvalErrorNoParameterToString)
JSTaggedValue result = EvalError::ToString(ecmaRuntimeCallInfo);
JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
EXPECT_TRUE(result.IsString());
EXPECT_EQ(EcmaStringAccessor::Compare(reinterpret_cast<EcmaString *>(
ecmascript::JSTaggedValue(*factory->NewFromASCII("EvalError")).GetRawData()),
*resultHandle),
0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, factory->NewFromASCII("EvalError"), resultHandle), 0);
}
/*
@ -1067,7 +977,7 @@ HWTEST_F_L0(BuiltinsErrorsTest, EvalErrorToString)
JSTaggedValue result = EvalError::ToString(ecmaRuntimeCallInfo);
JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
EXPECT_TRUE(result.IsString());
EXPECT_EQ(EcmaStringAccessor::Compare(
*factory->NewFromASCII("EvalError: This is EvalError!"), *resultHandle), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance,
factory->NewFromASCII("EvalError: This is EvalError!"), resultHandle), 0);
}
} // namespace panda::test

View File

@ -205,7 +205,7 @@ HWTEST_F_L0(BuiltinsFunctionTest, FunctionPrototypeBind)
JSHandle<JSTaggedValue> resultFuncHandle(thread, *resultFunc);
JSHandle<EcmaString> resultName(JSObject::GetProperty(thread, resultFuncHandle, nameKey).GetValue());
JSHandle<EcmaString> boundTarget = factory->NewFromASCII("bound target");
ASSERT_EQ(EcmaStringAccessor::Compare(*resultName, *boundTarget), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultName, boundTarget), 0);
// test length property
JSHandle<JSTaggedValue> lengthKey = globalConst->GetHandledLengthString();
JSHandle<JSTaggedValue> resultLength(JSObject::GetProperty(thread, resultFuncHandle, lengthKey).GetValue());
@ -260,7 +260,7 @@ HWTEST_F_L0(BuiltinsFunctionTest, FunctionPrototypeBind1)
JSHandle<JSTaggedValue> resultFuncHandle(thread, *resultFunc);
JSHandle<EcmaString> resultName(JSObject::GetProperty(thread, resultFuncHandle, nameKey).GetValue());
JSHandle<EcmaString> rulerName = factory->NewFromASCII("bound target1");
ASSERT_EQ(EcmaStringAccessor::Compare(*resultName, *rulerName), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultName, rulerName), 0);
// test length property
JSHandle<JSTaggedValue> lengthKey = globalConst->GetHandledLengthString();
JSHandle<JSTaggedValue> resultLength(JSObject::GetProperty(thread, resultFuncHandle, lengthKey).GetValue());
@ -316,7 +316,7 @@ HWTEST_F_L0(BuiltinsFunctionTest, FunctionPrototypeBind2)
JSHandle<JSTaggedValue> resultFuncHandle(resultFunc);
JSHandle<EcmaString> resultName(JSObject::GetProperty(thread, resultFuncHandle, nameKey).GetValue());
JSHandle<EcmaString> rulerName = factory->NewFromASCII("bound ");
ASSERT_EQ(EcmaStringAccessor::Compare(*resultName, *rulerName), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultName, rulerName), 0);
// test length property
JSHandle<JSTaggedValue> lengthKey = globalConst->GetHandledLengthString();
JSHandle<JSTaggedValue> resultLength(JSObject::GetProperty(thread, resultFuncHandle, lengthKey).GetValue());
@ -453,7 +453,7 @@ HWTEST_F_L0(BuiltinsFunctionTest, FunctionPrototypeToString)
JSTaggedValue result = BuiltinsFunction::FunctionPrototypeToString(ecmaRuntimeCallInfo);
ASSERT_TRUE(result.IsString());
JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
JSTaggedValue test = factory->NewFromASCII("function call() { [native code] }").GetTaggedValue();
ASSERT_EQ(EcmaStringAccessor::Compare(*resultHandle, reinterpret_cast<EcmaString *>(test.GetRawData())), 0);
JSHandle<EcmaString> test = factory->NewFromASCII("function call() { [native code] }");
ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0);
}
} // namespace panda::test

View File

@ -166,7 +166,7 @@ HWTEST_F_L0(BuiltinsLocaleTest, ToString)
JSHandle<EcmaString> handleEcmaStr(thread, result);
JSHandle<EcmaString> resultStr(
factory->NewFromASCII("en-Latn-US-u-ca-chinese-co-compat-hc-h24-kn-nu-mong"));
EXPECT_EQ(EcmaStringAccessor::Compare(*handleEcmaStr, *resultStr), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr, resultStr), 0);
}
HWTEST_F_L0(BuiltinsLocaleTest, GetBaseName)

View File

@ -418,7 +418,7 @@ HWTEST_F_L0(BuiltinsNumberTest, StringToDoubleFlags)
{
JSHandle<EcmaString> str;
Span<const uint8_t> sp;
[[maybe_unused]] CVector<uint8_t> buf;
CVector<uint8_t> buf;
// flags of IGNORE_TRAILING
@ -500,7 +500,7 @@ HWTEST_F_L0(BuiltinsNumberTest, StringToDoubleRadix)
{
JSHandle<EcmaString> str;
Span<const uint8_t> sp;
[[maybe_unused]] CVector<uint8_t> buf;
CVector<uint8_t> buf;
int radix;
radix = 0; // default 10
@ -586,42 +586,43 @@ HWTEST_F_L0(BuiltinsNumberTest, NumberToString)
{
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<EcmaString> res = factory->NewFromASCII("100");
ASSERT_EQ(EcmaStringAccessor::Compare(*base::NumberHelper::NumberToString(thread, JSTaggedValue(100)), *res), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
base::NumberHelper::NumberToString(thread, JSTaggedValue(100)), res), 0);
res = factory->NewFromASCII("11223344");
ASSERT_EQ(EcmaStringAccessor::Compare(
*base::NumberHelper::NumberToString(thread, JSTaggedValue(11223344)), *res), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
base::NumberHelper::NumberToString(thread, JSTaggedValue(11223344)), res), 0);
res = factory->NewFromASCII("1234567890");
ASSERT_EQ(EcmaStringAccessor::Compare(
*base::NumberHelper::NumberToString(thread, JSTaggedValue(1234567890)), *res), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
base::NumberHelper::NumberToString(thread, JSTaggedValue(1234567890)), res), 0);
res = factory->NewFromASCII("100");
ASSERT_EQ(EcmaStringAccessor::Compare(
*base::NumberHelper::NumberToString(thread, JSTaggedValue(double(100.0))), *res), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
base::NumberHelper::NumberToString(thread, JSTaggedValue(double(100.0))), res), 0);
res = factory->NewFromASCII("100.5");
ASSERT_EQ(EcmaStringAccessor::Compare(
*base::NumberHelper::NumberToString(thread, JSTaggedValue(double(100.5))), *res), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
base::NumberHelper::NumberToString(thread, JSTaggedValue(double(100.5))), res), 0);
res = factory->NewFromASCII("100.25");
ASSERT_EQ(EcmaStringAccessor::Compare(
*base::NumberHelper::NumberToString(thread, JSTaggedValue(double(100.25))), *res), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
base::NumberHelper::NumberToString(thread, JSTaggedValue(double(100.25))), res), 0);
res = factory->NewFromASCII("100.125");
ASSERT_EQ(EcmaStringAccessor::Compare(
*base::NumberHelper::NumberToString(thread, JSTaggedValue(double(100.125))), *res), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
base::NumberHelper::NumberToString(thread, JSTaggedValue(double(100.125))), res), 0);
res = factory->NewFromASCII("100.6125");
ASSERT_EQ(EcmaStringAccessor::Compare(
*base::NumberHelper::NumberToString(thread, JSTaggedValue(double(100.6125))), *res), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
base::NumberHelper::NumberToString(thread, JSTaggedValue(double(100.6125))), res), 0);
res = factory->NewFromASCII("0.0006125");
ASSERT_EQ(EcmaStringAccessor::Compare(
*base::NumberHelper::NumberToString(thread, JSTaggedValue(double(0.0006125))), *res), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
base::NumberHelper::NumberToString(thread, JSTaggedValue(double(0.0006125))), res), 0);
res = factory->NewFromASCII("-0.0006125");
ASSERT_EQ(EcmaStringAccessor::Compare(
*base::NumberHelper::NumberToString(thread, JSTaggedValue(double(-0.0006125))), *res), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
base::NumberHelper::NumberToString(thread, JSTaggedValue(double(-0.0006125))), res), 0);
res = factory->NewFromASCII("-1234567890.0006125");
ASSERT_EQ(EcmaStringAccessor::Compare(
*base::NumberHelper::NumberToString(thread, JSTaggedValue(double(-1234567890.0006125))), *res), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
base::NumberHelper::NumberToString(thread, JSTaggedValue(double(-1234567890.0006125))), res), 0);
res = factory->NewFromASCII("1234567890.0006125");
ASSERT_EQ(EcmaStringAccessor::Compare(
*base::NumberHelper::NumberToString(thread, JSTaggedValue(double(1234567890.0006125))), *res), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
base::NumberHelper::NumberToString(thread, JSTaggedValue(double(1234567890.0006125))), res), 0);
res = factory->NewFromASCII("11234567890.000612");
ASSERT_EQ(EcmaStringAccessor::Compare(
*base::NumberHelper::NumberToString(thread, JSTaggedValue(double(11234567890.0006125))), *res), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
base::NumberHelper::NumberToString(thread, JSTaggedValue(double(11234567890.0006125))), res), 0);
}
} // namespace panda::test

View File

@ -840,7 +840,7 @@ HWTEST_F_L0(BuiltinsObjectTest, ToLocaleString)
TestHelper::TearDownFrame(thread, prev);
ASSERT_TRUE(result.IsString());
ASSERT_EQ(EcmaStringAccessor::Compare(*resultValue, reinterpret_cast<EcmaString *>(result.GetRawData())), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultValue, JSHandle<EcmaString>(thread, result)), 0);
}
// obj.toString()
@ -859,7 +859,7 @@ HWTEST_F_L0(BuiltinsObjectTest, ToString)
TestHelper::TearDownFrame(thread, prev);
ASSERT_TRUE(result.IsString());
ASSERT_EQ(EcmaStringAccessor::Compare(*resultValue, reinterpret_cast<EcmaString *>(result.GetRawData())), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultValue, JSHandle<EcmaString>(thread, result)), 0);
// array
JSHandle<JSArray> arr = thread->GetEcmaVM()->GetFactory()->NewJSArray();
@ -874,7 +874,7 @@ HWTEST_F_L0(BuiltinsObjectTest, ToString)
TestHelper::TearDownFrame(thread, prev);
ASSERT_TRUE(resultArr.IsString());
ASSERT_EQ(EcmaStringAccessor::Compare(*resultArrValue, reinterpret_cast<EcmaString *>(resultArr.GetRawData())), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultArrValue, JSHandle<EcmaString>(thread, resultArr)), 0);
// string
JSHandle<EcmaString> str = thread->GetEcmaVM()->GetFactory()->NewFromASCII("hello");
@ -889,7 +889,7 @@ HWTEST_F_L0(BuiltinsObjectTest, ToString)
TestHelper::TearDownFrame(thread, prev);
ASSERT_TRUE(resultStr.IsString());
ASSERT_EQ(EcmaStringAccessor::Compare(*resultStrValue, reinterpret_cast<EcmaString *>(resultStr.GetRawData())), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultStrValue, JSHandle<EcmaString>(thread, resultStr)), 0);
// function
JSHandle<JSFunction> func = thread->GetEcmaVM()->GetFactory()->NewJSFunction(thread->GetEcmaVM()->GetGlobalEnv());
@ -904,8 +904,8 @@ HWTEST_F_L0(BuiltinsObjectTest, ToString)
TestHelper::TearDownFrame(thread, prev);
ASSERT_TRUE(resultFunc.IsString());
ASSERT_EQ(EcmaStringAccessor::Compare(
*resultFuncValue, reinterpret_cast<EcmaString *>(resultFunc.GetRawData())), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
resultFuncValue, JSHandle<EcmaString>(thread, resultFunc)), 0);
// error
auto ecmaVM = thread->GetEcmaVM();
@ -923,7 +923,7 @@ HWTEST_F_L0(BuiltinsObjectTest, ToString)
TestHelper::TearDownFrame(thread, prev);
ASSERT_TRUE(resultError.IsString());
ASSERT_EQ(EcmaStringAccessor::Compare(*errorValue, reinterpret_cast<EcmaString *>(resultError.GetRawData())), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance, errorValue, JSHandle<EcmaString>(thread, resultError)), 0);
// boolean
JSHandle<JSTaggedValue> value(thread, JSTaggedValue::False());
@ -940,8 +940,8 @@ HWTEST_F_L0(BuiltinsObjectTest, ToString)
TestHelper::TearDownFrame(thread, prev);
ASSERT_TRUE(resultBool.IsString());
ASSERT_EQ(EcmaStringAccessor::Compare(
*resultBoolValue, reinterpret_cast<EcmaString *>(resultBool.GetRawData())), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
resultBoolValue, JSHandle<EcmaString>(thread, resultBool)), 0);
// number
JSHandle<EcmaString> resultNumValue =
@ -955,7 +955,7 @@ HWTEST_F_L0(BuiltinsObjectTest, ToString)
TestHelper::TearDownFrame(thread, prev);
ASSERT_TRUE(resultNum.IsString());
ASSERT_EQ(EcmaStringAccessor::Compare(*resultNumValue, reinterpret_cast<EcmaString *>(resultNum.GetRawData())), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultNumValue, JSHandle<EcmaString>(thread, resultNum)), 0);
}
// object.valueOf()

View File

@ -166,7 +166,8 @@ HWTEST_F_L0(BuiltinsReflectTest, ReflectConstruct)
JSHandle<JSTaggedValue> taggedResult(thread, result);
JSHandle<JSPrimitiveRef> refResult = JSHandle<JSPrimitiveRef>::Cast(taggedResult);
JSHandle<EcmaString> ruler = factory->NewFromASCII("ReflectConstruct");
ASSERT_EQ(EcmaStringAccessor::Compare(EcmaString::Cast(refResult->GetValue().GetTaggedObject()), *ruler), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
JSHandle<EcmaString>(thread, EcmaString::Cast(refResult->GetValue())), ruler), 0);
TestHelper::TearDownFrame(thread, prev);
}
@ -431,17 +432,17 @@ HWTEST_F_L0(BuiltinsReflectTest, ReflectOwnKeys)
JSHandle<JSTaggedValue> resultKey0(thread, JSTaggedValue(0));
JSHandle<JSTaggedValue> resultValue0 =
JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(resultArray), resultKey0).GetValue();
ASSERT_EQ(EcmaStringAccessor::Compare(
reinterpret_cast<EcmaString *>(resultValue0.GetTaggedValue().GetTaggedObject()),
reinterpret_cast<EcmaString *>(key0.GetTaggedValue().GetTaggedObject())),
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
JSHandle<EcmaString>(resultValue0),
JSHandle<EcmaString>(key0)),
0);
// test array[1]
JSHandle<JSTaggedValue> resultKey1(thread, JSTaggedValue(1));
JSHandle<JSTaggedValue> resultValue1 =
JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(resultArray), resultKey1).GetValue();
ASSERT_EQ(EcmaStringAccessor::Compare(
reinterpret_cast<EcmaString *>(resultValue1.GetTaggedValue().GetTaggedObject()),
reinterpret_cast<EcmaString *>(key1.GetTaggedValue().GetTaggedObject())),
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
JSHandle<EcmaString>(resultValue1),
JSHandle<EcmaString>(key1)),
0);
TestHelper::TearDownFrame(thread, prev);
}

View File

@ -96,8 +96,8 @@ HWTEST_F_L0(BuiltinsRegExpTest, RegExpConstructor1)
JSHandle<JSTaggedValue> originalSource(thread, jsRegexp->GetOriginalSource());
uint8_t flagsBits = static_cast<uint8_t>(jsRegexp->GetOriginalFlags().GetInt());
JSHandle<JSTaggedValue> originalFlags(thread, BuiltinsRegExp::FlagsBitsToString(thread, flagsBits));
ASSERT_EQ(EcmaStringAccessor::Compare(static_cast<EcmaString *>(originalSource->GetTaggedObject()), *pattern), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(static_cast<EcmaString *>(originalFlags->GetTaggedObject()), *flags), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle<EcmaString>(originalSource), pattern), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle<EcmaString>(originalFlags), flags), 0);
}
HWTEST_F_L0(BuiltinsRegExpTest, RegExpConstructor2)
@ -131,8 +131,8 @@ HWTEST_F_L0(BuiltinsRegExpTest, RegExpConstructor2)
JSHandle<JSTaggedValue> originalSource(thread, jsRegexp->GetOriginalSource());
uint8_t flagsBits = static_cast<uint8_t>(jsRegexp->GetOriginalFlags().GetInt());
JSHandle<JSTaggedValue> originalFlags(thread, BuiltinsRegExp::FlagsBitsToString(thread, flagsBits));
ASSERT_EQ(EcmaStringAccessor::Compare(static_cast<EcmaString *>(originalSource->GetTaggedObject()), *pattern), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(static_cast<EcmaString *>(originalFlags->GetTaggedObject()), *flags), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle<EcmaString>(originalSource), pattern), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle<EcmaString>(originalFlags), flags), 0);
}
HWTEST_F_L0(BuiltinsRegExpTest, RegExpConstructor3)
@ -166,8 +166,8 @@ HWTEST_F_L0(BuiltinsRegExpTest, RegExpConstructor3)
JSHandle<JSTaggedValue> originalSource(thread, jsRegexp->GetOriginalSource());
uint8_t flagsBits = static_cast<uint8_t>(jsRegexp->GetOriginalFlags().GetInt());
JSHandle<JSTaggedValue> originalFlags(thread, BuiltinsRegExp::FlagsBitsToString(thread, flagsBits));
ASSERT_EQ(EcmaStringAccessor::Compare(static_cast<EcmaString *>(originalSource->GetTaggedObject()), *pattern1), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(static_cast<EcmaString *>(originalFlags->GetTaggedObject()), *flags2), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle<EcmaString>(originalSource), pattern1), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle<EcmaString>(originalFlags), flags2), 0);
}
HWTEST_F_L0(BuiltinsRegExpTest, GetSource1)
@ -184,7 +184,7 @@ HWTEST_F_L0(BuiltinsRegExpTest, GetSource1)
JSHandle<JSTaggedValue> sourceResult(JSObject::GetProperty(thread, result1Handle, source).GetValue());
JSHandle<EcmaString> expect = thread->GetEcmaVM()->GetFactory()->NewFromASCII("(?:)");
ASSERT_EQ(EcmaStringAccessor::Compare(static_cast<EcmaString *>(sourceResult->GetTaggedObject()), *expect), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle<EcmaString>(sourceResult), expect), 0);
}
HWTEST_F_L0(BuiltinsRegExpTest, GetSource2)
@ -200,7 +200,7 @@ HWTEST_F_L0(BuiltinsRegExpTest, GetSource2)
JSHandle<JSTaggedValue> sourceResult(JSObject::GetProperty(thread, result1Handle, source).GetValue());
JSHandle<EcmaString> expect = thread->GetEcmaVM()->GetFactory()->NewFromASCII("\\/w+");
ASSERT_EQ(EcmaStringAccessor::Compare(static_cast<EcmaString *>(sourceResult->GetTaggedObject()), *expect), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle<EcmaString>(sourceResult), expect), 0);
}
HWTEST_F_L0(BuiltinsRegExpTest, Get)
@ -250,7 +250,7 @@ HWTEST_F_L0(BuiltinsRegExpTest, GetFlags)
JSHandle<JSTaggedValue> flagsResult(JSObject::GetProperty(thread, result1Handle, flags).GetValue());
JSHandle<EcmaString> expectResult = thread->GetEcmaVM()->GetFactory()->NewFromASCII("gimuy");
ASSERT_EQ(EcmaStringAccessor::Compare(static_cast<EcmaString *>(flagsResult->GetTaggedObject()), *expectResult), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle<EcmaString>(flagsResult), expectResult), 0);
}
HWTEST_F_L0(BuiltinsRegExpTest, toString)
@ -271,8 +271,8 @@ HWTEST_F_L0(BuiltinsRegExpTest, toString)
ASSERT_TRUE(toStringResult.IsString());
JSHandle<JSTaggedValue> toStringResultHandle(thread, toStringResult);
JSHandle<EcmaString> expectResult = thread->GetEcmaVM()->GetFactory()->NewFromASCII("/\\w+/gimuy");
ASSERT_EQ(EcmaStringAccessor::Compare(
static_cast<EcmaString *>(toStringResultHandle->GetTaggedObject()), *expectResult), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
JSHandle<EcmaString>(toStringResultHandle), expectResult), 0);
}
HWTEST_F_L0(BuiltinsRegExpTest, Exec1)
@ -310,22 +310,22 @@ HWTEST_F_L0(BuiltinsRegExpTest, Exec1)
JSHandle<JSTaggedValue> inputHandle(JSObject::GetProperty(thread, execResult, input).GetValue());
JSHandle<EcmaString> outputInput = JSTaggedValue::ToString(thread, inputHandle);
ASSERT_EQ(EcmaStringAccessor::Compare(*outputInput, *inputString), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputInput, inputString), 0);
JSHandle<JSTaggedValue> zero(thread->GetEcmaVM()->GetFactory()->NewFromASCII("0"));
JSHandle<JSTaggedValue> zeroHandle(JSObject::GetProperty(thread, execResult, zero).GetValue());
JSHandle<EcmaString> outputZero = JSTaggedValue::ToString(thread, zeroHandle);
ASSERT_EQ(EcmaStringAccessor::Compare(*outputZero, *resultZero), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputZero, resultZero), 0);
JSHandle<JSTaggedValue> first(thread->GetEcmaVM()->GetFactory()->NewFromASCII("1"));
JSHandle<JSTaggedValue> oneHandle(JSObject::GetProperty(thread, execResult, first).GetValue());
JSHandle<EcmaString> outputOne = JSTaggedValue::ToString(thread, oneHandle);
ASSERT_EQ(EcmaStringAccessor::Compare(*outputOne, *resultOne), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputOne, resultOne), 0);
JSHandle<JSTaggedValue> second(thread->GetEcmaVM()->GetFactory()->NewFromASCII("2"));
JSHandle<JSTaggedValue> twoHandle(JSObject::GetProperty(thread, execResult, second).GetValue());
JSHandle<EcmaString> outputTwo = JSTaggedValue::ToString(thread, twoHandle);
ASSERT_EQ(EcmaStringAccessor::Compare(*outputTwo, *resultTwo), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputTwo, resultTwo), 0);
JSHandle<JSTaggedValue> regexp = JSHandle<JSTaggedValue>::Cast(value);
JSHandle<JSTaggedValue> lastIndexHandle(thread->GetEcmaVM()->GetFactory()->NewFromASCII("lastIndex"));
@ -368,22 +368,22 @@ HWTEST_F_L0(BuiltinsRegExpTest, Exec2)
JSHandle<JSTaggedValue> input(thread->GetEcmaVM()->GetFactory()->NewFromASCII("input"));
JSHandle<JSTaggedValue> inputHandle(JSObject::GetProperty(thread, execResult, input).GetValue());
JSHandle<EcmaString> outputInput = JSTaggedValue::ToString(thread, inputHandle);
ASSERT_EQ(EcmaStringAccessor::Compare(*outputInput, *inputString), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputInput, inputString), 0);
JSHandle<JSTaggedValue> zero(thread->GetEcmaVM()->GetFactory()->NewFromASCII("0"));
JSHandle<JSTaggedValue> zeroHandle(JSObject::GetProperty(thread, execResult, zero).GetValue());
JSHandle<EcmaString> outputZero = JSTaggedValue::ToString(thread, zeroHandle);
ASSERT_EQ(EcmaStringAccessor::Compare(*outputZero, *resultZero), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputZero, resultZero), 0);
JSHandle<JSTaggedValue> first(thread->GetEcmaVM()->GetFactory()->NewFromASCII("1"));
JSHandle<JSTaggedValue> oneHandle(JSObject::GetProperty(thread, execResult, first).GetValue());
JSHandle<EcmaString> outputOne = JSTaggedValue::ToString(thread, oneHandle);
ASSERT_EQ(EcmaStringAccessor::Compare(*outputOne, *resultOne), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputOne, resultOne), 0);
JSHandle<JSTaggedValue> second(thread->GetEcmaVM()->GetFactory()->NewFromASCII("2"));
JSHandle<JSTaggedValue> twoHandle(JSObject::GetProperty(thread, execResult, second).GetValue());
JSHandle<EcmaString> outputTwo = JSTaggedValue::ToString(thread, twoHandle);
ASSERT_EQ(EcmaStringAccessor::Compare(*outputTwo, *resultTwo), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputTwo, resultTwo), 0);
JSHandle<JSTaggedValue> regexp = JSHandle<JSTaggedValue>::Cast(value);
JSHandle<JSTaggedValue> lastIndexHandle(thread->GetEcmaVM()->GetFactory()->NewFromASCII("lastIndex"));
@ -398,7 +398,7 @@ HWTEST_F_L0(BuiltinsRegExpTest, Exec2)
JSHandle<JSTaggedValue> four(thread->GetEcmaVM()->GetFactory()->NewFromASCII("4"));
JSHandle<JSTaggedValue> fourHandle(JSObject::GetProperty(thread, execResult, four).GetValue());
JSHandle<EcmaString> outputFour = JSTaggedValue::ToString(thread, fourHandle);
ASSERT_EQ(EcmaStringAccessor::Compare(*outputFour, *resultFour), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputFour, resultFour), 0);
JSHandle<JSTaggedValue> five(thread->GetEcmaVM()->GetFactory()->NewFromASCII("5"));
JSHandle<JSTaggedValue> fiveHandle(JSObject::GetProperty(thread, execResult, five).GetValue());
@ -407,7 +407,7 @@ HWTEST_F_L0(BuiltinsRegExpTest, Exec2)
JSHandle<JSTaggedValue> six(thread->GetEcmaVM()->GetFactory()->NewFromASCII("6"));
JSHandle<JSTaggedValue> sixHandle(JSObject::GetProperty(thread, execResult, six).GetValue());
JSHandle<EcmaString> outputSix = JSTaggedValue::ToString(thread, sixHandle);
ASSERT_EQ(EcmaStringAccessor::Compare(*outputSix, *resultSix), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputSix, resultSix), 0);
}
HWTEST_F_L0(BuiltinsRegExpTest, Match1)
@ -436,7 +436,7 @@ HWTEST_F_L0(BuiltinsRegExpTest, Match1)
thread->GetEcmaVM()->GetFactory()->NewFromASCII("Quick Brown Fox Jumps");
JSHandle<JSTaggedValue> zeroHandle(JSObject::GetProperty(thread, matchResult, zero).GetValue());
JSHandle<EcmaString> outputZero = JSTaggedValue::ToString(thread, zeroHandle);
ASSERT_EQ(EcmaStringAccessor::Compare(*outputZero, *resultZero), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputZero, resultZero), 0);
}
HWTEST_F_L0(BuiltinsRegExpTest, Test1)
@ -508,7 +508,7 @@ HWTEST_F_L0(BuiltinsRegExpTest, Split1)
JSHandle<JSTaggedValue> zeroHandle(JSObject::GetProperty(thread, splitResult, zero).GetValue());
JSHandle<EcmaString> outputZero = JSTaggedValue::ToString(thread, zeroHandle);
ASSERT_EQ(EcmaStringAccessor::Compare(*outputZero, *inputString), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputZero, inputString), 0);
}
HWTEST_F_L0(BuiltinsRegExpTest, Split2)
@ -538,17 +538,17 @@ HWTEST_F_L0(BuiltinsRegExpTest, Split2)
JSHandle<JSTaggedValue> zero(thread->GetEcmaVM()->GetFactory()->NewFromASCII("0"));
JSHandle<JSTaggedValue> zeroHandle(JSObject::GetProperty(thread, splitResult, zero).GetValue());
JSHandle<EcmaString> outputZero = JSTaggedValue::ToString(thread, zeroHandle);
ASSERT_EQ(EcmaStringAccessor::Compare(*outputZero, *resultZero), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputZero, resultZero), 0);
JSHandle<JSTaggedValue> first(thread->GetEcmaVM()->GetFactory()->NewFromASCII("1"));
JSHandle<JSTaggedValue> oneHandle(JSObject::GetProperty(thread, splitResult, first).GetValue());
JSHandle<EcmaString> outputOne = JSTaggedValue::ToString(thread, oneHandle);
ASSERT_EQ(EcmaStringAccessor::Compare(*outputOne, *resultOne), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputOne, resultOne), 0);
JSHandle<JSTaggedValue> second(thread->GetEcmaVM()->GetFactory()->NewFromASCII("2"));
JSHandle<JSTaggedValue> twoHandle(JSObject::GetProperty(thread, splitResult, second).GetValue());
JSHandle<EcmaString> outputTwo = JSTaggedValue::ToString(thread, twoHandle);
ASSERT_EQ(EcmaStringAccessor::Compare(*outputTwo, *resultTwo), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputTwo, resultTwo), 0);
}
HWTEST_F_L0(BuiltinsRegExpTest, GetSpecies)
@ -590,7 +590,7 @@ HWTEST_F_L0(BuiltinsRegExpTest, Replace1)
JSHandle<JSTaggedValue> replaceResult(thread, results);
JSHandle<EcmaString> resultZero = thread->GetEcmaVM()->GetFactory()->NewFromASCII(
"The Quick Brown Fox Jumpsa The Over The Lazy Dog Jumps Brown $1 Jumps1 $32 a Over The Lazy Dog");
ASSERT_EQ(EcmaStringAccessor::Compare(static_cast<EcmaString *>(replaceResult->GetTaggedObject()), *resultZero), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle<EcmaString>(replaceResult), resultZero), 0);
}
HWTEST_F_L0(BuiltinsRegExpTest, Replace2)
@ -615,7 +615,7 @@ HWTEST_F_L0(BuiltinsRegExpTest, Replace2)
JSTaggedValue results = BuiltinsRegExp::Replace(ecmaRuntimeCallInfo);
JSHandle<JSTaggedValue> replaceResult(thread, results);
JSHandle<EcmaString> resultZero = factory->NewFromASCII("a[cd$04$00]e");
ASSERT_EQ(EcmaStringAccessor::Compare(static_cast<EcmaString *>(replaceResult->GetTaggedObject()), *resultZero), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle<EcmaString>(replaceResult), resultZero), 0);
}
HWTEST_F_L0(BuiltinsRegExpTest, Replace3)
@ -640,7 +640,7 @@ HWTEST_F_L0(BuiltinsRegExpTest, Replace3)
JSTaggedValue results = BuiltinsRegExp::Replace(ecmaRuntimeCallInfo);
JSHandle<JSTaggedValue> replaceResult(thread, results);
JSHandle<EcmaString> resultZero = factory->NewFromASCII("de");
ASSERT_EQ(EcmaStringAccessor::Compare(static_cast<EcmaString *>(replaceResult->GetTaggedObject()), *resultZero), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle<EcmaString>(replaceResult), resultZero), 0);
}
HWTEST_F_L0(BuiltinsRegExpTest, RegExpParseCache)

View File

@ -108,10 +108,9 @@ HWTEST_F_L0(BuiltinsStringTest, StringConstructor1)
JSTaggedValue value(static_cast<JSTaggedType>(result.GetRawData()));
ASSERT_TRUE(value.IsECMAObject());
JSHandle<JSPrimitiveRef> ref(thread, JSPrimitiveRef::Cast(value.GetTaggedObject()));
JSTaggedValue test = factory->NewFromASCII("ABC").GetTaggedValue();
ASSERT_EQ(EcmaStringAccessor::Compare(EcmaString::Cast(ref->GetValue().GetTaggedObject()),
reinterpret_cast<EcmaString *>(test.GetRawData())),
0);
JSHandle<EcmaString> test = factory->NewFromASCII("ABC");
ASSERT_EQ(EcmaStringAccessor::Compare(instance,
JSHandle<EcmaString>(thread, EcmaString::Cast(ref->GetValue())), test), 0);
}
// String.fromCharCode(65, 66, 67)
@ -134,10 +133,8 @@ HWTEST_F_L0(BuiltinsStringTest, fromCharCode1)
ASSERT_TRUE(result.IsString());
JSTaggedValue value(static_cast<JSTaggedType>(result.GetRawData()));
JSHandle<JSTaggedValue> valueHandle(thread, JSTaggedValue(value.GetTaggedObject()));
JSTaggedValue test = factory->NewFromASCII("ABC").GetTaggedValue();
ASSERT_EQ(EcmaStringAccessor::Compare(EcmaString::Cast(valueHandle->GetTaggedObject()),
reinterpret_cast<EcmaString *>(test.GetRawData())),
0);
JSHandle<EcmaString> test = factory->NewFromASCII("ABC");
ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle<EcmaString>::Cast(valueHandle), test), 0);
}
// String.fromCodePoint(65, 66, 67)
@ -159,8 +156,8 @@ HWTEST_F_L0(BuiltinsStringTest, fromCodePoint1)
JSTaggedValue result = BuiltinsString::FromCodePoint(ecmaRuntimeCallInfo);
ASSERT_TRUE(result.IsString());
JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
JSTaggedValue test = factory->NewFromASCII("ABC").GetTaggedValue();
ASSERT_EQ(EcmaStringAccessor::Compare(*resultHandle, reinterpret_cast<EcmaString *>(test.GetRawData())), 0);
JSHandle<EcmaString> test = factory->NewFromASCII("ABC");
ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0);
}
// "abcabcabc".charAt(5)
@ -178,8 +175,8 @@ HWTEST_F_L0(BuiltinsStringTest, charAt1)
JSTaggedValue result = BuiltinsString::CharAt(ecmaRuntimeCallInfo);
ASSERT_TRUE(result.IsString());
JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
JSTaggedValue test = factory->NewFromASCII("c").GetTaggedValue();
ASSERT_EQ(EcmaStringAccessor::Compare(*resultHandle, reinterpret_cast<EcmaString *>(test.GetRawData())), 0);
JSHandle<EcmaString> test = factory->NewFromASCII("c");
ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0);
}
// "一二三四".charAt(2)
@ -197,8 +194,8 @@ HWTEST_F_L0(BuiltinsStringTest, charAt2)
JSTaggedValue result = BuiltinsString::CharAt(ecmaRuntimeCallInfo);
ASSERT_TRUE(result.IsString());
JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
JSTaggedValue test = factory->NewFromUtf8("").GetTaggedValue();
ASSERT_EQ(EcmaStringAccessor::Compare(*resultHandle, reinterpret_cast<EcmaString *>(test.GetRawData())), 0);
JSHandle<EcmaString> test = factory->NewFromUtf8("");
ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0);
}
// "abcabcabc".charAt(-1)
@ -216,8 +213,8 @@ HWTEST_F_L0(BuiltinsStringTest, charAt3)
JSTaggedValue result = BuiltinsString::CharAt(ecmaRuntimeCallInfo);
ASSERT_TRUE(result.IsString());
JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
JSTaggedValue test = factory->GetEmptyString().GetTaggedValue();
ASSERT_EQ(EcmaStringAccessor::Compare(*resultHandle, reinterpret_cast<EcmaString *>(test.GetRawData())), 0);
JSHandle<EcmaString> test = factory->GetEmptyString();
ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0);
}
// "ABC".charCodeAt(0)
@ -292,8 +289,8 @@ HWTEST_F_L0(BuiltinsStringTest, concat1)
JSTaggedValue result = BuiltinsString::Concat(ecmaRuntimeCallInfo);
ASSERT_TRUE(result.IsString());
JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
JSTaggedValue test = factory->NewFromASCII("abcd").GetTaggedValue();
ASSERT_EQ(EcmaStringAccessor::Compare(*resultHandle, reinterpret_cast<EcmaString *>(test.GetRawData())), 0);
JSHandle<EcmaString> test = factory->NewFromASCII("abcd");
ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0);
}
// "abcabcabc".indexof('b')
@ -585,8 +582,8 @@ HWTEST_F_L0(BuiltinsStringTest, toLocaleLowerCase2)
JSTaggedValue result = BuiltinsString::ToLocaleLowerCase(ecmaRuntimeCallInfo);
ASSERT_TRUE(result.IsString());
JSHandle<EcmaString> result_handle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
JSTaggedValue test = factory->NewFromUtf8("有abc").GetTaggedValue();
ASSERT_EQ(EcmaStringAccessor::Compare(*result_handle, reinterpret_cast<EcmaString *>(test.GetRawData())), 0);
JSHandle<EcmaString> test = factory->NewFromUtf8("有abc");
ASSERT_EQ(EcmaStringAccessor::Compare(instance, result_handle, test), 0);
}
// "ABC".toLowerCase()
@ -621,8 +618,8 @@ HWTEST_F_L0(BuiltinsStringTest, toUpperCase1)
JSTaggedValue result = BuiltinsString::ToUpperCase(ecmaRuntimeCallInfo);
ASSERT_TRUE(result.IsString());
JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
JSTaggedValue test = factory->NewFromASCII("ABC").GetTaggedValue();
ASSERT_EQ(EcmaStringAccessor::Compare(*resultHandle, reinterpret_cast<EcmaString *>(test.GetRawData())), 0);
JSHandle<EcmaString> test = factory->NewFromASCII("ABC");
ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0);
}
// "abc".localecompare('b')
@ -719,8 +716,8 @@ HWTEST_F_L0(BuiltinsStringTest, normalize1)
JSTaggedValue result = BuiltinsString::Normalize(ecmaRuntimeCallInfo);
ASSERT_TRUE(result.IsString());
JSHandle<EcmaString> result_handle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
JSTaggedValue test = factory->NewFromASCII("abc").GetTaggedValue();
ASSERT_EQ(EcmaStringAccessor::Compare(*result_handle, reinterpret_cast<EcmaString *>(test.GetRawData())), 0);
JSHandle<EcmaString> test = factory->NewFromASCII("abc");
ASSERT_EQ(EcmaStringAccessor::Compare(instance, result_handle, test), 0);
}
// "abc".repeat(5)
@ -738,8 +735,8 @@ HWTEST_F_L0(BuiltinsStringTest, repeat1)
JSTaggedValue result = BuiltinsString::Repeat(ecmaRuntimeCallInfo);
ASSERT_TRUE(result.IsString());
JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
JSTaggedValue test = factory->NewFromASCII("abcabcabcabcabc").GetTaggedValue();
ASSERT_EQ(EcmaStringAccessor::Compare(*resultHandle, reinterpret_cast<EcmaString *>(test.GetRawData())), 0);
JSHandle<EcmaString> test = factory->NewFromASCII("abcabcabcabcabc");
ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0);
}
// 'The morning is upon us.'.slice(4, -2)
@ -758,8 +755,8 @@ HWTEST_F_L0(BuiltinsStringTest, slice1)
JSTaggedValue result = BuiltinsString::Slice(ecmaRuntimeCallInfo);
ASSERT_TRUE(result.IsString());
JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
JSTaggedValue test = factory->NewFromASCII("morning is upon u").GetTaggedValue();
ASSERT_EQ(EcmaStringAccessor::Compare(*resultHandle, reinterpret_cast<EcmaString *>(test.GetRawData())), 0);
JSHandle<EcmaString> test = factory->NewFromASCII("morning is upon u");
ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0);
}
// 'The morning is upon us.'.slice(12)
@ -777,8 +774,8 @@ HWTEST_F_L0(BuiltinsStringTest, slice2)
JSTaggedValue result = BuiltinsString::Slice(ecmaRuntimeCallInfo);
ASSERT_TRUE(result.IsString());
JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
JSTaggedValue test = factory->NewFromASCII("is upon us.").GetTaggedValue();
ASSERT_EQ(EcmaStringAccessor::Compare(*resultHandle, reinterpret_cast<EcmaString *>(test.GetRawData())), 0);
JSHandle<EcmaString> test = factory->NewFromASCII("is upon us.");
ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0);
}
// 'Mozilla'.substring(3, -3)
@ -797,8 +794,8 @@ HWTEST_F_L0(BuiltinsStringTest, substring1)
JSTaggedValue result = BuiltinsString::Substring(ecmaRuntimeCallInfo);
ASSERT_TRUE(result.IsString());
JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
JSTaggedValue test = factory->NewFromASCII("Moz").GetTaggedValue();
ASSERT_EQ(EcmaStringAccessor::Compare(*resultHandle, reinterpret_cast<EcmaString *>(test.GetRawData())), 0);
JSHandle<EcmaString> test = factory->NewFromASCII("Moz");
ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0);
}
// 'Mozilla'.substring(7, 4)
@ -817,8 +814,8 @@ HWTEST_F_L0(BuiltinsStringTest, substring2)
JSTaggedValue result = BuiltinsString::Substring(ecmaRuntimeCallInfo);
ASSERT_TRUE(result.IsString());
JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
JSTaggedValue test = factory->NewFromASCII("lla").GetTaggedValue();
ASSERT_EQ(EcmaStringAccessor::Compare(*resultHandle, reinterpret_cast<EcmaString *>(test.GetRawData())), 0);
JSHandle<EcmaString> test = factory->NewFromASCII("lla");
ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0);
}
// " Hello world! ".trim()
@ -835,8 +832,8 @@ HWTEST_F_L0(BuiltinsStringTest, trim1)
JSTaggedValue result = BuiltinsString::Trim(ecmaRuntimeCallInfo);
ASSERT_TRUE(result.IsString());
JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
JSTaggedValue test = factory->NewFromASCII("Hello world!").GetTaggedValue();
ASSERT_EQ(EcmaStringAccessor::Compare(*resultHandle, reinterpret_cast<EcmaString *>(test.GetRawData())), 0);
JSHandle<EcmaString> test = factory->NewFromASCII("Hello world!");
ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0);
}
HWTEST_F_L0(BuiltinsStringTest, trim2)
@ -858,8 +855,8 @@ HWTEST_F_L0(BuiltinsStringTest, trim2)
JSTaggedValue result = BuiltinsString::Trim(ecmaRuntimeCallInfo);
ASSERT_TRUE(result.IsString());
JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
JSTaggedValue test = factory->NewFromASCII("Hello world!").GetTaggedValue();
ASSERT_EQ(EcmaStringAccessor::Compare(*resultHandle, reinterpret_cast<EcmaString *>(test.GetRawData())), 0);
JSHandle<EcmaString> test = factory->NewFromASCII("Hello world!");
ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0);
}
HWTEST_F_L0(BuiltinsStringTest, ToString)

View File

@ -81,8 +81,8 @@ HWTEST_F_L0(BuiltinsSymbolTest, SymbolNoParameterToString)
JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
ASSERT_TRUE(result.IsString());
auto symbolValue = ecmascript::base::BuiltinsBase::GetTaggedString(thread, "Symbol()");
ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast<EcmaString *>(symbolValue.GetRawData()), *resultHandle), 0);
auto symbolValue = ecmaVM->GetFactory()->NewFromASCII("Symbol()");
ASSERT_EQ(EcmaStringAccessor::Compare(ecmaVM, symbolValue, resultHandle), 0);
}
// new Symbol("aaa").toString()
@ -101,8 +101,8 @@ HWTEST_F_L0(BuiltinsSymbolTest, SymbolWithParameterToString)
JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
ASSERT_TRUE(result.IsString());
auto symbolValue = ecmascript::base::BuiltinsBase::GetTaggedString(thread, "Symbol(aaa)");
ASSERT_EQ(EcmaStringAccessor::Compare(reinterpret_cast<EcmaString *>(symbolValue.GetRawData()), *resultHandle), 0);
auto symbolValue = ecmaVM->GetFactory()->NewFromASCII("Symbol(aaa)");
ASSERT_EQ(EcmaStringAccessor::Compare(ecmaVM, symbolValue, resultHandle), 0);
}
// new Symbol().valueOf()
@ -307,7 +307,7 @@ HWTEST_F_L0(BuiltinsSymbolTest, SymbolConstructor)
TestHelper::TearDownFrame(thread, prev);
JSHandle<EcmaString> resultString = JSTaggedValue::ToString(
thread, JSHandle<JSTaggedValue>(thread, reinterpret_cast<JSSymbol *>(result1.GetRawData())->GetDescription()));
ASSERT_EQ(EcmaStringAccessor::Compare(*resultString, *string), 0);
ASSERT_EQ(EcmaStringAccessor::Compare(ecmaVM, resultString, string), 0);
}
HWTEST_F_L0(BuiltinsSymbolTest, SymbolGetter)

View File

@ -87,7 +87,7 @@ int Main(const int argc, const char **argv)
std::string logOption = runtimeOptions.GetCompilerLogOption();
std::string logMethodsList = runtimeOptions.GetMethodsListForLog();
bool compilerLogTime = runtimeOptions.IsEnableCompilerLogTime();
bool isEnableBcTrace = runtimeOptions.IsEnableByteCodeTrace();
bool isTraceBC = runtimeOptions.IsTraceBC();
size_t maxAotMethodSize = runtimeOptions.GetMaxAotMethodSize();
bool isEnableTypeLowering = runtimeOptions.IsEnableTypeLowering();
uint32_t hotnessThreshold = runtimeOptions.GetPGOHotnessThreshold();
@ -95,7 +95,7 @@ int Main(const int argc, const char **argv)
CommonStubCSigns::Initialize();
RuntimeStubCSigns::Initialize();
CompilerLog log(logOption, isEnableBcTrace);
CompilerLog log(logOption, isTraceBC);
log.SetEnableCompilerLogTime(compilerLogTime);
AotMethodLogList logList(logMethodsList);
AOTFileGenerator generator(&log, &logList, vm);

View File

@ -14,7 +14,7 @@
*/
#include "ecmascript/compiler/assembler/x64/extended_assembler_x64.h"
#include "ecmascript/calleeReg.h"
#include "ecmascript/deoptimizer/calleeReg.h"
#include "ecmascript/frames.h"
namespace panda::ecmascript::x64 {

View File

@ -32,7 +32,7 @@ GateRef BuiltinsStringStubBuilder::StringAt(GateRef obj, GateRef index)
Label doIntOp(env);
Label leftIsNumber(env);
Label rightIsNumber(env);
GateRef dataUtf16 = PtrAdd(obj, IntPtr(EcmaString::DATA_OFFSET));
GateRef dataUtf16 = PtrAdd(obj, IntPtr(LineEcmaString::DATA_OFFSET));
Branch(IsUtf16String(obj), &isUtf16, &isUtf8);
Bind(&isUtf16);
{
@ -65,7 +65,7 @@ GateRef BuiltinsStringStubBuilder::CreateFromEcmaString(GateRef glue, GateRef ob
Label isUtf16(env);
Label isUtf8(env);
Label allocString(env);
GateRef dataUtf = PtrAdd(obj, IntPtr(EcmaString::DATA_OFFSET));
GateRef dataUtf = PtrAdd(obj, IntPtr(LineEcmaString::DATA_OFFSET));
Branch(IsUtf16String(obj), &isUtf16, &isUtf8);
Bind(&isUtf16);
{
@ -91,17 +91,17 @@ GateRef BuiltinsStringStubBuilder::CreateFromEcmaString(GateRef glue, GateRef ob
Branch(*canBeCompressed, &isUtf8Next, &isUtf16Next);
Bind(&isUtf8Next);
{
newBuilder.AllocStringObject(&result, &afterNew, Int32(1), true);
newBuilder.AllocLineStringObject(&result, &afterNew, Int32(1), true);
}
Bind(&isUtf16Next);
{
newBuilder.AllocStringObject(&result, &afterNew, Int32(1), false);
newBuilder.AllocLineStringObject(&result, &afterNew, Int32(1), false);
}
Bind(&afterNew);
{
Label isUtf8Copy(env);
Label isUtf16Copy(env);
GateRef dst = PtrAdd(*result, IntPtr(EcmaString::DATA_OFFSET));
GateRef dst = PtrAdd(*result, IntPtr(LineEcmaString::DATA_OFFSET));
Branch(*canBeCompressed, &isUtf8Copy, &isUtf16Copy);
Bind(&isUtf8Copy);
{
@ -144,12 +144,12 @@ GateRef BuiltinsStringStubBuilder::FastSubUtf8String(GateRef glue, GateRef thisV
NewObjectStubBuilder newBuilder(this);
newBuilder.SetParameters(glue, 0);
Label afterNew(env);
newBuilder.AllocStringObject(&result, &afterNew, len, true);
newBuilder.AllocLineStringObject(&result, &afterNew, len, true);
Bind(&afterNew);
{
GateRef dst = PtrAdd(*result, IntPtr(EcmaString::DATA_OFFSET));
GateRef source = PtrAdd(PtrAdd(thisValue, IntPtr(EcmaString::DATA_OFFSET)), ZExtInt32ToPtr(from));
StringCopy(glue, dst, source, len, IntPtr(sizeof(uint8_t)), VariableType::INT8());
GateRef dst = PtrAdd(*result, IntPtr(LineEcmaString::DATA_OFFSET));
GateRef source = PtrAdd(PtrAdd(thisValue, IntPtr(LineEcmaString::DATA_OFFSET)), ZExtInt32ToPtr(from));
CopyChars(glue, dst, source, len, IntPtr(sizeof(uint8_t)), VariableType::INT8());
Jump(&exit);
}
}
@ -184,7 +184,7 @@ GateRef BuiltinsStringStubBuilder::FastSubUtf16String(GateRef glue, GateRef this
Bind(&lenNotEqualZero);
{
GateRef fromOffset = PtrMul(ZExtInt32ToPtr(from), IntPtr(sizeof(uint16_t) / sizeof(uint8_t)));
GateRef source = PtrAdd(PtrAdd(thisValue, IntPtr(EcmaString::DATA_OFFSET)), fromOffset);
GateRef source = PtrAdd(PtrAdd(thisValue, IntPtr(LineEcmaString::DATA_OFFSET)), fromOffset);
GateRef canBeCompressed = CanBeCompressed(source, len, true);
NewObjectStubBuilder newBuilder(this);
newBuilder.SetParameters(glue, 0);
@ -192,16 +192,16 @@ GateRef BuiltinsStringStubBuilder::FastSubUtf16String(GateRef glue, GateRef this
Branch(canBeCompressed, &isUtf8, &isUtf16);
Bind(&isUtf8);
{
newBuilder.AllocStringObject(&result, &afterNew, len, true);
newBuilder.AllocLineStringObject(&result, &afterNew, len, true);
}
Bind(&isUtf16);
{
newBuilder.AllocStringObject(&result, &afterNew, len, false);
newBuilder.AllocLineStringObject(&result, &afterNew, len, false);
}
Bind(&afterNew);
{
GateRef source1 = PtrAdd(PtrAdd(thisValue, IntPtr(EcmaString::DATA_OFFSET)), fromOffset);
GateRef dst = PtrAdd(*result, IntPtr(EcmaString::DATA_OFFSET));
GateRef source1 = PtrAdd(PtrAdd(thisValue, IntPtr(LineEcmaString::DATA_OFFSET)), fromOffset);
GateRef dst = PtrAdd(*result, IntPtr(LineEcmaString::DATA_OFFSET));
Branch(canBeCompressed, &isUtf8Next, &isUtf16Next);
Bind(&isUtf8Next);
{
@ -210,7 +210,7 @@ GateRef BuiltinsStringStubBuilder::FastSubUtf16String(GateRef glue, GateRef this
}
Bind(&isUtf16Next);
{
StringCopy(glue, dst, source1, len, IntPtr(sizeof(uint16_t)), VariableType::INT16());
CopyChars(glue, dst, source1, len, IntPtr(sizeof(uint16_t)), VariableType::INT16());
Jump(&exit);
}
}
@ -221,7 +221,7 @@ GateRef BuiltinsStringStubBuilder::FastSubUtf16String(GateRef glue, GateRef this
return ret;
}
void BuiltinsStringStubBuilder::StringCopy(GateRef glue, GateRef dst, GateRef source,
void BuiltinsStringStubBuilder::CopyChars(GateRef glue, GateRef dst, GateRef source,
GateRef sourceLength, GateRef size, VariableType type)
{
auto env = GetEnvironment();
@ -520,8 +520,8 @@ GateRef BuiltinsStringStubBuilder::StringIndexOf(GateRef lhs, GateRef rhs, GateR
Branch(Int32LessThan(max, Int32(0)), &exit, &maxNotLessZero);
Bind(&maxNotLessZero);
{
GateRef rhsData = PtrAdd(rhs, IntPtr(EcmaString::DATA_OFFSET));
GateRef lhsData = PtrAdd(lhs, IntPtr(EcmaString::DATA_OFFSET));
GateRef rhsData = PtrAdd(rhs, IntPtr(LineEcmaString::DATA_OFFSET));
GateRef lhsData = PtrAdd(lhs, IntPtr(LineEcmaString::DATA_OFFSET));
Branch(IsUtf8String(rhs), &rhsIsUtf8, &rhsIsUtf16);
Bind(&rhsIsUtf8);
{

View File

@ -30,7 +30,7 @@ public:
GateRef StringAt(GateRef obj, GateRef index);
GateRef FastSubUtf8String(GateRef glue, GateRef thisValue, GateRef from, GateRef len);
GateRef FastSubUtf16String(GateRef glue, GateRef thisValue, GateRef from, GateRef len);
void StringCopy(GateRef glue, GateRef dst, GateRef source, GateRef sourceLength, GateRef size, VariableType type);
void CopyChars(GateRef glue, GateRef dst, GateRef source, GateRef sourceLength, GateRef size, VariableType type);
void CopyUtf16AsUtf8(GateRef glue, GateRef src, GateRef dst, GateRef sourceLength);
GateRef StringIndexOf(GateRef lhsData, bool lhsIsUtf8, GateRef rhsData, bool rhsIsUtf8,
GateRef pos, GateRef max, GateRef rhsCount);

View File

@ -56,7 +56,7 @@ void BytecodeCircuitBuilder::CollectRegionInfo(uint32_t bcIndex)
{
auto pc = pcOffsets_[bcIndex];
auto &info = infoData_[bcIndex];
int32_t offset;
int32_t offset = 0;
if (info.IsJump()) {
switch (info.GetOpcode()) {
case EcmaOpcode::JEQZ_IMM8:

View File

@ -593,9 +593,17 @@ GateRef CircuitBuilder::IsJSObject(GateRef obj)
return LogicAnd(TaggedIsHeapObject(obj), ret);
}
GateRef CircuitBuilder::TaggedObjectIsString(GateRef obj)
{
GateRef objectType = GetObjectType(LoadHClass(obj));
return BoolAnd(
Int32LessThanOrEqual(objectType, Int32(static_cast<int32_t>(JSType::STRING_LAST))),
Int32GreaterThanOrEqual(objectType, Int32(static_cast<int32_t>(JSType::STRING_FIRST))));
}
GateRef CircuitBuilder::TaggedObjectBothAreString(GateRef x, GateRef y)
{
return BoolAnd(IsJsType(x, JSType::STRING), IsJsType(y, JSType::STRING));
return BoolAnd(TaggedObjectIsString(x), TaggedObjectIsString(y));
}
GateRef CircuitBuilder::IsCallableFromBitField(GateRef bitfield)

View File

@ -534,8 +534,7 @@ GateRef CircuitBuilder::TaggedIsString(GateRef obj)
Branch(TaggedIsHeapObject(obj), &isHeapObject, &exit);
Bind(&isHeapObject);
{
result = Equal(GetObjectType(LoadHClass(obj)),
Int32(static_cast<int32_t>(JSType::STRING)));
result = TaggedObjectIsString(obj);
Jump(&exit);
}
Bind(&exit);
@ -554,13 +553,13 @@ GateRef CircuitBuilder::TaggedIsStringOrSymbol(GateRef obj)
Branch(TaggedIsHeapObject(obj), &isHeapObject, &exit);
Bind(&isHeapObject);
{
GateRef objType = GetObjectType(LoadHClass(obj));
result = Equal(objType, Int32(static_cast<int32_t>(JSType::STRING)));
result = TaggedObjectIsString(obj);
Label isString(env_);
Label notString(env_);
Branch(*result, &exit, &notString);
Bind(&notString);
{
GateRef objType = GetObjectType(LoadHClass(obj));
result = Equal(objType, Int32(static_cast<int32_t>(JSType::SYMBOL)));
Jump(&exit);
}
@ -691,6 +690,31 @@ GateRef CircuitBuilder::GetObjectFromConstPool(GateRef glue, GateRef constPool,
return ret;
}
GateRef CircuitBuilder::TryGetHashcodeFromString(GateRef string)
{
Label subentry(env_);
SubCfgEntry(&subentry);
Label noRawHashcode(env_);
Label storeHash(env_);
Label exit(env_);
DEFVAlUE(result, env_, VariableType::INT64(), Int64(-1));
GateRef hashCode = ZExtInt32ToInt64(Load(VariableType::INT32(), string, IntPtr(EcmaString::HASHCODE_OFFSET)));
Branch(Int64Equal(hashCode, Int64(0)), &noRawHashcode, &storeHash);
Bind(&noRawHashcode);
{
GateRef length = GetLengthFromString(string);
Label lengthNotZero(env_);
Branch(Int32Equal(length, Int32(0)), &storeHash, &exit);
}
Bind(&storeHash);
result = hashCode;
Jump(&exit);
Bind(&exit);
auto ret = *result;
SubCfgExit();
return ret;
}
GateRef CircuitBuilder::GetHashcodeFromString(GateRef glue, GateRef value)
{
Label subentry(env_);

View File

@ -134,8 +134,8 @@ public:
TRIPLE_ARM32,
};
explicit CompilationConfig(const std::string &triple, bool enablePGOProfiler = false, bool isEnableBcTrace = false)
: triple_(GetTripleFromString(triple)), isEnableBcTrace_(isEnableBcTrace), enablePGOProfiler_(enablePGOProfiler)
CompilationConfig(const std::string &triple, bool enablePGOProfiler = false, bool isTraceBC = false)
: triple_(GetTripleFromString(triple)), isTraceBc_(isTraceBC), enablePGOProfiler_(enablePGOProfiler)
{
}
~CompilationConfig() = default;
@ -165,9 +165,9 @@ public:
return triple_;
}
bool IsEnableByteCodeTrace() const
bool IsTraceBC() const
{
return isEnableBcTrace_;
return isTraceBc_;
}
bool IsEnablePGOProfiler() const
@ -192,7 +192,7 @@ private:
UNREACHABLE();
}
Triple triple_;
bool isEnableBcTrace_;
bool isTraceBc_;
bool enablePGOProfiler_;
};
@ -434,6 +434,7 @@ public:
inline GateRef IsExtensible(GateRef object);
inline GateRef TaggedObjectIsEcmaObject(GateRef obj);
inline GateRef IsJSObject(GateRef obj);
inline GateRef TaggedObjectIsString(GateRef obj);
inline GateRef TaggedObjectBothAreString(GateRef x, GateRef y);
inline GateRef IsCallable(GateRef obj);
inline GateRef IsCallableFromBitField(GateRef bitfield);
@ -448,6 +449,7 @@ public:
GateRef FunctionIsResolved(GateRef function);
GateRef GetLengthFromString(GateRef value);
GateRef GetHashcodeFromString(GateRef glue, GateRef value);
GateRef TryGetHashcodeFromString(GateRef string);
GateRef IsUtf16String(GateRef string);
GateRef TaggedIsBigInt(GateRef obj);
void SetLexicalEnvToFunction(GateRef glue, GateRef function, GateRef value);

View File

@ -22,6 +22,7 @@
namespace panda::ecmascript::kungfu {
using ControlFlowGraph = std::vector<std::vector<GateRef>>;
class CodeGeneratorImpl {
public:
CodeGeneratorImpl() = default;

View File

@ -324,7 +324,7 @@ void TryLoadICByValueStubBuilder::GenerateCircuit()
&hclassEqualFirstValue,
&hclassNotEqualFirstValue);
Bind(&hclassEqualFirstValue);
Return(LoadElement(receiver, key));
Return(LoadElement(glue, receiver, key));
Bind(&hclassNotEqualFirstValue);
{
Branch(Int64Equal(firstValue, key), &firstValueEqualKey, &receiverNotHeapObject);

View File

@ -16,7 +16,7 @@
#include "ecmascript/compiler/compiler_log.h"
namespace panda::ecmascript::kungfu {
CompilerLog::CompilerLog(const std::string &logOpt, bool enableBCTrace)
CompilerLog::CompilerLog(const std::string &logOpt, bool TraceBC)
{
outputCIR_ = logOpt.find("cir") != std::string::npos ||
logOpt.find("0") != std::string::npos;
@ -31,7 +31,7 @@ CompilerLog::CompilerLog(const std::string &logOpt, bool enableBCTrace)
logOpt.find("cer") != std::string::npos;
noneMethod_ = logOpt.find("all") == std::string::npos &&
logOpt.find("cer") == std::string::npos;
enableBCTrace_ = enableBCTrace;
traceBc_ = TraceBC;
}
bool MethodLogList::IncludesMethod(const std::string &methodName) const

View File

@ -30,7 +30,7 @@
namespace panda::ecmascript::kungfu {
class CompilerLog {
public:
explicit CompilerLog(const std::string &logOpt, bool enableBCTrace = false);
explicit CompilerLog(const std::string &logOpt, bool TraceBC = false);
~CompilerLog() = default;
bool AllMethod() const
@ -68,9 +68,9 @@ public:
return outputType_;
}
bool IsEnableByteCodeTrace() const
bool IsTraceBC() const
{
return enableBCTrace_;
return traceBc_;
}
bool GetEnableCompilerLogTime() const
@ -120,7 +120,7 @@ private:
bool outputLLIR_ {false};
bool outputASM_ {false};
bool outputType_ {false};
bool enableBCTrace_ {false};
bool traceBc_ {false};
bool compilerLogTime_ {true};
bool enableMethodLog_ {false};
std::map<std::string, double> timePassMap_ {};

View File

@ -37,6 +37,7 @@ public:
const ConstUseIterator operator++()
{
ASSERT(out_ != nullptr);
if (!out_->IsNextOutNull()) {
out_ = out_->GetNextOutConst();
return *this;
@ -93,6 +94,7 @@ public:
const UseIterator& operator++()
{
ASSERT(out_ != nullptr);
out_ = out_->IsNextOutNull() ? nullptr
: out_->GetNextOut();
return *this;

View File

@ -145,7 +145,7 @@ void ICStubBuilder::LoadICByValue(Variable* result, Label* tryFastPath, Label *s
ValuedICAccessor(&cachedHandler, &loadWithHandler, &loadElement);
Bind(&loadElement);
{
GateRef ret = LoadElement(receiver_, propKey_);
GateRef ret = LoadElement(glue_, receiver_, propKey_);
result->WriteVariable(ret);
Branch(TaggedIsHole(ret), slowPath_, success_);
}

View File

@ -692,7 +692,6 @@ GateRef InterpreterToolsStubBuilder::GetStringId(const StringIdInfo &info)
if (info.length == StringIdInfo::Length::BITS_16) {
stringId = ZExtInt16ToInt32(ReadInst16_0(info.pc));
} else {
stringId = 0;
std::abort();
}
break;
@ -703,7 +702,6 @@ GateRef InterpreterToolsStubBuilder::GetStringId(const StringIdInfo &info)
} else if (info.length == StringIdInfo::Length::BITS_32) {
stringId = ReadInst32_1(info.pc);
} else {
stringId = 0;
std::abort();
}
break;
@ -712,13 +710,11 @@ GateRef InterpreterToolsStubBuilder::GetStringId(const StringIdInfo &info)
if (info.length == StringIdInfo::Length::BITS_16) {
stringId = ZExtInt16ToInt32(ReadInst16_2(info.pc));
} else {
stringId = 0;
std::abort();
}
break;
}
default: {
stringId = 0;
std::abort();
break;
}

View File

@ -22,7 +22,7 @@
#include "ecmascript/compiler/common_stubs.h"
#include "ecmascript/compiler/gate.h"
#include "ecmascript/compiler/rt_call_signature.h"
#include "ecmascript/deoptimizer.h"
#include "ecmascript/deoptimizer/deoptimizer.h"
#include "ecmascript/frames.h"
#include "ecmascript/js_thread.h"
#include "ecmascript/method.h"
@ -314,7 +314,7 @@ BasicBlockImpl *LLVMIRBuilder::EnsureBBImpl(BasicBlock *bb) const
return bb->GetImpl<BasicBlockImpl>();
}
void LLVMIRBuilder::GenPrologue([[maybe_unused]] LLVMModuleRef &module, LLVMBuilderRef &builder)
void LLVMIRBuilder::GenPrologue()
{
if (compCfg_->Is32Bit()) {
return;
@ -325,25 +325,41 @@ void LLVMIRBuilder::GenPrologue([[maybe_unused]] LLVMModuleRef &module, LLVMBuil
}
LLVMAddTargetDependentFunctionAttr(function_, "frame-pointer", "all");
LLVMValueRef llvmFpAddr = CallingFp(module_, builder_, false);
LLVMValueRef frameAddr = LLVMBuildPtrToInt(builder, llvmFpAddr, slotType_, "cast_int_t");
LLVMValueRef frameTypeSlotAddr = LLVMBuildSub(builder, frameAddr, LLVMConstInt(slotType_, slotSize_, false), "");
LLVMValueRef addr = LLVMBuildIntToPtr(builder, frameTypeSlotAddr, LLVMPointerType(slotType_, 0), "frameType.Addr");
int reservedSlotsSize = slotSize_ * static_cast<int>(ReservedSlots::OPTIMIZED_RESERVED_SLOT);
if (frameType == panda::ecmascript::FrameType::OPTIMIZED_FRAME) {
int reservedSlotsSize = 0;
if (frameType == FrameType::OPTIMIZED_FRAME) {
reservedSlotsSize = OptimizedFrame::ComputeReservedSize(slotSize_);
LLVMAddTargetDependentFunctionAttr(function_, "frame-reserved-slots",
std::to_string(reservedSlotsSize).c_str());
} else if (frameType == panda::ecmascript::FrameType::OPTIMIZED_JS_FUNCTION_FRAME) {
reservedSlotsSize = slotSize_ * static_cast<int>(ReservedSlots::OPTIMIZED_JS_FUNCTION_RESERVED_SLOT);
SaveFrameTypeOnFrame(frameType);
} else if (frameType == FrameType::OPTIMIZED_JS_FUNCTION_FRAME) {
reservedSlotsSize = OptimizedJSFunctionFrame::ComputeReservedJSFuncOffset(slotSize_);
LLVMAddTargetDependentFunctionAttr(function_, "frame-reserved-slots",
std::to_string(reservedSlotsSize).c_str());
auto ArgList = Circuit::GetCircuitRoot(OpCode(OpCode::ARG_LIST));
auto uses = acc_.Uses(ArgList);
for (auto useIt = uses.begin(); useIt != uses.end(); ++useIt) {
int argth = static_cast<int>(acc_.GetBitField(*useIt));
LLVMValueRef value = LLVMGetParam(function_, argth);
if (argth == static_cast<int>(CommonArgIdx::LEXENV)) {
SaveLexicalEnvOnOptJSFuncFrame(value);
} else if (argth == static_cast<int>(CommonArgIdx::FUNC)) {
SaveJSFuncOnOptJSFuncFrame(value);
SaveFrameTypeOnFrame(frameType);
}
}
} else {
LOG_COMPILER(FATAL) << "frameType interpret type error !";
ASSERT_PRINT(static_cast<uintptr_t>(frameType), "is not support !");
}
}
void LLVMIRBuilder::SaveFrameTypeOnFrame(FrameType frameType)
{
LLVMValueRef llvmFpAddr = CallingFp(module_, builder_, false);
LLVMValueRef frameAddr = LLVMBuildPtrToInt(builder_, llvmFpAddr, slotType_, "cast_int_t");
LLVMValueRef frameTypeSlotAddr = LLVMBuildSub(builder_, frameAddr, LLVMConstInt(slotType_, slotSize_, false), "");
LLVMValueRef addr = LLVMBuildIntToPtr(builder_, frameTypeSlotAddr, LLVMPointerType(slotType_, 0), "frameType.Addr");
LLVMValueRef llvmFrameType = LLVMConstInt(slotType_, static_cast<uintptr_t>(frameType), 0);
LLVMBuildStore(builder_, llvmFrameType, addr);
}
@ -917,7 +933,7 @@ void LLVMIRBuilder::LinkToLLVMCfg(int bbId, const OperandsVector &predecessors)
LLVMMoveBasicBlockBefore(preLBB, lBB);
}
if (isPrologue(bbId)) {
GenPrologue(module_, builder_);
GenPrologue();
}
}
@ -1049,28 +1065,36 @@ void LLVMIRBuilder::VisitParameter(GateRef gate)
gate2LValue_[gate] = value;
// NOTE: caller put args, otherwise crash
ASSERT(value != nullptr);
// add env slot for optimized jsfunction frame
auto frameType = circuit_->GetFrameType();
if (frameType == panda::ecmascript::FrameType::OPTIMIZED_JS_FUNCTION_FRAME) {
if (argth == static_cast<int>(CommonArgIdx::LEXENV)) {
SaveLexicalEnvOnFrame(value);
}
}
}
void LLVMIRBuilder::SaveLexicalEnvOnFrame(LLVMValueRef value)
void LLVMIRBuilder::SaveLexicalEnvOnOptJSFuncFrame(LLVMValueRef value)
{
ASSERT(circuit_->GetFrameType() == FrameType::OPTIMIZED_JS_FUNCTION_FRAME);
LLVMValueRef llvmFpAddr = CallingFp(module_, builder_, false);
LLVMValueRef frameAddr = LLVMBuildPtrToInt(builder_, llvmFpAddr, slotType_, "cast_int_t");
size_t reservedOffset = OptimizedJSFunctionFrame::ComputeReservedEnvOffset(slotSize_);
LLVMValueRef frameEnvSlotAddr = LLVMBuildSub(builder_, frameAddr, LLVMConstInt(slotType_,
static_cast<int>(ReservedSlots::OPTIMIZED_JS_FUNCTION_RESERVED_SLOT) * slotSize_, false), "");
reservedOffset, false), "");
LLVMValueRef envAddr = LLVMBuildIntToPtr(builder_, frameEnvSlotAddr,
LLVMPointerType(slotType_, 0), "env.Addr");
LLVMValueRef envValue = LLVMBuildPtrToInt(builder_, value, slotType_, "cast_to_i64");
LLVMBuildStore(builder_, envValue, envAddr);
}
void LLVMIRBuilder::SaveJSFuncOnOptJSFuncFrame(LLVMValueRef value)
{
ASSERT(circuit_->GetFrameType() == FrameType::OPTIMIZED_JS_FUNCTION_FRAME);
LLVMValueRef llvmFpAddr = CallingFp(module_, builder_, false);
LLVMValueRef frameAddr = LLVMBuildPtrToInt(builder_, llvmFpAddr, slotType_, "cast_int_t");
size_t reservedOffset = OptimizedJSFunctionFrame::ComputeReservedJSFuncOffset(slotSize_);
LLVMValueRef frameJSFuncSlotAddr = LLVMBuildSub(builder_, frameAddr, LLVMConstInt(slotType_,
reservedOffset, false), "");
LLVMValueRef jsFuncAddr = LLVMBuildIntToPtr(builder_, frameJSFuncSlotAddr,
LLVMPointerType(slotType_, 0), "jsfunc.Addr");
LLVMValueRef jsFuncValue = LLVMBuildPtrToInt(builder_, value, slotType_, "cast_to_i64");
LLVMBuildStore(builder_, jsFuncValue, jsFuncAddr);
}
void LLVMIRBuilder::HandleBranch(GateRef gate)
{
std::vector<GateRef> ins;
@ -1369,8 +1393,9 @@ void LLVMIRBuilder::VisitGetEnv(GateRef gate)
returnType = ConvertLLVMTypeFromGate(gate);
LLVMValueRef llvmFpAddr = CallingFp(module_, builder_, false);
LLVMValueRef frameAddr = LLVMBuildPtrToInt(builder_, llvmFpAddr, slotType_, "cast_int_t");
size_t reservedOffset = OptimizedJSFunctionFrame::ComputeReservedEnvOffset(slotSize_);
LLVMValueRef frameEnvSlotAddr = LLVMBuildSub(builder_, frameAddr, LLVMConstInt(slotType_,
static_cast<int>(ReservedSlots::OPTIMIZED_JS_FUNCTION_RESERVED_SLOT) * slotSize_, false), "");
reservedOffset, false), "");
LLVMValueRef envAddr = LLVMBuildIntToPtr(builder_, frameEnvSlotAddr, LLVMPointerType(slotType_, 0), "env.Addr");
envAddr = LLVMBuildPointerCast(builder_, envAddr,
LLVMPointerType(returnType, LLVMGetPointerAddressSpace(LLVMTypeOf(envAddr))), "");

View File

@ -263,7 +263,7 @@ private:
LLVMValueRef GetCurrentSP();
LLVMValueRef ReadRegister(LLVMModuleRef &module, LLVMBuilderRef &builder,
LLVMMetadataRef meta);
void GenPrologue(LLVMModuleRef &module, LLVMBuilderRef &builder);
void GenPrologue();
LLVMBasicBlockRef EnsureLBB(BasicBlock *bb) const;
BasicBlockImpl *EnsureBBImpl(BasicBlock *bb) const;
void SetToCfg(BasicBlock *bb) const;
@ -330,13 +330,15 @@ private:
CallExceptionKind GetCallExceptionKind(size_t index, OpCode op) const;
void ComputeArgCountAndBCOffset(size_t &actualNumArgs, LLVMValueRef &bcOffset, const std::vector<GateRef> &inList,
CallExceptionKind kind);
void SaveLexicalEnvOnFrame(LLVMValueRef value);
void SaveLexicalEnvOnOptJSFuncFrame(LLVMValueRef value);
void SaveJSFuncOnOptJSFuncFrame(LLVMValueRef value);
void SaveFrameTypeOnFrame(FrameType frameType);
LLVMTypeRef GetExperimentalDeoptTy();
LLVMValueRef GetExperimentalDeopt(LLVMModuleRef &module);
const CompilationConfig *compCfg_ {nullptr};
const std::vector<std::vector<GateRef>> *scheduledGates_ {nullptr};
const Circuit *circuit_ {nullptr};
const GateAccessor acc_;
GateAccessor acc_;
BasicBlock *currentBb_ {nullptr};
int lineNumber_ {0};

View File

@ -283,7 +283,7 @@ void NewObjectStubBuilder::InitializeTaggedArrayWithSpeicalValue(Label *exit,
InitializeWithSpeicalValue(exit, array, value, dataOffset, endOffset);
}
void NewObjectStubBuilder::AllocStringObject(Variable *result, Label *exit, GateRef length, bool compressed)
void NewObjectStubBuilder::AllocLineStringObject(Variable *result, Label *exit, GateRef length, bool compressed)
{
auto env = GetEnvironment();
if (compressed) {
@ -297,9 +297,9 @@ void NewObjectStubBuilder::AllocStringObject(Variable *result, Label *exit, Gate
AllocateInYoung(result, &afterAllocate);
Bind(&afterAllocate);
GateRef arrayClass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_,
ConstantIndex::STRING_CLASS_INDEX);
StoreHClass(glue_, result->ReadVariable(), arrayClass);
GateRef stringClass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_,
ConstantIndex::LINE_STRING_CLASS_INDEX);
StoreHClass(glue_, result->ReadVariable(), stringClass);
SetLength(glue_, result->ReadVariable(), length, compressed);
SetRawHashcode(glue_, result->ReadVariable(), Int32(0));
Jump(exit);

View File

@ -39,7 +39,7 @@ public:
void NewJSObject(Variable *result, Label *exit, GateRef hclass);
void NewArgumentsList(Variable *result, Label *exit, GateRef sp, GateRef startIdx, GateRef numArgs);
void NewArgumentsObj(Variable *result, Label *exit, GateRef argumentsList, GateRef numArgs);
void AllocStringObject(Variable *result, Label *exit, GateRef length, bool compressed);
void AllocLineStringObject(Variable *result, Label *exit, GateRef length, bool compressed);
void HeapAlloc(Variable *result, Label *exit, RegionSpaceFlag spaceType);
void NewJSArrayLiteral(Variable *result, Label *exit, RegionSpaceFlag spaceType, GateRef obj, GateRef hclass,
bool isEmptyArray);

View File

@ -33,6 +33,7 @@
namespace panda::ecmascript::kungfu {
class CompilationInfo;
class PassData {
public:
explicit PassData(BytecodeCircuitBuilder *builder, Circuit *circuit, CompilationInfo *info, CompilerLog *log,
@ -46,14 +47,15 @@ public:
}
virtual ~PassData() = default;
const ControlFlowGraph &GetScheduleResult() const
const ControlFlowGraph &GetConstScheduleResult() const
{
return cfg_;
}
void SetScheduleResult(const ControlFlowGraph &result)
ControlFlowGraph &GetCfg()
{
cfg_ = result;
return cfg_;
}
virtual Circuit* GetCircuit() const
@ -254,7 +256,7 @@ public:
{
TimeScope timescope("SchedulingPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
bool enableLog = data->GetLog()->EnableMethodCIRLog();
data->SetScheduleResult(Scheduler::Run(data->GetCircuit(), data->GetMethodName(), enableLog));
Scheduler::Run(data->GetCircuit(), data->GetCfg(), data->GetMethodName(), enableLog);
return true;
}
};
@ -273,7 +275,7 @@ public:
bool enableLog = data->GetLog()->EnableMethodCIRLog();
CreateCodeGen(module, enableLog);
CodeGenerator codegen(llvmImpl_, data->GetMethodName());
codegen.Run(data->GetCircuit(), data->GetScheduleResult(), module->GetCompilationConfig(),
codegen.Run(data->GetCircuit(), data->GetConstScheduleResult(), module->GetCompilationConfig(),
data->GetMethodLiteral(), data->GetJSPandaFile());
return true;
}

View File

@ -41,7 +41,7 @@ bool PassManager::Compile(const std::string &fileName, AOTFileGenerator &generat
auto aotModuleAssembler = new LLVMAssembler(aotModule->GetModule(),
LOptions(optLevel_, true, relocMode_));
CompilationConfig cmpCfg(triple_, false, log_->IsEnableByteCodeTrace());
CompilationConfig cmpCfg(triple_, false, log_->IsTraceBC());
Bytecodes bytecodes;
auto &bytecodeInfo = bcInfoCollector.GetBytecodeInfo();
auto lexEnvManager = LexEnvManager(bytecodeInfo);

View File

@ -12,12 +12,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ecmascript/compiler/scheduler.h"
#include <cmath>
#include <stack>
#include "ecmascript/compiler/gate_accessor.h"
#include "ecmascript/compiler/verifier.h"
#include "ecmascript/compiler/scheduler.h"
namespace panda::ecmascript::kungfu {
void Scheduler::CalculateDominatorTree(const Circuit *circuit,
@ -116,9 +116,8 @@ void Scheduler::CalculateDominatorTree(const Circuit *circuit,
}
}
std::vector<std::vector<GateRef>> Scheduler::Run(const Circuit *circuit,
[[maybe_unused]] const std::string& methodName,
[[maybe_unused]] bool enableLog)
void Scheduler::Run(const Circuit *circuit, ControlFlowGraph &result,
[[maybe_unused]] const std::string& methodName, [[maybe_unused]] bool enableLog)
{
#ifndef NDEBUG
if (!Verifier::Run(circuit, methodName, enableLog)) {
@ -130,7 +129,8 @@ std::vector<std::vector<GateRef>> Scheduler::Run(const Circuit *circuit,
std::unordered_map<GateRef, size_t> bbGatesAddrToIdx;
std::vector<size_t> immDom;
Scheduler::CalculateDominatorTree(circuit, bbGatesList, bbGatesAddrToIdx, immDom);
std::vector<std::vector<GateRef>> result(bbGatesList.size());
ASSERT(result.size() == 0);
result.resize(bbGatesList.size());
for (size_t idx = 0; idx < bbGatesList.size(); idx++) {
result[idx].push_back(bbGatesList[idx]);
}
@ -200,8 +200,8 @@ std::vector<std::vector<GateRef>> Scheduler::Run(const Circuit *circuit,
};
{
std::vector<GateRef> order;
auto lowerBound =
Scheduler::CalculateSchedulingLowerBound(circuit, bbGatesAddrToIdx, lowestCommonAncestor, &order).value();
std::unordered_map<GateRef, size_t> lowerBound;
Scheduler::CalculateSchedulingLowerBound(circuit, bbGatesAddrToIdx, lowestCommonAncestor, lowerBound, &order);
for (const auto &schedulableGate : order) {
result[lowerBound.at(schedulableGate)].push_back(schedulableGate);
}
@ -226,17 +226,15 @@ std::vector<std::vector<GateRef>> Scheduler::Run(const Circuit *circuit,
if (enableLog) {
Print(&result, circuit);
}
return result;
}
std::optional<std::unordered_map<GateRef, size_t>> Scheduler::CalculateSchedulingUpperBound(
const Circuit *circuit,
bool Scheduler::CalculateSchedulingUpperBound(const Circuit *circuit,
const std::unordered_map<GateRef, size_t> &bbGatesAddrToIdx,
const std::function<bool(size_t, size_t)> &isAncestor,
const std::vector<GateRef> &schedulableGatesList)
const std::vector<GateRef> &schedulableGatesList,
std::unordered_map<GateRef, size_t> &upperBound)
{
GateAccessor acc(const_cast<Circuit*>(circuit));
std::unordered_map<GateRef, size_t> upperBound;
struct DFSState {
GateRef curGate = Circuit::NullGate();
std::vector<GateRef> predGates;
@ -296,9 +294,7 @@ std::optional<std::unordered_map<GateRef, size_t>> Scheduler::CalculateSchedulin
}
auto predUpperBound = returnValue.value();
if (!isAncestor(curUpperBound, predUpperBound) && !isAncestor(predUpperBound, curUpperBound)) {
LOG_COMPILER(ERROR) << "[Verifier][Error] Scheduling upper bound of gate (id="
<< GateAccessor(const_cast<Circuit*>(circuit)).GetId(curGate)
<< ") does not exist";
PrintUpperBoundError(circuit, curGate, predUpperBound, curUpperBound);
returnValue = std::nullopt;
break;
}
@ -321,18 +317,30 @@ std::optional<std::unordered_map<GateRef, size_t>> Scheduler::CalculateSchedulin
}
}
if (!returnValue.has_value()) {
return std::nullopt;
return false;
}
}
return upperBound;
return true;
}
std::optional<std::unordered_map<GateRef, size_t>> Scheduler::CalculateSchedulingLowerBound(const Circuit *circuit,
void Scheduler::PrintUpperBoundError(const Circuit *circuit, GateRef curGate,
GateRef predUpperBound, GateRef curUpperBound)
{
GateAccessor ac(const_cast<Circuit*>(circuit));
LOG_COMPILER(ERROR) << "[Verifier][Error] Scheduling upper bound of gate (id="
<< ac.GetId(curGate)
<< ") does not exist, current-upper-bound = "
<< curUpperBound << ", pred-upper-bound = "
<< predUpperBound << ", there is no dominator relationship between them.";
}
void Scheduler::CalculateSchedulingLowerBound(const Circuit *circuit,
const std::unordered_map<GateRef, size_t> &bbGatesAddrToIdx,
const std::function<size_t(size_t, size_t)> &lowestCommonAncestor, std::vector<GateRef> *order)
const std::function<size_t(size_t, size_t)> &lowestCommonAncestor,
std::unordered_map<GateRef, size_t> &lowerBound,
std::vector<GateRef> *order)
{
GateAccessor acc(const_cast<Circuit*>(circuit));
std::unordered_map<GateRef, size_t> lowerBound;
std::unordered_map<GateRef, size_t> useCount;
std::vector<GateRef> bbAndFixedGatesList;
for (const auto &item : bbGatesAddrToIdx) {
@ -434,7 +442,6 @@ std::optional<std::unordered_map<GateRef, size_t>> Scheduler::CalculateSchedulin
++idx;
}
}
return lowerBound;
}
void Scheduler::Print(const std::vector<std::vector<GateRef>> *cfg, const Circuit *circuit)

View File

@ -27,18 +27,26 @@ public:
std::unordered_map<GateRef, size_t> &bbGatesAddrToIdx,
std::vector<size_t> &immDom);
static ControlFlowGraph Run(const Circuit *circuit, [[maybe_unused]] const std::string& methodName = "",
bool enableLog = false);
static void Run(const Circuit *circuit, ControlFlowGraph &result,
[[maybe_unused]] const std::string& methodName = "", bool enableLog = false);
static std::optional<std::unordered_map<GateRef, size_t>> CalculateSchedulingUpperBound(const Circuit *circuit,
static bool CalculateSchedulingUpperBound(const Circuit *circuit,
const std::unordered_map<GateRef, size_t> &bbGatesAddrToIdx,
const std::function<bool(size_t, size_t)> &isAncestor, const std::vector<GateRef> &schedulableGatesList);
const std::function<bool(size_t, size_t)> &isAncestor,
const std::vector<GateRef> &schedulableGatesList,
std::unordered_map<GateRef, size_t> &upperBound);
static std::optional<std::unordered_map<GateRef, size_t>> CalculateSchedulingLowerBound(const Circuit *circuit,
static void CalculateSchedulingLowerBound(const Circuit *circuit,
const std::unordered_map<GateRef, size_t> &bbGatesAddrToIdx,
const std::function<size_t(size_t, size_t)> &lowestCommonAncestor, std::vector<GateRef> *order = nullptr);
const std::function<size_t(size_t, size_t)> &lowestCommonAncestor,
std::unordered_map<GateRef, size_t> &lowerBound,
std::vector<GateRef> *order = nullptr);
static void Print(const ControlFlowGraph *cfg, const Circuit *circuit);
private:
static void PrintUpperBoundError(const Circuit *circuit, GateRef curGate,
GateRef predUpperBound, GateRef curUpperBound);
};
}; // namespace panda::ecmascript::kungfu

View File

@ -1692,9 +1692,17 @@ GateRef SlowPathLowering::FastStrictEqual(GateRef glue, GateRef left, GateRef ri
builder_.Branch(builder_.Equal(builder_.GetLengthFromString(left), builder_.GetLengthFromString(right)),
&hashcodeCompare, &exit);
builder_.Bind(&hashcodeCompare);
builder_.Branch(
builder_.Equal(builder_.GetHashcodeFromString(glue, left), builder_.GetHashcodeFromString(glue, right)),
&contentsCompare, &exit);
Label leftNotNeg(&builder_);
GateRef leftHash = builder_.TryGetHashcodeFromString(left);
GateRef rightHash = builder_.TryGetHashcodeFromString(right);
builder_.Branch(builder_.Equal(leftHash, builder_.Int64(-1)), &contentsCompare, &leftNotNeg);
builder_.Bind(&leftNotNeg);
{
Label rightNotNeg(&builder_);
builder_.Branch(builder_.Equal(rightHash, builder_.Int64(-1)), &contentsCompare, &rightNotNeg);
builder_.Bind(&rightNotNeg);
builder_.Branch(builder_.Equal(leftHash, rightHash), &contentsCompare, &exit);
}
builder_.Bind(&contentsCompare);
{
GateRef stringEqual = LowerCallRuntime(glue, RTSTUB_ID(StringEqual), { left, right }, true);
@ -3108,7 +3116,7 @@ void SlowPathLowering::LowerTypeof(GateRef gate, GateRef glue)
{
Label objIsString(&builder_);
Label objNotString(&builder_);
builder_.Branch(builder_.IsJsType(obj, JSType::STRING), &objIsString, &objNotString);
builder_.Branch(builder_.TaggedObjectIsString(obj), &objIsString, &objNotString);
builder_.Bind(&objIsString);
{
result = builder_.Load(VariableType::JS_POINTER(), gConstAddr,
@ -3381,7 +3389,7 @@ void SlowPathLowering::LowerWideStPatchVar(GateRef gate, GateRef glue)
void SlowPathLowering::DebugPrintBC(GateRef gate, GateRef glue)
{
if (enableBcTrace_) {
if (traceBc_) {
EcmaOpcode ecmaOpcode = acc_.GetByteCodeOpcode(gate);
auto ecmaOpcodeGate = builder_.Int32(static_cast<uint32_t>(ecmaOpcode));
GateRef constOpcode = builder_.ToTaggedInt(builder_.ZExtInt32ToInt64(ecmaOpcodeGate));

View File

@ -119,7 +119,7 @@ public:
dependEntry_(Circuit::GetCircuitRoot(OpCode(OpCode::DEPEND_ENTRY))),
enableLog_(enableLog), methodName_(name)
{
enableBcTrace_ = cmpCfg->IsEnableByteCodeTrace();
traceBc_ = cmpCfg->IsTraceBC();
}
~SlowPathLowering() = default;
void CallRuntimeLowering();
@ -129,9 +129,9 @@ public:
return enableLog_;
}
bool IsEnableByteCodeTrace() const
bool IsTraceBC() const
{
return enableBcTrace_;
return traceBc_;
}
private:
@ -300,7 +300,7 @@ private:
CircuitBuilder builder_;
GateRef dependEntry_;
bool enableLog_ {false};
bool enableBcTrace_ {false};
bool traceBc_ {false};
std::string methodName_;
};
} // panda::ecmascript::kungfu

View File

@ -1011,9 +1011,27 @@ inline GateRef StubBuilder::IsSymbol(GateRef obj)
}
inline GateRef StubBuilder::IsString(GateRef obj)
{
return env_->GetBuilder()->TaggedObjectIsString(obj);
}
inline GateRef StubBuilder::IsLineString(GateRef obj)
{
GateRef objectType = GetObjectType(LoadHClass(obj));
return Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::STRING)));
return Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::LINE_STRING)));
}
inline GateRef StubBuilder::IsTreeString(GateRef obj)
{
GateRef objectType = GetObjectType(LoadHClass(obj));
return Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::TREE_STRING)));
}
inline GateRef StubBuilder::TreeStringIsFlat(GateRef string)
{
GateRef second = GetSecondFromTreeString(string);
GateRef len = GetLengthFromString(second);
return Int32Equal(len, Int32(0));
}
inline GateRef StubBuilder::TaggedObjectIsBigInt(GateRef obj)
@ -1336,6 +1354,18 @@ inline GateRef StubBuilder::GetLengthFromString(GateRef value)
return Int32LSR(len, Int32(2)); // 2 : 2 means len must be right shift 2 bits
}
inline GateRef StubBuilder::GetFirstFromTreeString(GateRef string)
{
GateRef offset = IntPtr(TreeEcmaString::FIRST_OFFSET);
return Load(VariableType::JS_POINTER(), string, offset);
}
inline GateRef StubBuilder::GetSecondFromTreeString(GateRef string)
{
GateRef offset = IntPtr(TreeEcmaString::SECOND_OFFSET);
return Load(VariableType::JS_POINTER(), string, offset);
}
inline void StubBuilder::SetBitFieldToHClass(GateRef glue, GateRef hClass, GateRef bitfield)
{
GateRef offset = IntPtr(JSHClass::BIT_FIELD_OFFSET);
@ -1999,12 +2029,12 @@ inline GateRef StubBuilder::GetBuiltinId(GateRef method)
inline GateRef StubBuilder::ComputeSizeUtf8(GateRef length)
{
return PtrAdd(IntPtr(EcmaString::DATA_OFFSET), length);
return PtrAdd(IntPtr(LineEcmaString::DATA_OFFSET), length);
}
inline GateRef StubBuilder::ComputeSizeUtf16(GateRef length)
{
return PtrAdd(IntPtr(EcmaString::DATA_OFFSET), PtrMul(length, IntPtr(sizeof(uint16_t))));
return PtrAdd(IntPtr(LineEcmaString::DATA_OFFSET), PtrMul(length, IntPtr(sizeof(uint16_t))));
}
inline GateRef StubBuilder::AlignUp(GateRef x, GateRef alignment)
@ -2029,5 +2059,10 @@ inline void StubBuilder::SetRawHashcode(GateRef glue, GateRef str, GateRef rawHa
{
Store(VariableType::INT32(), glue, str, IntPtr(EcmaString::HASHCODE_OFFSET), rawHashcode);
}
inline GateRef StubBuilder::TryGetHashcodeFromString(GateRef string)
{
return env_->GetBuilder()->TryGetHashcodeFromString(string);
}
} // namespace panda::ecmascript::kungfu
#endif // ECMASCRIPT_COMPILER_STUB_INL_H

View File

@ -1081,7 +1081,7 @@ GateRef StubBuilder::IsDigit(GateRef ch)
Int32GreaterThanOrEqual(ch, Int32('0')));
}
GateRef StubBuilder::StringToElementIndex(GateRef string)
GateRef StubBuilder::StringToElementIndex(GateRef glue, GateRef string)
{
auto env = GetEnvironment();
Label entry(env);
@ -1096,25 +1096,15 @@ GateRef StubBuilder::StringToElementIndex(GateRef string)
Branch(Int32GreaterThan(len, Int32(MAX_ELEMENT_INDEX_LEN)), &exit, &inRange);
Bind(&inRange);
{
GateRef dataUtf16 = PtrAdd(string, IntPtr(EcmaString::DATA_OFFSET));
DEFVARIABLE(c, VariableType::INT32(), Int32(0));
Label isUtf16(env);
Label isUtf8(env);
Label getChar1(env);
GateRef isUtf16String = IsUtf16String(string);
Branch(isUtf16String, &isUtf16, &isUtf8);
Bind(&isUtf16);
{
c = ZExtInt16ToInt32(Load(VariableType::INT16(), dataUtf16));
Jump(&getChar1);
}
Branch(isUtf16String, &exit, &isUtf8);
Bind(&isUtf8);
{
c = ZExtInt8ToInt32(Load(VariableType::INT8(), dataUtf16));
Jump(&getChar1);
}
Bind(&getChar1);
{
GateRef strFlat = FlattenString(glue, string);
GateRef dataUtf8 = PtrAdd(strFlat, IntPtr(LineEcmaString::DATA_OFFSET));
DEFVARIABLE(c, VariableType::INT32(), Int32(0));
c = ZExtInt8ToInt32(Load(VariableType::INT8(), dataUtf8));
Label isDigitZero(env);
Label notDigitZero(env);
Branch(Int32Equal(*c, Int32('0')), &isDigitZero, &notDigitZero);
@ -1141,39 +1131,20 @@ GateRef StubBuilder::StringToElementIndex(GateRef string)
Branch(Int32UnsignedLessThan(*i, len), &loopHead, &afterLoop);
LoopBegin(&loopHead);
{
Label isUtf16A(env);
Label notUtf16(env);
Label getChar2(env);
Branch(isUtf16String, &isUtf16A, &notUtf16);
Bind(&isUtf16A);
{
// 2 : 2 means utf16 char width is two bytes
auto charOffset = PtrMul(ZExtInt32ToPtr(*i), IntPtr(2));
c = ZExtInt16ToInt32(Load(VariableType::INT16(), dataUtf16, charOffset));
Jump(&getChar2);
}
Bind(&notUtf16);
{
c = ZExtInt8ToInt32(Load(VariableType::INT8(), dataUtf16, ZExtInt32ToPtr(*i)));
Jump(&getChar2);
}
Bind(&getChar2);
{
c = ZExtInt8ToInt32(Load(VariableType::INT8(), dataUtf8, ZExtInt32ToPtr(*i)));
Label isDigit2(env);
Label notDigit2(env);
Branch(IsDigit(*c), &isDigit2, &notDigit2);
Bind(&isDigit2);
{
// 10 means the base of digit is 10.
n = Int32Add(Int32Mul(*n, Int32(10)),
Int32Sub(*c, Int32('0')));
n = Int32Add(Int32Mul(*n, Int32(10)), Int32Sub(*c, Int32('0')));
i = Int32Add(*i, Int32(1));
Branch(Int32UnsignedLessThan(*i, len), &loopEnd, &afterLoop);
}
Bind(&notDigit2);
Jump(&exit);
}
}
Bind(&loopEnd);
LoopEnd(&loopHead);
Bind(&afterLoop);
@ -1196,7 +1167,7 @@ GateRef StubBuilder::StringToElementIndex(GateRef string)
return ret;
}
GateRef StubBuilder::TryToElementsIndex(GateRef key)
GateRef StubBuilder::TryToElementsIndex(GateRef glue, GateRef key)
{
auto env = GetEnvironment();
Label entry(env);
@ -1219,7 +1190,7 @@ GateRef StubBuilder::TryToElementsIndex(GateRef key)
Branch(TaggedIsString(key), &isString, &notString);
Bind(&isString);
{
resultKey = StringToElementIndex(key);
resultKey = StringToElementIndex(glue, key);
Jump(&exit);
}
Bind(&notString);
@ -1437,7 +1408,7 @@ GateRef StubBuilder::LoadICWithHandler(GateRef glue, GateRef receiver, GateRef a
return ret;
}
GateRef StubBuilder::LoadElement(GateRef receiver, GateRef key)
GateRef StubBuilder::LoadElement(GateRef glue, GateRef receiver, GateRef key)
{
auto env = GetEnvironment();
Label entry(env);
@ -1448,7 +1419,7 @@ GateRef StubBuilder::LoadElement(GateRef receiver, GateRef key)
Label lengthLessIndex(env);
Label lengthNotLessIndex(env);
DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
GateRef index = TryToElementsIndex(key);
GateRef index = TryToElementsIndex(glue, key);
Branch(Int32LessThan(index, Int32(0)), &indexLessZero, &indexNotLessZero);
Bind(&indexLessZero);
{
@ -1495,7 +1466,7 @@ GateRef StubBuilder::ICStoreElement(GateRef glue, GateRef receiver, GateRef key,
Label loopEnd(env);
DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
DEFVARIABLE(varHandler, VariableType::JS_ANY(), handler);
GateRef index = TryToElementsIndex(key);
GateRef index = TryToElementsIndex(glue, key);
Branch(Int32LessThan(index, Int32(0)), &indexLessZero, &indexNotLessZero);
Bind(&indexLessZero);
{
@ -2030,7 +2001,7 @@ GateRef StubBuilder::GetPropertyByValue(GateRef glue, GateRef receiver, GateRef
}
Bind(&isNumberOrStringSymbol);
{
GateRef index = TryToElementsIndex(*key);
GateRef index = TryToElementsIndex(glue, *key);
Label validIndex(env);
Label notValidIndex(env);
Branch(Int32GreaterThanOrEqual(index, Int32(0)), &validIndex, &notValidIndex);
@ -2736,7 +2707,7 @@ GateRef StubBuilder::SetPropertyByValue(GateRef glue, GateRef receiver, GateRef
}
Bind(&isNumberOrStringSymbol);
{
GateRef index = TryToElementsIndex(*varKey);
GateRef index = TryToElementsIndex(glue, *varKey);
Label validIndex(env);
Label notValidIndex(env);
Branch(Int32GreaterThanOrEqual(index, Int32(0)), &validIndex, &notValidIndex);
@ -3473,12 +3444,22 @@ GateRef StubBuilder::FastStringEqual(GateRef glue, GateRef left, GateRef right)
&exit);
Bind(&hashcodeCompare);
Branch(Int32Equal(GetHashcodeFromString(glue, left), GetHashcodeFromString(glue, right)), &contentsCompare,
&exit);
Label leftNotNeg(env);
GateRef leftHash = TryGetHashcodeFromString(left);
GateRef rightHash = TryGetHashcodeFromString(right);
Branch(Int64Equal(leftHash, Int64(-1)), &contentsCompare, &leftNotNeg);
Bind(&leftNotNeg);
{
Label rightNotNeg(env);
Branch(Int64Equal(rightHash, Int64(-1)), &contentsCompare, &rightNotNeg);
Bind(&rightNotNeg);
Branch(Int64Equal(leftHash, rightHash), &contentsCompare, &exit);
}
Bind(&contentsCompare);
{
result = UpdateLeaveFrameAndCallNGCRuntime(glue, RTSTUB_ID(StringsAreEquals), { left, right });
GateRef stringEqual = CallRuntime(glue, RTSTUB_ID(StringEqual), { left, right });
result = Equal(stringEqual, TaggedTrue());
Jump(&exit);
}
@ -4737,7 +4718,7 @@ void StubBuilder::CallFastPath(GateRef glue, GateRef nativeCode, GateRef func, G
Bind(notFastBuiltins);
}
GateRef StubBuilder::TryStringOrSymbelToElementIndex(GateRef key)
GateRef StubBuilder::TryStringOrSymbolToElementIndex(GateRef glue, GateRef key)
{
auto env = GetEnvironment();
Label entry(env);
@ -4760,8 +4741,8 @@ GateRef StubBuilder::TryStringOrSymbelToElementIndex(GateRef key)
Label isUtf8(env);
Branch(IsUtf16String(key), &exit, &isUtf8);
Bind(&isUtf8);
GateRef data = PtrAdd(key, IntPtr(EcmaString::DATA_OFFSET));
GateRef keyFlat = FlattenString(glue, key);
GateRef data = PtrAdd(keyFlat, IntPtr(LineEcmaString::DATA_OFFSET));
DEFVARIABLE(c, VariableType::INT32(), Int32(0));
c = ZExtInt8ToInt32(Load(VariableType::INT8(), data));
Label isDigitZero(env);
@ -4871,7 +4852,7 @@ GateRef StubBuilder::GetTypeArrayPropertyByName(GateRef glue, GateRef receiver,
}
Bind(&notNegativeZero);
{
GateRef index = TryStringOrSymbelToElementIndex(key);
GateRef index = TryStringOrSymbolToElementIndex(glue, key);
Label validIndex(env);
Label notValidIndex(env);
Branch(Int32GreaterThanOrEqual(index, Int32(0)), &validIndex, &notValidIndex);
@ -4932,7 +4913,7 @@ GateRef StubBuilder::SetTypeArrayPropertyByName(GateRef glue, GateRef receiver,
}
Bind(&notNegativeZero);
{
GateRef index = TryStringOrSymbelToElementIndex(key);
GateRef index = TryStringOrSymbolToElementIndex(glue, key);
Label validIndex(env);
Label notValidIndex(env);
Branch(Int32GreaterThanOrEqual(index, Int32(0)), &validIndex, &notValidIndex);
@ -5006,4 +4987,40 @@ void StubBuilder::PGOProfiler(GateRef glue, GateRef func)
env->SubCfgExit();
}
}
GateRef StubBuilder::FlattenString(GateRef glue, GateRef str)
{
auto env = GetEnvironment();
Label entry(env);
env->SubCfgEntry(&entry);
Label exit(env);
Label notLineString(env);
DEFVARIABLE(result, VariableType::JS_POINTER(), str);
Branch(IsLineString(str), &exit, &notLineString);
Bind(&notLineString);
{
Label isTreeString(env);
Branch(IsTreeString(str), &isTreeString, &exit);
Bind(&isTreeString);
{
Label isFlat(env);
Label notFlat(env);
Branch(TreeStringIsFlat(str), &isFlat, &notFlat);
Bind(&isFlat);
{
result = GetFirstFromTreeString(str);
Jump(&exit);
}
Bind(&notFlat);
{
result = CallRuntime(glue, RTSTUB_ID(SlowFlattenString), { str });
Jump(&exit);
}
}
}
Bind(&exit);
auto ret = *result;
env->SubCfgExit();
return ret;
}
} // namespace panda::ecmascript::kungfu

View File

@ -258,6 +258,9 @@ public:
GateRef IsEcmaObject(GateRef obj);
GateRef IsSymbol(GateRef obj);
GateRef IsString(GateRef obj);
GateRef IsLineString(GateRef obj);
GateRef IsTreeString(GateRef obj);
GateRef TreeStringIsFlat(GateRef string);
GateRef TaggedIsBigInt(GateRef obj);
GateRef TaggedObjectIsBigInt(GateRef obj);
GateRef IsJsProxy(GateRef obj);
@ -317,6 +320,9 @@ public:
GateRef GetBitFieldFromHClass(GateRef hClass);
GateRef GetLengthFromString(GateRef value);
GateRef GetHashcodeFromString(GateRef glue, GateRef value);
GateRef TryGetHashcodeFromString(GateRef string);
GateRef GetFirstFromTreeString(GateRef string);
GateRef GetSecondFromTreeString(GateRef string);
void SetBitFieldToHClass(GateRef glue, GateRef hClass, GateRef bitfield);
void SetPrototypeToHClass(VariableType type, GateRef glue, GateRef hClass, GateRef proto);
void SetProtoChangeDetailsToHClass(VariableType type, GateRef glue, GateRef hClass,
@ -370,15 +376,14 @@ public:
GateRef IsUtf8String(GateRef string);
GateRef IsInternalString(GateRef string);
GateRef IsDigit(GateRef ch);
GateRef StringToElementIndex(GateRef string);
GateRef TryToElementsIndex(GateRef key);
GateRef StringToElementIndex(GateRef glue, GateRef string);
GateRef ComputePropertyCapacityInJSObj(GateRef oldLength);
GateRef FindTransitions(GateRef glue, GateRef receiver, GateRef hClass, GateRef key, GateRef attr);
GateRef TaggedToRepresentation(GateRef value);
GateRef LdGlobalRecord(GateRef glue, GateRef key);
GateRef LoadFromField(GateRef receiver, GateRef handlerInfo);
GateRef LoadGlobal(GateRef cell);
GateRef LoadElement(GateRef receiver, GateRef key);
GateRef LoadElement(GateRef glue, GateRef receiver, GateRef key);
GateRef TryToElementsIndex(GateRef glue, GateRef key);
GateRef CheckPolyHClass(GateRef cachedValue, GateRef hClass);
GateRef LoadICWithHandler(GateRef glue, GateRef receiver, GateRef holder, GateRef handler);
@ -512,7 +517,7 @@ public:
GateRef GetTypeArrayPropertyByName(GateRef glue, GateRef receiver, GateRef holder, GateRef key, GateRef jsType);
GateRef SetTypeArrayPropertyByName(GateRef glue, GateRef receiver, GateRef holder, GateRef key, GateRef value,
GateRef jsType);
GateRef TryStringOrSymbelToElementIndex(GateRef string);
GateRef TryStringOrSymbolToElementIndex(GateRef glue, GateRef string);
inline GateRef DispatchBuiltins(GateRef glue, GateRef builtinsId, const std::initializer_list<GateRef>& args);
GateRef ComputeSizeUtf8(GateRef length);
GateRef ComputeSizeUtf16(GateRef length);
@ -524,6 +529,8 @@ public:
inline void SetRawHashcode(GateRef glue, GateRef str, GateRef rawHashcode);
void Assert(int messageId, int line, GateRef glue, GateRef condition, Label *nextLabel);
void PGOProfiler(GateRef glue, GateRef func);
GateRef FlattenString(GateRef glue, GateRef str);
private:
using BinaryOperation = std::function<GateRef(Environment*, GateRef, GateRef)>;
template<OpCode::Op Op>
@ -531,7 +538,7 @@ private:
GateRef FastBinaryOp(GateRef left, GateRef right,
const BinaryOperation& intOp, const BinaryOperation& floatOp);
void InitializeArguments();
CallSignature *callSignature_;
CallSignature *callSignature_ {nullptr};
Environment *env_;
};
} // namespace panda::ecmascript::kungfu

View File

@ -86,7 +86,7 @@ public:
auto stubModule = data->GetStubModule();
CreateCodeGen(stubModule, enableLog);
CodeGenerator codegen(llvmImpl_, "stubs");
codegen.RunForStub(data->GetCircuit(), data->GetScheduleResult(), index, data->GetCompilationConfig());
codegen.RunForStub(data->GetCircuit(), data->GetConstScheduleResult(), index, data->GetCompilationConfig());
return true;
}
private:
@ -105,15 +105,15 @@ void StubCompiler::RunPipeline(LLVMModule *module) const
Circuit circuit(cconfig->Is64Bit());
Stub stub(callSigns[i], &circuit);
ASSERT(callSigns[i]->HasConstructor());
StubBuilder* stubBuilder = static_cast<StubBuilder*>(
callSigns[i]->GetConstructor()(reinterpret_cast<void*>(stub.GetEnvironment())));
void* env = reinterpret_cast<void*>(stub.GetEnvironment());
StubBuilder* stubBuilder = static_cast<StubBuilder*>(callSigns[i]->GetConstructor()(env));
stub.SetStubBuilder(stubBuilder);
if (log->CertainMethod()) {
enableMethodLog = logList->IncludesMethod(stub.GetMethodName());
}
log->SetEnableMethodLog(enableMethodLog);
StubPassData data(&stub, module, log);
PassRunner<StubPassData> pipeline(&data);
pipeline.RunPass<StubBuildCircuitPass>();
@ -147,6 +147,7 @@ bool StubCompiler::BuildStubModuleAndSave() const
RunPipeline(&bcStubModule);
generator.AddModule(&bcStubModule, &bcStubAssembler);
res++;
LOG_COMPILER(INFO) << "compiling common stubs";
LLVMModule comStubModule("com_stub", triple_, enablePGOProfiler_);
LLVMAssembler comStubAssembler(comStubModule.GetModule(), LOptions(optLevel_, true, relocMode_));
@ -154,6 +155,7 @@ bool StubCompiler::BuildStubModuleAndSave() const
RunPipeline(&comStubModule);
generator.AddModule(&comStubModule, &comStubAssembler);
res++;
LOG_COMPILER(INFO) << "compiling builtins stubs";
LLVMModule builtinsStubModule("builtins_stub", triple_, enablePGOProfiler_);
LLVMAssembler builtinsStubAssembler(builtinsStubModule.GetModule(), LOptions(optLevel_, true, relocMode_));

View File

@ -118,7 +118,8 @@ HWTEST_F_L0(StubTest, FastAddTest)
stub.SetStubBuilder(&optimizer);
stub.GenerateCircuit(stubModule.GetCompilationConfig());
netOfGates.PrintAllGates();
auto cfg = Scheduler::Run(&netOfGates);
Scheduler::ControlFlowGraph cfg;
Scheduler::Run(&netOfGates, cfg);
PrintCircuitByBasicBlock(cfg, netOfGates);
LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function, stubModule.GetCompilationConfig(),
CallSignature::CallConv::CCallConv);
@ -159,7 +160,8 @@ HWTEST_F_L0(StubTest, FastSubTest)
stub.SetStubBuilder(&optimizer);
stub.GenerateCircuit(stubModule.GetCompilationConfig());
netOfGates.PrintAllGates();
auto cfg = Scheduler::Run(&netOfGates);
Scheduler::ControlFlowGraph cfg;
Scheduler::Run(&netOfGates, cfg);
PrintCircuitByBasicBlock(cfg, netOfGates);
LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function, stubModule.GetCompilationConfig(),
CallSignature::CallConv::CCallConv);
@ -196,7 +198,8 @@ HWTEST_F_L0(StubTest, FastMulTest)
stub.SetStubBuilder(&optimizer);
stub.GenerateCircuit(stubModule.GetCompilationConfig());
netOfGates.PrintAllGates();
auto cfg = Scheduler::Run(&netOfGates);
Scheduler::ControlFlowGraph cfg;
Scheduler::Run(&netOfGates, cfg);
PrintCircuitByBasicBlock(cfg, netOfGates);
LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function, stubModule.GetCompilationConfig(),
CallSignature::CallConv::CCallConv);
@ -252,7 +255,8 @@ HWTEST_F_L0(StubTest, FastDivTest)
stub.SetStubBuilder(&optimizer);
stub.GenerateCircuit(stubModule.GetCompilationConfig());
netOfGates.PrintAllGates();
auto cfg = Scheduler::Run(&netOfGates);
Scheduler::ControlFlowGraph cfg;
Scheduler::Run(&netOfGates, cfg);
PrintCircuitByBasicBlock(cfg, netOfGates);
LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function, stubModule.GetCompilationConfig(),
CallSignature::CallConv::CCallConv);
@ -301,7 +305,8 @@ HWTEST_F_L0(StubTest, FastModTest)
stub.SetStubBuilder(&optimizer);
stub.GenerateCircuit(stubModule.GetCompilationConfig());
netOfGates.PrintAllGates();
auto cfg = Scheduler::Run(&netOfGates);
Scheduler::ControlFlowGraph cfg;
Scheduler::Run(&netOfGates, cfg);
PrintCircuitByBasicBlock(cfg, netOfGates);
LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function, stubModule.GetCompilationConfig(),
CallSignature::CallConv::CCallConv);
@ -369,7 +374,8 @@ HWTEST_F_L0(StubTest, TryLoadICByName)
stub.SetStubBuilder(&optimizer);
stub.GenerateCircuit(stubModule.GetCompilationConfig());
netOfGates.PrintAllGates();
auto cfg = Scheduler::Run(&netOfGates);
Scheduler::ControlFlowGraph cfg;
Scheduler::Run(&netOfGates, cfg);
PrintCircuitByBasicBlock(cfg, netOfGates);
LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, findFunction, stubModule.GetCompilationConfig(),
CallSignature::CallConv::CCallConv);
@ -390,7 +396,8 @@ HWTEST_F_L0(StubTest, TryLoadICByValue)
stub.SetStubBuilder(&optimizer);
stub.GenerateCircuit(stubModule.GetCompilationConfig());
netOfGates.PrintAllGates();
auto cfg = Scheduler::Run(&netOfGates);
Scheduler::ControlFlowGraph cfg;
Scheduler::Run(&netOfGates, cfg);
PrintCircuitByBasicBlock(cfg, netOfGates);
LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, findFunction, stubModule.GetCompilationConfig(),
CallSignature::CallConv::CCallConv);
@ -411,7 +418,8 @@ HWTEST_F_L0(StubTest, TryStoreICByName)
stub.SetStubBuilder(&optimizer);
stub.GenerateCircuit(stubModule.GetCompilationConfig());
netOfGates.PrintAllGates();
auto cfg = Scheduler::Run(&netOfGates);
Scheduler::ControlFlowGraph cfg;
Scheduler::Run(&netOfGates, cfg);
PrintCircuitByBasicBlock(cfg, netOfGates);
LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, findFunction, stubModule.GetCompilationConfig(),
CallSignature::CallConv::CCallConv);
@ -432,7 +440,8 @@ HWTEST_F_L0(StubTest, TryStoreICByValue)
stub.SetStubBuilder(&optimizer);
stub.GenerateCircuit(stubModule.GetCompilationConfig());
netOfGates.PrintAllGates();
auto cfg = Scheduler::Run(&netOfGates);
Scheduler::ControlFlowGraph cfg;
Scheduler::Run(&netOfGates, cfg);
PrintCircuitByBasicBlock(cfg, netOfGates);
LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, findFunction, stubModule.GetCompilationConfig(),
CallSignature::CallConv::CCallConv);
@ -603,7 +612,7 @@ HWTEST_F_L0(StubTest, JSEntryTest)
/* implement stub1 */
LLVMValueRef stub1 = LLVMAddFunction(module, "stub1", LLVMFunctionType(LLVMInt64Type(), paramTys0, 1, 0));
LLVMAddTargetDependentFunctionAttr(stub1, "frame-pointer", "all");
int reservedSlotsSize = sizeof(uint64_t) * static_cast<int>(ReservedSlots::OPTIMIZED_ENTRY_RESERVED_SLOT);
int reservedSlotsSize = OptimizedEntryFrame::ComputeReservedSize(sizeof(uint64_t));
LLVMAddTargetDependentFunctionAttr(stub1, "frame-reserved-slots", std::to_string(reservedSlotsSize).c_str());
LLVMBasicBlockRef entryBb = LLVMAppendBasicBlock(stub1, "entry");
@ -642,7 +651,7 @@ HWTEST_F_L0(StubTest, JSEntryTest)
/* implement stub2 call stub3 */
LLVMValueRef stub2 = LLVMAddFunction(module, "stub2", LLVMFunctionType(LLVMInt64Type(), paramTys0, 1, 0));
LLVMAddTargetDependentFunctionAttr(stub2, "frame-pointer", "all");
int reservedSlotsSize = sizeof(uint64_t) * static_cast<int>(ReservedSlots::OPTIMIZED_ENTRY_RESERVED_SLOT);
int reservedSlotsSize = OptimizedEntryFrame::ComputeReservedSize(sizeof(uint64_t));
LLVMAddTargetDependentFunctionAttr(stub2, "frame-reserved-slots", std::to_string(reservedSlotsSize).c_str());
entryBb = LLVMAppendBasicBlock(stub2, "entry");
@ -673,7 +682,7 @@ HWTEST_F_L0(StubTest, JSEntryTest)
/* implement stub3 call RuntimeFunc2 */
LLVMAddTargetDependentFunctionAttr(stub3, "frame-pointer", "all");
int reservedSlotsSize = sizeof(uint64_t) * static_cast<int>(ReservedSlots::OPTIMIZED_RESERVED_SLOT);
int reservedSlotsSize = OptimizedFrame::ComputeReservedSize(sizeof(uint64_t));
LLVMAddTargetDependentFunctionAttr(stub3, "frame-reserved-slots", std::to_string(reservedSlotsSize).c_str());
entryBb = LLVMAppendBasicBlock(stub3, "entry");
@ -737,7 +746,7 @@ HWTEST_F_L0(StubTest, Prologue)
/* implement main implement */
LLVMValueRef func = LLVMAddFunction(module, "main", LLVMFunctionType(LLVMInt64Type(), nullptr, 0, 0));
LLVMAddTargetDependentFunctionAttr(func, "frame-pointer", "all");
int reservedSlotsSize = sizeof(uint64_t) * static_cast<int>(ReservedSlots::OPTIMIZED_ENTRY_RESERVED_SLOT);
int reservedSlotsSize = OptimizedEntryFrame::ComputeReservedSize(sizeof(uint64_t));
LLVMAddTargetDependentFunctionAttr(func, "frame-reserved-slots", std::to_string(reservedSlotsSize).c_str());
LLVMBasicBlockRef entryBb = LLVMAppendBasicBlock(func, "entry");
@ -747,7 +756,7 @@ HWTEST_F_L0(StubTest, Prologue)
LLVMBuilderRef builderBar = LLVMCreateBuilder();
LLVMValueRef bar = LLVMAddFunction(module, "bar", LLVMFunctionType(LLVMInt64Type(), paramTys0, 2, 0));
LLVMAddTargetDependentFunctionAttr(bar, "frame-pointer", "all");
int reservedSlotsSize = sizeof(uint64_t) * static_cast<int>(ReservedSlots::OPTIMIZED_RESERVED_SLOT);
int reservedSlotsSize = OptimizedFrame::ComputeReservedSize(sizeof(uint64_t));
LLVMAddTargetDependentFunctionAttr(bar, "frame-reserved-slots", std::to_string(reservedSlotsSize).c_str());
LLVMBasicBlockRef entryBbBar = LLVMAppendBasicBlock(bar, "entry");
LLVMPositionBuilderAtEnd(builderBar, entryBbBar);
@ -797,7 +806,7 @@ HWTEST_F_L0(StubTest, CEntryFp)
/* implement main call RuntimeFunc */
LLVMValueRef func = LLVMAddFunction(module, "main", LLVMFunctionType(LLVMInt64Type(), paramTys0, 1, 0));
LLVMAddTargetDependentFunctionAttr(func, "frame-pointer", "all");
int reservedSlotsSize = sizeof(uint64_t) * static_cast<int>(ReservedSlots::OPTIMIZED_ENTRY_RESERVED_SLOT);
int reservedSlotsSize = OptimizedEntryFrame::ComputeReservedSize(sizeof(uint64_t));
LLVMAddTargetDependentFunctionAttr(func, "frame-reserved-slots", std::to_string(reservedSlotsSize).c_str());
LLVMBasicBlockRef entryBb = LLVMAppendBasicBlock(func, "entry");
LLVMPositionBuilderAtEnd(builder, entryBb);
@ -899,7 +908,8 @@ HWTEST_F_L0(StubTest, GetPropertyByIndexStub)
stub.SetStubBuilder(&optimizer);
stub.GenerateCircuit(stubModule.GetCompilationConfig());
netOfGates.PrintAllGates();
auto cfg = Scheduler::Run(&netOfGates);
Scheduler::ControlFlowGraph cfg;
Scheduler::Run(&netOfGates, cfg);
PrintCircuitByBasicBlock(cfg, netOfGates);
LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function, stubModule.GetCompilationConfig(),
CallSignature::CallConv::CCallConv);
@ -935,7 +945,8 @@ HWTEST_F_L0(StubTest, SetPropertyByIndexStub)
netOfGates.PrintAllGates();
bool result = Verifier::Run(&netOfGates);
ASSERT_TRUE(result);
auto cfg = Scheduler::Run(&netOfGates);
Scheduler::ControlFlowGraph cfg;
Scheduler::Run(&netOfGates, cfg);
PrintCircuitByBasicBlock(cfg, netOfGates);
LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function, stubModule.GetCompilationConfig(),
CallSignature::CallConv::CCallConv);
@ -973,7 +984,8 @@ HWTEST_F_L0(StubTest, GetPropertyByNameStub)
netOfGates.PrintAllGates();
bool result = Verifier::Run(&netOfGates);
ASSERT_TRUE(result);
auto cfg = Scheduler::Run(&netOfGates);
Scheduler::ControlFlowGraph cfg;
Scheduler::Run(&netOfGates, cfg);
PrintCircuitByBasicBlock(cfg, netOfGates);
LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function, stubModule.GetCompilationConfig(),
CallSignature::CallConv::CCallConv);
@ -1011,7 +1023,8 @@ HWTEST_F_L0(StubTest, SetPropertyByNameStub)
stub.SetStubBuilder(&optimizer);
stub.GenerateCircuit(stubModule.GetCompilationConfig());
netOfGates.PrintAllGates();
auto cfg = Scheduler::Run(&netOfGates);
Scheduler::ControlFlowGraph cfg;
Scheduler::Run(&netOfGates, cfg);
PrintCircuitByBasicBlock(cfg, netOfGates);
LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function, stubModule.GetCompilationConfig(),
CallSignature::CallConv::CCallConv);
@ -1048,8 +1061,9 @@ HWTEST_F_L0(StubTest, GetPropertyByValueStub)
stub.SetStubBuilder(&optimizer);
stub.GenerateCircuit(stubModule.GetCompilationConfig());
netOfGates2.PrintAllGates();
auto cfg2 = Scheduler::Run(&netOfGates2);
LLVMIRBuilder llvmBuilder2(&cfg2, &netOfGates2, &stubModule, getPropertyByIndexfunction,
Scheduler::ControlFlowGraph cfg;
Scheduler::Run(&netOfGates2, cfg);
LLVMIRBuilder llvmBuilder2(&cfg, &netOfGates2, &stubModule, getPropertyByIndexfunction,
stubModule.GetCompilationConfig(), CallSignature::CallConv::CCallConv);
llvmBuilder2.Build();
@ -1063,7 +1077,8 @@ HWTEST_F_L0(StubTest, GetPropertyByValueStub)
stub1.GenerateCircuit(stubModule.GetCompilationConfig());
bool result = Verifier::Run(&netOfGates1);
ASSERT_TRUE(result);
auto cfg1 = Scheduler::Run(&netOfGates1);
Scheduler::ControlFlowGraph cfg1;
Scheduler::Run(&netOfGates1, cfg1);
LLVMIRBuilder llvmBuilder1(&cfg1, &netOfGates1, &stubModule, getPropertyByNamefunction,
stubModule.GetCompilationConfig(), CallSignature::CallConv::CCallConv);
llvmBuilder1.Build();
@ -1079,10 +1094,11 @@ HWTEST_F_L0(StubTest, GetPropertyByValueStub)
netOfGates.PrintAllGates();
result = Verifier::Run(&netOfGates);
ASSERT_TRUE(result);
auto cfg = Scheduler::Run(&netOfGates);
PrintCircuitByBasicBlock(cfg, netOfGates);
Scheduler::ControlFlowGraph cfg2;
Scheduler::Run(&netOfGates, cfg2);
PrintCircuitByBasicBlock(cfg2, netOfGates);
LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function, stubModule.GetCompilationConfig(),
LLVMIRBuilder llvmBuilder(&cfg2, &netOfGates, &stubModule, function, stubModule.GetCompilationConfig(),
CallSignature::CallConv::CCallConv);
llvmBuilder.Build();
LLVMAssembler assembler(module);
@ -1151,7 +1167,8 @@ HWTEST_F_L0(StubTest, FastTypeOfTest)
netOfGates.PrintAllGates();
bool verRes = Verifier::Run(&netOfGates);
ASSERT_TRUE(verRes);
auto cfg = Scheduler::Run(&netOfGates);
Scheduler::ControlFlowGraph cfg;
Scheduler::Run(&netOfGates, cfg);
PrintCircuitByBasicBlock(cfg, netOfGates);
LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function, stubModule.GetCompilationConfig(),
CallSignature::CallConv::CCallConv);
@ -1239,7 +1256,8 @@ HWTEST_F_L0(StubTest, FastEqualTest)
stub.SetStubBuilder(&optimizer);
stub.GenerateCircuit(stubModule.GetCompilationConfig());
netOfGates.PrintAllGates();
auto cfg = Scheduler::Run(&netOfGates);
Scheduler::ControlFlowGraph cfg;
Scheduler::Run(&netOfGates, cfg);
PrintCircuitByBasicBlock(cfg, netOfGates);
LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function, stubModule.GetCompilationConfig(),
CallSignature::CallConv::CCallConv);
@ -1472,7 +1490,8 @@ HWTEST_F_L0(StubTest, RelocateTest)
netOfGates.PrintAllGates();
bool verRes = Verifier::Run(&netOfGates);
ASSERT_TRUE(verRes);
auto cfg = Scheduler::Run(&netOfGates);
Scheduler::ControlFlowGraph cfg;
Scheduler::Run(&netOfGates, cfg);
PrintCircuitByBasicBlock(cfg, netOfGates);
LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function, stubModule.GetCompilationConfig(),
CallSignature::CallConv::CCallConv);

View File

@ -19,7 +19,7 @@
#include "ecmascript/compiler/argument_accessor.h"
#include "ecmascript/compiler/common_stubs.h"
#include "ecmascript/compiler/rt_call_signature.h"
#include "ecmascript/deoptimizer.h"
#include "ecmascript/deoptimizer/deoptimizer.h"
#include "ecmascript/ecma_runtime_call_info.h"
#include "ecmascript/frames.h"
#include "ecmascript/js_function.h"
@ -346,7 +346,9 @@ void OptimizedCall::CallBuiltinTrampoline(ExtendedAssembler *assembler)
// |--------------------------| OptimizedJSFunctionFrame
// | frameType | |
// |--------------------------| |
// | lexEnv | v
// | lexEnv | |
// |--------------------------| |
// | call-target | v
// +--------------------------+ ---------------
void OptimizedCall::GenJSCall(ExtendedAssembler *assembler, bool isNew)

View File

@ -19,7 +19,7 @@
#include "ecmascript/compiler/common_stubs.h"
#include "ecmascript/compiler/rt_call_signature.h"
#include "ecmascript/compiler/argument_accessor.h"
#include "ecmascript/deoptimizer.h"
#include "ecmascript/deoptimizer/deoptimizer.h"
#include "ecmascript/ecma_runtime_call_info.h"
#include "ecmascript/frames.h"
#include "ecmascript/js_function.h"
@ -530,7 +530,9 @@ void OptimizedCall::JSProxyCallInternalWithArgV(ExtendedAssembler *assembler)
// |--------------------------| OptimizedJSFunctionFrame
// | frameType | |
// |--------------------------| |
// | lexEnv | v
// | lexEnv | |
// |--------------------------| |
// | call-target | v
// +--------------------------+ ---------------
void OptimizedCall::JSCallNew(ExtendedAssembler *assembler)
{

View File

@ -15,7 +15,7 @@
#include "ecmascript/compiler/builtins_lowering.h"
#include "ecmascript/compiler/type_lowering.h"
#include "ecmascript/deoptimizer.h"
#include "ecmascript/deoptimizer/deoptimizer.h"
#include "ecmascript/js_arraybuffer.h"
#include "ecmascript/js_native_pointer.h"

View File

@ -383,7 +383,8 @@ bool Verifier::RunPrologGatesCheck(const Circuit *circuit, const std::vector<Gat
return true;
}
bool Verifier::RunSchedulingBoundsCheck(const Circuit *circuit, const std::vector<GateRef> &schedulableGatesList,
bool Verifier::RunSchedulingBoundsCheck(const Circuit *circuit,
const std::vector<GateRef> &schedulableGatesList,
const std::unordered_map<GateRef, size_t> &bbGatesAddrToIdx,
const std::function<bool(size_t, size_t)> &isAncestor,
const std::function<size_t(size_t, size_t)> &lowestCommonAncestor)
@ -391,18 +392,15 @@ bool Verifier::RunSchedulingBoundsCheck(const Circuit *circuit, const std::vecto
// check existence of scheduling upper bound
std::unordered_map<GateRef, size_t> upperBound;
{
auto result =
Scheduler::CalculateSchedulingUpperBound(circuit, bbGatesAddrToIdx, isAncestor, schedulableGatesList);
if (!result.has_value()) {
if (!Scheduler::CalculateSchedulingUpperBound(circuit, bbGatesAddrToIdx, isAncestor,
schedulableGatesList, upperBound)) {
return false;
}
upperBound = result.value();
}
// check existence of scheduling lower bound
std::unordered_map<GateRef, size_t> lowerBound;
{
auto result = Scheduler::CalculateSchedulingLowerBound(circuit, bbGatesAddrToIdx, lowestCommonAncestor);
lowerBound = result.value();
Scheduler::CalculateSchedulingLowerBound(circuit, bbGatesAddrToIdx, lowestCommonAncestor, lowerBound);
}
// check consistency of lower bound and upper bound
{

View File

@ -82,9 +82,9 @@ public:
JSHandle<JSTaggedValue> valueY = GetCallArg(argv, 1);
if (valueX->IsString() && valueY->IsString()) {
auto xString = static_cast<EcmaString *>(valueX->GetTaggedObject());
auto yString = static_cast<EcmaString *>(valueY->GetTaggedObject());
int result = EcmaStringAccessor::Compare(xString, yString);
auto xHandle = JSHandle<EcmaString>(valueX);
auto yHandle = JSHandle<EcmaString>(valueY);
int result = EcmaStringAccessor::Compare(thread->GetEcmaVM(), xHandle, yHandle);
if (result < 0) {
return JSTaggedValue(1);
}

View File

@ -79,9 +79,9 @@ public:
JSHandle<JSTaggedValue> valueY = GetCallArg(argv, 1);
if (valueX->IsString() && valueY->IsString()) {
auto xString = static_cast<EcmaString *>(valueX->GetTaggedObject());
auto yString = static_cast<EcmaString *>(valueY->GetTaggedObject());
int result = EcmaStringAccessor::Compare(xString, yString);
auto xHandle = JSHandle<EcmaString>(valueX);
auto yHandle = JSHandle<EcmaString>(valueY);
int result = EcmaStringAccessor::Compare(thread->GetEcmaVM(), xHandle, yHandle);
if (result < 0) {
return JSTaggedValue(1);
}

View File

@ -12,7 +12,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ecmascript/calleeReg.h"
#include "ecmascript/deoptimizer/calleeReg.h"
#include "libpandabase/macros.h"
#include <iostream>
@ -58,6 +58,7 @@ int CalleeReg::FindCallRegOrder(const DwarfRegType reg) const
if (it != reg2Location_.end()) {
return it->second;
} else {
LOG_FULL(FATAL) << "reg:" << std::dec << reg;
UNREACHABLE();
}
}

View File

@ -13,8 +13,9 @@
* limitations under the License.
*/
#ifndef ECMASCRIPT_COMPILER_CALLEE_REG_H
#define ECMASCRIPT_COMPILER_CALLEE_REG_H
#ifndef ECMASCRIPT_DEOPTIMIZER_CALLEE_REG_H
#define ECMASCRIPT_DEOPTIMIZER_CALLEE_REG_H
#include <map>
#include "ecmascript/common.h"
#include "ecmascript/llvm_stackmap_type.h"
@ -67,4 +68,4 @@ private:
std::map<DwarfReg, int> reg2Location_;
};
} // namespace panda::ecmascript
#endif // ECMASCRIPT_COMPILER_CALLEE_REG_H
#endif // ECMASCRIPT_DEOPTIMIZER_CALLEE_REG_H

View File

@ -136,7 +136,7 @@ void Deoptimizier::CollectDeoptBundleVec(std::vector<kungfu::ARKDeopt>& deoptBun
case FrameType::LEAVE_FRAME:
break;
default: {
LOG_ECMA(FATAL) << "frame type error!";
LOG_FULL(FATAL) << "frame type error!";
UNREACHABLE();
}
}
@ -227,13 +227,22 @@ bool Deoptimizier::CollectVirtualRegisters(Method* method, FrameWriter *frameWri
return true;
}
void Deoptimizier::Dump(Method* method)
{
if (traceDeopt_) {
std::string data = JsStackInfo::BuildMethodTrace(method, pc_);
LOG_COMPILER(INFO) << "Deoptimize" << data;
const uint8_t *pc = method->GetBytecodeArray() + pc_;
BytecodeInstruction inst(pc);
LOG_COMPILER(INFO) << inst;
}
}
JSTaggedType Deoptimizier::ConstructAsmInterpretFrame()
{
JSTaggedValue callTarget = GetFrameArgv(kungfu::CommonArgIdx::FUNC);
auto method = GetMethod(callTarget);
std::string data = JsStackInfo::BuildMethodTrace(method, pc_);
LOG_COMPILER(DEBUG) << "Deoptimize" << data;
Dump(method);
ASSERT(thread_ != nullptr);
FrameWriter frameWriter(this);

View File

@ -13,11 +13,12 @@
* limitations under the License.
*/
#ifndef ECMASCRIPT_DEOPTIMIZER_H
#define ECMASCRIPT_DEOPTIMIZER_H
#ifndef ECMASCRIPT_DEOPTIMIZER_DEOPTIMIZER_H
#define ECMASCRIPT_DEOPTIMIZER_DEOPTIMIZER_H
#include "ecmascript/base/aligned_struct.h"
#include "ecmascript/calleeReg.h"
#include "ecmascript/compiler/argument_accessor.h"
#include "ecmascript/deoptimizer/calleeReg.h"
#include "ecmascript/js_handle.h"
#include "ecmascript/js_tagged_value.h"
#include "ecmascript/llvm_stackmap_type.h"
@ -92,6 +93,8 @@ public:
{
kungfu::CalleeReg callreg;
numCalleeRegs_ = static_cast<size_t>(callreg.GetCallRegNum());
JSRuntimeOptions options = thread_->GetEcmaVM()->GetJSOptions();
traceDeopt_= options.GetTraceDeopt();
}
void CollectVregs(const std::vector<kungfu::ARKDeopt>& deoptBundle);
void CollectDeoptBundleVec(std::vector<kungfu::ARKDeopt>& deoptBundle);
@ -136,6 +139,7 @@ private:
}
Method* GetMethod(JSTaggedValue &target);
void RelocateCalleeSave();
void Dump(Method* method);
JSThread *thread_ {nullptr};
uintptr_t *calleeRegAddr_ {nullptr};
size_t numCalleeRegs_ {0};
@ -147,7 +151,8 @@ private:
JSTaggedValue env_ {JSTaggedValue::Undefined()};
size_t frameArgc_ {0};
JSTaggedType *frameArgvs_ {nullptr};
bool traceDeopt_{false};
};
} // namespace panda::ecmascript
#endif // ECMASCRIPT_DEOPTIMIZER_H
#endif // ECMASCRIPT_DEOPTIMIZER_DEOPTIMIZER_H

View File

@ -13,7 +13,7 @@
* limitations under the License.
*/
#include "ecmascript/relocator.h"
#include "ecmascript/deoptimizer/relocator.h"
#include <climits>
#include <iomanip>
#include "ecmascript/compiler/assembler/aarch64/assembler_aarch64_constants.h"

View File

@ -13,8 +13,8 @@
* limitations under the License.
*/
#ifndef ECMASCRIPT_RELCATOR_H
#define ECMASCRIPT_RELCATOR_H
#ifndef ECMASCRIPT_DEOPTIMIZER_RELCATOR_H
#define ECMASCRIPT_DEOPTIMIZER_RELCATOR_H
#include "ecmascript/common.h"
#if !WIN_OR_MAC_OR_IOS_PLATFORM
@ -80,5 +80,5 @@ private:
};
} // panda::ecmascript
#endif
#endif // ECMASCRIPT_RELCATOR_H
#endif // ECMASCRIPT_DEOPTIMIZER_RELCATOR_H

View File

@ -470,11 +470,11 @@ void CpuProfiler::GetStackSignalHandler(int signal, [[maybe_unused]] siginfo_t *
fp = reinterpret_cast<void*>(mcontext.regs[29]); // FP is an alias for x29.
sp = reinterpret_cast<void*>(mcontext.sp);
#else
LOG_ECMA(FATAL) << "Cpuprofiler does not currently support other platforms, please run on x64 and arm64";
LOG_FULL(FATAL) << "Cpuprofiler does not currently support other platforms, please run on x64 and arm64";
return;
#endif
if (reinterpret_cast<uint64_t*>(sp) > reinterpret_cast<uint64_t*>(fp)) {
LOG_ECMA(FATAL) << "sp > fp, stack frame exception";
LOG_FULL(FATAL) << "sp > fp, stack frame exception";
}
if (profiler->CheckFrameType(thread, reinterpret_cast<JSTaggedType *>(fp))) {
FrameHandler frameHandler(thread, fp);
@ -524,7 +524,7 @@ bool CpuProfiler::IsAddrAtStub(void *context)
#elif defined(PANDA_TARGET_ARM64)
pc = static_cast<uint64_t>(mcontext.pc);
#else
LOG_ECMA(FATAL) << "Cpuprofiler does not currently support other platforms, please run on x64 and arm64";
LOG_FULL(FATAL) << "Cpuprofiler does not currently support other platforms, please run on x64 and arm64";
return true;
#endif
AOTFileManager *loader = vm_->GetAOTFileManager();

View File

@ -217,7 +217,8 @@ CString *HeapSnapshot::GenerateNodeName(TaggedObject *entry)
return GetArrayString(TaggedArray::Cast(entry), "COWArray[");
case JSType::HCLASS:
return GetString("HiddenClass");
case JSType::STRING:
case JSType::LINE_STRING:
case JSType::TREE_STRING:
return GetString("BaseString");
case JSType::JS_OBJECT: {
CString objName = CString("JSOBJECT(Ctor="); // Ctor-name
@ -810,7 +811,7 @@ Node *HeapSnapshot::GenerateStringNode(JSTaggedValue entry, size_t size, int seq
// Allocation Event will generate string node for "".
// When we need to serialize and isFinish is true, the nodeName will be given the actual string content.
auto originStr = static_cast<EcmaString *>(entry.GetTaggedObject());
size_t selfsize = (size != 0) ? size : EcmaStringAccessor(originStr).ObjectSize();
size_t selfsize = (size != 0) ? size : EcmaStringAccessor(originStr).GetFlatStringSize();
const CString *nodeName = &EMPTY_STRING;
if (isInFinish) {
nodeName = GetString(EntryVisitor::ConvertKey(entry));
@ -833,7 +834,7 @@ Node *HeapSnapshot::GeneratePrivateStringNode(size_t size, int sequenceId)
Node *node = nullptr;
JSTaggedValue stringValue = vm_->GetJSThread()->GlobalConstants()->GetStringString();
auto originStr = static_cast<EcmaString *>(stringValue.GetTaggedObject());
size_t selfsize = (size != 0) ? size : EcmaStringAccessor(originStr).ObjectSize();
size_t selfsize = (size != 0) ? size : EcmaStringAccessor(originStr).GetFlatStringSize();
CString strContent;
strContent.append(EntryVisitor::ConvertKey(stringValue));
node = Node::NewNode(vm_, sequenceId, nodeCount_, GetString(strContent), NodeType::PRIM_STRING, selfsize,

View File

@ -56,13 +56,9 @@ void PrintBacktrace(uintptr_t value)
std::ostringstream stack;
for (int i = 1; i < level; i++) {
const char *file = "";
const char *symbol = "";
uintptr_t offset = 0;
Dl_info info;
if (dladdr(buffer[i], &info)) {
if (info.dli_sname) {
symbol = info.dli_sname;
}
if (info.dli_fname) {
file = info.dli_fname;
}

View File

@ -142,7 +142,8 @@ CString JSHClass::DumpJSType(JSType type)
return "ConstantPool";
case JSType::COW_TAGGED_ARRAY:
return "COWArray";
case JSType::STRING:
case JSType::LINE_STRING:
case JSType::TREE_STRING:
return "BaseString";
case JSType::JS_NATIVE_POINTER:
return "NativePointer";
@ -575,7 +576,8 @@ static void DumpObject(TaggedObject *obj, std::ostream &os)
case JSType::CONSTANT_POOL:
DumpConstantPoolClass(ConstantPool::Cast(obj), os);
break;
case JSType::STRING:
case JSType::LINE_STRING:
case JSType::TREE_STRING:
DumpStringClass(EcmaString::Cast(obj), os);
os << "\n";
break;
@ -1032,7 +1034,7 @@ void JSTaggedValue::DumpHeapObjectType(std::ostream &os) const
}
JSType type = obj->GetClass()->GetObjectType();
if (type == JSType::STRING) {
if (type >= JSType::STRING_FIRST && type <= JSType::STRING_LAST) {
CString string = ConvertToString(EcmaString::Cast(obj));
os << std::left << std::setw(DUMP_TYPE_OFFSET) << "[" + string + "]";
} else if (type == JSType::METHOD) {
@ -1681,8 +1683,8 @@ void JSForInIterator::Dump(std::ostream &os) const
os << "\n";
os << " - WasVisited : " << GetWasVisited();
os << "\n";
os << " - VisitedKeys : ";
GetVisitedKeys().DumpTaggedValue(os);
os << " - VisitedObjs : ";
GetVisitedObjs().DumpTaggedValue(os);
os << "\n";
os << " - RemainingKeys : ";
GetRemainingKeys().DumpTaggedValue(os);
@ -3459,7 +3461,8 @@ static void DumpObject(TaggedObject *obj,
case JSType::CONSTANT_POOL:
DumpConstantPoolClass(ConstantPool::Cast(obj), vec);
return;
case JSType::STRING:
case JSType::LINE_STRING:
case JSType::TREE_STRING:
DumpStringClass(EcmaString::Cast(obj), vec);
return;
case JSType::JS_NATIVE_POINTER:
@ -4165,7 +4168,7 @@ void JSForInIterator::DumpForSnapshot(std::vector<std::pair<CString, JSTaggedVal
{
vec.push_back(std::make_pair(CString("Object"), GetObject()));
vec.push_back(std::make_pair(CString("WasVisited"), JSTaggedValue(GetWasVisited())));
vec.push_back(std::make_pair(CString("VisitedKeys"), GetVisitedKeys()));
vec.push_back(std::make_pair(CString("VisitedObjs"), GetVisitedObjs()));
vec.push_back(std::make_pair(CString("RemainingKeys"), GetRemainingKeys()));
JSObject::DumpForSnapshot(vec);
}

View File

@ -27,36 +27,12 @@ namespace panda::ecmascript {
/* static */
inline EcmaString *EcmaString::CreateEmptyString(const EcmaVM *vm)
{
auto string = vm->GetFactory()->AllocNonMovableStringObject(EcmaString::SIZE);
auto string = vm->GetFactory()->AllocNonMovableLineStringObject(EcmaString::SIZE);
string->SetLength(0, true);
string->SetRawHashcode(0);
return string;
}
/* static */
inline EcmaString *EcmaString::AllocStringObjectWithSpaceType(const EcmaVM *vm, size_t length, bool compressed,
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 EcmaVM *vm, const uint8_t *utf8Data, uint32_t utf8Len,
bool canBeCompress, MemSpaceType type)
@ -66,7 +42,7 @@ inline EcmaString *EcmaString::CreateFromUtf8(const EcmaVM *vm, const uint8_t *u
}
EcmaString *string = nullptr;
if (canBeCompress) {
string = AllocStringObjectWithSpaceType(vm, utf8Len, true, type);
string = CreateLineStringWithSpaceType(vm, utf8Len, true, type);
ASSERT(string != nullptr);
if (memcpy_s(string->GetDataUtf8Writable(), utf8Len, utf8Data, utf8Len) != EOK) {
@ -75,7 +51,7 @@ inline EcmaString *EcmaString::CreateFromUtf8(const EcmaVM *vm, const uint8_t *u
}
} else {
auto utf16Len = base::utf_helper::Utf8ToUtf16Size(utf8Data, utf8Len);
string = AllocStringObjectWithSpaceType(vm, utf16Len, false, type);
string = CreateLineStringWithSpaceType(vm, utf16Len, false, type);
ASSERT(string != nullptr);
[[maybe_unused]] auto len =
@ -93,11 +69,11 @@ inline EcmaString *EcmaString::CreateFromUtf16(const EcmaVM *vm, const uint16_t
if (utf16Len == 0) {
return vm->GetFactory()->GetEmptyString().GetObject<EcmaString>();
}
auto string = AllocStringObjectWithSpaceType(vm, utf16Len, canBeCompress, type);
auto string = CreateLineStringWithSpaceType(vm, utf16Len, canBeCompress, type);
ASSERT(string != nullptr);
if (canBeCompress) {
CopyUtf16AsUtf8(utf16Data, string->GetDataUtf8Writable(), utf16Len);
CopyChars(string->GetDataUtf8Writable(), utf16Data, utf16Len);
} else {
uint32_t len = utf16Len * (sizeof(uint16_t) / sizeof(uint8_t));
if (memcpy_s(string->GetDataUtf16Writable(), len, utf16Data, len) != EOK) {
@ -110,8 +86,244 @@ inline EcmaString *EcmaString::CreateFromUtf16(const EcmaVM *vm, const uint16_t
return string;
}
/* static */
inline EcmaString *EcmaString::CreateLineString(const EcmaVM *vm, size_t length, bool compressed)
{
size_t size = compressed ? LineEcmaString::ComputeSizeUtf8(length) : LineEcmaString::ComputeSizeUtf16(length);
auto string = vm->GetFactory()->AllocLineStringObject(size);
string->SetLength(length, compressed);
string->SetRawHashcode(0);
return string;
}
/* static */
inline EcmaString *EcmaString::CreateLineStringNoGC(const EcmaVM *vm, size_t length, bool compressed)
{
size_t size = compressed ? LineEcmaString::ComputeSizeUtf8(length) : LineEcmaString::ComputeSizeUtf16(length);
size = AlignUp(size, static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT));
auto object = reinterpret_cast<TaggedObject *>(vm->GetHeap()->GetOldSpace()->Allocate(size));
object->SetClass(JSHClass::Cast(vm->GetJSThread()->GlobalConstants()->GetLineStringClass().GetTaggedObject()));
auto string = EcmaString::Cast(object);
string->SetLength(length, compressed);
string->SetRawHashcode(0);
return string;
}
/* static */
inline EcmaString *EcmaString::CreateLineStringWithSpaceType(const EcmaVM *vm, size_t length, bool compressed,
MemSpaceType type)
{
size_t size = compressed ? LineEcmaString::ComputeSizeUtf8(length) : LineEcmaString::ComputeSizeUtf16(length);
EcmaString *string = nullptr;
switch (type) {
case MemSpaceType::SEMI_SPACE:
string = vm->GetFactory()->AllocLineStringObject(size);
break;
case MemSpaceType::OLD_SPACE:
string = vm->GetFactory()->AllocOldSpaceLineStringObject(size);
break;
case MemSpaceType::NON_MOVABLE:
string = vm->GetFactory()->AllocNonMovableLineStringObject(size);
break;
default:
UNREACHABLE();
}
string->SetLength(length, compressed);
string->SetRawHashcode(0);
return string;
}
inline EcmaString *EcmaString::CreateTreeString(const EcmaVM *vm,
const JSHandle<EcmaString> &left, const JSHandle<EcmaString> &right, uint32_t length, bool compressed)
{
auto thread = vm->GetJSThread();
auto string = TreeEcmaString::Cast(vm->GetFactory()->AllocTreeStringObject());
string->SetLength(length, compressed);
string->SetRawHashcode(0);
string->SetFirst(thread, left.GetTaggedValue());
string->SetSecond(thread, right.GetTaggedValue());
return string;
}
/* static */
EcmaString *EcmaString::FastSubUtf8String(const EcmaVM *vm, const JSHandle<EcmaString> &src, uint32_t start,
uint32_t length)
{
ASSERT(src->IsLineString());
auto string = CreateLineString(vm, length, true);
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
Span<uint8_t> dst(string->GetDataUtf8Writable(), length);
Span<const uint8_t> source(src->GetDataUtf8() + start, length);
EcmaString::MemCopyChars(dst, length, source, length);
ASSERT_PRINT(CanBeCompressed(string), "canBeCompresse does not match the real value!");
return string;
}
/* static */
EcmaString *EcmaString::FastSubUtf16String(const EcmaVM *vm, const JSHandle<EcmaString> &src, uint32_t start,
uint32_t length)
{
ASSERT(src->IsLineString());
bool canBeCompressed = CanBeCompressed(src->GetDataUtf16() + start, length);
auto string = CreateLineString(vm, length, canBeCompressed);
if (canBeCompressed) {
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
CopyChars(string->GetDataUtf8Writable(), src->GetDataUtf16() + start, length);
} else {
uint32_t len = length * (sizeof(uint16_t) / sizeof(uint8_t));
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
Span<uint16_t> dst(string->GetDataUtf16Writable(), length);
Span<const uint16_t> source(src->GetDataUtf16() + start, length);
EcmaString::MemCopyChars(dst, len, source, len);
}
ASSERT_PRINT(canBeCompressed == CanBeCompressed(string), "canBeCompresse does not match the real value!");
return string;
}
inline uint16_t *EcmaString::GetData() const
{
ASSERT_PRINT(IsLineString(), "EcmaString: Read data from not LineString");
return LineEcmaString::Cast(this)->GetData();
}
inline const uint8_t *EcmaString::GetDataUtf8() const
{
ASSERT_PRINT(IsUtf8(), "EcmaString: Read data as utf8 for utf16 string");
return reinterpret_cast<uint8_t *>(GetData());
}
inline const uint16_t *EcmaString::GetDataUtf16() const
{
LOG_ECMA_IF(!IsUtf16(), FATAL) << "EcmaString: Read data as utf16 for utf8 string";
return GetData();
}
inline uint8_t *EcmaString::GetDataUtf8Writable()
{
ASSERT_PRINT(IsUtf8(), "EcmaString: Read data as utf8 for utf16 string");
return reinterpret_cast<uint8_t *>(GetData());
}
inline uint16_t *EcmaString::GetDataUtf16Writable()
{
LOG_ECMA_IF(!IsUtf16(), FATAL) << "EcmaString: Read data as utf16 for utf8 string";
return GetData();
}
inline size_t EcmaString::GetUtf8Length(bool modify) const
{
ASSERT(IsLineString());
if (!IsUtf16()) {
return GetLength() + 1; // add place for zero in the end
}
return base::utf_helper::Utf16ToUtf8Size(GetData(), GetLength(), modify);
}
template<bool verify>
inline uint16_t EcmaString::At(int32_t index) const
{
int32_t length = static_cast<int32_t>(GetLength());
if (verify) {
if ((index < 0) || (index >= length)) {
return 0;
}
}
if (IsLineString()) {
return LineEcmaString::Cast(this)->Get<verify>(index);
} else {
return TreeEcmaString::Cast(this)->Get<verify>(index);
}
}
inline void EcmaString::WriteData(uint32_t index, uint16_t src)
{
ASSERT(index < GetLength());
ASSERT(IsLineString());
LineEcmaString::Cast(this)->Set(index, src);
}
inline bool EcmaString::IsFlat() const
{
if (!JSTaggedValue(this).IsTreeString()) {
return true;
}
return TreeEcmaString::Cast(this)->IsFlat();
}
template <typename Char>
void EcmaString::WriteToFlat(EcmaString *src, Char *buf, uint32_t maxLength)
{
DISALLOW_GARBAGE_COLLECTION;
uint32_t length = src->GetLength();
if (length == 0) {
return;
}
while (true) {
ASSERT(length <= maxLength && length > 0);
ASSERT(length <= src->GetLength());
switch (src->GetStringType()) {
case JSType::LINE_STRING: {
if (src->IsUtf8()) {
CopyChars(buf, src->GetDataUtf8(), length);
} else {
CopyChars(buf, src->GetDataUtf16(), length);
}
return;
}
case JSType::TREE_STRING: {
TreeEcmaString *treeSrc = TreeEcmaString::Cast(src);
EcmaString *first = EcmaString::Cast(treeSrc->GetFirst());
EcmaString *second = EcmaString::Cast(treeSrc->GetSecond());
uint32_t firstLength = first->GetLength();
uint32_t secondLength = second->GetLength();
if (secondLength >= firstLength) {
// second string is longer. So recurse over first.
WriteToFlat(first, buf, maxLength);
if (first == second) {
CopyChars(buf + firstLength, buf, firstLength);
return;
}
buf += firstLength;
maxLength -= firstLength;
src = second;
length -= firstLength;
} else {
// first string is longer. So recurse over second.
if (secondLength > 0) {
if (secondLength == 1) {
buf[firstLength] = static_cast<Char>(second->At<false>(0));
} else if (second->IsLineString() && second->IsUtf8()) {
CopyChars(buf + firstLength, second->GetDataUtf8(), secondLength);
} else {
WriteToFlat(second, buf + firstLength, maxLength - firstLength);
}
}
maxLength = firstLength;
src = first;
length -= secondLength;
}
continue;
}
default:
UNREACHABLE();
}
}
}
/* static */
template<typename DstType, typename SrcType>
void EcmaString::CopyChars(DstType *dst, SrcType *src, uint32_t count)
{
Span<SrcType> srcSp(src, count);
Span<DstType> dstSp(dst, count);
for (uint32_t i = 0; i < count; i++) {
dstSp[i] = srcSp[i];
}
}
template<bool verify>
uint16_t LineEcmaString::Get(int32_t index) const
{
int32_t length = static_cast<int32_t>(GetLength());
if (verify) {
@ -127,54 +339,56 @@ inline uint16_t EcmaString::At(int32_t index) const
return sp[index];
}
/* static */
inline EcmaString *EcmaString::AllocStringObject(const EcmaVM *vm, size_t length, bool compressed)
template<bool verify>
uint16_t TreeEcmaString::Get(int32_t index) const
{
size_t size = compressed ? ComputeSizeUtf8(length) : ComputeSizeUtf16(length);
auto string = reinterpret_cast<EcmaString *>(vm->GetFactory()->AllocStringObject(size));
string->SetLength(length, compressed);
string->SetRawHashcode(0);
return string;
}
/* static */
EcmaString *EcmaString::FastSubUtf8String(const EcmaVM *vm, const JSHandle<EcmaString> &src, uint32_t start,
uint32_t length)
{
if (length == 0) {
return *vm->GetFactory()->GetEmptyString();
int32_t length = static_cast<int32_t>(GetLength());
if (verify) {
if ((index < 0) || (index >= length)) {
return 0;
}
auto string = AllocStringObject(vm, length, true);
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
Span<uint8_t> dst(string->GetDataUtf8Writable(), length);
Span<const uint8_t> source(src->GetDataUtf8() + start, length);
EcmaString::StringCopy(dst, length, source, length);
ASSERT_PRINT(CanBeCompressed(string), "canBeCompresse does not match the real value!");
return string;
}
/* static */
EcmaString *EcmaString::FastSubUtf16String(const EcmaVM *vm, const JSHandle<EcmaString> &src, uint32_t start,
uint32_t length)
{
if (length == 0) {
return *vm->GetFactory()->GetEmptyString();
}
bool canBeCompressed = CanBeCompressed(src->GetDataUtf16() + start, length);
auto string = AllocStringObject(vm, length, canBeCompressed);
if (canBeCompressed) {
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
CopyUtf16AsUtf8(src->GetDataUtf16() + start, string->GetDataUtf8Writable(), length);
if (IsFlat()) {
EcmaString *first = EcmaString::Cast(GetFirst());
return first->At<verify>(index);
}
EcmaString *string = const_cast<TreeEcmaString *>(this);
while (true) {
if (string->IsTreeString()) {
EcmaString *first = EcmaString::Cast(TreeEcmaString::Cast(string)->GetFirst());
if (static_cast<int32_t>(first->GetLength()) > index) {
string = first;
} else {
uint32_t len = length * (sizeof(uint16_t) / sizeof(uint8_t));
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
Span<uint16_t> dst(string->GetDataUtf16Writable(), length);
Span<const uint16_t> source(src->GetDataUtf16() + start, length);
EcmaString::StringCopy(dst, len, source, len);
index -= static_cast<int32_t>(first->GetLength());
string = EcmaString::Cast(TreeEcmaString::Cast(string)->GetSecond());
}
ASSERT_PRINT(canBeCompressed == CanBeCompressed(string), "canBeCompresse does not match the real value!");
return string;
} else {
return string->At<verify>(index);
}
}
UNREACHABLE();
}
inline const uint8_t *EcmaStringAccessor::GetDataUtf8()
{
return string_->GetDataUtf8();
}
inline const uint16_t *EcmaStringAccessor::GetDataUtf16()
{
return string_->GetDataUtf16();
}
inline size_t EcmaStringAccessor::GetUtf8Length() const
{
return string_->GetUtf8Length();
}
inline void EcmaStringAccessor::ReadData(EcmaString * dst, EcmaString *src,
uint32_t start, uint32_t destSize, uint32_t length)
{
dst->WriteData(src, start, destSize, length);
}
} // namespace panda::ecmascript
#endif

View File

@ -22,71 +22,117 @@ namespace panda::ecmascript {
static constexpr int SMALL_STRING_SIZE = 128;
EcmaString *EcmaString::Concat(const EcmaVM *vm,
const JSHandle<EcmaString> &str1Handle, const JSHandle<EcmaString> &str2Handle)
const JSHandle<EcmaString> &left, const JSHandle<EcmaString> &right)
{
// allocator may trig gc and move src, need to hold it
EcmaString *string1 = *str1Handle;
EcmaString *string2 = *str2Handle;
EcmaString *strLeft = *left;
EcmaString *strRight = *right;
uint32_t leftLength = strLeft->GetLength();
if (leftLength == 0) {
return strRight;
}
uint32_t rightLength = strRight->GetLength();
if (rightLength == 0) {
return strLeft;
}
uint32_t length1 = string1->GetLength();
uint32_t length2 = string2->GetLength();
uint32_t newLength = length1 + length2;
uint32_t newLength = leftLength + rightLength;
if (newLength == 0) {
return vm->GetFactory()->GetEmptyString().GetObject<EcmaString>();
} else if (length1 == 0) {
return string2;
} else if (length2 == 0) {
return string1;
}
bool compressed = (!string1->IsUtf16() && !string2->IsUtf16());
auto newString = AllocStringObject(vm, newLength, compressed);
bool compressed = (strLeft->IsUtf8() && strRight->IsUtf8());
// if the result string is small, make a LineString
if (newLength < TreeEcmaString::MIN_TREE_ECMASTRING_LENGTH) {
ASSERT(strLeft->IsLineString());
ASSERT(strRight->IsLineString());
auto newString = CreateLineString(vm, newLength, compressed);
// retrieve strings after gc
string1 = *str1Handle;
string2 = *str2Handle;
strLeft = *left;
strRight = *right;
if (compressed) {
// copy left part
Span<uint8_t> sp(newString->GetDataUtf8Writable(), newLength);
Span<const uint8_t> src1(string1->GetDataUtf8(), length1);
EcmaString::StringCopy(sp, newLength, src1, length1);
sp = sp.SubSpan(length1);
Span<const uint8_t> src2(string2->GetDataUtf8(), length2);
EcmaString::StringCopy(sp, newLength - length1, src2, length2);
Span<const uint8_t> srcLeft(strLeft->GetDataUtf8(), leftLength);
EcmaString::MemCopyChars(sp, newLength, srcLeft, leftLength);
// copy right part
sp = sp.SubSpan(leftLength);
Span<const uint8_t> srcRight(strRight->GetDataUtf8(), rightLength);
EcmaString::MemCopyChars(sp, rightLength, srcRight, rightLength);
} else {
// copy left part
Span<uint16_t> sp(newString->GetDataUtf16Writable(), newLength);
if (!string1->IsUtf16()) {
for (uint32_t i = 0; i < length1; ++i) {
sp[i] = string1->At<false>(i);
}
if (strLeft->IsUtf8()) {
EcmaString::CopyChars(sp.data(), strLeft->GetDataUtf8(), leftLength);
} else {
Span<const uint16_t> src1(string1->GetDataUtf16(), length1);
EcmaString::StringCopy(sp, newLength << 1U, src1, length1 << 1U);
}
sp = sp.SubSpan(length1);
if (!string2->IsUtf16()) {
for (uint32_t i = 0; i < length2; ++i) {
sp[i] = string2->At<false>(i);
Span<const uint16_t> srcLeft(strLeft->GetDataUtf16(), leftLength);
EcmaString::MemCopyChars(sp, newLength << 1U, srcLeft, leftLength << 1U);
}
// copy right part
sp = sp.SubSpan(leftLength);
if (strRight->IsUtf8()) {
EcmaString::CopyChars(sp.data(), strRight->GetDataUtf8(), rightLength);
} else {
uint32_t length = length2 << 1U;
Span<const uint16_t> src2(string2->GetDataUtf16(), length2);
EcmaString::StringCopy(sp, length, src2, length);
Span<const uint16_t> srcRight(strRight->GetDataUtf16(), rightLength);
EcmaString::MemCopyChars(sp, rightLength << 1U, srcRight, rightLength << 1U);
}
}
ASSERT_PRINT(compressed == CanBeCompressed(newString), "compressed does not match the real value!");
return newString;
}
return CreateTreeString(vm, left, right, newLength, compressed);
}
/* static */
EcmaString *EcmaString::FastSubString(const EcmaVM *vm,
const JSHandle<EcmaString> &src, uint32_t start, uint32_t utf16Len)
const JSHandle<EcmaString> &src, uint32_t start, uint32_t length)
{
if (src->IsUtf8()) {
return FastSubUtf8String(vm, src, start, utf16Len);
ASSERT((start + length) <= src->GetLength());
if (length == 0) {
return *vm->GetFactory()->GetEmptyString();
}
if (start == 0 && length == src->GetLength()) {
return *src;
}
auto srcFlat = JSHandle<EcmaString>(vm->GetJSThread(), Flatten(vm, src));
if (srcFlat->IsUtf8()) {
return FastSubUtf8String(vm, srcFlat, start, length);
}
return FastSubUtf16String(vm, srcFlat, start, length);
}
void EcmaString::WriteData(EcmaString *src, uint32_t start, uint32_t destSize, uint32_t length)
{
ASSERT(IsLineString());
if (IsUtf8()) {
ASSERT(src->IsUtf8());
CVector<uint8_t> buf;
const uint8_t *data = EcmaString::GetUtf8DataFlat(src, buf);
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
if (length != 0 && memcpy_s(GetDataUtf8Writable() + start, destSize, data, length) != EOK) {
LOG_FULL(FATAL) << "memcpy_s failed";
UNREACHABLE();
}
} else if (src->IsUtf8()) {
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
CVector<uint8_t> buf;
const uint8_t *data = EcmaString::GetUtf8DataFlat(src, buf);
Span<uint16_t> to(GetDataUtf16Writable() + start, length);
Span<const uint8_t> from(data, length);
for (uint32_t i = 0; i < length; i++) {
to[i] = from[i];
}
} else {
CVector<uint16_t> buf;
const uint16_t *data = EcmaString::GetUtf16DataFlat(src, buf);
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
if (length != 0 && memcpy_s(GetDataUtf16Writable() + start,
destSize * sizeof(uint16_t), data, length * sizeof(uint16_t)) != EOK) {
LOG_FULL(FATAL) << "memcpy_s failed";
UNREACHABLE();
}
}
return FastSubUtf16String(vm, src, start, utf16Len);
}
template<typename T1, typename T2>
@ -102,11 +148,15 @@ int32_t CompareStringSpan(Span<T1> &lhsSp, Span<T2> &rhsSp, int32_t count)
return 0;
}
int32_t EcmaString::Compare(EcmaString *lhs, EcmaString *rhs)
int32_t EcmaString::Compare(const EcmaVM *vm, const JSHandle<EcmaString> &left, const JSHandle<EcmaString> &right)
{
if (lhs == rhs) {
if (*left == *right) {
return 0;
}
auto leftFlat = JSHandle<EcmaString>(vm->GetJSThread(), Flatten(vm, left));
auto rightFlat = JSHandle<EcmaString>(vm->GetJSThread(), Flatten(vm, right));
EcmaString *lhs = *leftFlat;
EcmaString *rhs = *rightFlat;
int32_t lhsCount = static_cast<int32_t>(lhs->GetLength());
int32_t rhsCount = static_cast<int32_t>(rhs->GetLength());
int32_t countDiff = lhsCount - rhsCount;
@ -198,8 +248,11 @@ int32_t EcmaString::LastIndexOf(Span<const T1> &lhsSp, Span<const T2> &rhsSp, in
return -1;
}
int32_t EcmaString::IndexOf(EcmaString *lhs, EcmaString *rhs, int pos)
int32_t EcmaString::IndexOf(const EcmaVM *vm,
const JSHandle<EcmaString> &receiver, const JSHandle<EcmaString> &search, int pos)
{
EcmaString *lhs = *receiver;
EcmaString *rhs = *search;
if (lhs == nullptr || rhs == nullptr) {
return -1;
}
@ -222,6 +275,16 @@ int32_t EcmaString::IndexOf(EcmaString *lhs, EcmaString *rhs, int pos)
if (max < 0) {
return -1;
}
if (pos + rhsCount > lhsCount) {
return -1;
}
auto receiverFlat = JSHandle<EcmaString>(vm->GetJSThread(), Flatten(vm, receiver));
auto searchFlat = JSHandle<EcmaString>(vm->GetJSThread(), Flatten(vm, search));
lhs = *receiverFlat;
rhs = *searchFlat;
if (rhs->IsUtf8() && lhs->IsUtf8()) {
Span<const uint8_t> lhsSp(lhs->GetDataUtf8(), lhsCount);
Span<const uint8_t> rhsSp(rhs->GetDataUtf8(), rhsCount);
@ -239,8 +302,11 @@ int32_t EcmaString::IndexOf(EcmaString *lhs, EcmaString *rhs, int pos)
}
}
int32_t EcmaString::LastIndexOf(EcmaString *lhs, EcmaString *rhs, int pos)
int32_t EcmaString::LastIndexOf(const EcmaVM *vm,
const JSHandle<EcmaString> &receiver, const JSHandle<EcmaString> &search, int pos)
{
EcmaString *lhs = *receiver;
EcmaString *rhs = *search;
if (lhs == nullptr || rhs == nullptr) {
return -1;
}
@ -267,6 +333,11 @@ int32_t EcmaString::LastIndexOf(EcmaString *lhs, EcmaString *rhs, int pos)
return pos;
}
auto receiverFlat = JSHandle<EcmaString>(vm->GetJSThread(), Flatten(vm, receiver));
auto searchFlat = JSHandle<EcmaString>(vm->GetJSThread(), Flatten(vm, search));
lhs = *receiverFlat;
rhs = *searchFlat;
if (rhs->IsUtf8() && lhs->IsUtf8()) {
Span<const uint8_t> lhsSp(lhs->GetDataUtf8(), lhsCount);
Span<const uint8_t> rhsSp(rhs->GetDataUtf8(), rhsCount);
@ -289,9 +360,13 @@ std::u16string EcmaString::ToU16String(uint32_t len)
uint32_t length = len > 0 ? len : GetLength();
std::u16string result;
if (IsUtf16()) {
result = base::StringHelper::Utf16ToU16String(GetDataUtf16(), length);
CVector<uint16_t> buf;
const uint16_t *data = EcmaString::GetUtf16DataFlat(this, buf);
result = base::StringHelper::Utf16ToU16String(data, length);
} else {
result = base::StringHelper::Utf8ToU16String(GetDataUtf8(), length);
CVector<uint8_t> buf;
const uint8_t *data = EcmaString::GetUtf8DataFlat(this, buf);
result = base::StringHelper::Utf8ToU16String(data, length);
}
return result;
}
@ -299,6 +374,7 @@ std::u16string EcmaString::ToU16String(uint32_t len)
// static
bool EcmaString::CanBeCompressed(const EcmaString *string)
{
ASSERT(string->IsLineString());
if (string->IsUtf8()) {
return CanBeCompressed(string->GetDataUtf8(), string->GetLength());
}
@ -336,18 +412,10 @@ bool EcmaString::CanBeCompressed(const uint16_t *utf16Data, uint32_t utf16Len)
return isCompressed;
}
/* static */
void EcmaString::CopyUtf16AsUtf8(const uint16_t *utf16From, uint8_t *utf8To, uint32_t utf16Len)
{
Span<const uint16_t> from(utf16From, utf16Len);
Span<uint8_t> to(utf8To, utf16Len);
for (uint32_t i = 0; i < utf16Len; i++) {
to[i] = from[i];
}
}
bool EcmaString::EqualToSplicedString(const EcmaString *str1, const EcmaString *str2)
{
ASSERT(IsLineString());
ASSERT(str1->IsLineString() && str2->IsLineString());
if (GetLength() != str1->GetLength() + str2->GetLength()) {
return false;
}
@ -377,23 +445,77 @@ bool EcmaString::EqualToSplicedString(const EcmaString *str1, const EcmaString *
bool EcmaString::StringsAreEqualSameUtfEncoding(EcmaString *str1, EcmaString *str2)
{
if (str1->IsUtf16()) {
Span<const uint16_t> data1(str1->GetDataUtf16(), str1->GetLength());
Span<const uint16_t> data2(str2->GetDataUtf16(), str1->GetLength());
return EcmaString::StringsAreEquals(data1, data2);
CVector<uint16_t> buf1;
CVector<uint16_t> buf2;
const uint16_t *data1 = EcmaString::GetUtf16DataFlat(str1, buf1);
const uint16_t *data2 = EcmaString::GetUtf16DataFlat(str2, buf2);
Span<const uint16_t> sp1(data1, str1->GetLength());
Span<const uint16_t> sp2(data2, str2->GetLength());
return EcmaString::StringsAreEquals(sp1, sp2);
} else { // NOLINT(readability-else-after-return)
Span<const uint8_t> data1(str1->GetDataUtf8(), str1->GetLength());
Span<const uint8_t> data2(str2->GetDataUtf8(), str1->GetLength());
return EcmaString::StringsAreEquals(data1, data2);
CVector<uint8_t> buf1;
CVector<uint8_t> buf2;
const uint8_t *data1 = EcmaString::GetUtf8DataFlat(str1, buf1);
const uint8_t *data2 = EcmaString::GetUtf8DataFlat(str2, buf2);
Span<const uint8_t> sp1(data1, str1->GetLength());
Span<const uint8_t> sp2(data2, str2->GetLength());
return EcmaString::StringsAreEquals(sp1, sp2);
}
}
bool EcmaString::StringsAreEqual(const EcmaVM *vm, const JSHandle<EcmaString> &str1, const JSHandle<EcmaString> &str2)
{
if (str1 == str2) {
return true;
}
if (str1->IsUtf16() != str2->IsUtf16()) {
return false;
}
uint32_t str1Len = str1->GetLength();
if (str1Len != str2->GetLength()) {
return false;
}
if (str1Len == 0) {
return true;
}
uint32_t str1Hash;
uint32_t str2Hash;
if (str1->TryGetHashCode(&str1Hash) && str2->TryGetHashCode(&str2Hash)) {
if (str1Hash != str2Hash) {
return false;
}
}
auto str1Flat = JSHandle<EcmaString>(vm->GetJSThread(), Flatten(vm, str1));
auto str2Flat = JSHandle<EcmaString>(vm->GetJSThread(), Flatten(vm, str2));
return StringsAreEqualSameUtfEncoding(*str1Flat, *str2Flat);
}
/* static */
bool EcmaString::StringsAreEqual(EcmaString *str1, EcmaString *str2)
{
if ((str1->IsUtf16() != str2->IsUtf16()) || (str1->GetLength() != str2->GetLength()) ||
(str1->GetHashcode() != str2->GetHashcode())) {
if (str1 == str2) {
return true;
}
if (str1->IsUtf16() != str2->IsUtf16()) {
return false;
}
uint32_t str1Len = str1->GetLength();
if (str1Len != str2->GetLength()) {
return false;
}
if (str1Len == 0) {
return true;
}
uint32_t str1Hash;
uint32_t str2Hash;
if (str1->TryGetHashCode(&str1Hash) && str2->TryGetHashCode(&str2Hash)) {
if (str1Hash != str2Hash) {
return false;
}
}
return StringsAreEqualSameUtfEncoding(str1, str2);
}
@ -404,33 +526,38 @@ bool EcmaString::StringsAreEqualUtf8(const EcmaString *str1, const uint8_t *utf8
if (canBeCompress != str1->IsUtf8()) {
return false;
}
if (canBeCompress && str1->GetLength() != utf8Len) {
return false;
}
if (canBeCompress) {
Span<const uint8_t> data1(str1->GetDataUtf8(), utf8Len);
CVector<uint8_t> buf;
Span<const uint8_t> data1(EcmaString::GetUtf8DataFlat(str1, buf), utf8Len);
Span<const uint8_t> data2(utf8Data, utf8Len);
return EcmaString::StringsAreEquals(data1, data2);
}
return IsUtf8EqualsUtf16(utf8Data, utf8Len, str1->GetDataUtf16(), str1->GetLength());
CVector<uint16_t> buf;
uint32_t length = str1->GetLength();
const uint16_t *data = EcmaString::GetUtf16DataFlat(str1, buf);
return IsUtf8EqualsUtf16(utf8Data, utf8Len, data, length);
}
/* static */
bool EcmaString::StringsAreEqualUtf16(const EcmaString *str1, const uint16_t *utf16Data, uint32_t utf16Len)
{
bool result = false;
if (str1->GetLength() != utf16Len) {
result = false;
} else if (!str1->IsUtf16()) {
result = IsUtf8EqualsUtf16(str1->GetDataUtf8(), str1->GetLength(), utf16Data, utf16Len);
} else {
Span<const uint16_t> data1(str1->GetDataUtf16(), str1->GetLength());
Span<const uint16_t> data2(utf16Data, utf16Len);
result = EcmaString::StringsAreEquals(data1, data2);
uint32_t length = str1->GetLength();
if (length != utf16Len) {
return false;
}
if (str1->IsUtf8()) {
CVector<uint8_t> buf;
const uint8_t *data = EcmaString::GetUtf8DataFlat(str1, buf);
return IsUtf8EqualsUtf16(data, length, utf16Data, utf16Len);
} else {
CVector<uint16_t> buf;
Span<const uint16_t> data1(EcmaString::GetUtf16DataFlat(str1, buf), length);
Span<const uint16_t> data2(utf16Data, utf16Len);
return EcmaString::StringsAreEquals(data1, data2);
}
return result;
}
/* static */
@ -451,7 +578,7 @@ bool EcmaString::StringsAreEquals(Span<const T> &str1, Span<const T> &str2)
}
template<typename T>
bool EcmaString::StringCopy(Span<T> &dst, size_t dstMax, Span<const T> &src, size_t count)
bool EcmaString::MemCopyChars(Span<T> &dst, size_t dstMax, Span<const T> &src, size_t count)
{
ASSERT(dstMax >= count);
ASSERT(dst.Size() >= src.Size());
@ -463,7 +590,7 @@ bool EcmaString::StringCopy(Span<T> &dst, size_t dstMax, Span<const T> &src, siz
}
template<class T>
static int32_t ComputeHashForData(const T *data, size_t size, uint32_t hashSeed)
static uint32_t ComputeHashForData(const T *data, size_t size, uint32_t hashSeed)
{
uint32_t hash = hashSeed;
Span<const T> sp(data, size);
@ -471,40 +598,31 @@ static int32_t ComputeHashForData(const T *data, size_t size, uint32_t hashSeed)
constexpr size_t SHIFT = 5;
hash = (hash << SHIFT) - hash + c;
}
return static_cast<int32_t>(hash);
}
static int32_t ComputeHashForUtf8(const uint8_t *utf8Data, uint32_t utf8DataLength)
{
if (utf8Data == nullptr) {
return 0;
}
uint32_t hash = 0;
const uint8_t *end = utf8Data + utf8DataLength;
while (utf8Data < end) { // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
constexpr size_t SHIFT = 5;
hash = (hash << SHIFT) - hash + *utf8Data++; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
}
return static_cast<int32_t>(hash);
return hash;
}
uint32_t EcmaString::ComputeHashcode(uint32_t hashSeed) const
{
int32_t hash;
if (!IsUtf16()) {
hash = ComputeHashForData(GetDataUtf8(), GetLength(), hashSeed);
uint32_t hash;
uint32_t length = GetLength();
if (IsUtf8()) {
CVector<uint8_t> buf;
const uint8_t *data = EcmaString::GetUtf8DataFlat(this, buf);
hash = ComputeHashForData(data, length, hashSeed);
} else {
hash = ComputeHashForData(GetDataUtf16(), GetLength(), hashSeed);
CVector<uint16_t> buf;
const uint16_t *data = EcmaString::GetUtf16DataFlat(this, buf);
hash = ComputeHashForData(data, length, hashSeed);
}
return static_cast<uint32_t>(hash);
return hash;
}
/* static */
uint32_t EcmaString::ComputeHashcodeUtf8(const uint8_t *utf8Data, size_t utf8Len, bool canBeCompress)
{
int32_t hash;
uint32_t hash;
if (canBeCompress) {
hash = ComputeHashForUtf8(utf8Data, utf8Len);
hash = ComputeHashForData(utf8Data, utf8Len, 0);
} else {
auto utf16Len = base::utf_helper::Utf8ToUtf16Size(utf8Data, utf8Len);
CVector<uint16_t> tmpBuffer(utf16Len);
@ -513,7 +631,7 @@ uint32_t EcmaString::ComputeHashcodeUtf8(const uint8_t *utf8Data, size_t utf8Len
ASSERT(len == utf16Len);
hash = ComputeHashForData(tmpBuffer.data(), utf16Len, 0);
}
return static_cast<uint32_t>(hash);
return hash;
}
/* static */
@ -549,7 +667,9 @@ bool EcmaString::ToElementIndex(uint32_t *index)
return false;
}
uint32_t c = GetDataUtf8()[0];
CVector<uint8_t> buf;
const uint8_t *data = EcmaString::GetUtf8DataFlat(this, buf);
uint32_t c = data[0];
uint64_t n = 0;
if (c == '0') {
*index = 0;
@ -558,7 +678,7 @@ bool EcmaString::ToElementIndex(uint32_t *index)
if (c > '0' && c <= '9') {
n = c - '0';
for (uint32_t i = 1; i < len; i++) {
c = GetDataUtf8()[i]; // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
c = data[i]; // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
if (c < '0' || c > '9') {
return false;
}
@ -583,7 +703,9 @@ bool EcmaString::ToTypedArrayIndex(uint32_t *index)
return false;
}
uint32_t c = GetDataUtf8()[0]; // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
CVector<uint8_t> buf;
const uint8_t *data = EcmaString::GetUtf8DataFlat(this, buf);
uint32_t c = data[0]; // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
uint64_t n = 0;
if (c == '0') {
*index = 0;
@ -592,7 +714,7 @@ bool EcmaString::ToTypedArrayIndex(uint32_t *index)
if (c > '0' && c <= '9') {
n = c - '0';
for (uint32_t i = 1; i < len; i++) {
c = GetDataUtf8()[i]; // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
c = data[i]; // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
if (c >= '0' && c <= '9') {
// NOLINTNEXTLINE(readability-magic-numbers)
n = n * 10 + (c - '0'); // 10: decimal factor
@ -637,17 +759,18 @@ EcmaString *EcmaString::TrimBody(const JSThread *thread, const JSHandle<EcmaStri
/* static */
EcmaString *EcmaString::ToLower(const EcmaVM *vm, const JSHandle<EcmaString> &src)
{
uint32_t srcLength = src->GetLength();
auto srcFlat = JSHandle<EcmaString>(vm->GetJSThread(), Flatten(vm, src));
uint32_t srcLength = srcFlat->GetLength();
auto factory = vm->GetFactory();
if (src->IsUtf16()) {
std::u16string u16str = base::StringHelper::Utf16ToU16String(src->GetDataUtf16(), srcLength);
if (srcFlat->IsUtf16()) {
std::u16string u16str = base::StringHelper::Utf16ToU16String(srcFlat->GetDataUtf16(), srcLength);
std::string res = base::StringHelper::ToLower(u16str);
return *(factory->NewFromStdString(res));
} else {
const char start = 'A';
const char end = 'Z';
auto newString = AllocStringObject(vm, srcLength, true);
Span<uint8_t> data(src->GetDataUtf8Writable(), srcLength);
auto newString = CreateLineString(vm, srcLength, true);
Span<uint8_t> data(srcFlat->GetDataUtf8Writable(), srcLength);
auto newStringPtr = newString->GetDataUtf8Writable();
for (uint32_t index = 0; index < srcLength; ++index) {
if (base::StringHelper::Utf8CharInRange(data[index], start, end)) {
@ -663,17 +786,18 @@ EcmaString *EcmaString::ToLower(const EcmaVM *vm, const JSHandle<EcmaString> &sr
/* static */
EcmaString *EcmaString::ToUpper(const EcmaVM *vm, const JSHandle<EcmaString> &src)
{
uint32_t srcLength = src->GetLength();
auto srcFlat = JSHandle<EcmaString>(vm->GetJSThread(), Flatten(vm, src));
uint32_t srcLength = srcFlat->GetLength();
auto factory = vm->GetFactory();
if (src->IsUtf16()) {
std::u16string u16str = base::StringHelper::Utf16ToU16String(src->GetDataUtf16(), srcLength);
if (srcFlat->IsUtf16()) {
std::u16string u16str = base::StringHelper::Utf16ToU16String(srcFlat->GetDataUtf16(), srcLength);
std::string res = base::StringHelper::ToUpper(u16str);
return *(factory->NewFromStdString(res));
} else {
const char start = 'a';
const char end = 'z';
auto newString = AllocStringObject(vm, srcLength, true);
Span<uint8_t> data(src->GetDataUtf8Writable(), srcLength);
auto newString = CreateLineString(vm, srcLength, true);
Span<uint8_t> data(srcFlat->GetDataUtf8Writable(), srcLength);
auto newStringPtr = newString->GetDataUtf8Writable();
for (uint32_t index = 0; index < srcLength; ++index) {
if (base::StringHelper::Utf8CharInRange(data[index], start, end)) {
@ -690,7 +814,8 @@ EcmaString *EcmaString::ToUpper(const EcmaVM *vm, const JSHandle<EcmaString> &sr
EcmaString *EcmaString::ToLocaleLower(const EcmaVM *vm, const JSHandle<EcmaString> &src, const icu::Locale &locale)
{
auto factory = vm->GetFactory();
std::u16string utf16 = src->ToU16String();
auto srcFlat = JSHandle<EcmaString>(vm->GetJSThread(), Flatten(vm, src));
std::u16string utf16 = srcFlat->ToU16String();
std::string res = base::StringHelper::ToLocaleLower(utf16, locale);
return *(factory->NewFromStdString(res));
}
@ -699,26 +824,125 @@ EcmaString *EcmaString::ToLocaleLower(const EcmaVM *vm, const JSHandle<EcmaStrin
EcmaString *EcmaString::ToLocaleUpper(const EcmaVM *vm, const JSHandle<EcmaString> &src, const icu::Locale &locale)
{
auto factory = vm->GetFactory();
std::u16string utf16 = src->ToU16String();
auto srcFlat = JSHandle<EcmaString>(vm->GetJSThread(), Flatten(vm, src));
std::u16string utf16 = srcFlat->ToU16String();
std::string res = base::StringHelper::ToLocaleUpper(utf16, locale);
return *(factory->NewFromStdString(res));
}
EcmaString *EcmaString::Trim(const JSThread *thread, const JSHandle<EcmaString> &src, TrimMode mode)
{
uint32_t srcLen = src->GetLength();
auto srcFlat = JSHandle<EcmaString>(thread, Flatten(thread->GetEcmaVM(), src));
uint32_t srcLen = srcFlat->GetLength();
if (UNLIKELY(srcLen == 0)) {
return EcmaString::Cast(thread->GlobalConstants()->GetEmptyString().GetTaggedObject());
}
if (src->IsUtf8()) {
Span<const uint8_t> data(src->GetDataUtf8(), srcLen);
return TrimBody(thread, src, data, mode);
if (srcFlat->IsUtf8()) {
Span<const uint8_t> data(srcFlat->GetDataUtf8(), srcLen);
return TrimBody(thread, srcFlat, data, mode);
} else {
Span<const uint16_t> data(src->GetDataUtf16(), srcLen);
return TrimBody(thread, src, data, mode);
Span<const uint16_t> data(srcFlat->GetDataUtf16(), srcLen);
return TrimBody(thread, srcFlat, data, mode);
}
}
EcmaString *EcmaString::SlowFlatten(const EcmaVM *vm, const JSHandle<TreeEcmaString> &string)
{
auto thread = vm->GetJSThread();
ASSERT(EcmaString::Cast(string->GetSecond())->GetLength() != 0);
uint32_t length = string->GetLength();
EcmaString *result = nullptr;
if (string->IsUtf8()) {
result = CreateLineString(vm, length, true);
WriteToFlat<uint8_t>(*string, result->GetDataUtf8Writable(), length);
} else {
result = CreateLineString(vm, length, false);
WriteToFlat<uint16_t>(*string, result->GetDataUtf16Writable(), length);
}
string->SetFirst(thread, JSTaggedValue(result));
string->SetSecond(thread, JSTaggedValue(*vm->GetFactory()->GetEmptyString()));
return result;
}
EcmaString *EcmaString::Flatten(const EcmaVM *vm, const JSHandle<EcmaString> &string)
{
EcmaString *s = *string;
if (s->IsLineString()) {
return s;
}
if (s->IsTreeString()) {
JSHandle<TreeEcmaString> tree = JSHandle<TreeEcmaString>::Cast(string);
if (!tree->IsFlat()) {
return SlowFlatten(vm, tree);
}
s = EcmaString::Cast(tree->GetFirst());
}
return s;
}
EcmaString *EcmaString::FlattenNoGC(const EcmaVM *vm, EcmaString *string)
{
DISALLOW_GARBAGE_COLLECTION;
if (string->IsLineString()) {
return string;
}
if (string->IsTreeString()) {
TreeEcmaString *tree = TreeEcmaString::Cast(string);
if (tree->IsFlat()) {
string = EcmaString::Cast(tree->GetFirst());
} else {
uint32_t length = tree->GetLength();
EcmaString *result = nullptr;
if (tree->IsUtf8()) {
result = CreateLineStringNoGC(vm, length, true);
WriteToFlat<uint8_t>(tree, result->GetDataUtf8Writable(), length);
} else {
result = CreateLineStringNoGC(vm, length, false);
WriteToFlat<uint16_t>(tree, result->GetDataUtf16Writable(), length);
}
tree->SetFirst(vm->GetJSThread(), JSTaggedValue(result));
tree->SetSecond(vm->GetJSThread(), JSTaggedValue(*vm->GetFactory()->GetEmptyString()));
return result;
}
}
return string;
}
const uint8_t *EcmaString::GetUtf8DataFlat(const EcmaString *src, CVector<uint8_t> &buf)
{
ASSERT(src->IsUtf8());
uint32_t length = src->GetLength();
EcmaString *string = const_cast<EcmaString *>(src);
if (string->IsTreeString()) {
if (string->IsFlat()) {
string = EcmaString::Cast(TreeEcmaString::Cast(string)->GetFirst());
} else {
buf.reserve(length);
WriteToFlat(string, buf.data(), length);
return buf.data();
}
}
return string->GetDataUtf8();
}
const uint16_t *EcmaString::GetUtf16DataFlat(const EcmaString *src, CVector<uint16_t> &buf)
{
ASSERT(src->IsUtf16());
uint32_t length = src->GetLength();
EcmaString *string = const_cast<EcmaString *>(src);
if (string->IsTreeString()) {
if (string->IsFlat()) {
string = EcmaString::Cast(TreeEcmaString::Cast(string)->GetFirst());
} else {
buf.reserve(length);
WriteToFlat(string, buf.data(), length);
return buf.data();
}
}
return string->GetDataUtf16();
}
EcmaStringAccessor::EcmaStringAccessor(EcmaString *string)
{
ASSERT(string != nullptr);
@ -748,7 +972,7 @@ std::string EcmaStringAccessor::ToStdString(StringConvertedUsage usage)
return "";
}
bool modify = (usage != StringConvertedUsage::PRINT);
[[maybe_unused]] CVector<uint8_t> buf;
CVector<uint8_t> buf;
Span<const uint8_t> sp = string_->ToUtf8Span(buf, modify);
std::string res;
res.reserve(sp.size());
@ -764,7 +988,7 @@ CString EcmaStringAccessor::ToCString(StringConvertedUsage usage)
return "";
}
bool modify = (usage != StringConvertedUsage::PRINT);
[[maybe_unused]] CVector<uint8_t> buf;
CVector<uint8_t> buf;
Span<const uint8_t> sp = string_->ToUtf8Span(buf, modify);
CString res;
res.reserve(sp.size());

View File

@ -22,6 +22,7 @@
#include "ecmascript/base/utf_helper.h"
#include "ecmascript/ecma_macros.h"
#include "ecmascript/js_hclass.h"
#include "ecmascript/js_tagged_value.h"
#include "ecmascript/mem/barriers.h"
#include "ecmascript/mem/space.h"
@ -36,10 +37,11 @@ namespace ecmascript {
template<typename T>
class JSHandle;
class EcmaVM;
class LineEcmaString;
class TreeEcmaString;
class EcmaString : public TaggedObject {
public:
friend class EcmaStringAccessor;
CAST_CHECK(EcmaString, IsString);
static constexpr uint32_t STRING_COMPRESSED_BIT = 0x1;
@ -49,9 +51,6 @@ public:
// In last bit of mix_length we store if this string is compressed or not.
ACCESSORS_PRIMITIVE_FIELD(MixLength, uint32_t, MIX_LENGTH_OFFSET, HASHCODE_OFFSET)
ACCESSORS_PRIMITIVE_FIELD(RawHashcode, uint32_t, HASHCODE_OFFSET, SIZE)
// DATA_OFFSET: the string data stored after the string header.
// Data can be stored in utf8 or utf16 form according to compressed bit.
static constexpr size_t DATA_OFFSET = SIZE; // DATA_OFFSET equal to Empty String size
enum CompressedStatus {
STRING_COMPRESSED,
@ -65,84 +64,153 @@ public:
};
private:
friend class EcmaStringAccessor;
friend class LineEcmaString;
friend class TreeEcmaString;
static EcmaString *CreateEmptyString(const EcmaVM *vm);
static EcmaString *CreateFromUtf8(const EcmaVM *vm, const uint8_t *utf8Data, uint32_t utf8Len, bool canBeCompress,
MemSpaceType type = MemSpaceType::SEMI_SPACE);
static EcmaString *CreateFromUtf8(const EcmaVM *vm, const uint8_t *utf8Data, uint32_t utf8Len,
bool canBeCompress, MemSpaceType type = MemSpaceType::SEMI_SPACE);
static EcmaString *CreateFromUtf16(const EcmaVM *vm, const uint16_t *utf16Data, uint32_t utf16Len,
bool canBeCompress, MemSpaceType type = MemSpaceType::SEMI_SPACE);
static EcmaString *CreateLineString(const EcmaVM *vm, size_t length, bool compressed);
static EcmaString *CreateLineStringNoGC(const EcmaVM *vm, size_t length, bool compressed);
static EcmaString *CreateLineStringWithSpaceType(const EcmaVM *vm,
size_t length, bool compressed, MemSpaceType type);
static EcmaString *CreateTreeString(const EcmaVM *vm,
const JSHandle<EcmaString> &left, const JSHandle<EcmaString> &right, uint32_t length, bool compressed);
static EcmaString *Concat(const EcmaVM *vm,
const JSHandle<EcmaString> &str1Handle, const JSHandle<EcmaString> &str2Handle);
const JSHandle<EcmaString> &left, const JSHandle<EcmaString> &right);
static EcmaString *FastSubString(const EcmaVM *vm,
const JSHandle<EcmaString> &src, uint32_t start, uint32_t length);
template<bool verify = true>
uint16_t At(int32_t index) const;
static int32_t Compare(EcmaString *lhs, EcmaString *rhs);
bool IsUtf16() const
{
return (GetMixLength() & STRING_COMPRESSED_BIT) == STRING_UNCOMPRESSED;
}
// require src is LineString
// not change src data structure
static inline EcmaString *FastSubUtf8String(const EcmaVM *vm,
const JSHandle<EcmaString> &src, uint32_t start, uint32_t length);
// require src is LineString
// not change src data structure
static inline EcmaString *FastSubUtf16String(const EcmaVM *vm,
const JSHandle<EcmaString> &src, uint32_t start, uint32_t length);
bool IsUtf8() const
{
return (GetMixLength() & STRING_COMPRESSED_BIT) == STRING_COMPRESSED;
}
static size_t ComputeDataSizeUtf16(uint32_t length)
bool IsUtf16() const
{
return length * sizeof(uint16_t);
return (GetMixLength() & STRING_COMPRESSED_BIT) == STRING_UNCOMPRESSED;
}
/**
* Methods for uncompressed strings (UTF16):
*/
static size_t ComputeSizeUtf16(uint32_t utf16Len)
// require is LineString
inline uint16_t *GetData() const;
inline const uint8_t *GetDataUtf8() const;
inline const uint16_t *GetDataUtf16() const;
// require is LineString
inline uint8_t *GetDataUtf8Writable();
inline uint16_t *GetDataUtf16Writable();
uint32_t GetLength() const
{
return DATA_OFFSET + ComputeDataSizeUtf16(utf16Len);
return GetMixLength() >> 2U;
}
inline uint16_t *GetData() const
void SetLength(uint32_t length, bool compressed = false)
{
return reinterpret_cast<uint16_t *>(ToUintPtr(this) + DATA_OFFSET);
ASSERT(length < 0x40000000U);
// Use 0u for compressed/utf8 expression
SetMixLength((length << 2U) | (compressed ? STRING_COMPRESSED : STRING_UNCOMPRESSED));
}
const uint16_t *GetDataUtf16() const
inline size_t GetUtf8Length(bool modify = true) const;
void SetIsInternString()
{
LOG_ECMA_IF(!IsUtf16(), FATAL) << "EcmaString: Read data as utf16 for utf8 string";
return GetData();
SetMixLength(GetMixLength() | STRING_INTERN_BIT);
}
/**
* Methods for compresses strings (UTF8 or LATIN1):
*/
static size_t ComputeSizeUtf8(uint32_t utf8Len)
bool IsInternString() const
{
return DATA_OFFSET + utf8Len;
return (GetMixLength() & STRING_INTERN_BIT) != 0;
}
/**
* It's Utf8 format, but without 0 in the end.
*/
const uint8_t *GetDataUtf8() const
void ClearInternStringFlag()
{
ASSERT_PRINT(IsUtf8(), "EcmaString: Read data as utf8 for utf16 string");
return reinterpret_cast<uint8_t *>(GetData());
SetMixLength(GetMixLength() & ~STRING_INTERN_BIT);
}
size_t GetUtf8Length(bool modify = true) const
bool TryGetHashCode(uint32_t *hash)
{
if (!IsUtf16()) {
return GetLength() + 1; // add place for zero in the end
uint32_t hashcode = GetRawHashcode();
if (hashcode == 0 && GetLength() != 0) {
return false;
}
return base::utf_helper::Utf16ToUtf8Size(GetData(), GetLength(), modify);
*hash = hashcode;
return true;
}
size_t GetUtf16Length() const
// not change this data structure.
// if string is not flat, this func has low efficiency.
uint32_t PUBLIC_API GetHashcode()
{
return GetLength();
uint32_t hashcode = GetRawHashcode();
// GetLength() == 0 means it's an empty array.No need to computeHashCode again when hashseed is 0.
if (hashcode == 0 && GetLength() != 0) {
hashcode = ComputeHashcode(0);
SetRawHashcode(hashcode);
}
return hashcode;
}
// not change this data structure.
// if string is not flat, this func has low efficiency.
uint32_t PUBLIC_API ComputeHashcode(uint32_t hashSeed) const;
static uint32_t ComputeHashcodeUtf8(const uint8_t *utf8Data, size_t utf8Len, bool canBeCompress);
static uint32_t ComputeHashcodeUtf16(const uint16_t *utf16Data, uint32_t length);
template<bool verify = true>
uint16_t At(int32_t index) const;
// require is LineString
void WriteData(uint32_t index, uint16_t src);
// can change left and right data structure
static int32_t Compare(const EcmaVM *vm, const JSHandle<EcmaString> &left, const JSHandle<EcmaString> &right);
template<typename T>
// Check that two spans are equal. Should have the same length.
static bool StringsAreEquals(Span<const T> &str1, Span<const T> &str2);
// Converts utf8Data to utf16 and compare it with given utf16_data.
static bool IsUtf8EqualsUtf16(const uint8_t *utf8Data, size_t utf8Len, const uint16_t *utf16Data,
uint32_t utf16Len);
// Compares string1 + string2 by bytes, It doesn't check canonical unicode equivalence.
bool EqualToSplicedString(const EcmaString *str1, const EcmaString *str2);
// Compares strings by bytes, It doesn't check canonical unicode equivalence.
static bool StringsAreEqual(const EcmaVM *vm, const JSHandle<EcmaString> &str1, const JSHandle<EcmaString> &str2);
// Compares strings by bytes, It doesn't check canonical unicode equivalence.
static bool StringsAreEqual(EcmaString *str1, EcmaString *str2);
// Two strings have the same type of utf encoding format.
static bool StringsAreEqualSameUtfEncoding(EcmaString *str1, EcmaString *str2);
// Compares strings by bytes, It doesn't check canonical unicode equivalence.
// not change str1 data structure.
// if str1 is not flat, this func has low efficiency.
static bool StringsAreEqualUtf8(const EcmaString *str1, const uint8_t *utf8Data, uint32_t utf8Len,
bool canBeCompress);
// Compares strings by bytes, It doesn't check canonical unicode equivalence.
// not change str1 data structure.
// if str1 is not flat, this func has low efficiency.
static bool StringsAreEqualUtf16(const EcmaString *str1, const uint16_t *utf16Data, uint32_t utf16Len);
// can change receiver and search data structure
static int32_t IndexOf(const EcmaVM *vm,
const JSHandle<EcmaString> &receiver, const JSHandle<EcmaString> &search, int pos = 0);
// can change receiver and search data structure
static int32_t LastIndexOf(const EcmaVM *vm,
const JSHandle<EcmaString> &receiver, const JSHandle<EcmaString> &search, int pos = 0);
inline size_t CopyDataUtf8(uint8_t *buf, size_t maxLength, bool modify = true) const
{
@ -184,24 +252,28 @@ private:
}
// 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, GetDataUtf8() + start, maxLength) != EOK) {
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, GetDataUtf8() + start, length) != EOK) {
if (memcpy_s(buf, maxLength, data + start, length) != EOK) {
LOG_FULL(FATAL) << "memcpy_s failed when length <= maxlength";
UNREACHABLE();
}
return length;
}
CVector<uint16_t> tmpBuf;
const uint16_t *data = GetUtf16DataFlat(this, tmpBuf);
if (length > maxLength) {
return base::utf_helper::ConvertRegionUtf16ToUtf8(GetDataUtf16(), buf, maxLength, maxLength, start,
return base::utf_helper::ConvertRegionUtf16ToUtf8(data, buf, maxLength, maxLength, start,
modify, isWriteBuffer);
}
return base::utf_helper::ConvertRegionUtf16ToUtf8(GetDataUtf16(), buf, length, maxLength, start,
return base::utf_helper::ConvertRegionUtf16ToUtf8(data, buf, length, maxLength, start,
modify, isWriteBuffer);
}
@ -221,14 +293,18 @@ private:
}
if (IsUtf16()) {
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
if (memcpy_s(buf, ComputeDataSizeUtf16(maxLength), GetDataUtf16() + start, ComputeDataSizeUtf16(length)) !=
CVector<uint16_t> tmpBuf;
const uint16_t *data = EcmaString::GetUtf16DataFlat(this, tmpBuf);
if (memcpy_s(buf, maxLength * sizeof(uint16_t), data + start, length * sizeof(uint16_t)) !=
EOK) {
LOG_FULL(FATAL) << "memcpy_s failed";
UNREACHABLE();
}
return length;
}
return base::utf_helper::ConvertRegionUtf8ToUtf16(GetDataUtf8(), buf, len, maxLength, start);
CVector<uint8_t> tmpBuf;
const uint8_t *data = EcmaString::GetUtf8DataFlat(this, tmpBuf);
return base::utf_helper::ConvertRegionUtf8ToUtf16(data, buf, len, maxLength, start);
}
std::u16string ToU16String(uint32_t len = 0);
@ -238,7 +314,7 @@ private:
uint8_t *buf = nullptr;
auto length = GetLength();
if (IsUtf16()) {
auto size = ComputeDataSizeUtf16(length);
auto size = length * sizeof(uint16_t);
buf = new uint8_t[size]();
CopyDataUtf16(reinterpret_cast<uint16_t *>(buf), length);
} else {
@ -248,147 +324,98 @@ private:
return std::unique_ptr<uint8_t[]>(buf);
}
Span<const uint8_t> ToUtf8Span([[maybe_unused]] CVector<uint8_t> &buf, bool modify = true)
Span<const uint8_t> ToUtf8Span(CVector<uint8_t> &buf, bool modify = true)
{
Span<const uint8_t> str;
uint32_t strLen = GetLength();
if (UNLIKELY(IsUtf16())) {
size_t len = base::utf_helper::Utf16ToUtf8Size(GetDataUtf16(), strLen, modify) - 1;
CVector<uint16_t> tmpBuf;
const uint16_t *data = EcmaString::GetUtf16DataFlat(this, tmpBuf);
size_t len = base::utf_helper::Utf16ToUtf8Size(data, strLen, modify) - 1;
buf.reserve(len);
len = base::utf_helper::ConvertRegionUtf16ToUtf8(GetDataUtf16(), buf.data(), strLen, len, 0, modify);
len = base::utf_helper::ConvertRegionUtf16ToUtf8(data, buf.data(), strLen, len, 0, modify);
str = Span<const uint8_t>(buf.data(), len);
} else {
str = Span<const uint8_t>(GetDataUtf8(), strLen);
const uint8_t *data = EcmaString::GetUtf8DataFlat(this, buf);
str = Span<const uint8_t>(data, strLen);
}
return str;
}
void WriteData(EcmaString *src, uint32_t start, uint32_t destSize, uint32_t length)
{
if (IsUtf8()) {
ASSERT(src->IsUtf8());
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
if (length != 0 && memcpy_s(GetDataUtf8Writable() + start, destSize, src->GetDataUtf8(), length) != EOK) {
LOG_FULL(FATAL) << "memcpy_s failed";
UNREACHABLE();
}
} else if (src->IsUtf8()) {
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
Span<uint16_t> to(GetDataUtf16Writable() + start, length);
Span<const uint8_t> from(src->GetDataUtf8(), length);
for (uint32_t i = 0; i < length; i++) {
to[i] = from[i];
}
} else {
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
if (length != 0 && memcpy_s(GetDataUtf16Writable() + start,
ComputeDataSizeUtf16(destSize), src->GetDataUtf16(), ComputeDataSizeUtf16(length)) != EOK) {
LOG_FULL(FATAL) << "memcpy_s failed";
UNREACHABLE();
}
}
}
inline void WriteData(uint16_t src, uint32_t start)
{
if (IsUtf8()) {
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
*(GetDataUtf8Writable() + start) = static_cast<uint8_t>(src);
} else {
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
*(GetDataUtf16Writable() + start) = src;
}
}
uint32_t GetLength() const
{
return GetMixLength() >> 2U;
}
void SetIsInternString()
{
SetMixLength(GetMixLength() | STRING_INTERN_BIT);
}
bool IsInternString() const
{
return (GetMixLength() & STRING_INTERN_BIT) != 0;
}
void ClearInternStringFlag()
{
SetMixLength(GetMixLength() & ~STRING_INTERN_BIT);
}
size_t ObjectSize() const
{
uint32_t length = GetLength();
return IsUtf16() ? ComputeSizeUtf16(length) : ComputeSizeUtf8(length);
}
uint32_t PUBLIC_API GetHashcode()
{
uint32_t hashcode = GetRawHashcode();
// GetLength() == 0 means it's an empty array.No need to computeHashCode again when hashseed is 0.
if (hashcode == 0 && GetLength() != 0) {
hashcode = ComputeHashcode(0);
SetRawHashcode(hashcode);
}
return hashcode;
}
uint32_t PUBLIC_API ComputeHashcode(uint32_t hashSeed) const;
static int32_t IndexOf(EcmaString *lhs, EcmaString *rhs, int pos = 0);
static int32_t LastIndexOf(EcmaString *lhs, EcmaString *rhs, int pos = 0);
static constexpr uint32_t GetStringCompressionMask()
{
return STRING_COMPRESSED_BIT;
}
/**
* Compares string1 + string2 by bytes, It doesn't check canonical unicode equivalence.
*/
bool EqualToSplicedString(const EcmaString *str1, const EcmaString *str2);
/**
* Compares strings by bytes, It doesn't check canonical unicode equivalence.
*/
static bool StringsAreEqual(EcmaString *str1, EcmaString *str2);
/**
* Two strings have the same type of utf encoding format.
*/
static bool StringsAreEqualSameUtfEncoding(EcmaString *str1, EcmaString *str2);
/**
* Compares strings by bytes, It doesn't check canonical unicode equivalence.
*/
static bool StringsAreEqualUtf8(const EcmaString *str1, const uint8_t *utf8Data, uint32_t utf8Len,
bool canBeCompress);
/**
* Compares strings by bytes, It doesn't check canonical unicode equivalence.
*/
static bool StringsAreEqualUtf16(const EcmaString *str1, const uint16_t *utf16Data, uint32_t utf16Len);
static uint32_t ComputeHashcodeUtf8(const uint8_t *utf8Data, size_t utf8Len, bool canBeCompress);
static uint32_t ComputeHashcodeUtf16(const uint16_t *utf16Data, uint32_t length);
static EcmaString *AllocStringObject(const EcmaVM *vm, size_t length, bool compressed);
static EcmaString *AllocStringObjectWithSpaceType(const EcmaVM *vm, size_t length, bool compressed,
MemSpaceType type);
void WriteData(EcmaString *src, uint32_t start, uint32_t destSize, uint32_t length);
static bool CanBeCompressed(const uint8_t *utf8Data, uint32_t utf8Len);
static bool CanBeCompressed(const uint16_t *utf16Data, uint32_t utf16Len);
static bool CanBeCompressed(const EcmaString *string);
static inline EcmaString *FastSubUtf8String(const EcmaVM *vm, const JSHandle<EcmaString> &src, uint32_t start,
uint32_t length);
static inline EcmaString *FastSubUtf16String(const EcmaVM *vm, const JSHandle<EcmaString> &src, uint32_t start,
uint32_t length);
bool ToElementIndex(uint32_t *index);
bool ToTypedArrayIndex(uint32_t *index);
template<bool isLower>
static EcmaString *ConvertCase(const EcmaVM *vm, const JSHandle<EcmaString> &src);
template<bool isLower>
static EcmaString *LocaleConvertCase(const EcmaVM *vm, const JSHandle<EcmaString> &src, const icu::Locale &locale);
template<typename T>
static EcmaString *TrimBody(const JSThread *thread, const JSHandle<EcmaString> &src, Span<T> &data, TrimMode mode);
static EcmaString *Trim(const JSThread *thread, const JSHandle<EcmaString> &src, TrimMode mode = TrimMode::TRIM);
// single char copy for loop
template<typename DstType, typename SrcType>
static void CopyChars(DstType *dst, SrcType *src, uint32_t count);
// memory block copy
template<typename T>
static bool MemCopyChars(Span<T> &dst, size_t dstMax, Span<const T> &src, size_t count);
static bool IsASCIICharacter(uint16_t data)
{
// \0 is not considered ASCII in Ecma-Modified-UTF8 [only modify '\u0000']
return data - 1U < base::utf_helper::UTF8_1B_MAX;
}
template<typename T1, typename T2>
static int32_t IndexOf(Span<const T1> &lhsSp, Span<const T2> &rhsSp, int32_t pos, int32_t max);
template<typename T1, typename T2>
static int32_t LastIndexOf(Span<const T1> &lhsSp, Span<const T2> &rhsSp, int32_t pos);
bool IsFlat() const;
bool IsLineString() const
{
return GetClass()->IsLineString();
}
bool IsTreeString() const
{
return GetClass()->IsTreeString();
}
JSType GetStringType() const
{
JSType type = GetClass()->GetObjectType();
ASSERT(type >= JSType::STRING_FIRST && type <= JSType::STRING_LAST);
return type;
}
template <typename Char>
static void WriteToFlat(EcmaString *src, Char *buf, uint32_t maxLength);
static const uint8_t *GetUtf8DataFlat(const EcmaString *src, CVector<uint8_t> &buf);
static const uint16_t *GetUtf16DataFlat(const EcmaString *src, CVector<uint16_t> &buf);
// string must be not flat
static EcmaString *SlowFlatten(const EcmaVM *vm, const JSHandle<TreeEcmaString> &string);
static EcmaString *Flatten(const EcmaVM *vm, const JSHandle<EcmaString> &string);
static EcmaString *FlattenNoGC(const EcmaVM *vm, EcmaString *string);
static EcmaString *ToLower(const EcmaVM *vm, const JSHandle<EcmaString> &src);
static EcmaString *ToUpper(const EcmaVM *vm, const JSHandle<EcmaString> &src);
@ -396,66 +423,97 @@ private:
static EcmaString *ToLocaleLower(const EcmaVM *vm, const JSHandle<EcmaString> &src, const icu::Locale &locale);
static EcmaString *ToLocaleUpper(const EcmaVM *vm, const JSHandle<EcmaString> &src, const icu::Locale &locale);
template<typename T>
static EcmaString *TrimBody(const JSThread *thread, const JSHandle<EcmaString> &src, Span<T> &data, TrimMode mode);
static EcmaString *Trim(const JSThread *thread, const JSHandle<EcmaString> &src, TrimMode mode = TrimMode::TRIM);
void SetLength(uint32_t length, bool compressed = false)
{
ASSERT(length < 0x40000000U);
// Use 0u for compressed/utf8 expression
SetMixLength((length << 2U) | (compressed ? STRING_COMPRESSED : STRING_UNCOMPRESSED));
}
uint16_t *GetDataUtf16Writable()
{
LOG_ECMA_IF(!IsUtf16(), FATAL) << "EcmaString: Read data as utf16 for utf8 string";
return GetData();
}
uint8_t *GetDataUtf8Writable()
{
ASSERT_PRINT(IsUtf8(), "EcmaString: Read data as utf8 for utf16 string");
return reinterpret_cast<uint8_t *>(GetData());
}
static void CopyUtf16AsUtf8(const uint16_t *utf16From, uint8_t *utf8To, uint32_t utf16Len);
static bool IsASCIICharacter(uint16_t data)
{
// \0 is not considered ASCII in Ecma-Modified-UTF8 [only modify '\u0000']
return data - 1U < base::utf_helper::UTF8_1B_MAX;
}
/**
* str1 should have the same length as utf16_data.
* Converts utf8Data to utf16 and compare it with given utf16_data.
*/
static bool IsUtf8EqualsUtf16(const uint8_t *utf8Data, size_t utf8Len, const uint16_t *utf16Data,
uint32_t utf16Len);
template<typename T>
/**
* Check that two spans are equal. Should have the same length.
*/
static bool StringsAreEquals(Span<const T> &str1, Span<const T> &str2);
template<typename T>
/**
* Copy String from src to dst
* */
static bool StringCopy(Span<T> &dst, size_t dstMax, Span<const T> &src, size_t count);
template<typename T1, typename T2>
static int32_t IndexOf(Span<const T1> &lhsSp, Span<const T2> &rhsSp, int32_t pos, int32_t max);
template<typename T1, typename T2>
static int32_t LastIndexOf(Span<const T1> &lhsSp, Span<const T2> &rhsSp, int32_t pos);
};
static_assert((EcmaString::DATA_OFFSET % static_cast<uint8_t>(MemAlignment::MEM_ALIGN_OBJECT)) == 0);
// The LineEcmaString abstract class captures sequential string values, only LineEcmaString can store chars data
class LineEcmaString : public EcmaString {
public:
// DATA_OFFSET: the string data stored after the string header.
// Data can be stored in utf8 or utf16 form according to compressed bit.
static constexpr size_t DATA_OFFSET = EcmaString::SIZE; // DATA_OFFSET equal to Empty String size
CAST_CHECK(LineEcmaString, IsLineString);
static LineEcmaString *Cast(EcmaString *str)
{
return static_cast<LineEcmaString *>(str);
}
static LineEcmaString *Cast(const EcmaString *str)
{
return LineEcmaString::Cast(const_cast<EcmaString *>(str));
}
static size_t ComputeSizeUtf8(uint32_t utf8Len)
{
return DATA_OFFSET + utf8Len;
}
static size_t ComputeSizeUtf16(uint32_t utf16Len)
{
return DATA_OFFSET + utf16Len * sizeof(uint16_t);
}
static size_t ObjectSize(EcmaString *str)
{
uint32_t length = str->GetLength();
return str->IsUtf16() ? ComputeSizeUtf16(length) : ComputeSizeUtf8(length);
}
uint16_t *GetData() const
{
return reinterpret_cast<uint16_t *>(ToUintPtr(this) + DATA_OFFSET);
}
template<bool verify = true>
uint16_t Get(int32_t index) const;
void Set(uint32_t index, uint16_t src)
{
ASSERT(index < GetLength());
if (IsUtf8()) {
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
*(reinterpret_cast<uint8_t *>(GetData()) + index) = static_cast<uint8_t>(src);
} else {
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
*(GetData() + index) = src;
}
}
};
static_assert((LineEcmaString::DATA_OFFSET % static_cast<uint8_t>(MemAlignment::MEM_ALIGN_OBJECT)) == 0);
class TreeEcmaString : public EcmaString {
public:
// Minimum length for a tree string
static constexpr uint32_t MIN_TREE_ECMASTRING_LENGTH = 13;
static constexpr size_t FIRST_OFFSET = EcmaString::SIZE;
ACCESSORS(First, FIRST_OFFSET, SECOND_OFFSET);
ACCESSORS(Second, SECOND_OFFSET, SIZE);
DECL_VISIT_OBJECT(FIRST_OFFSET, SIZE);
CAST_CHECK(TreeEcmaString, IsTreeString);
static TreeEcmaString *Cast(EcmaString *str)
{
return static_cast<TreeEcmaString *>(str);
}
static TreeEcmaString *Cast(const EcmaString *str)
{
return TreeEcmaString::Cast(const_cast<EcmaString *>(str));
}
bool IsFlat() const
{
auto strSecond = EcmaString::Cast(GetSecond());
return strSecond->GetLength() == 0;
}
template<bool verify = true>
uint16_t Get(int32_t index) const;
};
// if you want to use functions of EcmaString, please not use directly,
// and use functions of EcmaStringAccessor alternatively.
@ -470,9 +528,9 @@ public:
explicit EcmaStringAccessor(const JSHandle<EcmaString> &strHandle);
static EcmaString *AllocStringObject(const EcmaVM *vm, size_t length, bool compressed)
static EcmaString *CreateLineString(const EcmaVM *vm, size_t length, bool compressed)
{
return EcmaString::AllocStringObject(vm, length, compressed);
return EcmaString::CreateLineString(vm, length, compressed);
}
static EcmaString *CreateEmptyString(const EcmaVM *vm)
@ -498,6 +556,7 @@ public:
return EcmaString::Concat(vm, str1Handle, str2Handle);
}
// can change src data structure
static EcmaString *FastSubString(const EcmaVM *vm,
const JSHandle<EcmaString> &src, uint32_t start, uint32_t length)
{
@ -519,14 +578,22 @@ public:
return string_->GetLength();
}
size_t GetUtf8Length() const
{
return string_->GetUtf8Length();
}
// require is LineString
inline size_t GetUtf8Length() const;
size_t ObjectSize() const
{
return string_->ObjectSize();
if (string_->IsLineString()) {
return LineEcmaString::ObjectSize(string_);
} else {
return TreeEcmaString::SIZE;
}
}
// For TreeString, the calculation result is size of LineString correspondingly.
size_t GetFlatStringSize() const
{
return LineEcmaString::ObjectSize(string_);
}
bool IsInternString() const
@ -544,66 +611,84 @@ public:
string_->ClearInternStringFlag();
}
const uint8_t *GetDataUtf8()
{
return string_->GetDataUtf8();
}
// require is LineString
// It's Utf8 format, but without 0 in the end.
inline const uint8_t *GetDataUtf8();
const uint16_t *GetDataUtf16()
{
return string_->GetDataUtf16();
}
// require is LineString
inline const uint16_t *GetDataUtf16();
// not change string data structure.
// if string is not flat, this func has low efficiency.
std::u16string ToU16String(uint32_t len = 0)
{
return string_->ToU16String(len);
}
// not change string data structure.
// if string is not flat, this func has low efficiency.
std::unique_ptr<uint8_t[]> ToOneByteDataForced()
{
return string_->ToOneByteDataForced();
}
Span<const uint8_t> ToUtf8Span([[maybe_unused]] CVector<uint8_t> &buf)
// not change string data structure.
// if string is not flat, this func has low efficiency.
Span<const uint8_t> ToUtf8Span(CVector<uint8_t> &buf)
{
return string_->ToUtf8Span(buf);
}
// not change string data structure.
// if string is not flat, this func has low efficiency.
std::string ToStdString(StringConvertedUsage usage = StringConvertedUsage::PRINT);
// not change string data structure.
// if string is not flat, this func has low efficiency.
CString ToCString(StringConvertedUsage usage = StringConvertedUsage::LOGICOPERATION);
// not change string data structure.
// if string is not flat, this func has low efficiency.
uint32_t WriteToFlatUtf8(uint8_t *buf, uint32_t maxLength, bool isWriteBuffer = false)
{
return string_->WriteUtf8(buf, maxLength, isWriteBuffer);
}
// not change string data structure.
// if string is not flat, this func has low efficiency.
uint32_t WriteToFlatUtf16(uint16_t *buf, uint32_t maxLength) const
{
return string_->CopyDataUtf16(buf, maxLength);
}
static void ReadData(EcmaString * dst, EcmaString *src, uint32_t start, uint32_t destSize, uint32_t length)
{
dst->WriteData(src, start, destSize, length);
}
// require dst is LineString
// not change src data structure.
// if src is not flat, this func has low efficiency.
inline static void ReadData(EcmaString * dst, EcmaString *src, uint32_t start, uint32_t destSize, uint32_t length);
// not change src data structure.
// if src is not flat, this func has low efficiency.
template<bool verify = true>
uint16_t Get(uint32_t index) const
{
return string_->At<verify>(index);
}
// require string is LineString.
void Set(uint32_t index, uint16_t src)
{
return string_->WriteData(src, index);
return string_->WriteData(index, src);
}
// not change src data structure.
// if src is not flat, this func has low efficiency.
uint32_t GetHashcode()
{
return string_->GetHashcode();
}
// not change src data structure.
// if src is not flat, this func has low efficiency.
uint32_t ComputeHashcode(uint32_t hashSeed)
{
return string_->ComputeHashcode(hashSeed);
@ -619,42 +704,64 @@ public:
return EcmaString::ComputeHashcodeUtf16(utf16Data, length);
}
static int32_t IndexOf(EcmaString *lhs, EcmaString *rhs, int pos = 0)
// can change receiver and search data structure
static int32_t IndexOf(const EcmaVM *vm,
const JSHandle<EcmaString> &receiver, const JSHandle<EcmaString> &search, int pos = 0)
{
return EcmaString::IndexOf(lhs, rhs, pos);
return EcmaString::IndexOf(vm, receiver, search, pos);
}
static int32_t LastIndexOf(EcmaString *lhs, EcmaString *rhs, int pos = 0)
// can change receiver and search data structure
static int32_t LastIndexOf(const EcmaVM *vm,
const JSHandle<EcmaString> &receiver, const JSHandle<EcmaString> &search, int pos = 0)
{
return EcmaString::LastIndexOf(lhs, rhs, pos);
return EcmaString::LastIndexOf(vm, receiver, search, pos);
}
static int32_t Compare(EcmaString *lhs, EcmaString *rhs)
// can change receiver and search data structure
static int32_t Compare(const EcmaVM *vm, const JSHandle<EcmaString>& left, const JSHandle<EcmaString>& right)
{
return EcmaString::Compare(lhs, rhs);
return EcmaString::Compare(vm, left, right);
}
// can change str1 and str2 data structure
static bool StringsAreEqual(const EcmaVM *vm, const JSHandle<EcmaString> &str1, const JSHandle<EcmaString> &str2)
{
return EcmaString::StringsAreEqual(vm, str1, str2);
}
// not change str1 and str2 data structure.
// if str1 or str2 is not flat, this func has low efficiency.
static bool StringsAreEqual(EcmaString *str1, EcmaString *str2)
{
return EcmaString::StringsAreEqual(str1, str2);
}
// not change str1 and str2 data structure.
// if str1 or str2 is not flat, this func has low efficiency.
static bool StringsAreEqualSameUtfEncoding(EcmaString *str1, EcmaString *str2)
{
return EcmaString::StringsAreEqualSameUtfEncoding(str1, str2);
}
// not change str1 data structure.
// if str1 is not flat, this func has low efficiency.
static bool StringsAreEqualUtf8(const EcmaString *str1, const uint8_t *utf8Data, uint32_t utf8Len,
bool canBeCompress)
{
return EcmaString::StringsAreEqualUtf8(str1, utf8Data, utf8Len, canBeCompress);
}
// not change str1 data structure.
// if str1 is not flat, this func has low efficiency.
static bool StringsAreEqualUtf16(const EcmaString *str1, const uint16_t *utf16Data, uint32_t utf16Len)
{
return EcmaString::StringsAreEqualUtf16(str1, utf16Data, utf16Len);
}
// require str1 and str2 are LineString.
// not change string data structure.
// if string is not flat, this func has low efficiency.
bool EqualToSplicedString(const EcmaString *str1, const EcmaString *str2)
{
return string_->EqualToSplicedString(str1, str2);
@ -670,16 +777,21 @@ public:
return EcmaString::CanBeCompressed(utf16Data, utf16Len);
}
// require string is LineString
static bool CanBeCompressed(const EcmaString *string)
{
return EcmaString::CanBeCompressed(string);
}
// not change string data structure.
// if string is not flat, this func has low efficiency.
bool ToElementIndex(uint32_t *index)
{
return string_->ToElementIndex(index);
}
// not change string data structure.
// if string is not flat, this func has low efficiency.
bool ToTypedArrayIndex(uint32_t *index)
{
return string_->ToTypedArrayIndex(index);
@ -711,6 +823,46 @@ public:
return EcmaString::Trim(thread, src, mode);
}
bool IsFlat() const
{
return string_->IsFlat();
}
bool IsLineString() const
{
return string_->IsLineString();
}
bool IsTreeString() const
{
return string_->IsTreeString();
}
static EcmaString *Flatten(const EcmaVM *vm, const JSHandle<EcmaString> &string)
{
return EcmaString::Flatten(vm, string);
}
static EcmaString *SlowFlatten(const EcmaVM *vm, const JSHandle<TreeEcmaString> &string)
{
return EcmaString::SlowFlatten(vm, string);
}
static EcmaString *FlattenNoGC(const EcmaVM *vm, EcmaString *string)
{
return EcmaString::FlattenNoGC(vm, string);
}
static const uint8_t *GetUtf8DataFlat(const EcmaString *src, CVector<uint8_t> &buf)
{
return EcmaString::GetUtf8DataFlat(src, buf);
}
static const uint16_t *GetUtf16DataFlat(const EcmaString *src, CVector<uint16_t> &buf)
{
return EcmaString::GetUtf16DataFlat(src, buf);
}
private:
EcmaString *string_ {nullptr};
};

View File

@ -27,6 +27,7 @@ EcmaStringTable::EcmaStringTable(const EcmaVM *vm) : vm_(vm) {}
EcmaString *EcmaStringTable::GetString(const JSHandle<EcmaString> &firstString,
const JSHandle<EcmaString> &secondString) const
{
ASSERT(EcmaStringAccessor(firstString).IsLineString() && EcmaStringAccessor(secondString).IsLineString());
uint32_t hashCode = EcmaStringAccessor(firstString).GetHashcode();
hashCode = EcmaStringAccessor(secondString).ComputeHashcode(hashCode);
auto range = table_.equal_range(hashCode);
@ -70,6 +71,7 @@ EcmaString *EcmaStringTable::GetString(const uint16_t *utf16Data, uint32_t utf16
EcmaString *EcmaStringTable::GetString(EcmaString *string) const
{
ASSERT(EcmaStringAccessor(string).IsLineString());
auto hashcode = EcmaStringAccessor(string).GetHashcode();
auto range = table_.equal_range(hashcode);
auto item = range.first;
@ -87,6 +89,7 @@ void EcmaStringTable::InternString(EcmaString *string)
if (EcmaStringAccessor(string).IsInternString()) {
return;
}
ASSERT(EcmaStringAccessor(string).IsLineString());
table_.emplace(EcmaStringAccessor(string).GetHashcode(), string);
EcmaStringAccessor(string).SetInternString();
}
@ -99,12 +102,14 @@ void EcmaStringTable::InternEmptyString(EcmaString *emptyStr)
EcmaString *EcmaStringTable::GetOrInternString(const JSHandle<EcmaString> &firstString,
const JSHandle<EcmaString> &secondString)
{
EcmaString *concatString = GetString(firstString, secondString);
auto firstFlat = JSHandle<EcmaString>(vm_->GetJSThread(), EcmaStringAccessor::Flatten(vm_, firstString));
auto secondFlat = JSHandle<EcmaString>(vm_->GetJSThread(), EcmaStringAccessor::Flatten(vm_, secondString));
EcmaString *concatString = GetString(firstFlat, secondFlat);
if (concatString != nullptr) {
return concatString;
}
concatString = EcmaStringAccessor::Concat(vm_, firstString, secondString);
JSHandle<EcmaString> concatHandle(vm_->GetJSThread(), EcmaStringAccessor::Concat(vm_, firstFlat, secondFlat));
concatString = EcmaStringAccessor::Flatten(vm_, concatHandle);
InternString(concatString);
return concatString;
}
@ -149,13 +154,18 @@ EcmaString *EcmaStringTable::GetOrInternString(EcmaString *string)
if (EcmaStringAccessor(string).IsInternString()) {
return string;
}
EcmaString *result = GetString(string);
JSHandle<EcmaString> strHandle(vm_->GetJSThread(), string);
// may gc
auto strFlat = EcmaStringAccessor::Flatten(vm_, strHandle);
if (EcmaStringAccessor(strFlat).IsInternString()) {
return strFlat;
}
EcmaString *result = GetString(strFlat);
if (result != nullptr) {
return result;
}
InternString(string);
return string;
InternString(strFlat);
return strFlat;
}
EcmaString *EcmaStringTable::GetOrInternStringWithSpaceType(const uint8_t *utf8Data, uint32_t utf8Len,
@ -207,6 +217,9 @@ bool EcmaStringTable::CheckStringTableValidity()
{
for (auto itemOuter = table_.begin(); itemOuter != table_.end(); ++itemOuter) {
auto outerString = itemOuter->second;
if (!EcmaStringAccessor(outerString).IsLineString()) {
return false;
}
int counter = 0;
auto hashcode = EcmaStringAccessor(outerString).GetHashcode();
auto range = table_.equal_range(hashcode);

View File

@ -108,6 +108,11 @@ enum class MethodIndex : uint8_t {
METHOD_END
};
enum class IcuFormatterType {
SimpleDateFormatDefault,
SimpleDateFormatDate,
SimpleDateFormatTime
};
using HostPromiseRejectionTracker = void (*)(const EcmaVM* vm,
const JSHandle<JSPromise> promise,
const JSHandle<JSTaggedValue> reason,
@ -512,6 +517,31 @@ public:
JSTaggedValue ExecuteAot(size_t actualNumArgs, JSTaggedType *args, const JSTaggedType *prevFp,
OptimizedEntryFrame::CallType callType);
// For icu objects cache
void SetIcuFormatterToCache(IcuFormatterType type, const std::string &locale, std::shared_ptr<icu::UMemory> icuObj)
{
EcmaVM::IcuFormatter icuFormatter = IcuFormatter(locale, icuObj);
icuObjCache_.insert({type, std::move(icuFormatter)});
}
icu::UMemory *GetIcuFormatterFromCache(IcuFormatterType type, std::string locale)
{
auto iter = icuObjCache_.find(type);
EcmaVM::IcuFormatter icuFormatter;
if (iter != icuObjCache_.end()) {
icuFormatter = iter->second;
if (icuFormatter.locale == locale) {
return icuFormatter.icuObj.get();
}
}
return nullptr;
}
void ClearIcuCache()
{
icuObjCache_.clear();
}
protected:
void HandleUncaughtException(TaggedObject *exception);
@ -632,6 +662,17 @@ private:
// PGO Profiler
PGOProfiler *pgoProfiler_;
// For icu objects cache
struct IcuFormatter {
std::string locale;
std::shared_ptr<icu::UMemory> icuObj;
IcuFormatter() = default;
IcuFormatter(const std::string &locale, std::shared_ptr<icu::UMemory> icuObj)
: locale(locale), icuObj(std::move(icuObj)) {}
};
std::unordered_map<IcuFormatterType, IcuFormatter> icuObjCache_;
friend class Snapshot;
friend class SnapshotProcessor;
friend class ObjectFactory;

View File

@ -296,7 +296,7 @@ uintptr_t FrameIterator::GetPrevFrameCallSiteSp([[maybe_unused]] uintptr_t curPc
return 0;
}
default: {
LOG_ECMA(FATAL) << "frame type error!";
LOG_FULL(FATAL) << "frame type error!";
}
}
}
@ -323,7 +323,7 @@ uintptr_t FrameIterator::GetPrevFrame() const
break;
}
default: {
LOG_ECMA(FATAL) << "frame type error!";
LOG_FULL(FATAL) << "frame type error!";
}
}
return end;
@ -386,8 +386,10 @@ ARK_INLINE void OptimizedJSFunctionFrame::GCIterate(const FrameIterator &it,
const RootBaseAndDerivedVisitor &derivedVisitor) const
{
OptimizedJSFunctionFrame *frame = OptimizedJSFunctionFrame::GetFrameFromSp(it.GetSp());
uintptr_t *envPtr = reinterpret_cast<uintptr_t *>(frame);
uintptr_t envslot = ToUintPtr(envPtr);
uintptr_t *jsFuncPtr = reinterpret_cast<uintptr_t *>(frame);
uintptr_t jsFuncSlot = ToUintPtr(jsFuncPtr);
uintptr_t envslot = jsFuncSlot + sizeof(uintptr_t);
visitor(Root::ROOT_FRAME, ObjectSlot(jsFuncSlot));
visitor(Root::ROOT_FRAME, ObjectSlot(envslot));
uintptr_t *preFrameSp = frame->ComputePrevFrameSp(it);
@ -603,78 +605,79 @@ bool ReadUintptrFromAddr(int pid, uintptr_t addr, uintptr_t &value)
bool GetTypeOffsetAndPrevOffsetFromFrameType(uintptr_t frameType, uintptr_t &typeOffset, uintptr_t &prevOffset)
{
switch (frameType) {
case (uintptr_t)(FrameType::OPTIMIZED_FRAME):
FrameType type = static_cast<FrameType>(frameType);
switch (type) {
case FrameType::OPTIMIZED_FRAME:
typeOffset = OptimizedFrame::GetTypeOffset();
prevOffset = OptimizedFrame::GetPrevOffset();
break;
case (uintptr_t)(FrameType::OPTIMIZED_ENTRY_FRAME):
typeOffset = MEMBER_OFFSET(OptimizedEntryFrame, type);
prevOffset = MEMBER_OFFSET(OptimizedEntryFrame, preLeaveFrameFp);
case FrameType::OPTIMIZED_ENTRY_FRAME:
typeOffset = OptimizedEntryFrame::GetTypeOffset();
prevOffset = OptimizedEntryFrame::GetLeaveFrameFpOffset();
break;
case (uintptr_t)(FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME):
case FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME:
typeOffset = OptimizedJSFunctionUnfoldArgVFrame::GetTypeOffset();
prevOffset = OptimizedJSFunctionUnfoldArgVFrame::GetPrevOffset();
break;
case (uintptr_t)(FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME):
case (uintptr_t)(FrameType::OPTIMIZED_JS_FUNCTION_FRAME):
case FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME:
case FrameType::OPTIMIZED_JS_FUNCTION_FRAME:
typeOffset = OptimizedJSFunctionFrame::GetTypeOffset();
prevOffset = OptimizedJSFunctionFrame::GetPrevOffset();
break;
case (uintptr_t)(FrameType::LEAVE_FRAME):
case FrameType::LEAVE_FRAME:
typeOffset = MEMBER_OFFSET(OptimizedLeaveFrame, type);
prevOffset = MEMBER_OFFSET(OptimizedLeaveFrame, callsiteFp);
break;
case (uintptr_t)(FrameType::LEAVE_FRAME_WITH_ARGV):
case FrameType::LEAVE_FRAME_WITH_ARGV:
typeOffset = MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, type);
prevOffset = MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, callsiteFp);
break;
case (uintptr_t)(FrameType::BUILTIN_CALL_LEAVE_FRAME):
case FrameType::BUILTIN_CALL_LEAVE_FRAME:
typeOffset = OptimizedBuiltinLeaveFrame::GetTypeOffset();
prevOffset = OptimizedBuiltinLeaveFrame::GetPrevOffset();
break;
case (uintptr_t)(FrameType::INTERPRETER_FRAME):
case (uintptr_t)(FrameType::INTERPRETER_FAST_NEW_FRAME):
case FrameType::INTERPRETER_FRAME:
case FrameType::INTERPRETER_FAST_NEW_FRAME:
typeOffset = MEMBER_OFFSET(InterpretedFrame, base) +
MEMBER_OFFSET(InterpretedFrameBase, type);
prevOffset = MEMBER_OFFSET(InterpretedFrame, base) +
MEMBER_OFFSET(InterpretedFrameBase, prev);
break;
case (uintptr_t)(FrameType::INTERPRETER_BUILTIN_FRAME):
case FrameType::INTERPRETER_BUILTIN_FRAME:
typeOffset = MEMBER_OFFSET(InterpretedBuiltinFrame, base) +
MEMBER_OFFSET(InterpretedFrameBase, type);
prevOffset = MEMBER_OFFSET(InterpretedBuiltinFrame, base) +
MEMBER_OFFSET(InterpretedFrameBase, prev);
break;
case (uintptr_t)(FrameType::INTERPRETER_CONSTRUCTOR_FRAME):
case (uintptr_t)(FrameType::ASM_INTERPRETER_FRAME):
case FrameType::INTERPRETER_CONSTRUCTOR_FRAME:
case FrameType::ASM_INTERPRETER_FRAME:
typeOffset = MEMBER_OFFSET(AsmInterpretedFrame, base) +
MEMBER_OFFSET(InterpretedFrameBase, type);
prevOffset = MEMBER_OFFSET(AsmInterpretedFrame, base) +
MEMBER_OFFSET(InterpretedFrameBase, prev);
break;
case (uintptr_t)(FrameType::BUILTIN_FRAME):
case (uintptr_t)(FrameType::BUILTIN_ENTRY_FRAME):
case FrameType::BUILTIN_FRAME:
case FrameType::BUILTIN_ENTRY_FRAME:
typeOffset = MEMBER_OFFSET(BuiltinFrame, type);
prevOffset = MEMBER_OFFSET(BuiltinFrame, prevFp);
break;
case (uintptr_t)(FrameType::BUILTIN_FRAME_WITH_ARGV):
case FrameType::BUILTIN_FRAME_WITH_ARGV:
typeOffset = MEMBER_OFFSET(BuiltinWithArgvFrame, type);
prevOffset = MEMBER_OFFSET(BuiltinWithArgvFrame, prevFp);
break;
case (uintptr_t)(FrameType::INTERPRETER_ENTRY_FRAME):
case FrameType::INTERPRETER_ENTRY_FRAME:
typeOffset = MEMBER_OFFSET(InterpretedEntryFrame, base) +
MEMBER_OFFSET(InterpretedFrameBase, type);
prevOffset = MEMBER_OFFSET(InterpretedEntryFrame, base) +
MEMBER_OFFSET(InterpretedFrameBase, prev);
break;
case (uintptr_t)(FrameType::ASM_INTERPRETER_ENTRY_FRAME):
case FrameType::ASM_INTERPRETER_ENTRY_FRAME:
typeOffset = MEMBER_OFFSET(AsmInterpretedEntryFrame, base) +
MEMBER_OFFSET(InterpretedFrameBase, type);
prevOffset = MEMBER_OFFSET(AsmInterpretedEntryFrame, base) +
MEMBER_OFFSET(InterpretedFrameBase, prev);
break;
case (uintptr_t)(FrameType::ASM_INTERPRETER_BRIDGE_FRAME):
case FrameType::ASM_INTERPRETER_BRIDGE_FRAME:
typeOffset = MEMBER_OFFSET(AsmInterpretedBridgeFrame, entry) +
MEMBER_OFFSET(AsmInterpretedEntryFrame, base) +
MEMBER_OFFSET(InterpretedFrameBase, type);

View File

@ -138,12 +138,6 @@ enum class FrameType: uintptr_t {
BUILTIN_LAST = BUILTIN_ENTRY_FRAME,
};
enum class ReservedSlots: int {
OPTIMIZED_RESERVED_SLOT = 1,
OPTIMIZED_JS_FUNCTION_RESERVED_SLOT = 2,
OPTIMIZED_ENTRY_RESERVED_SLOT = 2,
};
enum class JSCallMode : uintptr_t {
CALL_ARG0 = 0,
CALL_ARG1,
@ -188,6 +182,11 @@ public:
{
return MEMBER_OFFSET(OptimizedFrame, prevFp);
}
static size_t ComputeReservedSize(size_t slotSize)
{
size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::TypeIndex);
return slotSize * slotOffset;
}
private:
enum class Index : size_t {
TypeIndex = 0,
@ -359,11 +358,14 @@ STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedJSFunctionArgConfigFrame),
// |--------------------------| OptimizedJSFunctionFrame
// | frameType | |
// |--------------------------| |
// | lexEnv | v
// | lexEnv | |
// |--------------------------| |
// | call-target | v
// +--------------------------+ ---------------
//
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
struct OptimizedJSFunctionFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
JSTaggedValue,
JSTaggedValue,
base::AlignedPointer,
base::AlignedPointer,
@ -371,7 +373,8 @@ struct OptimizedJSFunctionFrame : public base::AlignedStruct<JSTaggedValue::Tagg
public:
static constexpr size_t ENV_SLOT_DIFF = 2;
enum class Index : size_t {
EnvIndex = 0,
JSFuncIndex = 0,
EnvIndex,
TypeIndex,
PrevFpIndex,
ReturnAddrIndex,
@ -425,6 +428,16 @@ public:
{
return MEMBER_OFFSET(OptimizedJSFunctionFrame, prevFp);
}
static size_t ComputeReservedEnvOffset(size_t slotSize)
{
size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::EnvIndex);
return slotSize * slotOffset;
}
static size_t ComputeReservedJSFuncOffset(size_t slotSize)
{
size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::JSFuncIndex);
return slotSize * slotOffset;
}
friend class FrameIterator;
void GetDeoptBundleInfo(const FrameIterator &it, std::vector<kungfu::ARKDeopt>& deopts) const;
void GetFuncCalleeRegAndOffset(
@ -439,6 +452,7 @@ private:
}
// dynamic callee saveregisters for x86-64
alignas(EAS) JSTaggedValue jsFunc {JSTaggedValue::Undefined()};
alignas(EAS) JSTaggedValue env {JSTaggedValue::Hole()};
[[maybe_unused]] alignas(EAS) FrameType type {0};
alignas(EAS) JSTaggedType *prevFp {nullptr};
@ -460,31 +474,56 @@ STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedJSFunctionFrame),
// | preLeaveFrameFp | v
// +--------------------------+ -----------------
struct OptimizedEntryFrame {
struct OptimizedEntryFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
base::AlignedPointer,
base::AlignedPointer,
base::AlignedPointer> {
public:
enum class CallType : size_t {
CALL_FUNC = 0,
CALL_NEW,
};
OptimizedEntryFrame() = default;
~OptimizedEntryFrame() = default;
JSTaggedType *preLeaveFrameFp;
[[maybe_unused]] FrameType type;
JSTaggedType *prevFp;
enum class Index : size_t {
PreLeaveFrameFpIndex = 0,
TypeIndex,
PrevFpIndex,
NumOfMembers
};
static size_t GetTypeOffset()
{
return MEMBER_OFFSET(OptimizedEntryFrame, type);
}
static size_t GetLeaveFrameFpOffset()
{
return MEMBER_OFFSET(OptimizedEntryFrame, preLeaveFrameFp);
}
inline JSTaggedType* GetPrevFrameFp()
{
return preLeaveFrameFp;
}
static size_t ComputeReservedSize(size_t slotSize)
{
size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::PreLeaveFrameFpIndex);
return slotSize * slotOffset;
}
friend class FrameIterator;
private:
alignas(EAS) JSTaggedType *preLeaveFrameFp {nullptr};
alignas(EAS) [[maybe_unused]] FrameType type {0};
alignas(EAS) [[maybe_unused]] JSTaggedType *prevFp {nullptr};
static OptimizedEntryFrame* GetFrameFromSp(const JSTaggedType *sp)
{
return reinterpret_cast<OptimizedEntryFrame *>(reinterpret_cast<uintptr_t>(sp) -
MEMBER_OFFSET(OptimizedEntryFrame, prevFp));
}
};
STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedEntryFrame), OptimizedEntryFrame::SizeArch32, OptimizedEntryFrame::SizeArch64);
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
struct InterpretedFrameBase : public base::AlignedStruct<base::AlignedPointer::Size(),

View File

@ -91,7 +91,8 @@ void GlobalEnvConstants::InitRootsClass([[maybe_unused]] JSThread *thread, JSHCl
factory->NewEcmaReadOnlyHClass(hClass, FreeObject::SIZE_OFFSET, JSType::FREE_OBJECT_WITH_ONE_FIELD));
SetConstant(ConstantIndex::FREE_OBJECT_WITH_TWO_FIELD_CLASS_INDEX,
factory->NewEcmaReadOnlyHClass(hClass, FreeObject::SIZE, JSType::FREE_OBJECT_WITH_TWO_FIELD));
SetConstant(ConstantIndex::STRING_CLASS_INDEX, factory->NewEcmaReadOnlyHClass(hClass, 0, JSType::STRING));
SetConstant(ConstantIndex::LINE_STRING_CLASS_INDEX, factory->NewEcmaReadOnlyHClass(hClass, 0, JSType::LINE_STRING));
SetConstant(ConstantIndex::TREE_STRING_CLASS_INDEX, factory->NewEcmaReadOnlyHClass(hClass, 0, JSType::TREE_STRING));
SetConstant(ConstantIndex::ARRAY_CLASS_INDEX,
factory->NewEcmaReadOnlyHClass(hClass, 0, JSType::TAGGED_ARRAY));
SetConstant(ConstantIndex::BYTE_ARRAY_CLASS_INDEX,

View File

@ -35,7 +35,8 @@ class JSThread;
V(JSTaggedValue, FreeObjectWithNoneFieldClass, FREE_OBJECT_WITH_NONE_FIELD_CLASS_INDEX, ecma_roots_class) \
V(JSTaggedValue, FreeObjectWithOneFieldClass, FREE_OBJECT_WITH_ONE_FIELD_CLASS_INDEX, ecma_roots_class) \
V(JSTaggedValue, FreeObjectWithTwoFieldClass, FREE_OBJECT_WITH_TWO_FIELD_CLASS_INDEX, ecma_roots_class) \
V(JSTaggedValue, StringClass, STRING_CLASS_INDEX, ecma_roots_class) \
V(JSTaggedValue, LineStringClass, LINE_STRING_CLASS_INDEX, ecma_roots_class) \
V(JSTaggedValue, TreeStringClass, TREE_STRING_CLASS_INDEX, ecma_roots_class) \
V(JSTaggedValue, ArrayClass, ARRAY_CLASS_INDEX, ecma_roots_class) \
V(JSTaggedValue, ByteArrayClass, BYTE_ARRAY_CLASS_INDEX, ecma_roots_class) \
V(JSTaggedValue, ConstantPoolClass, CONSTANT_POOL_CLASS_INDEX, ecma_roots_class) \

View File

@ -269,9 +269,9 @@ ComparisonResult CompareOp::Compare(JSThread *thread, JSTaggedValue left,
break;
}
case CompareOpType::STRING_STRING: {
auto xString = static_cast<EcmaString *>(left.GetTaggedObject());
auto yString = static_cast<EcmaString *>(right.GetTaggedObject());
int result = EcmaStringAccessor::Compare(xString, yString);
JSHandle<EcmaString> xHandle(thread, left);
JSHandle<EcmaString> yHandle(thread, right);
int result = EcmaStringAccessor::Compare(thread->GetEcmaVM(), xHandle, yHandle);
if (result < 0) {
ret = ComparisonResult::LESS;
} else if (result == 0) {

View File

@ -87,7 +87,7 @@ HWTEST_F_L0(ICBinaryOPTest, AddWithTSType)
JSTaggedValue resInICPath3 = ICBinaryOP::AddWithTSType(thread, Str1.GetTaggedValue(), Str2.GetTaggedValue(),
JSTaggedValue(static_cast<int>(BinaryType::STRING)));
ASSERT_TRUE(resInICPath3.IsString());
EXPECT_EQ(EcmaStringAccessor::Compare(*slowHandle3, reinterpret_cast<EcmaString *>(resInICPath3.GetRawData())), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(ecmaVm, slowHandle3, JSHandle<EcmaString>(thread, resInICPath3)), 0);
JSTaggedValue resInSlowPath4 = SlowRuntimeStub::Add2(thread, JSTaggedValue::Undefined(),
arg2.GetTaggedValue());
@ -104,7 +104,7 @@ HWTEST_F_L0(ICBinaryOPTest, AddWithTSType)
Str1.GetTaggedValue(),
JSTaggedValue(static_cast<int>(BinaryType::STRING_GEN)));
ASSERT_TRUE(resInICPath5.IsString());
EXPECT_EQ(EcmaStringAccessor::Compare(*slowHandle5, reinterpret_cast<EcmaString *>(resInICPath5.GetRawData())), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(ecmaVm, slowHandle5, JSHandle<EcmaString>(thread, resInICPath5)), 0);
JSTaggedValue resInSlowPath6 = SlowRuntimeStub::Add2(thread, Str1.GetTaggedValue(),
JSTaggedValue::Null());
@ -112,7 +112,7 @@ HWTEST_F_L0(ICBinaryOPTest, AddWithTSType)
JSTaggedValue resInICPath6 = ICBinaryOP::AddWithTSType(thread, Str1.GetTaggedValue(), JSTaggedValue::Null(),
JSTaggedValue(static_cast<int>(BinaryType::STRING_GEN)));
ASSERT_TRUE(resInICPath6.IsString());
EXPECT_EQ(EcmaStringAccessor::Compare(*slowHandle6, reinterpret_cast<EcmaString *>(resInICPath6.GetRawData())), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(ecmaVm, slowHandle6, JSHandle<EcmaString>(thread, resInICPath6)), 0);
JSTaggedValue resInSlowPath7 = SlowRuntimeStub::Add2(thread, arg1.GetTaggedValue(),
JSTaggedValue::True());
@ -127,7 +127,7 @@ HWTEST_F_L0(ICBinaryOPTest, AddWithTSType)
JSTaggedValue resInICPath8 = ICBinaryOP::AddWithTSType(thread, arg4.GetTaggedValue(), JSTaggedValue::Null(),
JSTaggedValue(static_cast<int>(BinaryType::GENERIC)));
ASSERT_TRUE(resInICPath8.IsString());
EXPECT_EQ(EcmaStringAccessor::Compare(*slowHandle8, reinterpret_cast<EcmaString *>(resInICPath8.GetRawData())), 0);
EXPECT_EQ(EcmaStringAccessor::Compare(ecmaVm, slowHandle8, JSHandle<EcmaString>(thread, resInICPath8)), 0);
};
HWTEST_F_L0(ICBinaryOPTest, SubWithTSType)

View File

@ -126,36 +126,42 @@ JSTaggedValue FastRuntimeStub::FastEqual(JSTaggedValue left, JSTaggedValue right
return JSTaggedValue::Hole();
}
bool FastRuntimeStub::FastStrictEqual(JSTaggedValue left, JSTaggedValue right)
JSTaggedValue FastRuntimeStub::FastStrictEqual(JSTaggedValue left, JSTaggedValue right)
{
if (left.IsNumber()) {
if (right.IsNumber()) {
double dLeft = left.IsInt() ? left.GetInt() : left.GetDouble();
double dRight = right.IsInt() ? right.GetInt() : right.GetDouble();
return JSTaggedValue::StrictNumberEquals(dLeft, dRight);
return JSTaggedValue::StrictNumberEquals(dLeft, dRight) ? JSTaggedValue::True() : JSTaggedValue::False();
}
return false;
return JSTaggedValue::False();
}
if (right.IsNumber()) {
return false;
return JSTaggedValue::False();
}
if (left == right) {
return true;
return JSTaggedValue::True();
}
if (left.IsString() && right.IsString()) {
auto leftStr = static_cast<EcmaString *>(left.GetTaggedObject());
auto rightStr = static_cast<EcmaString *>(right.GetTaggedObject());
if (EcmaStringAccessor(leftStr).IsFlat() && EcmaStringAccessor(rightStr).IsFlat()) {
return EcmaStringAccessor::StringsAreEqual(static_cast<EcmaString *>(left.GetTaggedObject()),
static_cast<EcmaString *>(right.GetTaggedObject()));
static_cast<EcmaString *>(right.GetTaggedObject())) ?
JSTaggedValue::True() : JSTaggedValue::False();
}
return JSTaggedValue::Hole();
}
if (left.IsBigInt()) {
if (right.IsBigInt()) {
return BigInt::Equal(left, right);
return BigInt::Equal(left, right) ? JSTaggedValue::True() : JSTaggedValue::False();
}
return false;
return JSTaggedValue::False();
}
if (right.IsBigInt()) {
return false;
return JSTaggedValue::False();
}
return false;
return JSTaggedValue::False();
}
bool FastRuntimeStub::IsSpecialIndexedObj(JSType jsType)

View File

@ -32,7 +32,7 @@ public:
static inline JSTaggedValue FastMod(JSTaggedValue left, JSTaggedValue right);
static inline JSTaggedValue FastEqual(JSTaggedValue left, JSTaggedValue right);
static inline JSTaggedValue FastTypeOf(JSThread *thread, JSTaggedValue obj);
static inline bool FastStrictEqual(JSTaggedValue left, JSTaggedValue right);
static inline JSTaggedValue FastStrictEqual(JSTaggedValue left, JSTaggedValue right);
static inline JSTaggedValue NewLexicalEnv(JSThread *thread, ObjectFactory *factory, uint16_t numVars);
static inline JSTaggedValue GetGlobalOwnProperty(JSThread *thread, JSTaggedValue receiver, JSTaggedValue key);
template<bool UseOwn = false>

View File

@ -2050,8 +2050,17 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, const uint8_t
<< " v" << v0;
JSTaggedValue left = GET_VREG_VALUE(v0);
JSTaggedValue right = GET_ACC();
bool res = FastRuntimeStub::FastStrictEqual(left, right);
SET_ACC(JSTaggedValue(!res));
JSTaggedValue res = FastRuntimeStub::FastStrictEqual(left, right);
if (!res.IsHole()) {
res = res.IsTrue() ? JSTaggedValue::False() : JSTaggedValue::True();
SET_ACC(res);
} else {
// slow path
SAVE_PC();
res = SlowRuntimeStub::NotEq(thread, left, right);
INTERPRETER_RETURN_IF_ABRUPT(res);
SET_ACC(res);
}
DISPATCH(STRICTNOTEQ_IMM8_V8);
}
HANDLE_OPCODE(STRICTEQ_IMM8_V8) {
@ -2060,8 +2069,16 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, const uint8_t
<< " v" << v0;
JSTaggedValue left = GET_VREG_VALUE(v0);
JSTaggedValue right = GET_ACC();
bool res = FastRuntimeStub::FastStrictEqual(left, right);
SET_ACC(JSTaggedValue(res));
JSTaggedValue res = FastRuntimeStub::FastStrictEqual(left, right);
if (!res.IsHole()) {
SET_ACC(res);
} else {
// slow path
SAVE_PC();
res = SlowRuntimeStub::Eq(thread, left, right);
INTERPRETER_RETURN_IF_ABRUPT(res);
SET_ACC(res);
}
DISPATCH(STRICTEQ_IMM8_V8);
}
HANDLE_OPCODE(CREATEITERRESULTOBJ_V8_V8) {

View File

@ -1540,8 +1540,16 @@ void InterpreterAssembly::HandleStrictnoteqImm8V8(
<< " v" << v0;
JSTaggedValue left = GET_VREG_VALUE(v0);
JSTaggedValue right = GET_ACC();
bool res = FastRuntimeStub::FastStrictEqual(left, right);
SET_ACC(JSTaggedValue(!res));
JSTaggedValue res = FastRuntimeStub::FastStrictEqual(left, right);
if (!res.IsHole()) {
res = res.IsTrue() ? JSTaggedValue::False() : JSTaggedValue::True();
SET_ACC(res);
} else {
// slow path
res = SlowRuntimeStub::NotEq(thread, left, right);
INTERPRETER_RETURN_IF_ABRUPT(res);
SET_ACC(res);
}
DISPATCH(STRICTNOTEQ_IMM8_V8);
}
@ -1554,8 +1562,15 @@ void InterpreterAssembly::HandleStricteqImm8V8(
<< " v" << v0;
JSTaggedValue left = GET_VREG_VALUE(v0);
JSTaggedValue right = GET_ACC();
bool res = FastRuntimeStub::FastStrictEqual(left, right);
SET_ACC(JSTaggedValue(res));
JSTaggedValue res = FastRuntimeStub::FastStrictEqual(left, right);
if (!res.IsHole()) {
SET_ACC(res);
} else {
// slow path
res = SlowRuntimeStub::Eq(thread, left, right);
INTERPRETER_RETURN_IF_ABRUPT(res);
SET_ACC(res);
}
DISPATCH(STRICTEQ_IMM8_V8);
}

View File

@ -394,15 +394,12 @@ bool JSAPIArrayList::Has(const JSTaggedValue value) const
JSHandle<TaggedArray> JSAPIArrayList::OwnKeys(JSThread *thread, const JSHandle<JSAPIArrayList> &obj)
{
uint32_t length = obj->GetLength().GetArrayLength();
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<TaggedArray> keys = factory->NewTaggedArray(length);
return JSObject::GetOwnPropertyKeys(thread, JSHandle<JSObject>::Cast(obj));
}
for (uint32_t i = 0; i < length; i++) {
keys->Set(thread, i, JSTaggedValue(i));
}
return keys;
JSHandle<TaggedArray> JSAPIArrayList::OwnEnumKeys(JSThread *thread, const JSHandle<JSAPIArrayList> &obj)
{
return JSObject::GetOwnEnumPropertyKeys(thread, JSHandle<JSObject>::Cast(obj));
}
bool JSAPIArrayList::GetOwnProperty(JSThread *thread, const JSHandle<JSAPIArrayList> &obj,

Some files were not shown because too many files have changed in this diff Show More