!2177 optimization math and number function

Merge pull request !2177 from 李_文强/master
This commit is contained in:
openharmony_ci 2022-08-27 13:01:34 +00:00 committed by Gitee
commit d347e9b87f
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
8 changed files with 79 additions and 26 deletions

View File

@ -20,6 +20,7 @@
#include <cstdint>
#include <iomanip>
#include <sstream>
#include <sys/time.h>
#include "ecmascript/base/builtins_base.h"
#include "ecmascript/base/string_helper.h"
@ -28,7 +29,7 @@
namespace panda::ecmascript::base {
enum class Sign { NONE, NEG, POS };
uint64_t* RandomGenerator::randomState {nullptr};
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define RETURN_IF_CONVERSION_END(p, end, result) \
if ((p) == (end)) { \
@ -793,4 +794,27 @@ int NumberHelper::GetMinmumDigits(double d, int *decpt, char *buf)
return digits;
}
uint64_t* RandomGenerator::GetRandomState()
{
return randomState;
}
uint64_t RandomGenerator::XorShift64(uint64_t *pVal)
{
uint64_t x = *pVal;
x ^= x >> RIGHT12;
x ^= x << LEFT25;
x ^= x >> RIGHT27;
*pVal = x;
return x * GET_MULTIPLY;
}
void RandomGenerator::InitRandom()
{
struct timeval tv;
gettimeofday(&tv, NULL);
auto val = static_cast<int64_t>((tv.tv_sec * SECONDS_TO_SUBTLE) + tv.tv_usec);
randomState = reinterpret_cast<uint64_t *>(&val);
// the state must be non zero
if (*randomState == 0)
*randomState = 1;
}
} // namespace panda::ecmascript::base

View File

@ -62,6 +62,15 @@ static constexpr size_t INT16_BITS = 16;
static constexpr size_t INT8_BITS = 8;
static constexpr size_t JS_DTOA_BUF_SIZE = 128;
// help defines for random
static constexpr int LEFT52 = 52 ;
static constexpr int RIGHT12 = 12;
static constexpr uint32_t USE_LEFT = 0x3ff;
static constexpr int SECONDS_TO_SUBTLE = 1000000;
static constexpr int RIGHT27 = 27;
static constexpr int LEFT25 = 25;
static constexpr uint64_t GET_MULTIPLY = 0x2545F4914F6CDD1D;
class NumberHelper {
public:
static inline JSTaggedType GetNaN()
@ -105,5 +114,13 @@ private:
static void GetBase(double d, int digits, int *decpt, char *buf, char *bufTmp, int size);
static int GetMinmumDigits(double d, int *decpt, char *buf);
};
class RandomGenerator {
public:
static uint64_t* GetRandomState();
static uint64_t XorShift64(uint64_t *pVal);
static void InitRandom();
private:
static uint64_t* randomState;
};
} // namespace panda::ecmascript::base
#endif // ECMASCRIPT_BASE_NUMBER_HELPER_H

View File

@ -162,6 +162,7 @@ using Promise = builtins::BuiltinsPromise;
using BuiltinsPromiseHandler = builtins::BuiltinsPromiseHandler;
using BuiltinsPromiseJob = builtins::BuiltinsPromiseJob;
using ErrorType = base::ErrorType;
using RandomGenerator = base::RandomGenerator;
using DataView = builtins::BuiltinsDataView;
using Intl = builtins::BuiltinsIntl;
using Locale = builtins::BuiltinsLocale;
@ -1477,6 +1478,7 @@ void Builtins::InitializeMath(const JSHandle<GlobalEnv> &env, const JSHandle<JST
[[maybe_unused]] EcmaHandleScope scope(thread_);
JSHandle<JSHClass> mathDynclass = factory_->NewEcmaDynClass(JSObject::SIZE, JSType::JS_OBJECT, objFuncPrototypeVal);
JSHandle<JSObject> mathObject = factory_->NewJSObjectWithInit(mathDynclass);
RandomGenerator::InitRandom();
SetFunction(env, mathObject, "abs", Math::Abs, FunctionLength::ONE);
SetFunction(env, mathObject, "acos", Math::Acos, FunctionLength::ONE);
SetFunction(env, mathObject, "acosh", Math::Acosh, FunctionLength::ONE);

View File

@ -14,14 +14,16 @@
*/
#include "ecmascript/builtins/builtins_math.h"
#include <random>
#include <sys/time.h>
#include "ecmascript/ecma_runtime_call_info.h"
#include "ecmascript/js_tagged_number.h"
#include "utils/bit_utils.h"
namespace panda::ecmascript::builtins {
using NumberHelper = base::NumberHelper;
using RandomGenerator = base::RandomGenerator;
// 20.2.2.1
JSTaggedValue BuiltinsMath::Abs(EcmaRuntimeCallInfo *argv)
@ -583,13 +585,15 @@ JSTaggedValue BuiltinsMath::Pow(EcmaRuntimeCallInfo *argv)
JSTaggedValue BuiltinsMath::Random([[maybe_unused]] EcmaRuntimeCallInfo *argv)
{
ASSERT(argv);
BUILTINS_API_TRACE(argv->GetThread(), Math, Random);
std::random_device rd;
std::default_random_engine engine(rd());
std::uniform_real_distribution<double> dis(0, std::random_device::max() - 1);
// result range [0,1)
double result = dis(engine) / std::random_device::max();
return GetTaggedDouble(result);
JSThread *thread = argv->GetThread();
BUILTINS_API_TRACE(thread, Math, Random);
[[maybe_unused]] EcmaHandleScope handleScope(thread);
Float64Union dataU;
uint64_t val;
uint64_t* randomState = RandomGenerator::GetRandomState();
val = RandomGenerator::XorShift64(randomState);
dataU.u64 = ((uint64_t)base::USE_LEFT << base::LEFT52) | (val >> base::RIGHT12);
return GetTaggedDouble(dataU.d - 1.0);
}
// 20.2.2.28

View File

@ -19,6 +19,10 @@
#include "ecmascript/base/builtins_base.h"
namespace panda::ecmascript::builtins {
union Float64Union {
double d;
uint64_t u64;
};
class BuiltinsMath : public base::BuiltinsBase {
public:
// 20.2.1.1

View File

@ -218,11 +218,11 @@ JSTaggedValue BuiltinsNumber::ParseInt(EcmaRuntimeCallInfo *argv)
JSTaggedValue BuiltinsNumber::ToExponential(EcmaRuntimeCallInfo *argv)
{
ASSERT(argv);
BUILTINS_API_TRACE(argv->GetThread(), Number, ToExponential);
JSThread *thread = argv->GetThread();
BUILTINS_API_TRACE(thread, Number, ToExponential);
[[maybe_unused]] EcmaHandleScope handleScope(thread);
// 1. Let x be ? thisNumberValue(this value).
JSTaggedNumber value = ThisNumberValue(argv);
JSTaggedNumber value = ThisNumberValue(thread, argv);
// 2. ReturnIfAbrupt(x).
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
@ -266,11 +266,11 @@ JSTaggedValue BuiltinsNumber::ToExponential(EcmaRuntimeCallInfo *argv)
JSTaggedValue BuiltinsNumber::ToFixed(EcmaRuntimeCallInfo *argv)
{
ASSERT(argv);
BUILTINS_API_TRACE(argv->GetThread(), Number, ToFixed);
JSThread *thread = argv->GetThread();
BUILTINS_API_TRACE(thread, Number, ToFixed);
[[maybe_unused]] EcmaHandleScope handleScope(thread);
// 1. Let x be ? thisNumberValue(this value).
JSTaggedNumber value = ThisNumberValue(argv);
JSTaggedNumber value = ThisNumberValue(thread, argv);
// 2. ReturnIfAbrupt(x).
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
// 3. Let f be ToInteger(fractionDigits). (If fractionDigits is undefined, this step produces the value 0).
@ -290,7 +290,8 @@ JSTaggedValue BuiltinsNumber::ToFixed(EcmaRuntimeCallInfo *argv)
// 6. If x is NaN, return the String "NaN".
double valueNumber = value.GetNumber();
if (std::isnan(valueNumber)) {
return GetTaggedString(thread, "NaN");
const GlobalEnvConstants *globalConst = thread->GlobalConstants();
return globalConst->GetNanCapitalString();
}
// 9. If x  1021, then
// a. Let m = ToString(x).
@ -310,7 +311,7 @@ JSTaggedValue BuiltinsNumber::ToLocaleString(EcmaRuntimeCallInfo *argv)
BUILTINS_API_TRACE(thread, Number, ToLocaleString);
[[maybe_unused]] EcmaHandleScope handleScope(thread);
// 1. Let x be ? thisNumberValue(this value).
JSTaggedNumber x = ThisNumberValue(argv);
JSTaggedNumber x = ThisNumberValue(thread, argv);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
// 2. Let numberFormat be ? Construct(%NumberFormat%, « locales, options »).
JSHandle<JSFunction> ctor(thread->GetEcmaVM()->GetGlobalEnv()->GetNumberFormatFunction());
@ -332,11 +333,11 @@ JSTaggedValue BuiltinsNumber::ToLocaleString(EcmaRuntimeCallInfo *argv)
JSTaggedValue BuiltinsNumber::ToPrecision(EcmaRuntimeCallInfo *argv)
{
ASSERT(argv);
BUILTINS_API_TRACE(argv->GetThread(), Number, ToPrecision);
JSThread *thread = argv->GetThread();
BUILTINS_API_TRACE(thread, Number, ToPrecision);
[[maybe_unused]] EcmaHandleScope handleScope(thread);
// 1. Let x be ? thisNumberValue(this value).
JSTaggedNumber value = ThisNumberValue(argv);
JSTaggedNumber value = ThisNumberValue(thread, argv);
// 2. ReturnIfAbrupt(x).
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
@ -376,11 +377,11 @@ JSTaggedValue BuiltinsNumber::ToPrecision(EcmaRuntimeCallInfo *argv)
JSTaggedValue BuiltinsNumber::ToString(EcmaRuntimeCallInfo *argv)
{
ASSERT(argv);
BUILTINS_API_TRACE(argv->GetThread(), Number, ToString);
JSThread *thread = argv->GetThread();
BUILTINS_API_TRACE(thread, Number, ToString);
[[maybe_unused]] EcmaHandleScope handleScope(thread);
// 1. Let x be ? thisNumberValue(this value).
JSTaggedNumber value = ThisNumberValue(argv);
JSTaggedNumber value = ThisNumberValue(thread, argv);
// 2. ReturnIfAbrupt(x).
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
@ -425,17 +426,18 @@ JSTaggedValue BuiltinsNumber::ToString(EcmaRuntimeCallInfo *argv)
JSTaggedValue BuiltinsNumber::ValueOf(EcmaRuntimeCallInfo *argv)
{
ASSERT(argv);
BUILTINS_API_TRACE(argv->GetThread(), Number, ValueOf);
// 1. Let x be ? thisNumberValue(this value).
JSTaggedValue x = ThisNumberValue(argv);
JSThread *thread = argv->GetThread();
BUILTINS_API_TRACE(thread, Number, ValueOf);
// 1. Let x be ? thisNumberValue(this value).
JSTaggedValue x = ThisNumberValue(thread, argv);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
return x;
}
JSTaggedNumber BuiltinsNumber::ThisNumberValue(EcmaRuntimeCallInfo *argv)
JSTaggedNumber BuiltinsNumber::ThisNumberValue(JSThread *thread, EcmaRuntimeCallInfo *argv)
{
BUILTINS_API_TRACE(argv->GetThread(), Number, ThisNumberValue);
BUILTINS_API_TRACE(thread, Number, ThisNumberValue);
JSHandle<JSTaggedValue> value = GetThis(argv);
if (value->IsNumber()) {
return JSTaggedNumber(value.GetTaggedValue());
@ -446,7 +448,6 @@ JSTaggedNumber BuiltinsNumber::ThisNumberValue(EcmaRuntimeCallInfo *argv)
return JSTaggedNumber(primitive);
}
}
JSThread *thread = argv->GetThread();
[[maybe_unused]] EcmaHandleScope handleScope(thread);
THROW_TYPE_ERROR_AND_RETURN(thread, "not number type", JSTaggedNumber::Exception());
}

View File

@ -53,7 +53,7 @@ public:
static JSTaggedValue ValueOf(EcmaRuntimeCallInfo *argv);
private:
static JSTaggedNumber ThisNumberValue(EcmaRuntimeCallInfo *argv);
static JSTaggedNumber ThisNumberValue(JSThread *thread, EcmaRuntimeCallInfo *argv);
};
} // namespace panda::ecmascript::builtins
#endif // ECMASCRIPT_BUILTINS_BUILTINS_NUBMER_H

View File

@ -435,6 +435,7 @@ public:
const JSHandle<JSTaggedValue> &newTarget);
JSHandle<JSObject> NewJSObjectByConstructor(const JSHandle<JSFunction> &constructor);
void InitializeJSObject(const JSHandle<JSObject> &obj, const JSHandle<JSHClass> &jshclass);
JSHandle<JSObject> NewJSObjectWithInit(const JSHandle<JSHClass> &jshclass);
uintptr_t NewSpaceBySnapshotAllocator(size_t size);
JSHandle<MachineCode> NewMachineCodeObject(size_t length, const uint8_t *data);