mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-10-06 23:54:03 +00:00
Merge branch 'master' of gitee.com:openharmony/arkcompiler_ets_runtime into master
Signed-off-by: zhaozhibo <zhaozhibo3@huawei.com>
This commit is contained in:
commit
5e4853b54b
6
BUILD.gn
6
BUILD.gn
@ -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",
|
||||
|
@ -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)
|
||||
|
@ -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};
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
|
@ -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);
|
||||
|
@ -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",
|
||||
|
112
ecmascript/base/tests/bit_helper_test.cpp
Normal file
112
ecmascript/base/tests/bit_helper_test.cpp
Normal 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
|
69
ecmascript/base/tests/file_path_helper_test.cpp
Normal file
69
ecmascript/base/tests/file_path_helper_test.cpp
Normal 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
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
88
ecmascript/base/tests/math_helper_test.cpp
Normal file
88
ecmascript/base/tests/math_helper_test.cpp
Normal 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
|
@ -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
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
@ -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".
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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++) {
|
||||
|
@ -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)
|
||||
|
@ -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 "));
|
||||
|
@ -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()
|
||||
|
@ -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")
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
@ -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)
|
||||
|
@ -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, ¬String);
|
||||
Bind(¬String);
|
||||
{
|
||||
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_);
|
||||
|
@ -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);
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
using ControlFlowGraph = std::vector<std::vector<GateRef>>;
|
||||
|
||||
class CodeGeneratorImpl {
|
||||
public:
|
||||
CodeGeneratorImpl() = default;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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_ {};
|
||||
|
@ -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;
|
||||
|
@ -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_);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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))), "");
|
||||
|
@ -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};
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
const std::unordered_map<GateRef, size_t> &bbGatesAddrToIdx,
|
||||
const std::function<bool(size_t, size_t)> &isAncestor,
|
||||
const std::vector<GateRef> &schedulableGatesList)
|
||||
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,
|
||||
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,
|
||||
const std::unordered_map<GateRef, size_t> &bbGatesAddrToIdx,
|
||||
const std::function<size_t(size_t, size_t)> &lowestCommonAncestor, std::vector<GateRef> *order)
|
||||
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::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)
|
||||
|
@ -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,
|
||||
const std::unordered_map<GateRef, size_t> &bbGatesAddrToIdx,
|
||||
const std::function<bool(size_t, size_t)> &isAncestor, const std::vector<GateRef> &schedulableGatesList);
|
||||
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,
|
||||
std::unordered_map<GateRef, size_t> &upperBound);
|
||||
|
||||
static std::optional<std::unordered_map<GateRef, size_t>> 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);
|
||||
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::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
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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, ¬DigitZero);
|
||||
@ -1141,38 +1131,19 @@ 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, ¬Utf16);
|
||||
Bind(&isUtf16A);
|
||||
c = ZExtInt8ToInt32(Load(VariableType::INT8(), dataUtf8, ZExtInt32ToPtr(*i)));
|
||||
Label isDigit2(env);
|
||||
Label notDigit2(env);
|
||||
Branch(IsDigit(*c), &isDigit2, ¬Digit2);
|
||||
Bind(&isDigit2);
|
||||
{
|
||||
// 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(¬Utf16);
|
||||
{
|
||||
c = ZExtInt8ToInt32(Load(VariableType::INT8(), dataUtf16, ZExtInt32ToPtr(*i)));
|
||||
Jump(&getChar2);
|
||||
}
|
||||
Bind(&getChar2);
|
||||
{
|
||||
Label isDigit2(env);
|
||||
Label notDigit2(env);
|
||||
Branch(IsDigit(*c), &isDigit2, ¬Digit2);
|
||||
Bind(&isDigit2);
|
||||
{
|
||||
// 10 means the base of digit is 10.
|
||||
n = Int32Add(Int32Mul(*n, Int32(10)),
|
||||
Int32Sub(*c, Int32('0')));
|
||||
i = Int32Add(*i, Int32(1));
|
||||
Branch(Int32UnsignedLessThan(*i, len), &loopEnd, &afterLoop);
|
||||
}
|
||||
Bind(¬Digit2);
|
||||
Jump(&exit);
|
||||
// 10 means the base of digit is 10.
|
||||
n = Int32Add(Int32Mul(*n, Int32(10)), Int32Sub(*c, Int32('0')));
|
||||
i = Int32Add(*i, Int32(1));
|
||||
Branch(Int32UnsignedLessThan(*i, len), &loopEnd, &afterLoop);
|
||||
}
|
||||
Bind(¬Digit2);
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(&loopEnd);
|
||||
LoopEnd(&loopHead);
|
||||
@ -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, ¬String);
|
||||
Bind(&isString);
|
||||
{
|
||||
resultKey = StringToElementIndex(key);
|
||||
resultKey = StringToElementIndex(glue, key);
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(¬String);
|
||||
@ -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, ¬ValidIndex);
|
||||
@ -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, ¬ValidIndex);
|
||||
@ -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(¬NegativeZero);
|
||||
{
|
||||
GateRef index = TryStringOrSymbelToElementIndex(key);
|
||||
GateRef index = TryStringOrSymbolToElementIndex(glue, key);
|
||||
Label validIndex(env);
|
||||
Label notValidIndex(env);
|
||||
Branch(Int32GreaterThanOrEqual(index, Int32(0)), &validIndex, ¬ValidIndex);
|
||||
@ -4932,7 +4913,7 @@ GateRef StubBuilder::SetTypeArrayPropertyByName(GateRef glue, GateRef receiver,
|
||||
}
|
||||
Bind(¬NegativeZero);
|
||||
{
|
||||
GateRef index = TryStringOrSymbelToElementIndex(key);
|
||||
GateRef index = TryStringOrSymbolToElementIndex(glue, key);
|
||||
Label validIndex(env);
|
||||
Label notValidIndex(env);
|
||||
Branch(Int32GreaterThanOrEqual(index, Int32(0)), &validIndex, ¬ValidIndex);
|
||||
@ -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, ¬LineString);
|
||||
Bind(¬LineString);
|
||||
{
|
||||
Label isTreeString(env);
|
||||
Branch(IsTreeString(str), &isTreeString, &exit);
|
||||
Bind(&isTreeString);
|
||||
{
|
||||
Label isFlat(env);
|
||||
Label notFlat(env);
|
||||
Branch(TreeStringIsFlat(str), &isFlat, ¬Flat);
|
||||
Bind(&isFlat);
|
||||
{
|
||||
result = GetFirstFromTreeString(str);
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(¬Flat);
|
||||
{
|
||||
result = CallRuntime(glue, RTSTUB_ID(SlowFlattenString), { str });
|
||||
Jump(&exit);
|
||||
}
|
||||
}
|
||||
}
|
||||
Bind(&exit);
|
||||
auto ret = *result;
|
||||
env->SubCfgExit();
|
||||
return ret;
|
||||
}
|
||||
} // namespace panda::ecmascript::kungfu
|
||||
|
@ -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
|
||||
|
@ -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_));
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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"
|
||||
|
||||
|
@ -383,26 +383,24 @@ bool Verifier::RunPrologGatesCheck(const Circuit *circuit, const std::vector<Gat
|
||||
return true;
|
||||
}
|
||||
|
||||
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)
|
||||
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)
|
||||
{
|
||||
// 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
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
@ -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
|
@ -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);
|
@ -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
|
@ -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"
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
int32_t length = static_cast<int32_t>(GetLength());
|
||||
if (verify) {
|
||||
if ((index < 0) || (index >= length)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
index -= static_cast<int32_t>(first->GetLength());
|
||||
string = EcmaString::Cast(TreeEcmaString::Cast(string)->GetSecond());
|
||||
}
|
||||
} else {
|
||||
return string->At<verify>(index);
|
||||
}
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
/* static */
|
||||
EcmaString *EcmaString::FastSubUtf8String(const EcmaVM *vm, const JSHandle<EcmaString> &src, uint32_t start,
|
||||
uint32_t length)
|
||||
inline const uint8_t *EcmaStringAccessor::GetDataUtf8()
|
||||
{
|
||||
if (length == 0) {
|
||||
return *vm->GetFactory()->GetEmptyString();
|
||||
}
|
||||
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;
|
||||
return string_->GetDataUtf8();
|
||||
}
|
||||
|
||||
/* static */
|
||||
EcmaString *EcmaString::FastSubUtf16String(const EcmaVM *vm, const JSHandle<EcmaString> &src, uint32_t start,
|
||||
uint32_t length)
|
||||
inline const uint16_t *EcmaStringAccessor::GetDataUtf16()
|
||||
{
|
||||
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);
|
||||
} 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);
|
||||
}
|
||||
ASSERT_PRINT(canBeCompressed == CanBeCompressed(string), "canBeCompresse does not match the real value!");
|
||||
return string;
|
||||
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
|
||||
|
@ -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);
|
||||
|
||||
// retrieve strings after gc
|
||||
string1 = *str1Handle;
|
||||
string2 = *str2Handle;
|
||||
if (compressed) {
|
||||
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);
|
||||
} else {
|
||||
Span<uint16_t> sp(newString->GetDataUtf16Writable(), newLength);
|
||||
if (!string1->IsUtf16()) {
|
||||
for (uint32_t i = 0; i < length1; ++i) {
|
||||
sp[i] = string1->At<false>(i);
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
} else {
|
||||
uint32_t length = length2 << 1U;
|
||||
Span<const uint16_t> src2(string2->GetDataUtf16(), length2);
|
||||
EcmaString::StringCopy(sp, length, src2, length);
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT_PRINT(compressed == CanBeCompressed(newString), "compressed does not match the real value!");
|
||||
return newString;
|
||||
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
|
||||
strLeft = *left;
|
||||
strRight = *right;
|
||||
if (compressed) {
|
||||
// copy left part
|
||||
Span<uint8_t> sp(newString->GetDataUtf8Writable(), newLength);
|
||||
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 (strLeft->IsUtf8()) {
|
||||
EcmaString::CopyChars(sp.data(), strLeft->GetDataUtf8(), leftLength);
|
||||
} else {
|
||||
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 {
|
||||
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());
|
||||
|
@ -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,85 +64,154 @@ 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);
|
||||
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
|
||||
{
|
||||
if (maxLength == 0) {
|
||||
@ -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};
|
||||
};
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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(),
|
||||
|
@ -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,
|
||||
|
@ -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) \
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
|
@ -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()) {
|
||||
return EcmaStringAccessor::StringsAreEqual(static_cast<EcmaString *>(left.GetTaggedObject()),
|
||||
static_cast<EcmaString *>(right.GetTaggedObject()));
|
||||
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())) ?
|
||||
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)
|
||||
|
@ -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>
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user