Reason: fix Date cache bug

Issue: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/IB1MTB?from=project-issue
Test: Build & Boot devices

Signed-off-by: wupengyong <wupengyong@huawei.com>
Change-Id: I2a4b21bae79ff8d97b624acce4410d48ac954259
This commit is contained in:
wupengyong 2024-11-04 21:22:23 +08:00
parent 915632ea3d
commit 2ac7a1eb83
6 changed files with 56 additions and 47 deletions

View File

@ -39,7 +39,7 @@ JSTaggedValue BuiltinsDate::DateConstructor(EcmaRuntimeCallInfo *argv)
JSHandle<JSTaggedValue> newTarget = GetNewTarget(argv);
if (newTarget->IsUndefined()) {
double now = JSDate::Now().GetDouble();
CString str = JSDate::ToDateString(now);
CString str = JSDate::ToDateString(thread, now);
return GetTaggedString(thread, str.c_str());
}

View File

@ -342,19 +342,19 @@
}
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define GET_DATE_VALUE(name, code, isLocal) \
static JSTaggedValue name(EcmaRuntimeCallInfo *argv) \
{ \
ASSERT(argv); \
JSThread *thread = argv->GetThread(); \
[[maybe_unused]] EcmaHandleScope handleScope(thread); \
JSHandle<JSTaggedValue> msg = GetThis(argv); \
if (!msg->IsDate()) { \
THROW_TYPE_ERROR_AND_RETURN(thread, "Not a Date Object", JSTaggedValue::Exception()); \
} \
JSHandle<JSDate> jsDate(msg); \
double result = jsDate->GetDateValue(jsDate->GetTimeValue().GetDouble(), code, isLocal); \
return GetTaggedDouble(result); \
#define GET_DATE_VALUE(name, code, isLocal) \
static JSTaggedValue name(EcmaRuntimeCallInfo *argv) \
{ \
ASSERT(argv); \
JSThread *thread = argv->GetThread(); \
[[maybe_unused]] EcmaHandleScope handleScope(thread); \
JSHandle<JSTaggedValue> msg = GetThis(argv); \
if (!msg->IsDate()) { \
THROW_TYPE_ERROR_AND_RETURN(thread, "Not a Date Object", JSTaggedValue::Exception()); \
} \
JSHandle<JSDate> jsDate(msg); \
double result = jsDate->GetDateValue(thread, jsDate->GetTimeValue().GetDouble(), code, isLocal); \
return GetTaggedDouble(result); \
}
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)

View File

@ -25,11 +25,6 @@
namespace panda::ecmascript {
using NumberHelper = base::NumberHelper;
bool DateUtils::isCached_ = false;
int DateUtils::preSumDays_ = 0;
int DateUtils::preDays_ = 0;
int DateUtils::preMonth_ = 0;
int DateUtils::preYear_ = 0;
static const std::array<CString, WEEKDAY> WEEK_DAY_NAME = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
static const std::array<CString, MOUTH_PER_YEAR> MONTH_NAME = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
@ -652,13 +647,13 @@ void JSDate::AppendStrToTargetLength(const CString &str, int length, CString &ta
}
}
bool JSDate::GetThisDateValues(std::array<int64_t, DATE_LENGTH> *date, bool isLocal) const
bool JSDate::GetThisDateValues(JSThread *thread, std::array<int64_t, DATE_LENGTH> *date, bool isLocal) const
{
double timeMs = this->GetTimeValue().GetDouble();
if (std::isnan(timeMs)) {
return false;
}
GetDateValues(timeMs, date, isLocal);
GetDateValues(thread, timeMs, date, isLocal);
return true;
}
@ -666,7 +661,7 @@ bool JSDate::GetThisDateValues(std::array<int64_t, DATE_LENGTH> *date, bool isLo
JSTaggedValue JSDate::ToDateString(JSThread *thread) const
{
std::array<int64_t, DATE_LENGTH> fields = {0};
if (!GetThisDateValues(&fields, true)) {
if (!GetThisDateValues(thread, &fields, true)) {
return JSTaggedValue(base::NAN_VALUE);
}
CString str;
@ -683,13 +678,13 @@ JSTaggedValue JSDate::ToDateString(JSThread *thread) const
}
// static
CString JSDate::ToDateString(double timeMs)
CString JSDate::ToDateString(JSThread *thread, double timeMs)
{
if (std::isnan(timeMs)) {
return "Invalid Date";
}
std::array<int64_t, DATE_LENGTH> fields = {0};
GetDateValues(timeMs, &fields, true);
GetDateValues(thread, timeMs, &fields, true);
CString localTime;
int localMin = 0;
localMin = GetLocalOffsetFromOS(timeMs, true);
@ -725,7 +720,7 @@ CString JSDate::ToDateString(double timeMs)
JSTaggedValue JSDate::ToISOString(JSThread *thread) const
{
std::array<int64_t, DATE_LENGTH> fields = {0};
if (!GetThisDateValues(&fields, false)) {
if (!GetThisDateValues(thread, &fields, false)) {
return JSTaggedValue(base::NAN_VALUE);
}
CString year = ToCString(fields[YEAR]);
@ -760,7 +755,7 @@ JSTaggedValue JSDate::ToString(JSThread *thread) const
{
int localMin = 0;
std::array<int64_t, DATE_LENGTH> fields = {0};
if (!GetThisDateValues(&fields, true)) {
if (!GetThisDateValues(thread, &fields, true)) {
return JSTaggedValue(base::NAN_VALUE);
}
CString localTime;
@ -799,7 +794,7 @@ JSTaggedValue JSDate::ToTimeString(JSThread *thread) const
{
int localMin = 0;
std::array<int64_t, DATE_LENGTH> fields = {0};
if (!GetThisDateValues(&fields, true)) {
if (!GetThisDateValues(thread, &fields, true)) {
return JSTaggedValue(base::NAN_VALUE);
}
CString localTime;
@ -829,7 +824,7 @@ JSTaggedValue JSDate::ToTimeString(JSThread *thread) const
JSTaggedValue JSDate::ToUTCString(JSThread *thread) const
{
std::array<int64_t, DATE_LENGTH> fields = {0};
if (!GetThisDateValues(&fields, false)) {
if (!GetThisDateValues(thread, &fields, false)) {
return JSTaggedValue(base::NAN_VALUE);
}
CString str;
@ -860,7 +855,7 @@ JSTaggedValue JSDate::ValueOf() const
}
// static
void JSDate::GetDateValues(double timeMs, std::array<int64_t, DATE_LENGTH> *date, bool isLocal)
void JSDate::GetDateValues(JSThread *thread, double timeMs, std::array<int64_t, DATE_LENGTH> *date, bool isLocal)
{
int64_t tz = 0;
int64_t timeMsInt = static_cast<int64_t>(timeMs);
@ -869,17 +864,17 @@ void JSDate::GetDateValues(double timeMs, std::array<int64_t, DATE_LENGTH> *date
timeMsInt += tz * MS_PER_SECOND * SEC_PER_MINUTE;
}
DateUtils::TransferTimeToDate(timeMsInt, date);
thread->GetDateUtils()->TransferTimeToDate(timeMsInt, date);
(*date)[TIMEZONE] = -tz;
}
double JSDate::GetDateValue(double timeMs, uint8_t code, bool isLocal) const
double JSDate::GetDateValue(JSThread *thread, double timeMs, uint8_t code, bool isLocal) const
{
if (std::isnan(timeMs)) {
return base::NAN_VALUE;
}
std::array<int64_t, DATE_LENGTH> date = {0};
GetDateValues(timeMs, &date, isLocal);
GetDateValues(thread, timeMs, &date, isLocal);
return static_cast<double>(date[code]);
}
@ -907,13 +902,13 @@ JSTaggedValue JSDate::SetDateValue(EcmaRuntimeCallInfo *argv, uint32_t code, boo
timeMs = 0.0;
isSelectLocal = false;
}
JSThread *thread = argv->GetThread();
if (!std::isnan(timeMs)) {
GetDateValues(timeMs, &date, isSelectLocal);
GetDateValues(thread, timeMs, &date, isSelectLocal);
}
// When timeMs is NaN, the corresponding parameters still need to be obtained
for (uint32_t i = 0; i < count; i++) {
JSHandle<JSTaggedValue> value = base::BuiltinsBase::GetCallArg(argv, i);
JSThread *thread = argv->GetThread();
JSTaggedNumber res = JSTaggedValue::ToNumber(thread, value);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
double temp = res.GetNumber();

View File

@ -71,21 +71,24 @@ static constexpr char DEL = 127;
class DateUtils {
public:
static void TransferTimeToDate(int64_t timeMs, std::array<int64_t, DATE_LENGTH> *date);
explicit DateUtils() = default;
virtual ~DateUtils() = default;
void TransferTimeToDate(int64_t timeMs, std::array<int64_t, DATE_LENGTH> *date);
// return the year, update days.
void GetYearFromDays(std::array<int64_t, DATE_LENGTH> *date);
static int64_t Mod(int64_t a, int b);
static bool IsLeap(int64_t year);
static int64_t GetDaysInYear(int64_t year);
static int64_t GetDaysFromYear(int64_t year);
// return the year, update days.
static void GetYearFromDays(std::array<int64_t, DATE_LENGTH> *date);
static int64_t FloorDiv(int64_t a, int64_t b);
private:
static bool isCached_;
static int preSumDays_;
static int preDays_;
static int preMonth_;
static int preYear_;
bool isCached_ {false};
int preSumDays_ {0};
int preDays_ {0};
int preMonth_ {0};
int preYear_ {0};
};
class JSDate : public JSObject {
public:
@ -133,7 +136,7 @@ public:
// 20.4.4.35
JSTaggedValue ToDateString(JSThread *thread) const;
static CString ToDateString(double timeMs);
static CString ToDateString(JSThread *thread, double timeMs);
// 20.4.4.36
JSTaggedValue ToISOString(JSThread *thread) const;
@ -151,7 +154,7 @@ public:
JSTaggedValue ValueOf() const;
JSTaggedValue SetDateValue(EcmaRuntimeCallInfo *argv, uint32_t code, bool isLocal) const;
double GetDateValue(double timeMs, uint8_t code, bool isLocal) const;
double GetDateValue(JSThread *thread, double timeMs, uint8_t code, bool isLocal) const;
static JSTaggedValue GetTimeFromString(const char *str, int len);
static constexpr double MAX_DOUBLE = std::numeric_limits<double>::max();
@ -165,13 +168,13 @@ public:
static constexpr int MAX_DAYS_MONTH = 31;
static double SetDateValues(const std::array<int64_t, DATE_LENGTH> *date, bool isLocal);
static double SetDateValues(int64_t year, int64_t month, int64_t day);
static void GetDateValues(double timeMs, std::array<int64_t, DATE_LENGTH> *date, bool isLocal);
static void GetDateValues(JSThread *thread, double timeMs, std::array<int64_t, DATE_LENGTH> *date, bool isLocal);
static CString StrToTargetLength(const CString &str, int length);
static void AppendStrToTargetLength(const CString &str, int length, CString &target);
DECL_DUMP()
private:
bool GetThisDateValues(std::array<int64_t, DATE_LENGTH> *date, bool isLocal) const;
bool GetThisDateValues(JSThread *thread, std::array<int64_t, DATE_LENGTH> *date, bool isLocal) const;
CString GetLocaleTimeStr(const std::array<int64_t, DATE_LENGTH> &fields) const;
CString GetLocaleDateStr(const std::array<int64_t, DATE_LENGTH> &fields) const;
static int64_t MathMod(int64_t a, int b);

View File

@ -17,6 +17,7 @@
#include "ecmascript/runtime.h"
#include "ecmascript/debugger/js_debugger_manager.h"
#include "ecmascript/js_date.h"
#include "ecmascript/js_object-inl.h"
#include "ecmascript/js_tagged_value.h"
#include "ecmascript/runtime_call_id.h"
@ -130,6 +131,7 @@ JSThread::JSThread(EcmaVM *vm) : id_(os::thread::GetCurrentThreadId()), vm_(vm)
}
vmThreadControl_ = new VmThreadControl(this);
SetBCStubStatus(BCStubStatus::NORMAL_BC_STUB);
dateUtils_ = new DateUtils();
}
JSThread::JSThread(EcmaVM *vm, ThreadType threadType) : id_(os::thread::GetCurrentThreadId()),
@ -181,6 +183,10 @@ JSThread::~JSThread()
if (!IsDaemonThread()) {
UnregisterThread(this);
}
if (dateUtils_ != nullptr) {
delete dateUtils_;
dateUtils_ = nullptr;
}
}
ThreadId JSThread::GetCurrentThreadId()

View File

@ -40,6 +40,7 @@
#endif
namespace panda::ecmascript {
class DateUtils;
class EcmaContext;
class EcmaVM;
class EcmaHandleScope;
@ -1474,7 +1475,10 @@ public:
RegisterRTInterface(kungfu::RuntimeStubCSigns::ID_ASMFastWriteBarrier, asmCheckStub);
}
DateUtils *GetDateUtils() const
{
return dateUtils_;
}
#ifndef NDEBUG
inline void LaunchSuspendAll()
@ -1620,6 +1624,7 @@ private:
RecursiveMutex jitMutex_;
bool machineCodeLowMemory_ {false};
RecursiveMutex profileTypeAccessorLockMutex_;
DateUtils *dateUtils_ {nullptr};
#ifndef NDEBUG
MutatorLock::MutatorLockState mutatorLockState_ = MutatorLock::MutatorLockState::UNLOCKED;