Merge remote-tracking branch 'origin/master' into wcc_0808

Change-Id: I1566e28d02d931b390ac5d7c3cb11c3485aed5de
This commit is contained in:
wengchangcheng 2022-08-30 19:19:34 +08:00
commit 447847cb1d
311 changed files with 5550 additions and 1200 deletions

View File

@ -143,7 +143,7 @@ config("ark_jsruntime_public_config") {
]
defines = []
if (!is_mingw && !is_mac && target_os != "android") {
if (!is_mingw && !is_mac) {
defines += [
"ECMASCRIPT_SUPPORT_CPUPROFILER",
"ECMASCRIPT_SUPPORT_HEAPPROFILER",
@ -358,7 +358,7 @@ ecma_source = [
"ecmascript/base/string_helper.cpp",
"ecmascript/base/typed_array_helper.cpp",
"ecmascript/base/utf_helper.cpp",
"ecmascript/builtins.cpp",
"ecmascript/builtins/builtins.cpp",
"ecmascript/builtins/builtins_ark_tools.cpp",
"ecmascript/builtins/builtins_array.cpp",
"ecmascript/builtins/builtins_arraybuffer.cpp",
@ -449,6 +449,8 @@ ecma_source = [
"ecmascript/jspandafile/js_pandafile_executor.cpp",
"ecmascript/jspandafile/scope_info_extractor.cpp",
"ecmascript/jspandafile/method_literal.cpp",
"ecmascript/jspandafile/program_object.cpp",
"ecmascript/jspandafile/js_patch_manager.cpp",
"ecmascript/js_api/js_api_arraylist.cpp",
"ecmascript/js_api/js_api_arraylist_iterator.cpp",
"ecmascript/js_api/js_api_deque.cpp",
@ -660,6 +662,13 @@ source_set("libark_jsruntime_set") {
include_dirs +=
[ "//base/hiviewdfx/hilog/interfaces/native/innerkits/include" ]
}
if (enable_leak_check) {
sources += [ "ecmascript/dfx/native_dfx/backtrace.cpp" ]
defines += [
"ECMASCRIPT_ENABLE_HANDLE_LEAK_CHECK",
"ECMASCRIPT_ENABLE_GLOBAL_LEAK_CHECK",
]
}
}
}

View File

@ -82,4 +82,4 @@ LD_LIBRARY_PATH=out/hispark_taurus/clang_x64/ark/ark:out/hispark_taurus/clang_x6
**[arkcompiler\_ets\_runtime](https://gitee.com/openharmony/arkcompiler_ets_runtime)**
[arkcompiler\_ets\_frontend_](https://gitee.com/openharmony/arkcompiler_ets_frontend)
[arkcompiler\_ets\_frontend](https://gitee.com/openharmony/arkcompiler_ets_frontend)

View File

@ -50,7 +50,6 @@ namespace panda::ecmascript {
#define ECMASCRIPT_SWITCH_GC_MODE_TO_FULL_GC 1
#define ECMASCRIPT_ENABLE_CAST_CHECK 1
#define ECMASCRIPT_ENABLE_NEW_HANDLE_CHECK 1
#define ECMASCRIPT_ENABLE_HANDLE_LEAK_CHECK 1
#define ECMASCRIPT_ENABLE_HEAP_VERIFY 1
#define ECMASCRIPT_ENABLE_ACTIVE_CPUPROFILER 0
#else
@ -60,7 +59,6 @@ namespace panda::ecmascript {
#define ECMASCRIPT_SWITCH_GC_MODE_TO_FULL_GC 0
#define ECMASCRIPT_ENABLE_CAST_CHECK 0
#define ECMASCRIPT_ENABLE_NEW_HANDLE_CHECK 0
#define ECMASCRIPT_ENABLE_HANDLE_LEAK_CHECK 0
#define ECMASCRIPT_ENABLE_HEAP_VERIFY 0
#define ECMASCRIPT_ENABLE_ACTIVE_CPUPROFILER 0
#endif

View File

@ -117,6 +117,9 @@ JSHandle<JSTaggedValue> ErrorHelper::GetErrorName(JSThread *thread, const JSHand
case ErrorType::SYNTAX_ERROR:
errorKey = reinterpret_cast<TaggedObject *>(*globalConst->GetHandledSyntaxErrorString());
break;
case ErrorType::OOM_ERROR:
errorKey = reinterpret_cast<TaggedObject *>(*globalConst->GetHandledOOMErrorString());
break;
default:
errorKey = reinterpret_cast<TaggedObject *>(*globalConst->GetHandledErrorString());
break;

View File

@ -28,6 +28,7 @@ enum class ErrorType : uint8_t {
TYPE_ERROR,
URI_ERROR,
AGGREGATE_ERROR,
OOM_ERROR,
};
} // namespace panda::ecmascript::base

View File

@ -17,20 +17,46 @@
#define ECMASCRIPT_BASE_MATH_HELPER_H
#include <cstdint>
#include <cmath>
#define panda_bit_utils_ctz __builtin_ctz // NOLINT(cppcoreguidelines-macro-usage)
#define panda_bit_utils_ctzll __builtin_ctzll // NOLINT(cppcoreguidelines-macro-usage)
namespace panda::ecmascript::base::math {
static constexpr uint32_t GetIntLog2(const uint32_t X)
{
return static_cast<uint32_t>(panda_bit_utils_ctz(X));
}
namespace panda::ecmascript::base {
class MathHelper {
public:
static constexpr uint32_t GetIntLog2(const uint32_t X)
{
return static_cast<uint32_t>(panda_bit_utils_ctz(X));
}
static constexpr uint64_t GetIntLog2(const uint64_t X)
{
return static_cast<uint64_t>(panda_bit_utils_ctzll(X));
}
static constexpr uint64_t GetIntLog2(const uint64_t X)
{
return static_cast<uint64_t>(panda_bit_utils_ctzll(X));
}
static double Asinh(double input)
{
#if defined(PANDA_TARGET_WINDOWS)
if (input == 0 && !std::signbit(input)) {
// +0.0(double) is the special case for std::asinh() function compiled in linux for windows.
return +0.0;
}
#endif
return std::asinh(input);
}
static inline double Atanh(double input)
{
#if defined(PANDA_TARGET_WINDOWS)
if (input == 0 && std::signbit(input)) {
// -0.0(double) is the special case for std::atanh() function compiled in linux for windows.
return -0.0;
}
#endif
return std::atanh(input);
}
};
} // panda::ecmascript::base
#endif // ECMASCRIPT_BASE_MATH_HELPER_H

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 {0};
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define RETURN_IF_CONVERSION_END(p, end, result) \
if ((p) == (end)) { \
@ -793,4 +794,26 @@ 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);
randomState = static_cast<uint64_t>((tv.tv_sec * SECONDS_TO_SUBTLE) + tv.tv_usec);
// 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

@ -13,7 +13,7 @@
* limitations under the License.
*/
#include "ecmascript/builtins.h"
#include "ecmascript/builtins/builtins.h"
#ifdef PANDA_TARGET_WINDOWS
#ifdef ERROR
@ -144,6 +144,7 @@ using AggregateError = builtins::BuiltinsAggregateError;
using URIError = builtins::BuiltinsURIError;
using SyntaxError = builtins::BuiltinsSyntaxError;
using EvalError = builtins::BuiltinsEvalError;
using OOMError = builtins::BuiltinsOOMError;
using ErrorType = base::ErrorType;
using Global = builtins::BuiltinsGlobal;
using BuiltinsString = builtins::BuiltinsString;
@ -162,6 +163,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;
@ -1003,6 +1005,7 @@ void Builtins::InitializeAllTypeError(const JSHandle<GlobalEnv> &env, const JSHa
InitializeError(env, errorNativeFuncInstanceHClass, JSType::JS_URI_ERROR);
InitializeError(env, errorNativeFuncInstanceHClass, JSType::JS_SYNTAX_ERROR);
InitializeError(env, errorNativeFuncInstanceHClass, JSType::JS_EVAL_ERROR);
InitializeError(env, errorNativeFuncInstanceHClass, JSType::JS_OOM_ERROR);
}
void Builtins::InitializeAllTypeErrorWithRealm(const JSHandle<GlobalEnv> &realm) const
@ -1019,6 +1022,7 @@ void Builtins::InitializeAllTypeErrorWithRealm(const JSHandle<GlobalEnv> &realm)
SetErrorWithRealm(realm, JSType::JS_URI_ERROR);
SetErrorWithRealm(realm, JSType::JS_SYNTAX_ERROR);
SetErrorWithRealm(realm, JSType::JS_EVAL_ERROR);
SetErrorWithRealm(realm, JSType::JS_OOM_ERROR);
}
void Builtins::SetErrorWithRealm(const JSHandle<GlobalEnv> &realm, const JSType &errorTag) const
@ -1064,6 +1068,11 @@ void Builtins::SetErrorWithRealm(const JSHandle<GlobalEnv> &realm, const JSType
nameString = JSHandle<JSTaggedValue>(thread_->GlobalConstants()->GetHandledSyntaxErrorString());
realm->SetSyntaxErrorFunction(thread_, nativeErrorFunction);
break;
case JSType::JS_OOM_ERROR:
nativeErrorFunction = env->GetOOMErrorFunction();
nameString = JSHandle<JSTaggedValue>(thread_->GlobalConstants()->GetHandledOOMErrorString());
realm->SetOOMErrorFunction(thread_, nativeErrorFunction);
break;
default:
break;
}
@ -1118,6 +1127,10 @@ void Builtins::InitializeError(const JSHandle<GlobalEnv> &env, const JSHandle<JS
GeneralUpdateError(&errorParameter, SyntaxError::SyntaxErrorConstructor, SyntaxError::ToString,
"SyntaxError", JSType::JS_SYNTAX_ERROR);
break;
case JSType::JS_OOM_ERROR:
GeneralUpdateError(&errorParameter, OOMError::OOMErrorConstructor, OOMError::ToString,
"OutOfMemoryError", JSType::JS_OOM_ERROR);
break;
default:
break;
}
@ -1163,8 +1176,10 @@ void Builtins::InitializeError(const JSHandle<GlobalEnv> &env, const JSHandle<JS
env->SetURIErrorFunction(thread_, nativeErrorFunction);
} else if (errorTag == JSType::JS_SYNTAX_ERROR) {
env->SetSyntaxErrorFunction(thread_, nativeErrorFunction);
} else {
} else if (errorTag == JSType::JS_EVAL_ERROR) {
env->SetEvalErrorFunction(thread_, nativeErrorFunction);
} else {
env->SetOOMErrorFunction(thread_, nativeErrorFunction);
}
} // namespace panda::ecmascript
@ -1475,8 +1490,14 @@ void Builtins::InitializeFinalizationRegistry(const JSHandle<GlobalEnv> &env,
void Builtins::InitializeMath(const JSHandle<GlobalEnv> &env, const JSHandle<JSTaggedValue> &objFuncPrototypeVal) const
{
[[maybe_unused]] EcmaHandleScope scope(thread_);
<<<<<<< HEAD:ecmascript/builtins.cpp
JSHandle<JSHClass> mathClass = factory_->NewEcmaHClass(JSObject::SIZE, JSType::JS_OBJECT, objFuncPrototypeVal);
JSHandle<JSObject> mathObject = factory_->NewJSObjectWithInit(mathClass);
=======
JSHandle<JSHClass> mathDynclass = factory_->NewEcmaDynClass(JSObject::SIZE, JSType::JS_OBJECT, objFuncPrototypeVal);
JSHandle<JSObject> mathObject = factory_->NewJSObjectWithInit(mathDynclass);
RandomGenerator::InitRandom();
>>>>>>> origin/master:ecmascript/builtins/builtins.cpp
SetFunction(env, mathObject, "abs", Math::Abs, FunctionLength::ONE);
SetFunction(env, mathObject, "acos", Math::Acos, FunctionLength::ONE);
SetFunction(env, mathObject, "acosh", Math::Acosh, FunctionLength::ONE);
@ -1568,7 +1589,8 @@ 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);
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, "codePointAt", BuiltinsString::CodePointAt, FunctionLength::ONE);
@ -1591,7 +1613,8 @@ 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);
SetFunction(env, stringFuncPrototype, "substring", BuiltinsString::Substring, FunctionLength::TWO,
static_cast<uint8_t>(BUILTINS_STUB_ID(Substring)));
SetFunction(env, stringFuncPrototype, "substr", BuiltinsString::SubStr, FunctionLength::TWO);
SetFunction(env, stringFuncPrototype, "toLocaleLowerCase", BuiltinsString::ToLocaleLowerCase, FunctionLength::ZERO);
SetFunction(env, stringFuncPrototype, "toLocaleUpperCase", BuiltinsString::ToLocaleUpperCase, FunctionLength::ZERO);
@ -2534,6 +2557,8 @@ void Builtins::InitializePromiseJob(const JSHandle<GlobalEnv> &env)
env->SetPromiseReactionJob(thread_, func);
func = NewFunction(env, keyString, BuiltinsPromiseJob::PromiseResolveThenableJob, FunctionLength::THREE);
env->SetPromiseResolveThenableJob(thread_, func);
func = NewFunction(env, keyString, BuiltinsPromiseJob::DynamicImportJob, FunctionLength::FOUR);
env->SetDynamicImportJob(thread_, func);
}
void Builtins::InitializeDataView(const JSHandle<GlobalEnv> &env, const JSHandle<JSHClass> &objFuncClass) const

View File

@ -430,6 +430,9 @@ JSTaggedValue BuiltinsArray::Concat(EcmaRuntimeCallInfo *argv)
THROW_TYPE_ERROR_AND_RETURN(thread, "out of range.", JSTaggedValue::Exception());
}
double k = 0;
if (thisObjVal->IsStableJSArray(thread)) {
JSStableArray::Concat(thread, newArrayHandle, thisObjHandle, k, n);
}
while (k < thisLen) {
fromKey.Update(JSTaggedValue(k));
toKey.Update(JSTaggedValue(n));
@ -474,6 +477,10 @@ JSTaggedValue BuiltinsArray::Concat(EcmaRuntimeCallInfo *argv)
THROW_TYPE_ERROR_AND_RETURN(thread, "out of range.", JSTaggedValue::Exception());
}
double k = 0;
JSHandle<JSTaggedValue> addObjVal(addObjHandle);
if (addObjVal->IsStableJSArray(thread)) {
JSStableArray::Concat(thread, newArrayHandle, addObjHandle, k, n);
}
// v. Repeat, while k < len
while (k < len) {
fromKey.Update(JSTaggedValue(k));
@ -880,6 +887,12 @@ JSTaggedValue BuiltinsArray::Filter(EcmaRuntimeCallInfo *argv)
JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
JSMutableHandle<JSTaggedValue> toIndexHandle(thread, JSTaggedValue::Undefined());
uint32_t k = 0;
if (thisObjVal->IsStableJSArray(thread)) {
JSStableArray::Filter(newArrayHandle, thisObjHandle, argv, k, toIndex);
}
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
const int32_t argsLength = 3; // 3: «kValue, k, O»
JSTaggedValue callResult = GetTaggedBoolean(true);
while (k < len) {
bool exists = JSTaggedValue::HasProperty(thread, thisObjVal, k);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
@ -887,16 +900,12 @@ JSTaggedValue BuiltinsArray::Filter(EcmaRuntimeCallInfo *argv)
JSHandle<JSTaggedValue> kValue = JSArray::FastGetPropertyByValue(thread, thisObjVal, k);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
key.Update(JSTaggedValue(k));
const int32_t argsLength = 3; // 3: «kValue, k, O»
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
EcmaRuntimeCallInfo *info =
EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, thisArgHandle, undefined, argsLength);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
info->SetCallArg(kValue.GetTaggedValue(), key.GetTaggedValue(), thisObjVal.GetTaggedValue());
JSTaggedValue callResult = JSFunction::Call(info);
bool boolResult = callResult.ToBoolean();
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
if (boolResult) {
callResult = JSFunction::Call(info);
if (callResult.ToBoolean()) {
toIndexHandle.Update(JSTaggedValue(toIndex));
JSObject::CreateDataPropertyOrThrow(thread, newArrayHandle, toIndexHandle, kValue);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
@ -1425,9 +1434,14 @@ JSTaggedValue BuiltinsArray::Map(EcmaRuntimeCallInfo *argv)
// v. Let status be CreateDataPropertyOrThrow (A, Pk, mappedValue).
// vi. ReturnIfAbrupt(status).
// e. Increase k by 1.
uint32_t k = 0;
if (thisObjVal->IsStableJSArray(thread)) {
JSStableArray::Map(newArrayHandle, thisObjHandle, argv, k, len);
}
JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
JSMutableHandle<JSTaggedValue> mapResultHandle(thread, JSTaggedValue::Undefined());
uint32_t k = 0;
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
const int32_t argsLength = 3; // 3: «kValue, k, O»
while (k < len) {
bool exists = JSTaggedValue::HasProperty(thread, thisObjVal, k);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
@ -1435,8 +1449,6 @@ JSTaggedValue BuiltinsArray::Map(EcmaRuntimeCallInfo *argv)
JSHandle<JSTaggedValue> kValue = JSArray::FastGetPropertyByValue(thread, thisObjVal, k);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
key.Update(JSTaggedValue(k));
const int32_t argsLength = 3; // 3: «kValue, k, O»
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
EcmaRuntimeCallInfo *info =
EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, thisArgHandle, undefined, argsLength);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
@ -1839,6 +1851,9 @@ JSTaggedValue BuiltinsArray::Reverse(EcmaRuntimeCallInfo *argv)
JSMutableHandle<JSTaggedValue> upperP(thread, JSTaggedValue::Undefined());
JSHandle<JSTaggedValue> lowerValueHandle(thread, JSTaggedValue::Undefined());
JSHandle<JSTaggedValue> upperValueHandle(thread, JSTaggedValue::Undefined());
if (thisObjVal->IsStableJSArray(thread)) {
JSStableArray::Reverse(thread, thisObjHandle, thisHandle, lower, len);
}
while (lower != middle) {
double upper = len - lower - 1;
lowerP.Update(JSTaggedValue(lower));

View File

@ -160,4 +160,15 @@ JSTaggedValue BuiltinsAggregateError::ToString(EcmaRuntimeCallInfo *argv)
{
return ErrorHelper::ErrorCommonToString(argv, ErrorType::AGGREGATE_ERROR);
}
// OOMError
JSTaggedValue BuiltinsOOMError::OOMErrorConstructor(EcmaRuntimeCallInfo *argv)
{
return ErrorHelper::ErrorCommonConstructor(argv, ErrorType::OOM_ERROR);
}
JSTaggedValue BuiltinsOOMError::ToString(EcmaRuntimeCallInfo *argv)
{
return ErrorHelper::ErrorCommonToString(argv, ErrorType::OOM_ERROR);
}
} // namespace panda::ecmascript::builtins

View File

@ -85,5 +85,12 @@ public:
static JSTaggedValue ToString(EcmaRuntimeCallInfo *argv);
};
class BuiltinsOOMError : public base::BuiltinsBase {
public:
static JSTaggedValue OOMErrorConstructor(EcmaRuntimeCallInfo *argv);
static JSTaggedValue ToString(EcmaRuntimeCallInfo *argv);
};
} // namespace panda::ecmascript::builtins
#endif // ECMASCRIPT_BUILTINS_BUILTINS_ERRORS_H

View File

@ -276,7 +276,11 @@ JSTaggedValue BuiltinsFunction::FunctionPrototypeToString(EcmaRuntimeCallInfo *a
tooling::JSPtExtractor *debugExtractor =
JSPandaFileManager::GetInstance()->GetJSPtExtractor(method->GetJSPandaFile());
const std::string &sourceCode = debugExtractor->GetSourceCode(method->GetMethodId());
return GetTaggedString(thread, sourceCode.c_str());
if (!sourceCode.empty()) {
return GetTaggedString(thread, sourceCode.c_str());
} else {
return GetTaggedString(thread, "Cannot get source code of funtion");
}
}
THROW_TYPE_ERROR_AND_RETURN(thread,

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)
@ -106,7 +108,7 @@ JSTaggedValue BuiltinsMath::Asinh(EcmaRuntimeCallInfo *argv)
double result = base::NAN_VALUE;
// value == -NaN, NaN, result is NaN
if (!std::isnan(std::abs(value))) {
result = std::asinh(value);
result = base::MathHelper::Asinh(value);
}
return GetTaggedDouble(result);
}
@ -141,7 +143,7 @@ JSTaggedValue BuiltinsMath::Atanh(EcmaRuntimeCallInfo *argv)
double value = numberValue.GetNumber();
double result = base::NAN_VALUE;
if (value >= -1 && value <= 1) {
result = std::atanh(value);
result = base::MathHelper::Atanh(value);
}
return GetTaggedDouble(result);
}
@ -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

@ -20,9 +20,11 @@
#include "ecmascript/interpreter/interpreter.h"
#include "ecmascript/js_function.h"
#include "ecmascript/js_handle.h"
#include "ecmascript/jspandafile/js_pandafile_executor.h"
#include "ecmascript/js_promise.h"
#include "ecmascript/js_tagged_value.h"
#include "ecmascript/module/js_module_manager.h"
#include "ecmascript/require/js_cjs_module.h"
#include "libpandabase/macros.h"
namespace panda::ecmascript::builtins {
@ -119,4 +121,57 @@ JSTaggedValue BuiltinsPromiseJob::PromiseResolveThenableJob(EcmaRuntimeCallInfo
// 4. NextJob Completion(thenCallResult).
return result;
}
JSTaggedValue BuiltinsPromiseJob::DynamicImportJob(EcmaRuntimeCallInfo *argv)
{
ASSERT(argv);
BUILTINS_API_TRACE(argv->GetThread(), PromiseJob, DynamicImportJob);
JSThread *thread = argv->GetThread();
[[maybe_unused]] EcmaHandleScope handleScope(thread);
EcmaVM *vm = thread->GetEcmaVM();
JSHandle<JSPromiseReactionsFunction> resolve(GetCallArg(argv, 0));
JSHandle<JSPromiseReactionsFunction> reject(GetCallArg(argv, 1)); // 1 : first argument
JSHandle<EcmaString> dirPath(GetCallArg(argv, 2)); // 2: second argument
JSHandle<EcmaString> specifier(GetCallArg(argv, 3)); // 3 : third argument
// dirPath + specifier ----> fileName
JSHandle<EcmaString> fileName = CjsModule::ResolveFilenameFromNative(thread, dirPath.GetTaggedValue(),
specifier.GetTaggedValue());
CString moduleName = ConvertToString(fileName.GetTaggedValue());
// std::string entry = "_GLOBAL::func_main_0";
if (!vm->GetModuleManager()->IsImportedModuleLoaded(fileName.GetTaggedValue())) {
if (!JSPandaFileExecutor::ExecuteFromFile(thread, moduleName.c_str(), "_GLOBAL::func_main_0")) {
LOG_FULL(FATAL) << "Cannot execute dynamic-imported panda file : ";
}
}
// b. Let moduleRecord be ! HostResolveImportedModule(referencingScriptOrModule, specifier).
JSHandle<SourceTextModule> moduleRecord = vm->GetModuleManager()->HostGetImportedModule(fileName);
// d. Let namespace be ? GetModuleNamespace(moduleRecord).
JSHandle<JSTaggedValue> moduleNamespace = SourceTextModule::GetModuleNamespace(thread, moduleRecord);
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
EcmaRuntimeCallInfo *info =
EcmaInterpreter::NewRuntimeCallInfo(thread,
JSHandle<JSTaggedValue>(resolve),
undefined, undefined, 1);
info->SetCallArg(moduleNamespace.GetTaggedValue());
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
JSTaggedValue result = JSFunction::Call(info);
if (thread->HasPendingException()) {
auto thenResult = JSPromise::IfThrowGetThrowValue(thread);
thread->ClearException();
JSHandle<JSTaggedValue> rejectfun(reject);
EcmaRuntimeCallInfo *runtimeInfo =
EcmaInterpreter::NewRuntimeCallInfo(thread, rejectfun, undefined, undefined, 1);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
runtimeInfo->SetCallArg(thenResult.GetTaggedValue());
return JSFunction::Call(runtimeInfo);
}
return result;
}
} // namespace panda::ecmascript::builtins

View File

@ -23,6 +23,7 @@ class BuiltinsPromiseJob : base::BuiltinsBase {
public:
static JSTaggedValue PromiseReactionJob(EcmaRuntimeCallInfo *argv);
static JSTaggedValue PromiseResolveThenableJob(EcmaRuntimeCallInfo *argv);
static JSTaggedValue DynamicImportJob(EcmaRuntimeCallInfo *argv);
};
} // namespace panda::ecmascript::builtins
#endif // ECMASCRIPT_JS_PROMISE_JOB_H

View File

@ -1319,29 +1319,48 @@ JSTaggedValue BuiltinsTypedArray::Sort(EcmaRuntimeCallInfo *argv)
uint32_t len = JSHandle<JSTypedArray>::Cast(thisObjHandle)->GetArrayLength();
JSHandle<JSTaggedValue> callbackFnHandle = GetCallArg(argv, 0);
JSMutableHandle<JSTaggedValue> presentValue(thread, JSTaggedValue::Undefined());
JSMutableHandle<JSTaggedValue> middleValue(thread, JSTaggedValue::Undefined());
JSMutableHandle<JSTaggedValue> previousValue(thread, JSTaggedValue::Undefined());
JSMutableHandle<JSTaggedValue> key1(thread, JSTaggedValue::Undefined());
JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
JSMutableHandle<JSTaggedValue> key2(thread, JSTaggedValue::Undefined());
for (uint32_t i = 1; i < len; i++) {
uint32_t beginIndex = 0;
uint32_t endIndex = i;
key.Update(JSTaggedValue(i));
presentValue.Update(FastRuntimeStub::FastGetPropertyByValue(thread, thisObjHandle.GetTaggedValue(),
key.GetTaggedValue()));
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
while (beginIndex < endIndex) {
uint32_t middleIndex = (beginIndex + endIndex) / 2; // 2 : half
key1.Update(JSTaggedValue(middleIndex));
middleValue.Update(FastRuntimeStub::FastGetPropertyByValue(thread, thisObjHandle.GetTaggedValue(),
key1.GetTaggedValue()));
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
int32_t compareResult = TypedArrayHelper::SortCompare(thread, callbackFnHandle, buffer,
middleValue, presentValue);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
compareResult > 0 ? (endIndex = middleIndex) : (beginIndex = middleIndex + 1);
}
uint32_t i = 0;
while (i < len - 1) {
uint32_t j = len - 1;
while (j > i) {
JSHandle<JSTaggedValue> xValue = JSTaggedValue::GetProperty(thread, thisObjVal, j - 1).GetValue();
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
JSHandle<JSTaggedValue> yValue = JSTaggedValue::GetProperty(thread, thisObjVal, j).GetValue();
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
int32_t compareResult;
compareResult = TypedArrayHelper::SortCompare(thread, callbackFnHandle, buffer, xValue, yValue);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
if (compareResult > 0) {
JSTaggedValue::SetProperty(thread, thisObjVal, j - 1, yValue, true);
if (endIndex >= 0 && endIndex < i) {
for (uint32_t j = i; j > endIndex; j--) {
key2.Update(JSTaggedValue(j - 1));
previousValue.Update(
FastRuntimeStub::FastGetPropertyByValue(thread, thisObjHandle.GetTaggedValue(),
key2.GetTaggedValue()));
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
JSTaggedValue::SetProperty(thread, thisObjVal, j, xValue, true);
FastRuntimeStub::FastSetPropertyByIndex(thread, thisObjHandle.GetTaggedValue(), j,
previousValue.GetTaggedValue());
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
}
j--;
FastRuntimeStub::FastSetPropertyByIndex(thread, thisObjHandle.GetTaggedValue(), endIndex,
presentValue.GetTaggedValue());
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
}
i++;
}
return JSTaggedValue::ToObject(thread, thisHandle).GetTaggedValue();
return thisObjHandle.GetTaggedValue();
}
// 22.2.3.26 %TypedArray%.prototype.subarray( [ begin [ , end ] ] )

View File

@ -425,7 +425,13 @@ HWTEST_F_L0(BuiltinsFunctionTest, FunctionPrototypeHasInstance)
TestHelper::TearDownFrame(thread, prev);
}
// Function.prototype.call.toString()
/**
* @tc.name: FunctionPrototypeToString
* @tc.desc: Create msgs through "CreateEcmaRuntimeCallInfo" function, Set ArgsNumber and CallArg, then call
* the "FunctionPrototypeToString" function to get the result of Function.prototype.call.toString().
* @tc.type: FUNC
* @tc.require: issueI5INW1
*/
HWTEST_F_L0(BuiltinsFunctionTest, FunctionPrototypeToString)
{
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();

View File

@ -878,6 +878,36 @@ HWTEST_F_L0(BuiltinsMathTest, Asinh_8)
ASSERT_EQ(result.GetRawData(), expect.GetRawData());
}
// Math.asinh(-0.0)
HWTEST_F_L0(BuiltinsMathTest, Asinh_9)
{
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread_, JSTaggedValue::Undefined(), 6);
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(-0.0));
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread_, ecmaRuntimeCallInfo);
JSTaggedValue result = BuiltinsMath::Asinh(ecmaRuntimeCallInfo);
TestHelper::TearDownFrame(thread_, prev);
JSTaggedValue expect = BuiltinsBase::GetTaggedDouble(-0.0);
ASSERT_EQ(result.GetRawData(), expect.GetRawData());
}
// Math.asinh(+0.0)
HWTEST_F_L0(BuiltinsMathTest, Asinh_10)
{
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread_, JSTaggedValue::Undefined(), 6);
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(+0.0));
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread_, ecmaRuntimeCallInfo);
JSTaggedValue result = BuiltinsMath::Asinh(ecmaRuntimeCallInfo);
TestHelper::TearDownFrame(thread_, prev);
JSTaggedValue expect = BuiltinsBase::GetTaggedDouble(+0.0);
ASSERT_EQ(result.GetRawData(), expect.GetRawData());
}
// Math.atan(-1)
HWTEST_F_L0(BuiltinsMathTest, Atan)
{
@ -1152,6 +1182,36 @@ HWTEST_F_L0(BuiltinsMathTest, Atanh_8)
ASSERT_EQ(result.GetRawData(), expect.GetRawData());
}
// Math.atanh(-0.0)
HWTEST_F_L0(BuiltinsMathTest, Atanh_9)
{
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread_, JSTaggedValue::Undefined(), 6);
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(-0.0));
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread_, ecmaRuntimeCallInfo);
JSTaggedValue result = BuiltinsMath::Atanh(ecmaRuntimeCallInfo);
TestHelper::TearDownFrame(thread_, prev);
JSTaggedValue expect = BuiltinsBase::GetTaggedDouble(-0.0);
ASSERT_EQ(result.GetRawData(), expect.GetRawData());
}
// Math.atanh(+0.0)
HWTEST_F_L0(BuiltinsMathTest, Atanh_10)
{
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread_, JSTaggedValue::Undefined(), 6);
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(+0.0));
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread_, ecmaRuntimeCallInfo);
JSTaggedValue result = BuiltinsMath::Atanh(ecmaRuntimeCallInfo);
TestHelper::TearDownFrame(thread_, prev);
JSTaggedValue expect = BuiltinsBase::GetTaggedDouble(+0.0);
ASSERT_EQ(result.GetRawData(), expect.GetRawData());
}
// Math.atan2(NaN, 1.5)
HWTEST_F_L0(BuiltinsMathTest, Atan2)
{

View File

@ -50,6 +50,7 @@ source_set("libark_jsoptimizer_set") {
"async_function_lowering.cpp",
"bc_call_signature.cpp",
"builtins/builtins_call_signature.cpp",
"builtins/builtins_string_stub_builder.cpp",
"builtins/builtins_stubs.cpp",
"bytecode_circuit_builder.cpp",
"bytecode_info_collector.cpp",
@ -207,7 +208,7 @@ source_set("ark_aot_compiler_set") {
source_set("libark_stub_set") {
deps = [ ":build_stub_to_cpp" ]
sources = [ "$root_gen_dir/arkcompiler/ets_runtime/stub_aot.cpp" ]
sources = [ "$root_gen_dir/arkcompiler/ets_runtime/stub_an.cpp" ]
public_configs = [
"$js_root:ark_jsruntime_common_config",
@ -216,7 +217,7 @@ source_set("libark_stub_set") {
}
source_set("libark_mock_stub_set") {
sources = [ "mock/mock_stub_aot.cpp" ]
sources = [ "mock/mock_stub_an.cpp" ]
public_configs = [
"$js_root:ark_jsruntime_common_config",
@ -297,10 +298,10 @@ action("gen_stub_file") {
get_label_info(":ark_stub_compiler(${host_toolchain})", "root_out_dir")
if (current_toolchain == host_toolchain) {
stub_option = " --stub-file=" + rebase_path(stub_file_gen_dir) + "/stub.aot"
stub_option = " --stub-file=" + rebase_path(stub_file_gen_dir) + "/stub.an"
} else {
stub_option = " --stub-file=" + rebase_path(stub_file_gen_dir) +
"/stub.aot" + " --target-triple=aarch64-unknown-linux-gnu"
"/stub.an" + " --target-triple=aarch64-unknown-linux-gnu"
}
if (defined(ark_standalone_build)) {
@ -331,11 +332,11 @@ action("gen_stub_file") {
stub_env,
]
outputs = [ "$stub_file_gen_dir/stub.aot" ]
outputs = [ "$stub_file_gen_dir/stub.an" ]
}
action("build_stub_to_cpp") {
sources = [ "$root_gen_dir/arkcompiler/ets_runtime/stub.aot" ]
sources = [ "$root_gen_dir/arkcompiler/ets_runtime/stub.an" ]
script = "$js_root/script/build_resource_to_cpp.py"
@ -343,10 +344,10 @@ action("build_stub_to_cpp") {
args = [
"--input",
rebase_path("$root_gen_dir/arkcompiler/ets_runtime/stub.aot"),
rebase_path("$root_gen_dir/arkcompiler/ets_runtime/stub.an"),
"--output",
rebase_path("$root_gen_dir/arkcompiler/ets_runtime/stub_aot.cpp"),
rebase_path("$root_gen_dir/arkcompiler/ets_runtime/stub_an.cpp"),
]
outputs = [ "$root_gen_dir/arkcompiler/ets_runtime/stub_aot.cpp" ]
outputs = [ "$root_gen_dir/arkcompiler/ets_runtime/stub_an.cpp" ]
}

View File

@ -98,6 +98,8 @@ int Main(const int argc, const char **argv)
CompilerLog log(logOption, isEnableBcTrace);
AotMethodLogList logList(logMethodsList);
AOTFileGenerator generator(&log, &logList, vm);
generator.InitializeConstantPoolInfos(pandaFileNames);
vm->GetTSManager()->SetConstantPoolInfo(generator.GetCpProcessor().GetInfos());
PassManager passManager(vm, entry, triple, optLevel, relocMode, &log, &logList, maxAotMethodSize);
for (const auto &fileName : pandaFileNames) {
LOG_COMPILER(INFO) << "AOT start to execute ark file: " << fileName;
@ -106,7 +108,7 @@ int Main(const int argc, const char **argv)
continue;
}
}
generator.SaveAOTFile(outputFileName + ".aot");
generator.SaveAOTFile(outputFileName + ".an");
generator.SaveSnapshotFile();
JSNApi::DestroyJSVM(vm);

View File

@ -165,7 +165,8 @@ namespace panda::ecmascript::kungfu {
T(HandleStthisbyvalueImm16V8) \
T(HandleLdpatchvarImm8) \
T(HandleStpatchvarImm8V8) \
T(HandleJeqzImm8) \
T(HandleDynamicimportV8) \
T(HandleJeqzImm8) \
T(HandleDefineclasswithbufferImm8Id16Id16Imm16V8) \
T(HandleDefineclasswithbufferImm16Id16Id16Imm16V8) \
T(HandleResumegenerator) \
@ -173,8 +174,8 @@ namespace panda::ecmascript::kungfu {
T(HandleGettemplateobjectImm8) \
T(HandleGettemplateobjectImm16) \
T(HandleGetnextpropnameV8) \
T(HandleJeqzImm16) \
T(HandleJeqzImm32) \
T(HandleJeqzImm16) \
T(HandleJeqzImm32) \
T(HandleSetobjectwithprotoImm8V8) \
T(HandleDelobjpropV8) \
T(HandleSuspendgeneratorV8) \

View File

@ -25,6 +25,8 @@ namespace panda::ecmascript::kungfu {
#define BUILTINS_STUB_LIST(V) \
V(CharCodeAt) \
V(IndexOf) \
V(Substring) \
V(CharAt) \
class BuiltinsStubCSigns {
public:

View File

@ -0,0 +1,567 @@
/*
* 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/compiler/builtins/builtins_string_stub_builder.h"
#include "ecmascript/compiler/builtins/builtins_stubs.h"
#include "ecmascript/compiler/new_object_stub_builder.h"
namespace panda::ecmascript::kungfu {
GateRef BuiltinsStringStubBuilder::StringAt(GateRef obj, GateRef index)
{
auto env = GetEnvironment();
Label entry(env);
env->SubCfgEntry(&entry);
DEFVARIABLE(result, VariableType::INT32(), Int32(0));
Label exit(env);
Label isUtf16(env);
Label isUtf8(env);
Label doIntOp(env);
Label leftIsNumber(env);
Label rightIsNumber(env);
GateRef dataUtf16 = PtrAdd(obj, IntPtr(EcmaString::DATA_OFFSET));
Branch(IsUtf16String(obj), &isUtf16, &isUtf8);
Bind(&isUtf16);
{
result = ZExtInt16ToInt32(Load(VariableType::INT16(), PtrAdd(dataUtf16,
PtrMul(ChangeInt32ToIntPtr(index), IntPtr(sizeof(uint16_t))))));
Jump(&exit);
}
Bind(&isUtf8);
{
result = ZExtInt8ToInt32(Load(VariableType::INT8(), PtrAdd(dataUtf16,
PtrMul(ChangeInt32ToIntPtr(index), IntPtr(sizeof(uint8_t))))));
Jump(&exit);
}
Bind(&exit);
auto ret = *result;
env->SubCfgExit();
return ret;
}
GateRef BuiltinsStringStubBuilder::CreateFromEcmaString(GateRef glue, GateRef obj, GateRef index)
{
auto env = GetEnvironment();
Label entry(env);
env->SubCfgEntry(&entry);
DEFVARIABLE(result, VariableType::JS_POINTER(), Hole());
DEFVARIABLE(canBeCompressed, VariableType::BOOL(), False());
DEFVARIABLE(data, VariableType::INT16(), Int32(0));
Label exit(env);
Label isUtf16(env);
Label isUtf8(env);
Label allocString(env);
GateRef dataUtf = PtrAdd(obj, IntPtr(EcmaString::DATA_OFFSET));
Branch(IsUtf16String(obj), &isUtf16, &isUtf8);
Bind(&isUtf16);
{
GateRef dataAddr = PtrAdd(dataUtf, PtrMul(ChangeInt32ToIntPtr(index), IntPtr(sizeof(uint16_t))));
data = Load(VariableType::INT16(), dataAddr);
canBeCompressed = CanBeCompressed(dataAddr, Int32(1), true);
Jump(&allocString);
}
Bind(&isUtf8);
{
GateRef dataAddr = PtrAdd(dataUtf, PtrMul(ChangeInt32ToIntPtr(index), IntPtr(sizeof(uint8_t))));
data = ZExtInt8ToInt16(Load(VariableType::INT8(), dataAddr));
canBeCompressed = CanBeCompressed(dataAddr, Int32(1), false);
Jump(&allocString);
}
Bind(&allocString);
{
Label afterNew(env);
Label isUtf8Next(env);
Label isUtf16Next(env);
NewObjectStubBuilder newBuilder(this);
newBuilder.SetParameters(glue, 0);
Branch(*canBeCompressed, &isUtf8Next, &isUtf16Next);
Bind(&isUtf8Next);
{
newBuilder.AllocStringObject(&result, &afterNew, Int32(1), true);
}
Bind(&isUtf16Next);
{
newBuilder.AllocStringObject(&result, &afterNew, Int32(1), false);
}
Bind(&afterNew);
{
Label isUtf8Copy(env);
Label isUtf16Copy(env);
GateRef dst = PtrAdd(*result, IntPtr(EcmaString::DATA_OFFSET));
Branch(*canBeCompressed, &isUtf8Copy, &isUtf16Copy);
Bind(&isUtf8Copy);
{
Store(VariableType::INT8(), glue, dst, IntPtr(0), ChangeInt16ToInt8(*data));
Jump(&exit);
}
Bind(&isUtf16Copy);
{
Store(VariableType::INT16(), glue, dst, IntPtr(0), *data);
Jump(&exit);
}
}
}
Bind(&exit);
auto ret = *result;
env->SubCfgExit();
return ret;
}
GateRef BuiltinsStringStubBuilder::FastSubUtf8String(GateRef glue, GateRef thisValue, GateRef from, GateRef len)
{
auto env = GetEnvironment();
Label entry(env);
env->SubCfgEntry(&entry);
DEFVARIABLE(result, VariableType::JS_POINTER(), Undefined());
Label exit(env);
Label lenEqualZero(env);
Label lenNotEqualZero(env);
Branch(Int32Equal(len, Int32(0)), &lenEqualZero, &lenNotEqualZero);
Bind(&lenEqualZero);
{
result = GetGlobalConstantValue(
VariableType::JS_POINTER(), glue, ConstantIndex::EMPTY_STRING_OBJECT_INDEX);
Jump(&exit);
}
Bind(&lenNotEqualZero);
{
NewObjectStubBuilder newBuilder(this);
newBuilder.SetParameters(glue, 0);
Label afterNew(env);
newBuilder.AllocStringObject(&result, &afterNew, len, true);
Bind(&afterNew);
{
GateRef dst = PtrAdd(*result, IntPtr(EcmaString::DATA_OFFSET));
GateRef source = PtrAdd(PtrAdd(thisValue, IntPtr(EcmaString::DATA_OFFSET)), ChangeInt32ToIntPtr(from));
StringCopy(glue, dst, source, len, IntPtr(sizeof(uint8_t)), VariableType::INT8());
Jump(&exit);
}
}
Bind(&exit);
auto ret = *result;
env->SubCfgExit();
return ret;
}
GateRef BuiltinsStringStubBuilder::FastSubUtf16String(GateRef glue, GateRef thisValue, GateRef from, GateRef len)
{
auto env = GetEnvironment();
Label entry(env);
env->SubCfgEntry(&entry);
DEFVARIABLE(result, VariableType::JS_POINTER(), Undefined());
Label exit(env);
Label isUtf16(env);
Label isUtf8(env);
Label isUtf8Next(env);
Label isUtf16Next(env);
Label lenEqualZero(env);
Label lenNotEqualZero(env);
Branch(Int32Equal(len, Int32(0)), &lenEqualZero, &lenNotEqualZero);
Bind(&lenEqualZero);
{
result = GetGlobalConstantValue(
VariableType::JS_POINTER(), glue, ConstantIndex::EMPTY_STRING_OBJECT_INDEX);
Jump(&exit);
}
Bind(&lenNotEqualZero);
{
GateRef fromOffset = PtrMul(ChangeInt32ToIntPtr(from), IntPtr(sizeof(uint16_t) / sizeof(uint8_t)));
GateRef source = PtrAdd(PtrAdd(thisValue, IntPtr(EcmaString::DATA_OFFSET)), fromOffset);
GateRef canBeCompressed = CanBeCompressed(source, len, true);
NewObjectStubBuilder newBuilder(this);
newBuilder.SetParameters(glue, 0);
Label afterNew(env);
Branch(canBeCompressed, &isUtf8, &isUtf16);
Bind(&isUtf8);
{
newBuilder.AllocStringObject(&result, &afterNew, len, true);
}
Bind(&isUtf16);
{
newBuilder.AllocStringObject(&result, &afterNew, len, false);
}
Bind(&afterNew);
{
GateRef source1 = PtrAdd(PtrAdd(thisValue, IntPtr(EcmaString::DATA_OFFSET)), fromOffset);
GateRef dst = PtrAdd(*result, IntPtr(EcmaString::DATA_OFFSET));
Branch(canBeCompressed, &isUtf8Next, &isUtf16Next);
Bind(&isUtf8Next);
{
CopyUtf16AsUtf8(glue, source1, dst, len);
Jump(&exit);
}
Bind(&isUtf16Next);
{
StringCopy(glue, dst, source1, len, IntPtr(sizeof(uint16_t)), VariableType::INT16());
Jump(&exit);
}
}
}
Bind(&exit);
auto ret = *result;
env->SubCfgExit();
return ret;
}
void BuiltinsStringStubBuilder::StringCopy(GateRef glue, GateRef dst, GateRef source,
GateRef sourceLength, GateRef size, VariableType type)
{
auto env = GetEnvironment();
Label entry(env);
env->SubCfgEntry(&entry);
DEFVARIABLE(dstTmp, VariableType::JS_ANY(), dst);
DEFVARIABLE(sourceTmp, VariableType::JS_ANY(), source);
DEFVARIABLE(len, VariableType::INT32(), sourceLength);
Label loopHead(env);
Label loopEnd(env);
Label next(env);
Label exit(env);
Jump(&loopHead);
LoopBegin(&loopHead);
{
Branch(Int32GreaterThan(*len, Int32(0)), &next, &exit);
Bind(&next);
{
len = Int32Sub(*len, Int32(1));
GateRef i = Load(type, *sourceTmp);
Store(type, glue, *dstTmp, IntPtr(0), i);
Jump(&loopEnd);
}
}
Bind(&loopEnd);
sourceTmp = PtrAdd(*sourceTmp, size);
dstTmp = PtrAdd(*dstTmp, size);
LoopEnd(&loopHead);
Bind(&exit);
env->SubCfgExit();
return;
}
GateRef BuiltinsStringStubBuilder::CanBeCompressed(GateRef data, GateRef len, bool isUtf16)
{
auto env = GetEnvironment();
Label entry(env);
env->SubCfgEntry(&entry);
DEFVARIABLE(result, VariableType::BOOL(), True());
DEFVARIABLE(i, VariableType::INT32(), Int32(0));
Label loopHead(env);
Label loopEnd(env);
Label nextCount(env);
Label isNotASCIICharacter(env);
Label exit(env);
Jump(&loopHead);
LoopBegin(&loopHead);
{
Branch(Int32LessThan(*i, len), &nextCount, &exit);
Bind(&nextCount);
{
if (isUtf16) {
GateRef tmp = Load(VariableType::INT16(), data,
PtrMul(ChangeInt32ToIntPtr(*i), IntPtr(sizeof(uint16_t))));
Branch(IsASCIICharacter(ZExtInt16ToInt32(tmp)), &loopEnd, &isNotASCIICharacter);
} else {
GateRef tmp = Load(VariableType::INT8(), data,
PtrMul(ChangeInt32ToIntPtr(*i), IntPtr(sizeof(uint8_t))));
Branch(IsASCIICharacter(ZExtInt8ToInt32(tmp)), &loopEnd, &isNotASCIICharacter);
}
Bind(&isNotASCIICharacter);
{
result = False();
Jump(&exit);
}
}
}
Bind(&loopEnd);
i = Int32Add(*i, Int32(1));
LoopEnd(&loopHead);
Bind(&exit);
auto ret = *result;
env->SubCfgExit();
return ret;
}
void BuiltinsStringStubBuilder::CopyUtf16AsUtf8(GateRef glue, GateRef src, GateRef dst,
GateRef sourceLength)
{
auto env = GetEnvironment();
Label entry(env);
env->SubCfgEntry(&entry);
DEFVARIABLE(dstTmp, VariableType::JS_ANY(), dst);
DEFVARIABLE(sourceTmp, VariableType::JS_ANY(), src);
DEFVARIABLE(len, VariableType::INT32(), sourceLength);
Label loopHead(env);
Label loopEnd(env);
Label next(env);
Label exit(env);
Jump(&loopHead);
LoopBegin(&loopHead);
{
Branch(Int32GreaterThan(*len, Int32(0)), &next, &exit);
Bind(&next);
{
len = Int32Sub(*len, Int32(1));
GateRef i = Load(VariableType::INT16(), *sourceTmp);
Store(VariableType::INT8(), glue, *dstTmp, IntPtr(0), ChangeInt16ToInt8(i));
Jump(&loopEnd);
}
}
Bind(&loopEnd);
sourceTmp = PtrAdd(*sourceTmp, IntPtr(sizeof(uint16_t)));
dstTmp = PtrAdd(*dstTmp, IntPtr(sizeof(uint8_t)));
LoopEnd(&loopHead);
Bind(&exit);
env->SubCfgExit();
return;
}
GateRef BuiltinsStringStubBuilder::GetUtf16Date(GateRef stringData, GateRef index)
{
return ZExtInt16ToInt32(Load(VariableType::INT16(), PtrAdd(stringData,
PtrMul(ChangeInt32ToIntPtr(index), IntPtr(sizeof(uint16_t))))));
}
GateRef BuiltinsStringStubBuilder::IsASCIICharacter(GateRef data)
{
return Int32LessThan(Int32Sub(data, Int32(1)), Int32(base::utf_helper::UTF8_1B_MAX));
}
GateRef BuiltinsStringStubBuilder::GetUtf8Date(GateRef stringData, GateRef index)
{
return ZExtInt8ToInt32(Load(VariableType::INT8(), PtrAdd(stringData,
PtrMul(ChangeInt32ToIntPtr(index), IntPtr(sizeof(uint8_t))))));
}
GateRef BuiltinsStringStubBuilder::StringIndexOf(GateRef lhsData, bool lhsIsUtf8, GateRef rhsData, bool rhsIsUtf8,
GateRef pos, GateRef max, GateRef rhsCount)
{
auto env = GetEnvironment();
Label entry(env);
env->SubCfgEntry(&entry);
DEFVARIABLE(i, VariableType::INT32(), pos);
DEFVARIABLE(result, VariableType::INT32(), Int32(-1));
DEFVARIABLE(j, VariableType::INT32(), Int32(0));
DEFVARIABLE(k, VariableType::INT32(), Int32(1));
Label exit(env);
Label next(env);
Label continueFor(env);
Label lhsNotEqualFirst(env);
Label continueCount(env);
Label lessEnd(env);
Label equalEnd(env);
Label loopHead(env);
Label loopEnd(env);
Label nextCount(env);
Label nextCount1(env);
Label nextCount2(env);
GateRef first;
if (rhsIsUtf8) {
first = ZExtInt8ToInt32(Load(VariableType::INT8(), rhsData));
} else {
first = ZExtInt16ToInt32(Load(VariableType::INT16(), rhsData));
}
Jump(&loopHead);
LoopBegin(&loopHead);
Branch(Int32LessThanOrEqual(*i, max), &next, &exit);
Bind(&next);
{
Label loopHead1(env);
Label loopEnd1(env);
GateRef lhsTemp;
if (lhsIsUtf8) {
lhsTemp = GetUtf8Date(lhsData, *i);
} else {
lhsTemp = GetUtf16Date(lhsData, *i);
}
Branch(Int32NotEqual(lhsTemp, first), &nextCount1, &nextCount);
Bind(&nextCount1);
{
i = Int32Add(*i, Int32(1));
Jump(&loopHead1);
}
LoopBegin(&loopHead1);
{
Branch(Int32LessThanOrEqual(*i, max), &continueFor, &nextCount);
Bind(&continueFor);
{
GateRef lhsTemp1;
if (lhsIsUtf8) {
lhsTemp1 = GetUtf8Date(lhsData, *i);
} else {
lhsTemp1 = GetUtf16Date(lhsData, *i);
}
Branch(Int32NotEqual(lhsTemp1, first), &lhsNotEqualFirst, &nextCount);
Bind(&lhsNotEqualFirst);
{
i = Int32Add(*i, Int32(1));
Jump(&loopEnd1);
}
}
}
Bind(&loopEnd1);
LoopEnd(&loopHead1);
Bind(&nextCount);
{
Branch(Int32LessThanOrEqual(*i, max), &continueCount, &loopEnd);
Bind(&continueCount);
{
Label loopHead2(env);
Label loopEnd2(env);
j = Int32Add(*i, Int32(1));
GateRef end = Int32Sub(Int32Add(*j, rhsCount), Int32(1));
k = Int32(1);
Jump(&loopHead2);
LoopBegin(&loopHead2);
{
Branch(Int32LessThan(*j, end), &lessEnd, &nextCount2);
Bind(&lessEnd);
{
GateRef lhsTemp2;
if (lhsIsUtf8) {
lhsTemp2 = GetUtf8Date(lhsData, *j);
} else {
lhsTemp2 = GetUtf16Date(lhsData, *j);
}
GateRef rhsTemp;
if (rhsIsUtf8) {
rhsTemp = GetUtf8Date(rhsData, *k);
} else {
rhsTemp = GetUtf16Date(rhsData, *k);
}
Branch(Int32Equal(lhsTemp2, rhsTemp), &loopEnd2, &nextCount2);
}
}
Bind(&loopEnd2);
j = Int32Add(*j, Int32(1));
k = Int32Add(*k, Int32(1));
LoopEnd(&loopHead2);
Bind(&nextCount2);
{
Branch(Int32Equal(*j, end), &equalEnd, &loopEnd);
Bind(&equalEnd);
result = *i;
Jump(&exit);
}
}
}
}
Bind(&loopEnd);
i = Int32Add(*i, Int32(1));
LoopEnd(&loopHead);
Bind(&exit);
auto ret = *result;
env->SubCfgExit();
return ret;
}
GateRef BuiltinsStringStubBuilder::StringIndexOf(GateRef lhs, GateRef rhs, GateRef pos)
{
auto env = GetEnvironment();
Label entry(env);
env->SubCfgEntry(&entry);
DEFVARIABLE(result, VariableType::INT32(), Int32(-1));
DEFVARIABLE(posTag, VariableType::INT32(), pos);
Label exit(env);
Label rhsCountEqualZero(env);
Label nextCount(env);
Label rhsCountNotEqualZero(env);
Label posLessZero(env);
Label posNotLessZero(env);
Label maxNotLessZero(env);
Label rhsIsUtf8(env);
Label rhsIsUtf16(env);
GateRef lhsCount = GetLengthFromString(lhs);
GateRef rhsCount = GetLengthFromString(rhs);
Branch(Int32GreaterThan(pos, lhsCount), &exit, &nextCount);
Bind(&nextCount);
{
Branch(Int32Equal(rhsCount, Int32(0)), &rhsCountEqualZero, &rhsCountNotEqualZero);
Bind(&rhsCountEqualZero);
{
result = pos;
Jump(&exit);
}
Bind(&rhsCountNotEqualZero);
{
Branch(Int32LessThan(pos, Int32(0)), &posLessZero, &posNotLessZero);
Bind(&posLessZero);
{
posTag = Int32(0);
Jump(&posNotLessZero);
}
Bind(&posNotLessZero);
{
GateRef max = Int32Sub(lhsCount, rhsCount);
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));
Branch(IsUtf8String(rhs), &rhsIsUtf8, &rhsIsUtf16);
Bind(&rhsIsUtf8);
{
Label lhsIsUtf8(env);
Label lhsIsUtf16(env);
Branch(IsUtf8String(lhs), &lhsIsUtf8, &lhsIsUtf16);
Bind(&lhsIsUtf8);
{
result = StringIndexOf(lhsData, true, rhsData, true, *posTag, max, rhsCount);
Jump(&exit);
}
Bind(&lhsIsUtf16);
{
result = StringIndexOf(lhsData, false, rhsData, true, *posTag, max, rhsCount);
Jump(&exit);
}
}
Bind(&rhsIsUtf16);
{
Label lhsIsUtf8(env);
Label lhsIsUtf16(env);
Branch(IsUtf8String(lhs), &lhsIsUtf8, &lhsIsUtf16);
Bind(&lhsIsUtf8);
{
result = StringIndexOf(lhsData, true, rhsData, false, *posTag, max, rhsCount);
Jump(&exit);
}
Bind(&lhsIsUtf16);
{
result = StringIndexOf(lhsData, false, rhsData, false, *posTag, max, rhsCount);
Jump(&exit);
}
}
}
}
}
}
Bind(&exit);
auto ret = *result;
env->SubCfgExit();
return ret;
}
} // namespace panda::ecmascript::kungfu

View File

@ -0,0 +1,46 @@
/*
* 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.
*/
#ifndef ECMASCRIPT_COMPILER_BUILTINS_STRING_STUB_BUILDER_H
#define ECMASCRIPT_COMPILER_BUILTINS_STRING_STUB_BUILDER_H
#include "ecmascript/compiler/stub_builder-inl.h"
namespace panda::ecmascript::kungfu {
class BuiltinsStringStubBuilder : public StubBuilder {
public:
explicit BuiltinsStringStubBuilder(StubBuilder *parent)
: StubBuilder(parent) {}
~BuiltinsStringStubBuilder() = default;
NO_MOVE_SEMANTIC(BuiltinsStringStubBuilder);
NO_COPY_SEMANTIC(BuiltinsStringStubBuilder);
void GenerateCircuit() override {}
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 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);
GateRef StringIndexOf(GateRef lhs, GateRef rhs, GateRef pos);
GateRef CreateFromEcmaString(GateRef glue, GateRef obj, GateRef index);
private:
GateRef CanBeCompressed(GateRef utf16Data, GateRef utf16Len, bool isUtf16);
GateRef GetUtf16Date(GateRef stringData, GateRef index);
GateRef IsASCIICharacter(GateRef data);
GateRef GetUtf8Date(GateRef stringData, GateRef index);
};
} // namespace panda::ecmascript::kungfu
#endif // ECMASCRIPT_COMPILER_BUILTINS_STRING_STUB_BUILDER_H

View File

@ -1,55 +0,0 @@
/*
* 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.
*/
#ifndef ECMASCRIPT_COMPILER_BUILTINS_STUBS_INL_H
#define ECMASCRIPT_COMPILER_BUILTINS_STUBS_INL_H
#include "ecmascript/compiler/builtins/builtins_stubs.h"
namespace panda::ecmascript::kungfu {
GateRef BuiltinsStubBuilder::StringAt(GateRef obj, GateRef index)
{
auto env = GetEnvironment();
Label entry(env);
env->SubCfgEntry(&entry);
DEFVARIABLE(result, VariableType::INT32(), Int32(0));
Label exit(env);
Label isUtf16(env);
Label isUtf8(env);
Label doIntOp(env);
Label leftIsNumber(env);
Label rightIsNumber(env);
GateRef dataUtf16 = PtrAdd(obj, IntPtr(EcmaString::DATA_OFFSET));
Branch(IsUtf16String(obj), &isUtf16, &isUtf8);
Bind(&isUtf16);
{
result = ZExtInt16ToInt32(Load(VariableType::INT16(), PtrAdd(dataUtf16,
PtrMul(ChangeInt32ToIntPtr(index), IntPtr(sizeof(uint16_t))))));
Jump(&exit);
}
Bind(&isUtf8);
{
result = ZExtInt8ToInt32(Load(VariableType::INT8(), PtrAdd(dataUtf16,
PtrMul(ChangeInt32ToIntPtr(index), IntPtr(sizeof(uint8_t))))));
Jump(&exit);
}
Bind(&exit);
auto ret = *result;
env->SubCfgExit();
return ret;
}
} // namespace panda::ecmascript::kungfu
#endif // ECMASCRIPT_COMPILER_BUILTINS_STUBS_INL_H

View File

@ -13,10 +13,11 @@
* limitations under the License.
*/
#include "ecmascript/compiler/builtins/builtins_stubs-inl.h"
#include "ecmascript/compiler/builtins/builtins_stubs.h"
#include "ecmascript/base/number_helper.h"
#include "ecmascript/compiler/builtins/builtins_call_signature.h"
#include "ecmascript/compiler/builtins/builtins_string_stub_builder.h"
#include "ecmascript/compiler/interpreter_stub-inl.h"
#include "ecmascript/compiler/llvm_ir_builder.h"
#include "ecmascript/compiler/stub_builder-inl.h"
@ -58,223 +59,12 @@ void name##StubBuilder::GenerateCircuitImpl(GateRef glue, GateRef nativeCode, Ga
CallNGCRuntime(glue, RTSTUB_ID(PushCallRangeAndDispatchNative), \
{ glue, nativeCode, func, thisValue, numArgs, argv })
GateRef BuiltinsStubBuilder::StringIndexOf(GateRef lhsData, bool lhsIsUtf8, GateRef rhsData, bool rhsIsUtf8,
GateRef pos, GateRef max, GateRef rhsCount)
{
auto env = GetEnvironment();
Label entry(env);
env->SubCfgEntry(&entry);
DEFVARIABLE(i, VariableType::INT32(), pos);
DEFVARIABLE(result, VariableType::INT32(), Int32(-1));
DEFVARIABLE(j, VariableType::INT32(), Int32(0));
DEFVARIABLE(k, VariableType::INT32(), Int32(1));
Label exit(env);
Label next(env);
Label next1(env);
Label next2(env);
Label next3(env);
Label next4(env);
Label next5(env);
Label loopHead(env);
Label loopEnd(env);
Label nextCount(env);
Label nextCount1(env);
Label nextCount2(env);
GateRef first;
if (rhsIsUtf8) {
first = ZExtInt8ToInt32(Load(VariableType::INT8(), rhsData));
} else {
first = ZExtInt16ToInt32(Load(VariableType::INT16(), rhsData));
}
Jump(&loopHead);
LoopBegin(&loopHead);
Branch(Int32LessThanOrEqual(*i, max), &next, &exit);
Bind(&next);
{
Label loopHead1(env);
Label loopEnd1(env);
GateRef lhsTemp;
if (lhsIsUtf8) {
lhsTemp = GetUtf8Date(lhsData, *i);
} else {
lhsTemp = GetUtf16Date(lhsData, *i);
}
Branch(Int32NotEqual(lhsTemp, first), &nextCount1, &nextCount);
Bind(&nextCount1);
{
i = Int32Add(*i, Int32(1));
Jump(&loopHead1);
}
LoopBegin(&loopHead1);
{
Branch(Int32LessThanOrEqual(*i, max), &next1, &nextCount);
Bind(&next1);
{
GateRef lhsTemp1;
if (lhsIsUtf8) {
lhsTemp1 = GetUtf8Date(lhsData, *i);
} else {
lhsTemp1 = GetUtf16Date(lhsData, *i);
}
Branch(Int32NotEqual(lhsTemp1, first), &next2, &nextCount);
Bind(&next2);
{
i = Int32Add(*i, Int32(1));
Jump(&loopEnd1);
}
}
}
Bind(&loopEnd1);
LoopEnd(&loopHead1);
Bind(&nextCount);
{
Branch(Int32LessThanOrEqual(*i, max), &next3, &loopEnd);
Bind(&next3);
{
Label loopHead2(env);
Label loopEnd2(env);
j = Int32Add(*i, Int32(1));
GateRef end = Int32Sub(Int32Add(*j, rhsCount), Int32(1));
k = Int32(1);
Jump(&loopHead2);
LoopBegin(&loopHead2);
{
Branch(Int32LessThan(*j, end), &next4, &nextCount2);
Bind(&next4);
{
GateRef lhsTemp2;
if (lhsIsUtf8) {
lhsTemp2 = GetUtf8Date(lhsData, *j);
} else {
lhsTemp2 = GetUtf16Date(lhsData, *j);
}
GateRef rhsTemp;
if (rhsIsUtf8) {
rhsTemp = GetUtf8Date(rhsData, *k);
} else {
rhsTemp = GetUtf16Date(rhsData, *k);
}
Branch(Int32Equal(lhsTemp2, rhsTemp), &loopEnd2, &nextCount2);
}
}
Bind(&loopEnd2);
j = Int32Add(*j, Int32(1));
k = Int32Add(*k, Int32(1));
LoopEnd(&loopHead2);
Bind(&nextCount2);
{
Branch(Int32Equal(*j, end), &next5, &loopEnd);
Bind(&next5);
result = *i;
Jump(&exit);
}
}
}
}
Bind(&loopEnd);
i = Int32Add(*i, Int32(1));
LoopEnd(&loopHead);
Bind(&exit);
auto ret = *result;
env->SubCfgExit();
return ret;
}
GateRef BuiltinsStubBuilder::StringIndexOf(GateRef lhs, GateRef rhs, GateRef pos)
{
auto env = GetEnvironment();
Label entry(env);
env->SubCfgEntry(&entry);
DEFVARIABLE(result, VariableType::INT32(), Int32(-1));
DEFVARIABLE(posTag, VariableType::INT32(), pos);
Label exit(env);
Label exit1(env);
Label next1(env);
Label next2(env);
Label next3(env);
Label next4(env);
Label next5(env);
Label rhsIsUtf8(env);
Label rhsIsUtf16(env);
GateRef lhsCount = GetLengthFromString(lhs);
GateRef rhsCount = GetLengthFromString(rhs);
Branch(Int32GreaterThan(pos, lhsCount), &exit, &next1);
Bind(&next1);
{
Branch(Int32Equal(rhsCount, Int32(0)), &exit1, &next2);
Bind(&exit1);
{
result = pos;
Jump(&exit);
}
Bind(&next2);
{
Branch(Int32LessThan(pos, Int32(0)), &next3, &next4);
Bind(&next3);
{
posTag = Int32(0);
Jump(&next4);
}
Bind(&next4);
{
GateRef max = Int32Sub(lhsCount, rhsCount);
Branch(Int32LessThan(max, Int32(0)), &exit, &next5);
Bind(&next5);
{
GateRef rhsData = PtrAdd(rhs, IntPtr(EcmaString::DATA_OFFSET));
GateRef lhsData = PtrAdd(lhs, IntPtr(EcmaString::DATA_OFFSET));
Branch(IsUtf8String(rhs), &rhsIsUtf8, &rhsIsUtf16);
Bind(&rhsIsUtf8);
{
Label lhsIsUtf8(env);
Label lhsIsUtf16(env);
Branch(IsUtf8String(lhs), &lhsIsUtf8, &lhsIsUtf16);
Bind(&lhsIsUtf8);
{
result = StringIndexOf(lhsData, true, rhsData, true, *posTag, max, rhsCount);
Jump(&exit);
}
Bind(&lhsIsUtf16);
{
result = StringIndexOf(lhsData, false, rhsData, true, *posTag, max, rhsCount);
Jump(&exit);
}
}
Bind(&rhsIsUtf16);
{
Label lhsIsUtf8(env);
Label lhsIsUtf16(env);
Branch(IsUtf8String(lhs), &lhsIsUtf8, &lhsIsUtf16);
Bind(&lhsIsUtf8);
{
result = StringIndexOf(lhsData, true, rhsData, false, *posTag, max, rhsCount);
Jump(&exit);
}
Bind(&lhsIsUtf16);
{
result = StringIndexOf(lhsData, false, rhsData, false, *posTag, max, rhsCount);
Jump(&exit);
}
}
}
}
}
}
Bind(&exit);
auto ret = *result;
env->SubCfgExit();
return ret;
}
DECLARE_BUILTINS(CharCodeAt)
{
auto env = GetEnvironment();
DEFVARIABLE(res, VariableType::JS_ANY(), DoubleBuildTaggedWithNoGC(Double(base::NAN_VALUE)));
DEFVARIABLE(pos, VariableType::INT32(), Int32(0));
Label objNotUndefinedAndNull(env);
Label isString(env);
Label slowPath(env);
@ -286,10 +76,13 @@ DECLARE_BUILTINS(CharCodeAt)
Label posNotLessZero(env);
Label exit(env);
Label posTagIsDouble(env);
Label thisIsHeapobject(env);
Branch(TaggedIsUndefinedOrNull(thisValue), &slowPath, &objNotUndefinedAndNull);
Bind(&objNotUndefinedAndNull);
{
Branch(TaggedIsHeapObject(thisValue), &thisIsHeapobject, &slowPath);
Bind(&thisIsHeapobject);
Branch(IsString(thisValue), &isString, &slowPath);
Bind(&isString);
{
@ -316,7 +109,8 @@ DECLARE_BUILTINS(CharCodeAt)
Branch(Int32LessThan(*pos, Int32(0)), &exit, &posNotLessZero);
Bind(&posNotLessZero);
{
res = IntToTaggedNGC(StringAt(thisValue, *pos));
BuiltinsStringStubBuilder stringBuilder(this);
res = IntToTaggedNGC(stringBuilder.StringAt(thisValue, *pos));
Jump(&exit);
}
}
@ -343,7 +137,7 @@ DECLARE_BUILTINS(IndexOf)
Label isSearchString(env);
Label slowPath(env);
Label next(env);
Label next1(env);
Label resPosGreaterZero(env);
Label searchTagIsHeapObject(env);
Label posTagNotUndefined(env);
Label posTagIsInt(env);
@ -352,10 +146,13 @@ DECLARE_BUILTINS(IndexOf)
Label posTagIsDouble(env);
Label nextCount(env);
Label posNotLessThanLen(env);
Label thisIsHeapobject(env);
Branch(TaggedIsUndefinedOrNull(thisValue), &slowPath, &objNotUndefinedAndNull);
Bind(&objNotUndefinedAndNull);
{
Branch(TaggedIsHeapObject(thisValue), &thisIsHeapobject, &slowPath);
Bind(&thisIsHeapobject);
Branch(IsString(thisValue), &isString, &slowPath);
Bind(&isString);
{
@ -401,13 +198,14 @@ DECLARE_BUILTINS(IndexOf)
}
Bind(&nextCount);
{
GateRef resPos = StringIndexOf(thisValue, searchTag, *pos);
Branch(Int32GreaterThanOrEqual(resPos, Int32(0)), &next1, &exit);
Bind(&next1);
BuiltinsStringStubBuilder stringBuilder(this);
GateRef resPos = stringBuilder.StringIndexOf(thisValue, searchTag, *pos);
Branch(Int32GreaterThanOrEqual(resPos, Int32(0)), &resPosGreaterZero, &exit);
Bind(&resPosGreaterZero);
{
Label next2(env);
Branch(Int32LessThanOrEqual(resPos, thisLen), &next2, &exit);
Bind(&next2);
Label resPosLessZero(env);
Branch(Int32LessThanOrEqual(resPos, thisLen), &resPosLessZero, &exit);
Bind(&resPosLessZero);
{
res = IntToTaggedNGC(resPos);
Jump(&exit);
@ -426,4 +224,243 @@ DECLARE_BUILTINS(IndexOf)
Bind(&exit);
Return(*res);
}
DECLARE_BUILTINS(Substring)
{
auto env = GetEnvironment();
DEFVARIABLE(res, VariableType::JS_ANY(), IntToTaggedNGC(Int32(-1)));
DEFVARIABLE(start, VariableType::INT32(), Int32(0));
DEFVARIABLE(end, VariableType::INT32(), Int32(0));
DEFVARIABLE(from, VariableType::INT32(), Int32(0));
DEFVARIABLE(to, VariableType::INT32(), Int32(0));
Label objNotUndefinedAndNull(env);
Label isString(env);
Label isSearchString(env);
Label slowPath(env);
Label countStart(env);
Label endTagIsUndefined(env);
Label startNotGreatZero(env);
Label countEnd(env);
Label endNotGreatZero(env);
Label countFrom(env);
Label countRes(env);
Label startTagNotUndefined(env);
Label posTagIsInt(env);
Label posTagNotInt(env);
Label exit(env);
Label posTagIsDouble(env);
Label endTagNotUndefined(env);
Label endTagIsInt(env);
Label endTagNotInt(env);
Label endTagIsDouble(env);
Label endGreatZero(env);
Label endGreatLen(env);
Label startGreatZero(env);
Label startGreatEnd(env);
Label startNotGreatEnd(env);
Label thisIsHeapobject(env);
Branch(TaggedIsUndefinedOrNull(thisValue), &slowPath, &objNotUndefinedAndNull);
Bind(&objNotUndefinedAndNull);
{
Branch(TaggedIsHeapObject(thisValue), &thisIsHeapobject, &slowPath);
Bind(&thisIsHeapobject);
Branch(IsString(thisValue), &isString, &slowPath);
Bind(&isString);
{
Label next(env);
GateRef thisLen = GetLengthFromString(thisValue);
Branch(Int64GreaterThanOrEqual(IntPtr(0), numArgs), &next, &startTagNotUndefined);
Bind(&startTagNotUndefined);
{
GateRef startTag = GetCallArg(argv, IntPtr(0));
Branch(TaggedIsInt(startTag), &posTagIsInt, &posTagNotInt);
Bind(&posTagIsInt);
start = TaggedCastToInt32(startTag);
Jump(&next);
Bind(&posTagNotInt);
Branch(TaggedIsDouble(startTag), &posTagIsDouble, &slowPath);
Bind(&posTagIsDouble);
start = DoubleToInt(glue, TaggedCastToDouble(startTag));
Jump(&next);
}
Bind(&next);
{
Branch(Int64GreaterThanOrEqual(IntPtr(1), numArgs), &endTagIsUndefined, &endTagNotUndefined);
Bind(&endTagIsUndefined);
{
end = thisLen;
Jump(&countStart);
}
Bind(&endTagNotUndefined);
{
GateRef endTag = GetCallArg(argv, IntPtr(1));
Branch(TaggedIsInt(endTag), &endTagIsInt, &endTagNotInt);
Bind(&endTagIsInt);
end = TaggedCastToInt32(endTag);
Jump(&countStart);
Bind(&endTagNotInt);
Branch(TaggedIsDouble(endTag), &endTagIsDouble, &slowPath);
Bind(&endTagIsDouble);
end = DoubleToInt(glue, TaggedCastToDouble(endTag));
Jump(&countStart);
}
}
Bind(&countStart);
{
Label startGreatLen(env);
Branch(Int32GreaterThan(*start, Int32(0)), &startGreatZero, &startNotGreatZero);
Bind(&startNotGreatZero);
{
start = Int32(0);
Jump(&countEnd);
}
Bind(&startGreatZero);
{
Branch(Int32GreaterThan(*start, thisLen), &startGreatLen, &countEnd);
Bind(&startGreatLen);
{
start = thisLen;
Jump(&countEnd);
}
}
}
Bind(&countEnd);
{
Branch(Int32GreaterThan(*end, Int32(0)), &endGreatZero, &endNotGreatZero);
Bind(&endNotGreatZero);
{
end = Int32(0);
Jump(&countFrom);
}
Bind(&endGreatZero);
{
Branch(Int32GreaterThan(*end, thisLen), &endGreatLen, &countFrom);
Bind(&endGreatLen);
{
end = thisLen;
Jump(&countFrom);
}
}
}
Bind(&countFrom);
{
Branch(Int32GreaterThan(*start, *end), &startGreatEnd, &startNotGreatEnd);
Bind(&startGreatEnd);
{
from = *end;
to = *start;
Jump(&countRes);
}
Bind(&startNotGreatEnd);
{
from = *start;
to = *end;
Jump(&countRes);
}
}
Bind(&countRes);
{
BuiltinsStringStubBuilder stringBuilder(this);
GateRef len = Int32Sub(*to, *from);
Label isUtf8(env);
Label isUtf16(env);
Branch(IsUtf8String(thisValue), &isUtf8, &isUtf16);
Bind(&isUtf8);
{
res = stringBuilder.FastSubUtf8String(glue, thisValue, *from, len);
Jump(&exit);
}
Bind(&isUtf16);
{
res = stringBuilder.FastSubUtf16String(glue, thisValue, *from, len);
Jump(&exit);
}
}
}
}
Bind(&slowPath);
{
res = CALLSLOWPATH();
Jump(&exit);
}
Bind(&exit);
Return(*res);
}
DECLARE_BUILTINS(CharAt)
{
auto env = GetEnvironment();
DEFVARIABLE(res, VariableType::JS_POINTER(), Hole());
DEFVARIABLE(pos, VariableType::INT32(), Int32(0));
Label objNotUndefinedAndNull(env);
Label isString(env);
Label slowPath(env);
Label next(env);
Label posTagNotUndefined(env);
Label posTagIsInt(env);
Label posTagNotInt(env);
Label posNotGreaterLen(env);
Label posGreaterLen(env);
Label posNotLessZero(env);
Label exit(env);
Label posTagIsDouble(env);
Label thisIsHeapobject(env);
Branch(TaggedIsUndefinedOrNull(thisValue), &slowPath, &objNotUndefinedAndNull);
Bind(&objNotUndefinedAndNull);
{
Branch(TaggedIsHeapObject(thisValue), &thisIsHeapobject, &slowPath);
Bind(&thisIsHeapobject);
Branch(IsString(thisValue), &isString, &slowPath);
Bind(&isString);
{
GateRef thisLen = GetLengthFromString(thisValue);
Branch(Int64GreaterThanOrEqual(IntPtr(0), numArgs), &next, &posTagNotUndefined);
Bind(&posTagNotUndefined);
{
GateRef posTag = GetCallArg(argv, IntPtr(0));
Branch(TaggedIsInt(posTag), &posTagIsInt, &posTagNotInt);
Bind(&posTagIsInt);
pos = TaggedCastToInt32(posTag);
Jump(&next);
Bind(&posTagNotInt);
Branch(TaggedIsDouble(posTag), &posTagIsDouble, &slowPath);
Bind(&posTagIsDouble);
pos = DoubleToInt(glue, TaggedCastToDouble(posTag));
Jump(&next);
}
Bind(&next);
{
Branch(Int32GreaterThanOrEqual(*pos, thisLen), &posGreaterLen, &posNotGreaterLen);
Bind(&posNotGreaterLen);
{
Branch(Int32LessThan(*pos, Int32(0)), &posGreaterLen, &posNotLessZero);
Bind(&posNotLessZero);
{
BuiltinsStringStubBuilder stringBuilder(this);
res = stringBuilder.CreateFromEcmaString(glue, thisValue, *pos);
Jump(&exit);
}
}
Bind(&posGreaterLen);
{
res = GetGlobalConstantValue(
VariableType::JS_POINTER(), glue, ConstantIndex::EMPTY_STRING_OBJECT_INDEX);
Jump(&exit);
}
}
}
}
Bind(&slowPath);
{
res = CALLSLOWPATH();
Jump(&exit);
}
Bind(&exit);
Return(*res);
}
} // namespace panda::ecmascript::kungfu

View File

@ -66,25 +66,6 @@ public:
{
return Load(VariableType::JS_ANY(), argv, PtrMul(index, IntPtr(sizeof(JSTaggedType))));
}
inline GateRef StringAt(GateRef obj, GateRef index);
GateRef StringIndexOf(GateRef lhsData, bool lhsIsUtf8, GateRef rhsData, bool rhsIsUtf8,
GateRef pos, GateRef max, GateRef rhsCount);
GateRef StringIndexOf(GateRef lhs, GateRef rhs, GateRef pos);
GateRef GetUtf16Date(GateRef stringData, GateRef index)
{
return ZExtInt16ToInt32(Load(VariableType::INT16(), PtrAdd(stringData,
PtrMul(ChangeInt32ToIntPtr(index), IntPtr(sizeof(uint16_t))))));
}
GateRef GetUtf8Date(GateRef stringData, GateRef index)
{
return ZExtInt8ToInt32(Load(VariableType::INT8(), PtrAdd(stringData,
PtrMul(ChangeInt32ToIntPtr(index), IntPtr(sizeof(uint8_t))))));
}
};
#define DECLARE_BUILTINS_STUB_CLASS(name) \

View File

@ -1394,6 +1394,11 @@ BytecodeInfo BytecodeCircuitBuilder::GetBytecodeInfo(const uint8_t *pc)
case EcmaBytecode::TONUMERIC_IMM8: {
break;
}
case EcmaBytecode::DYNAMICIMPORT_V8: {
uint16_t v0 = READ_INST_8_0();
info.inputs.emplace_back(VirtualRegister(v0));
break;
}
case EcmaBytecode::SUPERCALL_IMM8_IMM16_V8: {
uint16_t range = READ_INST_16_1();
uint16_t v0 = READ_INST_8_3();
@ -1725,8 +1730,8 @@ std::vector<GateRef> BytecodeCircuitBuilder::CreateGateInList(const BytecodeInfo
{Circuit::GetCircuitRoot(OpCode(OpCode::CONSTANT_LIST))},
GateType::NJSValue());
} else if (std::holds_alternative<StringId>(input)) {
size_t index = tsManager_->GetStringIdx(constantPool_, std::get<StringId>(input).GetId());
inList[i + length] = circuit_.NewGate(OpCode(OpCode::CONSTANT), MachineType::I32, index,
inList[i + length] = circuit_.NewGate(OpCode(OpCode::CONSTANT), MachineType::I32,
std::get<StringId>(input).GetId(),
{Circuit::GetCircuitRoot(OpCode(OpCode::CONSTANT_LIST))},
GateType::NJSValue());
} else if (std::holds_alternative<Immediate>(input)) {

View File

@ -420,9 +420,8 @@ public:
const MethodLiteral *methodLiteral,
BytecodeInfoCollector::MethodPcInfo &methodPCInfo,
TSManager *tsManager, bool enableLog)
: tsManager_(tsManager), file_(jsPandaFile), pf_(jsPandaFile->GetPandaFile()),
method_(methodLiteral), constantPool_(constantPool), gateAcc_(&circuit_),
argAcc_(&circuit_, method_, jsPandaFile),
: file_(jsPandaFile), pf_(jsPandaFile->GetPandaFile()), method_(methodLiteral), constantPool_(constantPool),
gateAcc_(&circuit_), argAcc_(&circuit_, method_, jsPandaFile),
typeRecorder_(jsPandaFile, method_, tsManager), hasTypes_(file_->HasTSTypes()),
enableLog_(enableLog), pcToBCOffset_(methodPCInfo.pcToBCOffset),
byteCodeCurPrePc_(methodPCInfo.byteCodeCurPrePc), bytecodeBlockInfos_(methodPCInfo.bytecodeBlockInfos)
@ -512,6 +511,11 @@ public:
}
}
JSHandle<JSTaggedValue> GetConstantPool() const
{
return constantPool_;
}
private:
void CollectTryCatchBlockInfo(std::map<std::pair<uint8_t *, uint8_t *>, std::vector<uint8_t *>> &Exception);
void CompleteBytecodeBlockInfo();
@ -557,7 +561,6 @@ private:
std::map<kungfu::GateRef, std::pair<size_t, const uint8_t *>> jsgateToBytecode_;
std::map<const uint8_t *, kungfu::GateRef> byteCodeToJSGate_;
BytecodeGraph graph_;
TSManager *tsManager_ {nullptr};
const JSPandaFile *file_ {nullptr};
const panda_file::File *pf_ {nullptr};
const MethodLiteral *method_ {nullptr};

View File

@ -91,7 +91,7 @@ void BytecodeInfoCollector::ProcessClasses(JSPandaFile *jsPandaFile, const CStri
} else {
methodPcInfos[it->second].methods.emplace_back(methodLiteral);
}
jsPandaFile->SetMethodToMap(methodLiteral);
jsPandaFile->SetMethodLiteralToMap(methodLiteral);
});
}
LOG_COMPILER(INFO) << "Total number of methods in file: " << jsPandaFile->GetJSPandaFileDesc()

View File

@ -79,6 +79,95 @@ GateRef CircuitBuilder::ChangeTaggedPointerToInt64(GateRef x)
return UnaryArithmetic(OpCode(OpCode::TAGGED_TO_INT64), x);
}
GateRef CircuitBuilder::ChangeInt32ToFloat64(GateRef x)
{
return UnaryArithmetic(OpCode(OpCode::SIGNED_INT_TO_FLOAT), MachineType::F64, x);
}
GateRef CircuitBuilder::ChangeUInt32ToFloat64(GateRef x)
{
return UnaryArithmetic(OpCode(OpCode::UNSIGNED_INT_TO_FLOAT), MachineType::F64, x);
}
GateRef CircuitBuilder::PointerSub(GateRef x, GateRef y)
{
return BinaryArithmetic(OpCode(OpCode::SUB), MachineType::ARCH, x, y);
}
GateRef CircuitBuilder::Int8Equal(GateRef x, GateRef y)
{
return BinaryLogic(OpCode(OpCode::EQ), x, y);
}
GateRef CircuitBuilder::Int32NotEqual(GateRef x, GateRef y)
{
return BinaryLogic(OpCode(OpCode::NE), x, y);
}
GateRef CircuitBuilder::Int64NotEqual(GateRef x, GateRef y)
{
return BinaryLogic(OpCode(OpCode::NE), x, y);
}
GateRef CircuitBuilder::DoubleEqual(GateRef x, GateRef y)
{
return BinaryLogic(OpCode(OpCode::EQ), x, y);
}
GateRef CircuitBuilder::Int64Equal(GateRef x, GateRef y)
{
return BinaryLogic(OpCode(OpCode::EQ), x, y);
}
GateRef CircuitBuilder::Int32Equal(GateRef x, GateRef y)
{
return BinaryLogic(OpCode(OpCode::EQ), x, y);
}
template<OpCode::Op Op, MachineType Type>
GateRef CircuitBuilder::BinaryOp(GateRef x, GateRef y)
{
return BinaryArithmetic(OpCode(Op), Type, x, y);
}
GateRef CircuitBuilder::IntPtrLSR(GateRef x, GateRef y)
{
auto ptrSize = env_->Is32Bit() ? MachineType::I32 : MachineType::I64;
return BinaryArithmetic(OpCode(OpCode::LSR), ptrSize, x, y);
}
GateRef CircuitBuilder::IntPtrLSL(GateRef x, GateRef y)
{
auto ptrSize = env_->Is32Bit() ? MachineType::I32 : MachineType::I64;
return BinaryArithmetic(OpCode(OpCode::LSL), ptrSize, x, y);
}
GateRef CircuitBuilder::IntPtrOr(GateRef x, GateRef y)
{
auto ptrsize = env_->Is32Bit() ? MachineType::I32 : MachineType::I64;
return BinaryArithmetic(OpCode(OpCode::OR), ptrsize, x, y);
}
GateRef CircuitBuilder::IntPtrDiv(GateRef x, GateRef y)
{
return env_->Is32Bit() ? Int32Div(x, y) : Int64Div(x, y);
}
GateRef CircuitBuilder::ChangeFloat64ToInt32(GateRef x)
{
return UnaryArithmetic(OpCode(OpCode::FLOAT_TO_SIGNED_INT), MachineType::I32, x);
}
GateRef CircuitBuilder::SExtInt16ToInt64(GateRef x)
{
return UnaryArithmetic(OpCode(OpCode::SEXT_TO_INT64), x);
}
GateRef CircuitBuilder::SExtInt8ToInt64(GateRef x)
{
return UnaryArithmetic(OpCode(OpCode::SEXT_TO_INT64), x);
}
GateRef CircuitBuilder::ChangeInt64ToTagged(GateRef x)
{
return TaggedNumber(OpCode(OpCode::INT64_TO_TAGGED), x);
@ -227,8 +316,7 @@ GateRef CircuitBuilder::TaggedNGC(GateRef x)
GateRef CircuitBuilder::DoubleToTaggedNGC(GateRef x)
{
GateRef val = CastDoubleToInt64(x);
return ChangeInt64ToTagged(Int64Add(val,
Int64(JSTaggedValue::DOUBLE_ENCODE_OFFSET)));
return ChangeInt64ToTagged(Int64Add(val, Int64(JSTaggedValue::DOUBLE_ENCODE_OFFSET)));
}
GateRef CircuitBuilder::DoubleToTaggedTypeNGC(GateRef x)
@ -544,6 +632,11 @@ void CircuitBuilder::SetDepend(GateRef depend)
GetCurrentLabel()->SetDepend(depend);
}
void CircuitBuilder::SetState(GateRef state)
{
GetCurrentLabel()->SetControl(state);
}
void Label::Seal()
{
return impl_->Seal();

View File

@ -16,8 +16,6 @@
#ifndef ECMASCRIPT_COMPILER_CIRCUIT_BUILDER_H
#define ECMASCRIPT_COMPILER_CIRCUIT_BUILDER_H
#include <stack>
#include "ecmascript/base/number_helper.h"
#include "ecmascript/compiler/circuit.h"
#include "ecmascript/compiler/call_signature.h"
@ -99,6 +97,7 @@ class Variable;
V(ZExtInt16ToInt32, OpCode::ZEXT_TO_INT32) \
V(ZExtInt16ToInt64, OpCode::ZEXT_TO_INT64) \
V(ChangeInt64ToInt32, OpCode::TRUNC_TO_INT32) \
V(ChangeInt16ToInt8, OpCode::TRUNC_TO_INT8) \
V(ChangeInt32ToIntPtr, OpCode::ZEXT_TO_ARCH) \
V(TruncInt64ToInt32, OpCode::TRUNC_TO_INT32) \
V(TruncPtrToInt32, OpCode::TRUNC_TO_INT32) \
@ -341,12 +340,31 @@ public:
inline GateRef DoubleToTagged(GateRef x);
inline GateRef TaggedTrue();
inline GateRef TaggedFalse();
inline GateRef SExtInt8ToInt64(GateRef x);
inline GateRef SExtInt16ToInt64(GateRef x);
inline GateRef ChangeFloat64ToInt32(GateRef x);
inline GateRef ChangeUInt32ToFloat64(GateRef x);
inline GateRef ChangeInt32ToFloat64(GateRef x);
// Pointer/Arithmetic/Logic Operations
inline GateRef PointerSub(GateRef x, GateRef y);
inline GateRef IntPtrDiv(GateRef x, GateRef y);
inline GateRef IntPtrOr(GateRef x, GateRef y);
inline GateRef IntPtrLSL(GateRef x, GateRef y);
inline GateRef IntPtrLSR(GateRef x, GateRef y);
inline GateRef Int64NotEqual(GateRef x, GateRef y);
inline GateRef Int32NotEqual(GateRef x, GateRef y);
inline GateRef Int64Equal(GateRef x, GateRef y);
inline GateRef DoubleEqual(GateRef x, GateRef y);
inline GateRef Int8Equal(GateRef x, GateRef y);
inline GateRef Int32Equal(GateRef x, GateRef y);
template<OpCode::Op Op, MachineType Type>
inline GateRef BinaryOp(GateRef x, GateRef y);
inline GateRef GetValueFromTaggedArray(VariableType returnType, GateRef array, GateRef index);
inline void SetValueToTaggedArray(VariableType valType, GateRef glue, GateRef array, GateRef index, GateRef val);
GateRef TaggedIsString(GateRef obj);
GateRef TaggedIsStringOrSymbol(GateRef obj);
inline GateRef GetGlobalConstantString(ConstantIndex index);
// object operation
// Object Operations
inline GateRef LoadHClass(GateRef object);
inline GateRef IsJsType(GateRef object, JSType type);
inline GateRef GetObjectType(GateRef hClass);
@ -412,6 +430,7 @@ public:
inline GateRef GetState() const;
inline GateRef GetDepend() const;
inline void SetDepend(GateRef depend);
inline void SetState(GateRef state);
private:
Circuit *circuit_ {nullptr};

View File

@ -281,6 +281,7 @@ bool LatticeUpdateRuleSCCP::Run(GateRef gate)
{OpCode::SEXT_TO_ARCH, [&]() -> bool { return RunSExtToArch(gate); }},
{OpCode::TRUNC_TO_INT32, [&]() -> bool { return RunTruncToInt32(gate); }},
{OpCode::TRUNC_TO_INT1, [&]() -> bool { return RunTruncToInt1(gate); }},
{OpCode::TRUNC_TO_INT8, [&]() -> bool { return RunTruncToInt8(gate); }},
{OpCode::TRUNC_TO_INT16, [&]() -> bool { return RunTruncToInt16(gate); }},
{OpCode::REV, [&]() -> bool { return RunRev(gate); }},
{OpCode::ADD, [&]() -> bool { return RunAdd(gate); }},
@ -665,6 +666,12 @@ bool LatticeUpdateRuleSCCP::RunTruncToInt1(GateRef gate)
return UpdateValueLattice(gate, operandA);
}
bool LatticeUpdateRuleSCCP::RunTruncToInt8(GateRef gate)
{
const ValueLattice &operandA = valueLatticeMap_(acc_.GetIn(gate, 0));
return UpdateValueLattice(gate, operandA);
}
bool LatticeUpdateRuleSCCP::RunTruncToInt16(GateRef gate)
{
const ValueLattice &operandA = valueLatticeMap_(acc_.GetIn(gate, 0));
@ -1328,4 +1335,324 @@ bool SubGraphRewriteFramework::Run(Circuit *circuit, bool enableLogging)
}
return true;
}
PartitionNode::PartitionNode() : gate_(Circuit::NullGate())
{
}
PartitionNode::PartitionNode(GateRef gate) : gate_(gate)
{
}
std::shared_ptr<PartitionNode> PartitionNode::GetPrev() const
{
return prev_.lock();
}
std::shared_ptr<PartitionNode> PartitionNode::GetNext() const
{
return next_.lock();
}
std::shared_ptr<Partition> PartitionNode::GetBelong() const
{
return belong_.lock();
}
GateRef PartitionNode::GetGate() const
{
return gate_;
}
void PartitionNode::SetPrev(std::shared_ptr<PartitionNode> prev)
{
prev_ = prev;
}
void PartitionNode::SetNext(std::shared_ptr<PartitionNode> next)
{
next_ = next;
}
void PartitionNode::SetBelong(std::shared_ptr<Partition> belong)
{
belong_ = belong;
}
bool PartitionNode::ExistUseByIndex(uint32_t index) const
{
return indexToUses_.count(index) > 0;
}
void PartitionNode::SetUseByIndex(uint32_t index, std::shared_ptr<PartitionNode> node)
{
if (!ExistUseByIndex(index)) {
indexToUses_.emplace(index, std::vector<std::shared_ptr<PartitionNode>>(0));
}
indexToUses_[index].emplace_back(node);
}
void PartitionNode::GetUsesVector(std::vector<std::pair<uint32_t,
std::vector<std::shared_ptr<PartitionNode>>>> &uses) const
{
for (const auto &p : indexToUses_) {
uses.emplace_back(p);
}
}
Partition::Partition() : isTouched_(false), onWorkList_(false), size_(0)
{
}
std::shared_ptr<PartitionNode> Partition::GetHead() const
{
return head_.lock();
}
void Partition::SetHead(std::shared_ptr<PartitionNode> head)
{
head_ = head;
}
void Partition::SetTouched()
{
isTouched_ = true;
}
void Partition::SetNotTouched()
{
isTouched_ = false;
}
void Partition::SetOnWorkList()
{
onWorkList_ = true;
}
void Partition::SetNotOnWorkList()
{
onWorkList_ = false;
}
bool Partition::IsTouched() const
{
return isTouched_;
}
bool Partition::IsOnWorkList() const
{
return onWorkList_;
}
uint32_t Partition::GetSize() const
{
return size_;
}
void Partition::SizeUp()
{
++size_;
}
void Partition::SizeDown()
{
--size_;
}
void Partition::AddTouchedNode(std::shared_ptr<PartitionNode> node)
{
touched_.emplace_back(node);
}
void Partition::CleanTouchedNode()
{
touched_.clear();
}
size_t Partition::GetTouchedSize() const
{
return touched_.size();
}
void Partition::Insert(std::shared_ptr<PartitionNode> node)
{
if (this->GetHead() != nullptr) {
this->GetHead()->SetPrev(node);
}
node->SetPrev(nullptr);
node->SetNext(this->GetHead());
this->SetHead(node);
this->SizeUp();
}
void Partition::Delete(std::shared_ptr<PartitionNode> node)
{
if (node->GetPrev() != nullptr) {
node->GetPrev()->SetNext(node->GetNext());
} else {
this->SetHead(node->GetNext());
}
if (node->GetNext() != nullptr) {
node->GetNext()->SetPrev(node->GetPrev());
}
node->SetPrev(nullptr);
node->SetNext(nullptr);
this->SizeDown();
}
std::shared_ptr<Partition> Partition::SplitByTouched()
{
for (auto node : touched_) {
this->Delete(node);
}
auto newPartition = std::make_shared<Partition>(Partition());
for (auto node : touched_) {
newPartition->Insert(node);
node->SetBelong(newPartition);
}
return newPartition;
}
void Partition::MergeUses(std::map<uint32_t, std::vector<std::shared_ptr<PartitionNode>>> &indexToUses) const
{
std::vector<std::pair<uint32_t, std::vector<std::shared_ptr<PartitionNode>>>> uses;
for (auto defNode = this->GetHead(); defNode != nullptr; defNode = defNode->GetNext()) {
uses.clear();
defNode->GetUsesVector(uses);
for (const auto &use : uses) {
auto index = use.first;
const auto &useNodes = use.second;
if (indexToUses.count(index) == 0) {
indexToUses.emplace(index, std::vector<std::shared_ptr<PartitionNode>>(0));
}
for (auto useNode : useNodes) {
indexToUses[index].emplace_back(useNode);
}
}
}
}
GlobalValueNumbering::GlobalValueNumbering(Circuit *circuit) : acc_(GateAccessor(circuit))
{
}
void GlobalValueNumbering::GetPartitionNodes(std::vector<std::shared_ptr<PartitionNode>> &pNodes)
{
std::vector<GateRef> gates;
std::map<GateRef, std::shared_ptr<PartitionNode>> gateToNode;
acc_.GetAllGates(gates);
for (auto gate : gates) {
auto node = std::make_shared<PartitionNode>(PartitionNode(gate));
pNodes.emplace_back(node);
gateToNode[gate] = node;
}
for (auto gate : gates) {
std::vector<GateRef> ins;
acc_.GetInVector(gate, ins);
auto node = gateToNode[gate];
for (size_t i = 0; i < ins.size(); ++i) {
auto defNode = gateToNode[ins[i]];
defNode->SetUseByIndex(i, node);
}
}
}
void GlobalValueNumbering::SplitByOpCode(const std::vector<std::shared_ptr<PartitionNode>> &nodes,
std::vector<std::shared_ptr<Partition>> &partitions)
{
std::map<std::tuple<OpCode::Op, BitField, MachineType, uint32_t>, std::shared_ptr<Partition>> opToPartition;
for (auto node : nodes) {
auto op = OpCode::Op(acc_.GetOpCode(node->GetGate()));
auto bit = acc_.GetBitField(node->GetGate());
auto mt = acc_.GetMachineType(node->GetGate());
auto gt = acc_.GetGateType(node->GetGate()).GetType();
auto tp = std::make_tuple(op, bit, mt, gt);
if (opToPartition.count(tp) == 0) {
auto p = std::make_shared<Partition>(Partition());
opToPartition[tp] = p;
partitions.emplace_back(p);
}
auto p = opToPartition[tp];
node->SetBelong(p);
p->Insert(node);
}
}
void GlobalValueNumbering::TrySplit(std::queue<std::shared_ptr<Partition>> &workList,
std::vector<std::shared_ptr<Partition>> &partitions)
{
auto curPartition = workList.front();
workList.pop();
curPartition->SetNotOnWorkList();
std::vector<std::shared_ptr<Partition>> touchedPartition;
std::map<uint32_t, std::vector<std::shared_ptr<PartitionNode>>> indexToUses;
curPartition->MergeUses(indexToUses);
for (const auto &use : indexToUses) {
const auto &useNodes = use.second;
for (auto useNode : useNodes) {
if (!useNode->GetBelong()->IsTouched()) {
useNode->GetBelong()->SetTouched();
touchedPartition.emplace_back(useNode->GetBelong());
}
useNode->GetBelong()->AddTouchedNode(useNode);
}
for (auto partition : touchedPartition) {
if (partition->GetSize() != static_cast<uint32_t>(partition->GetTouchedSize())) {
auto newPartition = partition->SplitByTouched();
if (partition->IsOnWorkList() || partition->GetSize() > newPartition->GetSize()) {
workList.push(newPartition);
newPartition->SetOnWorkList();
} else {
workList.push(partition);
partition->SetOnWorkList();
}
partitions.emplace_back(newPartition);
}
partition->CleanTouchedNode();
}
for (auto partition : touchedPartition) {
partition->SetNotTouched();
}
touchedPartition.clear();
}
}
void GlobalValueNumbering::EliminateRedundantGates(const std::vector<std::shared_ptr<Partition>> &partitions)
{
for (auto partition : partitions) {
std::map<uint32_t, std::vector<std::shared_ptr<PartitionNode>>> indexToUses;
partition->MergeUses(indexToUses);
auto kingNode = partition->GetHead();
for (const auto &uses : indexToUses) {
auto index = uses.first;
const auto &useNodes = uses.second;
for (auto useNode : useNodes) {
acc_.ReplaceIn(useNode->GetGate(), index, kingNode->GetGate());
}
}
}
for (auto partition : partitions) {
auto kingNode = partition->GetHead();
for (auto node = kingNode->GetNext(); node != nullptr; node = node->GetNext()) {
acc_.DeleteGate(node->GetGate());
}
}
}
void GlobalValueNumbering::Run()
{
std::vector<std::shared_ptr<PartitionNode>> pNodes;
GetPartitionNodes(pNodes);
std::vector<std::shared_ptr<Partition>> partitions;
SplitByOpCode(pNodes, partitions);
std::queue<std::shared_ptr<Partition>> workList;
for (auto p : partitions) {
workList.push(p);
p->SetOnWorkList();
}
while (!workList.empty()) {
TrySplit(workList, partitions);
}
EliminateRedundantGates(partitions);
}
} // namespace panda::ecmascript::kungfu

View File

@ -16,12 +16,7 @@
#ifndef ECMASCRIPT_COMPILER_CIRCUIT_OPTIMIZER_H_
#define ECMASCRIPT_COMPILER_CIRCUIT_OPTIMIZER_H_
#include <cstdint>
#include <deque>
#include <map>
#include <optional>
#include <random>
#include <stdexcept>
#include <queue>
#include "ecmascript/base/bit_helper.h"
#include "ecmascript/compiler/circuit.h"
@ -153,6 +148,7 @@ public:
bool RunTruncToInt32(GateRef gate);
bool RunTruncToInt1(GateRef gate);
bool RunTruncToInt16(GateRef gate);
bool RunTruncToInt8(GateRef gate);
bool RunRev(GateRef gate);
bool RunAdd(GateRef gate);
bool RunSub(GateRef gate);
@ -242,6 +238,77 @@ private:
GateAccessor acc_;
SubgraphRewriteRule *subgraphRewriteRule_;
};
class Partition;
class PartitionNode {
public:
PartitionNode();
PartitionNode(GateRef gate);
~PartitionNode() = default;
std::shared_ptr<PartitionNode> GetPrev() const;
std::shared_ptr<PartitionNode> GetNext() const;
std::shared_ptr<Partition> GetBelong() const;
GateRef GetGate() const;
void SetPrev(std::shared_ptr<PartitionNode> prev);
void SetNext(std::shared_ptr<PartitionNode> next);
void SetBelong(std::shared_ptr<Partition> belong);
bool ExistUseByIndex(uint32_t index) const;
void SetUseByIndex(uint32_t index, std::shared_ptr<PartitionNode> node);
void GetUsesVector(std::vector<std::pair<uint32_t, std::vector<std::shared_ptr<PartitionNode>>>> &uses) const;
private:
std::weak_ptr<PartitionNode> prev_;
std::weak_ptr<PartitionNode> next_;
std::weak_ptr<Partition> belong_;
GateRef gate_;
std::map<uint32_t, std::vector<std::shared_ptr<PartitionNode>>> indexToUses_;
};
class Partition {
public:
Partition();
~Partition() = default;
std::shared_ptr<PartitionNode> GetHead() const;
void SetHead(std::shared_ptr<PartitionNode> head);
void SetTouched();
void SetNotTouched();
void SetOnWorkList();
void SetNotOnWorkList();
bool IsTouched() const;
bool IsOnWorkList() const;
uint32_t GetSize() const;
void SizeUp();
void SizeDown();
void AddTouchedNode(std::shared_ptr<PartitionNode> node);
void CleanTouchedNode();
size_t GetTouchedSize() const;
void Insert(std::shared_ptr<PartitionNode> node);
void Delete(std::shared_ptr<PartitionNode> node);
std::shared_ptr<Partition> SplitByTouched();
void MergeUses(std::map<uint32_t, std::vector<std::shared_ptr<PartitionNode>>> &indexToUses) const;
private:
std::weak_ptr<PartitionNode> head_;
bool isTouched_;
bool onWorkList_;
uint32_t size_;
std::vector<std::shared_ptr<PartitionNode>> touched_;
};
class GlobalValueNumbering {
public:
GlobalValueNumbering(Circuit *circuit);
~GlobalValueNumbering() = default;
void GetPartitionNodes(std::vector<std::shared_ptr<PartitionNode>> &nodes);
void SplitByOpCode(const std::vector<std::shared_ptr<PartitionNode>> &nodes,
std::vector<std::shared_ptr<Partition>> &partitions);
uint32_t GetMaxIndex(std::shared_ptr<Partition> partition) const;
void TrySplit(std::queue<std::shared_ptr<Partition>> &workList,
std::vector<std::shared_ptr<Partition>> &partitions);
void EliminateRedundantGates(const std::vector<std::shared_ptr<Partition>> &partitions);
void Run();
private:
GateAccessor acc_;
};
} // namespace panda::ecmascript::kungfu
#endif // ECMASCRIPT_COMPILER_CIRCUIT_OPTIMIZER_H_

View File

@ -13,8 +13,9 @@
* limitations under the License.
*/
#include "ecmascript/ark_stackmap_builder.h"
#include "ecmascript/compiler/file_generators.h"
#include "ecmascript/ark_stackmap_builder.h"
#include "ecmascript/compiler/llvm_ir_builder.h"
#include "ecmascript/ecma_vm.h"
#include "ecmascript/llvm_stackmap_parser.h"
@ -126,14 +127,8 @@ void AOTFileGenerator::SaveAOTFile(const std::string &filename)
void AOTFileGenerator::SaveSnapshotFile()
{
TSManager *tsManager = vm_->GetTSManager();
Snapshot snapshot(vm_);
CVector<JSTaggedType> constStringTable = tsManager->GetConstStringTable();
CVector<JSTaggedType> staticHClassTable = tsManager->GetStaticHClassTable();
CVector<JSTaggedType> tsManagerSerializeTable(constStringTable);
tsManagerSerializeTable.insert(tsManagerSerializeTable.end(), staticHClassTable.begin(), staticHClassTable.end());
const CString snapshotPath(vm_->GetJSOptions().GetAOTOutputFile().c_str());
snapshot.Serialize(reinterpret_cast<uintptr_t>(tsManagerSerializeTable.data()), tsManagerSerializeTable.size(),
snapshotPath + ".etso");
snapshot.Serialize(snapshotPath + ".etso");
}
} // namespace panda::ecmascript::kungfu

View File

@ -22,8 +22,11 @@
#include "ecmascript/compiler/compiler_log.h"
#include "ecmascript/compiler/llvm_codegen.h"
#include "ecmascript/compiler/llvm_ir_builder.h"
#include "ecmascript/compiler/bytecode_info_collector.h"
#include "ecmascript/compiler/bytecode_circuit_builder.h"
#include "ecmascript/file_loader.h"
#include "ecmascript/jspandafile/js_pandafile.h"
#include "ecmascript/snapshot/mem/snapshot_processor.h"
namespace panda::ecmascript::kungfu {
class Module {
@ -206,23 +209,40 @@ protected:
class AOTFileGenerator : public FileGenerator {
public:
AOTFileGenerator(const CompilerLog *log, const MethodLogList *logList,
EcmaVM* vm) : FileGenerator(log, logList), vm_(vm) {};
EcmaVM* vm) : FileGenerator(log, logList), vm_(vm), cpProcessor_(vm) {};
~AOTFileGenerator() override = default;
void AddModule(LLVMModule *llvmModule, LLVMAssembler *assembler, const JSPandaFile *jsPandaFile)
void InitializeConstantPoolInfos(const arg_list_t pandaFileNames)
{
cpProcessor_.InitializeConstantPoolInfos(pandaFileNames.size());
}
void AddModule(LLVMModule *llvmModule, LLVMAssembler *assembler, const BytecodeInfoCollector::BCInfo &bytecodeInfo)
{
modulePackage_.emplace_back(Module(llvmModule, assembler));
auto hash = jsPandaFile->GetFileUniqId();
auto hash = bytecodeInfo.jsPandaFile->GetFileUniqId();
aotfileHashs_.emplace_back(hash);
CollectConstantPoolInfo(bytecodeInfo.jsPandaFile, bytecodeInfo.constantPool);
}
ConstantPoolProcessor& GetCpProcessor()
{
return cpProcessor_;
}
// save function for aot files containing normal func translated from JS/TS
void SaveAOTFile(const std::string &filename);
void SaveSnapshotFile();
private:
void CollectConstantPoolInfo(const JSPandaFile* pf, const JSHandle<JSTaggedValue> constantPool)
{
cpProcessor_.CollectConstantPoolInfo(pf, constantPool);
}
AOTModulePackInfo aotInfo_;
std::vector<uint32_t> aotfileHashs_ {};
EcmaVM* vm_;
ConstantPoolProcessor cpProcessor_;
// collect aot component info
void CollectCodeInfo();

View File

@ -131,6 +131,8 @@ Properties OpCode::GetProperties() const
return {ARCH, NO_STATE, NO_DEPEND, VALUE(ANYVALUE), NO_ROOT};
case TRUNC_TO_INT32:
return {I32, NO_STATE, NO_DEPEND, VALUE(ANYVALUE), NO_ROOT};
case TRUNC_TO_INT8:
return {I8, NO_STATE, NO_DEPEND, VALUE(ANYVALUE), NO_ROOT};
case TRUNC_TO_INT1:
return {I1, NO_STATE, NO_DEPEND, VALUE(ANYVALUE), NO_ROOT};
case TRUNC_TO_INT16:
@ -258,6 +260,7 @@ std::string OpCode::Str() const
{SEXT_TO_INT32, "SEXT_TO_INT32"},
{SEXT_TO_ARCH, "SEXT_TO_ARCH"},
{TRUNC_TO_INT32, "TRUNC_TO_INT32"},
{TRUNC_TO_INT8, "TRUNC_TO_INT8"},
{TRUNC_TO_INT1, "TRUNC_TO_INT1"},
{TRUNC_TO_INT16, "TRUNC_TO_INT16"},
{REV, "REV"},

View File

@ -118,6 +118,7 @@ public:
SEXT_TO_ARCH,
TRUNC_TO_INT32,
TRUNC_TO_INT1,
TRUNC_TO_INT8,
TRUNC_TO_INT16,
REV,
ADD,
@ -161,6 +162,13 @@ public:
BITCAST,
RESTORE_REGISTER,
SAVE_REGISTER,
COMMON_CIR_FIRST = NOP,
COMMON_CIR_LAST = DEPEND_AND,
HIGH_CIR_FIRST = JS_BYTECODE,
HIGH_CIR_LAST = GET_EXCEPTION,
MID_CIR_FIRST = RUNTIME_CALL,
MID_CIR_LAST = SAVE_REGISTER
};
OpCode() = default;

View File

@ -148,6 +148,30 @@ void GateAccessor::GetOutVector(GateRef gate, std::vector<GateRef>& outs) const
}
}
void GateAccessor::GetOutStateVector(GateRef gate, std::vector<GateRef>& outStates) const
{
const Gate *curGate = circuit_->LoadGatePtrConst(gate);
if (!curGate->IsFirstOutNull()) {
const Out *curOut = curGate->GetFirstOutConst();
GateRef ref = circuit_->GetGateRef(curOut->GetGateConst());
if (circuit_->GetOpCode(ref).IsState()) {
outStates.push_back(ref);
}
while (!curOut->IsNextOutNull()) {
curOut = curOut->GetNextOutConst();
ref = circuit_->GetGateRef(curOut->GetGateConst());
if (circuit_->GetOpCode(ref).IsState()) {
outStates.push_back(ref);
}
}
}
}
void GateAccessor::GetAllGates(std::vector<GateRef>& gates) const
{
circuit_->GetAllGates(gates);
}
bool GateAccessor::IsInGateNull(GateRef gate, size_t idx) const
{
return circuit_->IsInGateNull(gate, idx);

View File

@ -294,6 +294,8 @@ public:
void GetInVector(GateRef gate, std::vector<GateRef>& ins) const;
void GetOutVector(GateRef gate, std::vector<GateRef>& outs) const;
void GetOutStateVector(GateRef gate, std::vector<GateRef>& outStates) const;
void GetAllGates(std::vector<GateRef>& gates) const;
size_t GetNumIns(GateRef gate) const;
OpCode GetOpCode(GateRef gate) const;
bool IsGCRelated(GateRef gate) const;

View File

@ -2893,7 +2893,6 @@ DECLARE_ASM_HANDLER(HandleShl2Imm8V8)
DECLARE_ASM_HANDLER(HandleStobjbynameImm8Id16V8)
{
auto env = GetEnvironment();
GateRef receiver = GetVregValue(sp, ZExtInt8ToPtr(ReadInst8_3(pc)));
GateRef slotId = ZExtInt8ToInt32(ReadInst8_0(pc));
DEFVARIABLE(result, VariableType::INT64(), Hole(VariableType::INT64()));
@ -4125,6 +4124,15 @@ DECLARE_ASM_HANDLER(HandleDeprecatedTonumericPrefV8)
}
}
DECLARE_ASM_HANDLER(HandleDynamicimportV8)
{
DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc);
GateRef v0 = ReadInst8_1(pc);
GateRef specifier = GetVregValue(sp, ZExtInt8ToPtr(v0));
GateRef res = CallRuntime(glue, RTSTUB_ID(DynamicImport), { specifier });
CHECK_EXCEPTION_WITH_ACC(res, INT_PTR(PREF_V8));
}
DECLARE_ASM_HANDLER(HandleCreateasyncgeneratorobjV8)
{
auto env = GetEnvironment();
@ -4752,6 +4760,37 @@ DECLARE_ASM_HANDLER(HandleDefineclasswithbufferImm16Id16Id16Imm16V8)
DECLARE_ASM_HANDLER(HandleDeprecatedDefineclasswithbufferPrefId16Imm16Imm16V8V8)
{
// TODO
// auto env = GetEnvironment();
// DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc);
// GateRef methodId = ReadInst16_1(pc);
// GateRef length = ReadInst16_5(pc);
// GateRef v0 = ReadInst8_7(pc);
// GateRef v1 = ReadInst8_8(pc);
// GateRef lexicalEnv = GetVregValue(sp, ZExtInt8ToPtr(v0));
// GateRef proto = GetVregValue(sp, ZExtInt8ToPtr(v1));
// GateRef res = CallRuntime(glue, RTSTUB_ID(CreateClassWithBuffer),
// { proto, lexicalEnv, constpool, Int16ToTaggedTypeNGC(methodId) });
// Label isException(env);
// Label isNotException(env);
// Branch(TaggedIsException(res), &isException, &isNotException);
// Bind(&isException);
// {
// DISPATCH_LAST_WITH_ACC();
// }
// Bind(&isNotException);
// GateRef newLexicalEnv = GetVregValue(sp, ZExtInt8ToPtr(v0)); // slow runtime may gc
// SetLexicalEnvToFunction(glue, res, newLexicalEnv);
// GateRef currentFunc = GetFunctionFromFrame(GetFrame(sp));
// SetModuleToFunction(glue, res, GetModuleFromFunction(currentFunc));
// CallRuntime(glue, RTSTUB_ID(SetClassConstructorLength), { res, Int16ToTaggedTypeNGC(length) });
// varAcc = res;
// DISPATCH_WITH_ACC(DEPRECATED_DEFINECLASSWITHBUFFER_PREF_ID16_IMM16_IMM16_V8_V8);
auto env = GetEnvironment();
DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc);

View File

@ -144,25 +144,21 @@ void LLVMAssembler::BuildAndRunPasses()
// pass manager creation:rs4gc pass is the only pass in modPass, other opt module-based pass are in modPass1
LLVMPassManagerRef funcPass = LLVMCreateFunctionPassManagerForModule(module_);
LLVMPassManagerRef modPass = LLVMCreatePassManager();
LLVMPassManagerRef modPass1 = LLVMCreatePassManager();
// add pass into pass managers
LLVMPassManagerBuilderPopulateFunctionPassManager(pmBuilder, funcPass);
llvm::unwrap(modPass)->add(llvm::createRewriteStatepointsForGCLegacyPass()); // rs4gc pass added
LLVMPassManagerBuilderPopulateModulePassManager(pmBuilder, modPass1);
LLVMRunPassManager(modPass, module_); // make sure rs4gc pass run first
LLVMInitializeFunctionPassManager(funcPass);
for (LLVMValueRef fn = LLVMGetFirstFunction(module_); fn; fn = LLVMGetNextFunction(fn)) {
LLVMRunFunctionPassManager(funcPass, fn);
}
LLVMFinalizeFunctionPassManager(funcPass);
LLVMRunPassManager(modPass1, module_);
LLVMRunPassManager(modPass, module_);
LLVMPassManagerBuilderDispose(pmBuilder);
LLVMDisposePassManager(funcPass);
LLVMDisposePassManager(modPass);
LLVMDisposePassManager(modPass1);
}
LLVMAssembler::LLVMAssembler(LLVMModuleRef module, LOptions option) : module_(module)

View File

@ -154,6 +154,7 @@ void LLVMIRBuilder::InitializeHandlers()
{OpCode::SEXT_TO_INT64, &LLVMIRBuilder::HandleSExtInt},
{OpCode::SEXT_TO_ARCH, &LLVMIRBuilder::HandleSExtInt},
{OpCode::TRUNC_TO_INT1, &LLVMIRBuilder::HandleCastIntXToIntY},
{OpCode::TRUNC_TO_INT8, &LLVMIRBuilder::HandleCastIntXToIntY},
{OpCode::TRUNC_TO_INT32, &LLVMIRBuilder::HandleCastIntXToIntY},
{OpCode::TRUNC_TO_INT16, &LLVMIRBuilder::HandleCastIntXToIntY},
{OpCode::REV, &LLVMIRBuilder::HandleIntRev},
@ -968,7 +969,7 @@ void LLVMIRBuilder::LinkToLLVMCfg(int bbId, const OperandsVector &predecessors)
void LLVMIRBuilder::HandleGoto(GateRef gate)
{
std::vector<GateRef> outs;
acc_.GetOutVector(gate, outs);
acc_.GetOutStateVector(gate, outs);
int block = instID2bbID_[acc_.GetId(gate)];
int bbOut = instID2bbID_[acc_.GetId(outs[0])];
switch (acc_.GetOpCode(gate)) {
@ -1129,7 +1130,7 @@ void LLVMIRBuilder::HandleBranch(GateRef gate)
std::vector<GateRef> ins;
acc_.GetInVector(gate, ins);
std::vector<GateRef> outs;
acc_.GetOutVector(gate, outs);
acc_.GetOutStateVector(gate, outs);
GateRef bTrue = (acc_.GetOpCode(outs[0]) == OpCode::IF_TRUE) ? outs[0] : outs[1];
GateRef bFalse = (acc_.GetOpCode(outs[0]) == OpCode::IF_FALSE) ? outs[0] : outs[1];
int bbTrue = instID2bbID_[acc_.GetId(bTrue)];
@ -1187,7 +1188,7 @@ void LLVMIRBuilder::HandleSwitch(GateRef gate)
std::vector<GateRef> ins;
acc_.GetInVector(gate, ins);
std::vector<GateRef> outs;
acc_.GetOutVector(gate, outs);
acc_.GetOutStateVector(gate, outs);
VisitSwitch(gate, ins[1], outs);
}

View File

@ -14,5 +14,5 @@
*/
#include <cstdint>
extern const uint8_t _binary_stub_aot_start[1] = {0x0};
extern const uint32_t _binary_stub_aot_length = 1;
extern const uint8_t _binary_stub_an_start[1] = {0x0};
extern const uint32_t _binary_stub_an_length = 1;

View File

@ -22,6 +22,7 @@
#include "ecmascript/js_object.h"
#include "ecmascript/js_thread.h"
#include "ecmascript/lexical_env.h"
#include "ecmascript/mem/mem.h"
namespace panda::ecmascript::kungfu {
void NewObjectStubBuilder::NewLexicalEnv(Variable *result, Label *exit, GateRef numSlots, GateRef parent)
@ -231,4 +232,26 @@ void NewObjectStubBuilder::InitializeTaggedArrayWithSpeicalValue(Label *exit,
auto endOffset = Int32Add(offset, Int32(TaggedArray::DATA_OFFSET));
InitializeWithSpeicalValue(exit, array, value, dataOffset, endOffset);
}
void NewObjectStubBuilder::AllocStringObject(Variable *result, Label *exit, GateRef length, bool compressed)
{
auto env = GetEnvironment();
if (compressed) {
size_ = AlignUp(ComputeSizeUtf8(ChangeInt32ToIntPtr(length)),
IntPtr(static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT)));
} else {
size_ = AlignUp(ComputeSizeUtf16(ChangeInt32ToIntPtr(length)),
IntPtr(static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT)));
}
Label afterAllocate(env);
AllocateInYoung(result, &afterAllocate);
Bind(&afterAllocate);
GateRef arrayClass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_,
ConstantIndex::STRING_CLASS_INDEX);
StoreHClass(glue_, result->ReadVariable(), arrayClass);
SetLength(glue_, result->ReadVariable(), length, compressed);
SetRawHashcode(glue_, result->ReadVariable(), Int32(0));
Jump(exit);
}
} // namespace panda::ecmascript::kungfu

View File

@ -37,6 +37,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);
private:
void AllocateInYoung(Variable *result, Label *exit);
void InitializeWithSpeicalValue(Label *exit,

View File

@ -41,7 +41,7 @@ bool PassManager::Compile(const std::string &fileName, AOTFileGenerator &generat
TSManager *tsManager = vm_->GetTSManager();
uint32_t mainMethodIndex = bytecodeInfo.jsPandaFile->GetMainMethodIndex();
uint32_t skipMethodNum = 0;
auto mainMethod = bytecodeInfo.jsPandaFile->FindMethods(mainMethodIndex);
auto mainMethod = bytecodeInfo.jsPandaFile->FindMethodLiteral(mainMethodIndex);
bool enableLog = !log_->NoneMethod();
bytecodeInfo.EnumerateBCInfo([this, &fileName, &enableLog, aotModule, &cmpCfg, tsManager,
@ -77,7 +77,7 @@ bool PassManager::Compile(const std::string &fileName, AOTFileGenerator &generat
}
});
LOG_COMPILER(INFO) << skipMethodNum << " large methods in '" << fileName << "' have been skipped";
generator.AddModule(aotModule, aotModuleAssembler, bytecodeInfo.jsPandaFile);
generator.AddModule(aotModule, aotModuleAssembler, bytecodeInfo);
return true;
}
@ -101,13 +101,17 @@ bool PassManager::CollectBCInfo(const std::string &fileName, BytecodeInfoCollect
LOG_COMPILER(INFO) << fileName << " has no type info";
}
JSThread *thread = vm_->GetJSThread();
if (jsPandaFile->IsModule()) {
ModuleManager *moduleManager = vm_->GetModuleManager();
moduleManager->HostResolveImportedModule(fileName.c_str());
CString moduleFileName = moduleManager->ResolveModuleFileName(fileName.c_str());
jsPandaFile =
const_cast<JSPandaFile *>(JSPandaFileManager::GetInstance()->LoadJSPandaFile(thread, moduleFileName,
entry_));
}
auto program = PandaFileTranslator::GenerateProgram(vm_, jsPandaFile);
JSThread *thread = vm_->GetJSThread();
JSHandle<JSFunction> mainFunc(thread, program->GetMainFunction());
JSHandle<Method> method(thread, mainFunc->GetMethod());
JSHandle<JSTaggedValue> constPool(thread, method->GetConstantPool());

View File

@ -260,15 +260,6 @@ GateRef SlowPathLowering::GetHomeObjectFromJSFunction(GateRef jsFunc)
return builder_.Load(VariableType::JS_ANY(), jsFunc, offset);
}
GateRef SlowPathLowering::GetValueFromConstStringTable(GateRef glue, GateRef gate, uint32_t inIndex)
{
GateRef target = builder_.IntPtr(RTSTUB_ID(LoadValueFromConstantStringTable));
auto idGate = builder_.TaggedTypeNGC(builder_.ZExtInt32ToInt64(acc_.GetValueIn(gate, inIndex)));
GateRef dependGate = acc_.GetDep(gate);
const CallSignature *cs = RuntimeStubCSigns::Get(RTSTUB_ID(CallRuntime));
return builder_.Call(cs, glue, target, dependGate, {idGate});
}
void SlowPathLowering::Lower(GateRef gate)
{
GateRef glue = argAcc_.GetCommonArgGate(CommonArgIdx::GLUE);
@ -282,7 +273,7 @@ void SlowPathLowering::Lower(GateRef gate)
Environment env(gate, circuit_, &builder_);
switch (op) {
case EcmaBytecode::LDASTR:
LowerLoadStr(gate, glue);
LowerLoadStr(gate, glue, jsFunc);
break;
case EcmaBytecode::CALLARG0:
LowerCallArg0(gate, glue);
@ -384,10 +375,10 @@ void SlowPathLowering::Lower(GateRef gate)
LowerAsyncFunctionReject(gate, glue);
break;
case EcmaBytecode::TRYLDGLOBALBYNAME:
LowerTryLdGlobalByName(gate, glue);
LowerTryLdGlobalByName(gate, glue, jsFunc);
break;
case EcmaBytecode::STGLOBALVAR:
LowerStGlobalVar(gate, glue);
LowerStGlobalVar(gate, glue, jsFunc);
break;
case EcmaBytecode::GETITERATOR:
LowerGetIterator(gate, glue);
@ -501,11 +492,14 @@ void SlowPathLowering::Lower(GateRef gate)
LowerSetObjectWithProto(gate, glue);
break;
case EcmaBytecode::LDBIGINT:
LowerLdBigInt(gate, glue);
LowerLdBigInt(gate, glue, jsFunc);
break;
case EcmaBytecode::TONUMERIC:
LowerToNumeric(gate, glue);
break;
case DYNAMICIMPORT_V8:
LowerDynamicImport(gate, glue, jsFunc);
break;
case EcmaBytecode::LDMODULEVAR:
LowerLdModuleVar(gate, glue, jsFunc);
break;
@ -546,7 +540,7 @@ void SlowPathLowering::Lower(GateRef gate)
LowerCreateObjectWithExcludedKeys(gate, glue);
break;
case EcmaBytecode::CREATEREGEXPWITHLITERAL:
LowerCreateRegExpWithLiteral(gate, glue);
LowerCreateRegExpWithLiteral(gate, glue, jsFunc);
break;
case EcmaBytecode::STOWNBYVALUE:
LowerStOwnByValue(gate, glue);
@ -555,7 +549,7 @@ void SlowPathLowering::Lower(GateRef gate)
LowerStOwnByIndex(gate, glue);
break;
case EcmaBytecode::STOWNBYNAME:
LowerStOwnByName(gate, glue);
LowerStOwnByName(gate, glue, jsFunc);
break;
case EcmaBytecode::DEFINEGENERATORFUNC:
LowerDefineGeneratorFunc(gate, glue, jsFunc);
@ -582,31 +576,31 @@ void SlowPathLowering::Lower(GateRef gate)
LowerStSuperByValue(gate, glue, jsFunc);
break;
case EcmaBytecode::TRYSTGLOBALBYNAME:
LowerTryStGlobalByName(gate, glue);
LowerTryStGlobalByName(gate, glue, jsFunc);
break;
case EcmaBytecode::STCONSTTOGLOBALRECORD:
LowerStConstToGlobalRecord(gate, glue);
LowerStConstToGlobalRecord(gate, glue, jsFunc);
break;
case EcmaBytecode::STLETTOGLOBALRECORD:
LowerStLetToGlobalRecord(gate, glue);
LowerStLetToGlobalRecord(gate, glue, jsFunc);
break;
// case EcmaBytecode::STCLASSTOGLOBALRECORD:
// LowerStClassToGlobalRecord(gate, glue);
// LowerStClassToGlobalRecord(gate, glue, jsFunc);
// break;
case EcmaBytecode::STOWNBYVALUEWITHNAMESET:
LowerStOwnByValueWithNameSet(gate, glue);
break;
case EcmaBytecode::STOWNBYNAMEWITHNAMESET:
LowerStOwnByNameWithNameSet(gate, glue);
LowerStOwnByNameWithNameSet(gate, glue, jsFunc);
break;
case EcmaBytecode::LDGLOBALVAR:
LowerLdGlobalVar(gate, glue);
LowerLdGlobalVar(gate, glue, jsFunc);
break;
case EcmaBytecode::LDOBJBYNAME:
LowerLdObjByName(gate, glue);
LowerLdObjByName(gate, glue, jsFunc);
break;
case EcmaBytecode::STOBJBYNAME:
LowerStObjByName(gate, glue);
LowerStObjByName(gate, glue, jsFunc);
break;
case EcmaBytecode::DEFINEGETTERSETTERBYVALUE:
LowerDefineGetterSetterByValue(gate, glue);
@ -818,11 +812,13 @@ void SlowPathLowering::LowerAsyncFunctionReject(GateRef gate, GateRef glue)
ReplaceHirToCall(gate, newGate);
}
void SlowPathLowering::LowerLoadStr(GateRef gate, GateRef glue)
void SlowPathLowering::LowerLoadStr(GateRef gate, GateRef glue, GateRef jsFunc)
{
// DebugPrintBC(gate, glue, builder_.Int32(GET_MESSAGE_STRING_ID(HandleLdaStrId16)));
GateRef newGate = GetValueFromConstStringTable(glue, gate, 0);
ReplaceHirToCall(gate, newGate);
GateRef newGate = GetObjectFromConstPool(jsFunc, acc_.GetValueIn(gate, 0));
std::vector<GateRef> successControl {builder_.GetState(), builder_.GetDepend()};
std::vector<GateRef> failControl {Circuit::NullGate(), Circuit::NullGate()};
ReplaceHirToSubCfg(gate, newGate, successControl, failControl, true);
}
void SlowPathLowering::LowerLexicalEnv(GateRef gate, GateRef glue)
@ -833,12 +829,11 @@ void SlowPathLowering::LowerLexicalEnv(GateRef gate, GateRef glue)
ReplaceHirToCall(gate, newGate, true);
}
void SlowPathLowering::LowerTryLdGlobalByName(GateRef gate, GateRef glue)
void SlowPathLowering::LowerTryLdGlobalByName(GateRef gate, GateRef glue, GateRef jsFunc)
{
// DebugPrintBC(gate, glue, builder_.Int32(GET_MESSAGE_STRING_ID(HandleTryLdGlobalByNameImm8Id16)));
DEFVAlUE(result, (&builder_), VariableType::JS_ANY(), acc_.GetValueIn(gate, 0));
GateRef stringId = builder_.TaggedTypeNGC(builder_.ZExtInt32ToInt64(acc_.GetValueIn(gate, 0)));
GateRef prop = LowerCallRuntime(glue, RTSTUB_ID(LoadValueFromConstantStringTable), { stringId }, true);
GateRef prop = GetObjectFromConstPool(jsFunc, acc_.GetValueIn(gate, 0));
GateRef recordResult = LowerCallRuntime(glue, RTSTUB_ID(LdGlobalRecord), {prop}, true);
Label isFound(&builder_);
Label isNotFound(&builder_);
@ -872,15 +867,18 @@ void SlowPathLowering::LowerTryLdGlobalByName(GateRef gate, GateRef glue)
ReplaceHirToSubCfg(gate, value, successControl, failControl);
}
void SlowPathLowering::LowerStGlobalVar(GateRef gate, GateRef glue)
void SlowPathLowering::LowerStGlobalVar(GateRef gate, GateRef glue, GateRef jsFunc)
{
// DebugPrintBC(gate, glue, builder_.Int32(GET_MESSAGE_STRING_ID(HandleStGlobalVarId16)));
GateRef prop = GetValueFromConstStringTable(glue, gate, 0);
acc_.SetDep(gate, prop);
DebugPrintBC(gate, glue, builder_.Int32(GET_MESSAGE_STRING_ID(HandleStGlobalVarId16)));
Label successExit(&builder_);
Label exceptionExit(&builder_);
GateRef prop = GetObjectFromConstPool(jsFunc, acc_.GetValueIn(gate, 0));
const int id = RTSTUB_ID(StGlobalVar);
ASSERT(acc_.GetNumValueIn(gate) == 2); // 2: number of value inputs
GateRef newGate = LowerCallRuntime(glue, id, {prop, acc_.GetValueIn(gate, 1)});
ReplaceHirToCall(gate, newGate);
builder_.Branch(builder_.IsSpecial(newGate, JSTaggedValue::VALUE_EXCEPTION), &exceptionExit, &successExit);
CREATE_DOUBLE_EXIT(successExit, exceptionExit)
ReplaceHirToSubCfg(gate, newGate, successControl, failControl);
}
void SlowPathLowering::LowerGetIterator(GateRef gate, GateRef glue)
@ -1554,8 +1552,7 @@ void SlowPathLowering::LowerStModuleVar(GateRef gate, GateRef glue, GateRef jsFu
std::vector<GateRef> failControl;
// 2: number of value inputs
ASSERT(acc_.GetNumValueIn(gate) == 2);
GateRef stringId = builder_.TaggedTypeNGC(builder_.ZExtInt32ToInt64(acc_.GetValueIn(gate, 0)));
GateRef prop = LowerCallRuntime(glue, RTSTUB_ID(LoadValueFromConstantStringTable), { stringId }, true);
GateRef prop = GetObjectFromConstPool(jsFunc, acc_.GetValueIn(gate, 0));
GateRef result = LowerCallRuntime(glue, RTSTUB_ID(StModuleVarOnJSFunc),
{ prop, acc_.GetValueIn(gate, 1), jsFunc }, true);
successControl.emplace_back(builder_.GetState());
@ -1589,15 +1586,14 @@ void SlowPathLowering::LowerSetObjectWithProto(GateRef gate, GateRef glue)
ReplaceHirToCall(gate, newGate);
}
void SlowPathLowering::LowerLdBigInt(GateRef gate, GateRef glue)
void SlowPathLowering::LowerLdBigInt(GateRef gate, GateRef glue, GateRef jsFunc)
{
// DebugPrintBC(gate, glue, builder_.Int32(GET_MESSAGE_STRING_ID(HandleLdBigIntId16)));
Label successExit(&builder_);
Label exceptionExit(&builder_);
// 1: number of value inputs
ASSERT(acc_.GetNumValueIn(gate) == 1);
GateRef stringId = builder_.TaggedTypeNGC(builder_.ZExtInt32ToInt64(acc_.GetValueIn(gate, 0)));
GateRef numberBigInt = LowerCallRuntime(glue, RTSTUB_ID(LoadValueFromConstantStringTable), { stringId }, true);
GateRef numberBigInt = GetObjectFromConstPool(jsFunc, acc_.GetValueIn(gate, 0));
GateRef result = LowerCallRuntime(glue, RTSTUB_ID(LdBigInt), {numberBigInt}, true);
builder_.Branch(builder_.IsSpecial(result, JSTaggedValue::VALUE_EXCEPTION),
&exceptionExit, &successExit);
@ -1615,6 +1611,16 @@ void SlowPathLowering::LowerToNumeric(GateRef gate, GateRef glue)
ReplaceHirToCall(gate, newGate);
}
void SlowPathLowering::LowerDynamicImport(GateRef gate, GateRef glue)
{
DebugPrintBC(gate, glue, builder_.Int32(GET_MESSAGE_STRING_ID(HandleDynamicimportV8)));
const int id = RTSTUB_ID(DynamicImport);
// 1: number of value inputs
ASSERT(acc_.GetNumValueIn(gate) == 1);
GateRef newGate = LowerCallRuntime(glue, id, {acc_.GetValueIn(gate, 0)});
ReplaceHirToCall(gate, newGate);
}
void SlowPathLowering::LowerLdModuleVar(GateRef gate, GateRef glue, GateRef jsFunc)
{
// DebugPrintBC(gate, glue, builder_.Int32(GET_MESSAGE_STRING_ID(HandleLdModuleVarId16Imm8)));
@ -1622,8 +1628,7 @@ void SlowPathLowering::LowerLdModuleVar(GateRef gate, GateRef glue, GateRef jsFu
std::vector<GateRef> failControl;
// 2: number of value inputs
ASSERT(acc_.GetNumValueIn(gate) == 2);
GateRef stringId = builder_.TaggedTypeNGC(builder_.ZExtInt32ToInt64(acc_.GetValueIn(gate, 0)));
GateRef key = LowerCallRuntime(glue, RTSTUB_ID(LoadValueFromConstantStringTable), { stringId }, true);
GateRef key = GetObjectFromConstPool(jsFunc, acc_.GetValueIn(gate, 0));
GateRef inner = builder_.TaggedTypeNGC(acc_.GetValueIn(gate, 1));
GateRef result = LowerCallRuntime(glue, RTSTUB_ID(LdModuleVarOnJSFunc), {key, inner, jsFunc}, true);
successControl.emplace_back(builder_.GetState());
@ -1640,8 +1645,7 @@ void SlowPathLowering::LowerGetModuleNamespace(GateRef gate, GateRef glue, GateR
std::vector<GateRef> failControl;
// 1: number of value inputs
ASSERT(acc_.GetNumValueIn(gate) == 1);
GateRef stringId = builder_.TaggedTypeNGC(builder_.ZExtInt32ToInt64(acc_.GetValueIn(gate, 0)));
GateRef localName = LowerCallRuntime(glue, RTSTUB_ID(LoadValueFromConstantStringTable), { stringId }, true);
GateRef localName = GetObjectFromConstPool(jsFunc, acc_.GetValueIn(gate, 0));
GateRef result = LowerCallRuntime(glue, RTSTUB_ID(GetModuleNamespaceOnJSFunc), { localName, jsFunc }, true);
successControl.emplace_back(builder_.GetState());
successControl.emplace_back(builder_.GetDepend());
@ -1842,16 +1846,20 @@ void SlowPathLowering::LowerCreateObjectWithExcludedKeys(GateRef gate, GateRef g
ReplaceHirToCall(gate, newGate);
}
void SlowPathLowering::LowerCreateRegExpWithLiteral(GateRef gate, GateRef glue)
void SlowPathLowering::LowerCreateRegExpWithLiteral(GateRef gate, GateRef glue, GateRef jsFunc)
{
// DebugPrintBC(gate, glue, builder_.Int32(GET_MESSAGE_STRING_ID(HandleCreateRegExpWithLiteralImm8Id16Imm8)));
Label successExit(&builder_);
Label exceptionExit(&builder_);
const int id = RTSTUB_ID(CreateRegExpWithLiteral);
// 2: number of value inputs
ASSERT(acc_.GetNumValueIn(gate) == 2);
GateRef pattern = GetValueFromConstStringTable(glue, gate, 0);
GateRef pattern = GetObjectFromConstPool(jsFunc, acc_.GetValueIn(gate, 0));
GateRef flags = acc_.GetValueIn(gate, 1);
GateRef newGate = LowerCallRuntime(glue, id, { pattern, builder_.TaggedTypeNGC(flags) });
ReplaceHirToCall(gate, newGate);
builder_.Branch(builder_.IsSpecial(newGate, JSTaggedValue::VALUE_EXCEPTION), &exceptionExit, &successExit);
CREATE_DOUBLE_EXIT(successExit, exceptionExit)
ReplaceHirToSubCfg(gate, newGate, successControl, failControl);
}
void SlowPathLowering::LowerStOwnByValue(GateRef gate, GateRef glue)
@ -1939,13 +1947,12 @@ void SlowPathLowering::LowerStOwnByIndex(GateRef gate, GateRef glue)
ReplaceHirToSubCfg(gate, Circuit::NullGate(), successControl, failControl);
}
void SlowPathLowering::LowerStOwnByName(GateRef gate, GateRef glue)
void SlowPathLowering::LowerStOwnByName(GateRef gate, GateRef glue, GateRef jsFunc)
{
// DebugPrintBC(gate, glue, builder_.Int32(GET_MESSAGE_STRING_ID(HandleStOwnByNameImm8Id16V8)));
// 3: number of value inputs
ASSERT(acc_.GetNumValueIn(gate) == 3);
auto args = { builder_.TaggedTypeNGC(builder_.ZExtInt32ToInt64(acc_.GetValueIn(gate, 0))) };
GateRef propKey = LowerCallRuntime(glue, RTSTUB_ID(LoadValueFromConstantStringTable), args, true);
GateRef propKey = GetObjectFromConstPool(jsFunc, acc_.GetValueIn(gate, 0));
GateRef receiver = acc_.GetValueIn(gate, 1);
GateRef accValue = acc_.GetValueIn(gate, 2);
// we do not need to merge outValueGate, so using GateRef directly instead of using Variable
@ -2163,15 +2170,14 @@ void SlowPathLowering::LowerStSuperByValue(GateRef gate, GateRef glue, GateRef j
ReplaceHirToCall(gate, newGate);
}
void SlowPathLowering::LowerTryStGlobalByName(GateRef gate, GateRef glue)
void SlowPathLowering::LowerTryStGlobalByName(GateRef gate, GateRef glue, GateRef jsFunc)
{
// DebugPrintBC(gate, glue, builder_.Int32(GET_MESSAGE_STRING_ID(HandleTryStGlobalByNameImm8Id16)));
// order: 1. global record 2. global object
DEFVAlUE(res, (&builder_), VariableType::JS_ANY(), builder_.Int64(JSTaggedValue::VALUE_HOLE));
// 2 : number of value inputs
ASSERT(acc_.GetNumValueIn(gate) == 2);
GateRef stringId = builder_.TaggedTypeNGC(builder_.ZExtInt32ToInt64(acc_.GetValueIn(gate, 0)));
GateRef propKey = LowerCallRuntime(glue, RTSTUB_ID(LoadValueFromConstantStringTable), { stringId }, true);
GateRef propKey = GetObjectFromConstPool(jsFunc, acc_.GetValueIn(gate, 0));
Label isUndefined(&builder_);
Label notUndefined(&builder_);
Label successExit(&builder_);
@ -2211,10 +2217,12 @@ void SlowPathLowering::LowerTryStGlobalByName(GateRef gate, GateRef glue)
ReplaceHirToSubCfg(gate, Circuit::NullGate(), successControl, failControl);
}
void SlowPathLowering::LowerStConstToGlobalRecord(GateRef gate, GateRef glue)
void SlowPathLowering::LowerStConstToGlobalRecord(GateRef gate, GateRef glue, GateRef jsFunc)
{
// DebugPrintBC(gate, glue, builder_.Int32(GET_MESSAGE_STRING_ID(HandleStConstToGlobalRecordId16)));
GateRef propKey = GetValueFromConstStringTable(glue, gate, 0);
Label successExit(&builder_);
Label exceptionExit(&builder_);
GateRef propKey = GetObjectFromConstPool(jsFunc, acc_.GetValueIn(gate, 0));
acc_.SetDep(gate, propKey);
// 2 : number of value inputs
ASSERT(acc_.GetNumValueIn(gate) == 2);
@ -2222,18 +2230,19 @@ void SlowPathLowering::LowerStConstToGlobalRecord(GateRef gate, GateRef glue)
GateRef value = acc_.GetValueIn(gate, 1);
GateRef isConst = builder_.TaggedTrue();
GateRef newGate = LowerCallRuntime(glue, id, { propKey, value, isConst });
ReplaceHirToCall(gate, newGate);
builder_.Branch(builder_.IsSpecial(newGate, JSTaggedValue::VALUE_EXCEPTION), &exceptionExit, &successExit);
CREATE_DOUBLE_EXIT(successExit, exceptionExit)
ReplaceHirToSubCfg(gate, newGate, successControl, failControl);
}
void SlowPathLowering::LowerStLetToGlobalRecord(GateRef gate, GateRef glue)
void SlowPathLowering::LowerStLetToGlobalRecord(GateRef gate, GateRef glue, GateRef jsFunc)
{
// DebugPrintBC(gate, glue, builder_.Int32(GET_MESSAGE_STRING_ID(HandleStLetToGlobalRecordId16)));
Label successExit(&builder_);
Label exceptionExit(&builder_);
// 2: number of value inputs
ASSERT(acc_.GetNumValueIn(gate) == 2);
GateRef stringId = builder_.TaggedTypeNGC(builder_.ZExtInt32ToInt64(acc_.GetValueIn(gate, 0)));
GateRef prop = LowerCallRuntime(glue, RTSTUB_ID(LoadValueFromConstantStringTable), { stringId }, true);
GateRef prop = GetObjectFromConstPool(jsFunc, acc_.GetValueIn(gate, 0));
GateRef taggedFalse = builder_.TaggedFalse();
GateRef result = LowerCallRuntime(glue, RTSTUB_ID(StGlobalRecord),
{prop, acc_.GetValueIn(gate, 1), taggedFalse}, true);
@ -2243,15 +2252,14 @@ void SlowPathLowering::LowerStLetToGlobalRecord(GateRef gate, GateRef glue)
ReplaceHirToSubCfg(gate, Circuit::NullGate(), successControl, failControl);
}
void SlowPathLowering::LowerStClassToGlobalRecord(GateRef gate, GateRef glue)
void SlowPathLowering::LowerStClassToGlobalRecord(GateRef gate, GateRef glue, GateRef jsFunc)
{
// DebugPrintBC(gate, glue, builder_.Int32(GET_MESSAGE_STRING_ID(HandleStClassToGlobalRecordId16)));
Label successExit(&builder_);
Label exceptionExit(&builder_);
// 2: number of value inputs
ASSERT(acc_.GetNumValueIn(gate) == 2);
GateRef stringId = builder_.TaggedTypeNGC(builder_.ZExtInt32ToInt64(acc_.GetValueIn(gate, 0)));
GateRef prop = LowerCallRuntime(glue, RTSTUB_ID(LoadValueFromConstantStringTable), { stringId }, true);
GateRef prop = GetObjectFromConstPool(jsFunc, acc_.GetValueIn(gate, 0));
GateRef taggedFalse = builder_.TaggedFalse();
GateRef result = LowerCallRuntime(glue, RTSTUB_ID(StGlobalRecord),
{prop, acc_.GetValueIn(gate, 1), taggedFalse}, true);
@ -2312,13 +2320,12 @@ void SlowPathLowering::LowerStOwnByValueWithNameSet(GateRef gate, GateRef glue)
ReplaceHirToSubCfg(gate, Circuit::NullGate(), successControl, failControl);
}
void SlowPathLowering::LowerStOwnByNameWithNameSet(GateRef gate, GateRef glue)
void SlowPathLowering::LowerStOwnByNameWithNameSet(GateRef gate, GateRef glue, GateRef jsFunc)
{
// DebugPrintBC(gate, glue, builder_.Int32(GET_MESSAGE_STRING_ID(HandleStOwnByNameWithNameSetImm8Id16V8)));
// 3: number of value inputs
ASSERT(acc_.GetNumValueIn(gate) == 3);
GateRef stringId = builder_.TaggedTypeNGC(builder_.ZExtInt32ToInt64(acc_.GetValueIn(gate, 0)));
GateRef propKey = LowerCallRuntime(glue, RTSTUB_ID(LoadValueFromConstantStringTable), { stringId }, true);
GateRef propKey = GetObjectFromConstPool(jsFunc, acc_.GetValueIn(gate, 0));
GateRef receiver = acc_.GetValueIn(gate, 1);
GateRef accValue = acc_.GetValueIn(gate, 2);
GateRef result;
@ -2364,7 +2371,7 @@ void SlowPathLowering::LowerStOwnByNameWithNameSet(GateRef gate, GateRef glue)
ReplaceHirToSubCfg(gate, Circuit::NullGate(), successControl, failControl);
}
void SlowPathLowering::LowerLdGlobalVar(GateRef gate, GateRef glue)
void SlowPathLowering::LowerLdGlobalVar(GateRef gate, GateRef glue, GateRef jsFunc)
{
// DebugPrintBC(gate, glue, builder_.Int32(GET_MESSAGE_STRING_ID(HandleLdGlobalVarId16)));
std::vector<GateRef> successControl;
@ -2375,8 +2382,7 @@ void SlowPathLowering::LowerLdGlobalVar(GateRef gate, GateRef glue)
GateRef ret;
DEFVAlUE(result, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
ASSERT(acc_.GetNumValueIn(gate) == 1);
GateRef stringId = builder_.TaggedTypeNGC(builder_.ZExtInt32ToInt64(acc_.GetValueIn(gate, 0)));
GateRef propKey = LowerCallRuntime(glue, RTSTUB_ID(LoadValueFromConstantStringTable), { stringId }, true);
GateRef propKey = GetObjectFromConstPool(jsFunc, acc_.GetValueIn(gate, 0));
GateRef globalObject = builder_.GetGlobalObject(glue);
result = LowerCallRuntime(glue, RTSTUB_ID(GetGlobalOwnProperty), { propKey }, true);
builder_.Branch(builder_.IsSpecial(*result, JSTaggedValue::VALUE_HOLE),
@ -2401,7 +2407,7 @@ void SlowPathLowering::LowerLdGlobalVar(GateRef gate, GateRef glue)
ReplaceHirToSubCfg(gate, ret, successControl, failControl);
}
void SlowPathLowering::LowerLdObjByName(GateRef gate, GateRef glue)
void SlowPathLowering::LowerLdObjByName(GateRef gate, GateRef glue, GateRef jsFunc)
{
// DebugPrintBC(gate, glue, builder_.Int32(GET_MESSAGE_STRING_ID(HandleLdObjByNameImm8Id16V8)));
std::vector<GateRef> successControl;
@ -2416,8 +2422,7 @@ void SlowPathLowering::LowerLdObjByName(GateRef gate, GateRef glue)
// 2: number of value inputs
ASSERT(acc_.GetNumValueIn(gate) == 2);
GateRef receiver = acc_.GetValueIn(gate, 1);
GateRef stringId = builder_.TaggedTypeNGC(builder_.ZExtInt32ToInt64(acc_.GetValueIn(gate, 0)));
GateRef prop = LowerCallRuntime(glue, RTSTUB_ID(LoadValueFromConstantStringTable), {stringId}, true);
GateRef prop = GetObjectFromConstPool(jsFunc, acc_.GetValueIn(gate, 0));
builder_.Branch(builder_.TaggedIsHeapObject(receiver), &receiverIsHeapObject, &slowPath);
builder_.Bind(&receiverIsHeapObject);
{
@ -2451,7 +2456,7 @@ void SlowPathLowering::LowerLdObjByName(GateRef gate, GateRef glue)
ReplaceHirToSubCfg(gate, result, successControl, failControl);
}
void SlowPathLowering::LowerStObjByName(GateRef gate, GateRef glue)
void SlowPathLowering::LowerStObjByName(GateRef gate, GateRef glue, GateRef jsFunc)
{
// DebugPrintBC(gate, glue, builder_.Int32(GET_MESSAGE_STRING_ID(HandleStObjByNameImm8Id16V8)));
Label receiverIsHeapObject(&builder_);
@ -2460,8 +2465,7 @@ void SlowPathLowering::LowerStObjByName(GateRef gate, GateRef glue)
Label exceptionExit(&builder_);
// 3: number of value inputs
ASSERT(acc_.GetNumValueIn(gate) == 3);
GateRef stringId = builder_.TaggedTypeNGC(builder_.ZExtInt32ToInt64(acc_.GetValueIn(gate, 0)));
GateRef prop = LowerCallRuntime(glue, RTSTUB_ID(LoadValueFromConstantStringTable), {stringId}, true);
GateRef prop = GetObjectFromConstPool(jsFunc, acc_.GetValueIn(gate, 0));
GateRef receiver = acc_.GetValueIn(gate, 1);
GateRef result;
builder_.Branch(builder_.TaggedIsHeapObject(receiver), &receiverIsHeapObject, &slowPath);
@ -2681,8 +2685,7 @@ void SlowPathLowering::LowerLdSuperByName(GateRef gate, GateRef glue, GateRef js
Label exceptionExit(&builder_);
// 2: number of value inputs
ASSERT(acc_.GetNumValueIn(gate) == 2);
auto args1 = { builder_.TaggedTypeNGC(builder_.ZExtInt32ToInt64(acc_.GetValueIn(gate, 0))) };
GateRef prop = LowerCallRuntime(glue, RTSTUB_ID(LoadValueFromConstantStringTable), args1, true);
GateRef prop = GetObjectFromConstPool(jsFunc, acc_.GetValueIn(gate, 0));
GateRef result =
LowerCallRuntime(glue, RTSTUB_ID(OptLdSuperByValue), {acc_.GetValueIn(gate, 1), prop, jsFunc}, true);
builder_.Branch(builder_.IsSpecial(result, JSTaggedValue::VALUE_EXCEPTION),
@ -2698,8 +2701,7 @@ void SlowPathLowering::LowerStSuperByName(GateRef gate, GateRef glue, GateRef js
Label exceptionExit(&builder_);
// 3: number of value inputs
ASSERT(acc_.GetNumValueIn(gate) == 3);
auto args1 = { builder_.TaggedTypeNGC(builder_.ZExtInt32ToInt64(acc_.GetValueIn(gate, 0))) };
GateRef prop = LowerCallRuntime(glue, RTSTUB_ID(LoadValueFromConstantStringTable), args1, true);
GateRef prop = GetObjectFromConstPool(jsFunc, acc_.GetValueIn(gate, 0));
auto args2 = { acc_.GetValueIn(gate, 1), prop, acc_.GetValueIn(gate, 2), jsFunc };
GateRef result = LowerCallRuntime(glue, RTSTUB_ID(OptStSuperByValue), args2, true);
builder_.Branch(builder_.IsSpecial(result, JSTaggedValue::VALUE_EXCEPTION),
@ -2857,18 +2859,17 @@ void SlowPathLowering::LowerDefineClassWithBuffer(GateRef gate, GateRef glue, Ga
// DebugPrintBC(gate, glue, builder_.Int32(GET_MESSAGE_STRING_ID(HandleDefineClassWithBufferImm8Id16Imm16Imm16V8V8)));
// 5: number of value inputs
ASSERT(acc_.GetNumValueIn(gate) == 5);
GateRef methodId = builder_.ZExtInt16ToInt32(acc_.GetValueIn(gate, 0));
GateRef methodId = acc_.GetValueIn(gate, 0);
GateRef length = acc_.GetValueIn(gate, 2);
GateRef classTemplate = GetObjectFromConstPool(jsFunc, methodId);
GateRef lexicalEnv = acc_.GetValueIn(gate, 3);
GateRef proto = acc_.GetValueIn(gate, 4);
GateRef constpool = GetConstPool(jsFunc);
Label isException(&builder_);
Label isNotException(&builder_);
auto args = { classTemplate, proto, lexicalEnv, constpool };
GateRef result = LowerCallRuntime(glue, RTSTUB_ID(CloneClassFromTemplate), args, true);
auto args = { proto, lexicalEnv, constpool, builder_.TaggedNGC(methodId) };
GateRef result = LowerCallRuntime(glue, RTSTUB_ID(CreateClassWithBuffer), args, true);
builder_.Branch(builder_.IsSpecial(result, JSTaggedValue::VALUE_EXCEPTION),
&isException, &isNotException);
std::vector<GateRef> successControl;

View File

@ -150,7 +150,6 @@ private:
GateRef GetObjectFromConstPool(GateRef jsFunc, GateRef index);
// environment must be initialized
GateRef GetHomeObjectFromJSFunction(GateRef jsFunc);
GateRef GetValueFromConstStringTable(GateRef glue, GateRef gate, uint32_t inIndex);
void Lower(GateRef gate);
void LowerAdd2(GateRef gate, GateRef glue);
void LowerCreateIterResultObj(GateRef gate, GateRef glue);
@ -159,10 +158,10 @@ private:
void LowerAsyncFunctionAwaitUncaught(GateRef gate, GateRef glue);
void LowerAsyncFunctionResolve(GateRef gate, GateRef glue);
void LowerAsyncFunctionReject(GateRef gate, GateRef glue);
void LowerLoadStr(GateRef gate, GateRef glue);
void LowerLoadStr(GateRef gate, GateRef glue, GateRef jsFunc);
void LowerLexicalEnv(GateRef gate, GateRef glue);
void LowerStGlobalVar(GateRef gate, GateRef glue);
void LowerTryLdGlobalByName(GateRef gate, GateRef glue);
void LowerStGlobalVar(GateRef gate, GateRef glue, GateRef jsFunc);
void LowerTryLdGlobalByName(GateRef gate, GateRef glue, GateRef jsFunc);
void LowerGetIterator(GateRef gate, GateRef glue);
void LowerToJSCall(GateRef gate, GateRef glue, const std::vector<GateRef> &args);
void LowerCallArg0(GateRef gate, GateRef glue);
@ -220,8 +219,9 @@ private:
void LowerStModuleVar(GateRef gate, GateRef glue, GateRef jsFunc);
void LowerGetTemplateObject(GateRef gate, GateRef glue);
void LowerSetObjectWithProto(GateRef gate, GateRef glue);
void LowerLdBigInt(GateRef gate, GateRef glue);
void LowerLdBigInt(GateRef gate, GateRef glue, GateRef jsFunc);
void LowerToNumeric(GateRef gate, GateRef glue);
void LowerDynamicImport(GateRef gate, GateRef glue);
void LowerLdModuleVar(GateRef gate, GateRef glue, GateRef jsFunc);
void LowerGetModuleNamespace(GateRef gate, GateRef glue, GateRef jsFunc);
void LowerGetIteratorNext(GateRef gate, GateRef glue);
@ -233,10 +233,10 @@ private:
void LowerGetNextPropName(GateRef gate, GateRef glue);
void LowerCopyDataProperties(GateRef gate, GateRef glue);
void LowerCreateObjectWithExcludedKeys(GateRef gate, GateRef glue);
void LowerCreateRegExpWithLiteral(GateRef gate, GateRef glue);
void LowerCreateRegExpWithLiteral(GateRef gate, GateRef glue, GateRef jsFunc);
void LowerStOwnByValue(GateRef gate, GateRef glue);
void LowerStOwnByIndex(GateRef gate, GateRef glue);
void LowerStOwnByName(GateRef gate, GateRef glue);
void LowerStOwnByName(GateRef gate, GateRef glue, GateRef jsFunc);
void LowerDefineFunc(GateRef gate, GateRef glue, GateRef jsFunc);
void LowerDefineGeneratorFunc(GateRef gate, GateRef glue, GateRef jsFunc);
void LowerDefineAsyncGeneratorFunc(GateRef gate, GateRef glue, GateRef jsFunc);
@ -246,15 +246,15 @@ private:
void LowerPopLexicalEnv(GateRef gate, GateRef glue);
void LowerLdSuperByValue(GateRef gate, GateRef glue, GateRef jsFunc);
void LowerStSuperByValue(GateRef gate, GateRef glue, GateRef jsFunc);
void LowerTryStGlobalByName(GateRef gate, GateRef glue);
void LowerStConstToGlobalRecord(GateRef gate, GateRef glue);
void LowerStLetToGlobalRecord(GateRef gate, GateRef glue);
void LowerStClassToGlobalRecord(GateRef gate, GateRef glue);
void LowerTryStGlobalByName(GateRef gate, GateRef glue, GateRef jsFunc);
void LowerStConstToGlobalRecord(GateRef gate, GateRef glue, GateRef jsFunc);
void LowerStLetToGlobalRecord(GateRef gate, GateRef glue, GateRef jsFunc);
void LowerStClassToGlobalRecord(GateRef gate, GateRef glue, GateRef jsFunc);
void LowerStOwnByValueWithNameSet(GateRef gate, GateRef glue);
void LowerStOwnByNameWithNameSet(GateRef gate, GateRef glue);
void LowerLdGlobalVar(GateRef gate, GateRef glue);
void LowerLdObjByName(GateRef gate, GateRef glue);
void LowerStObjByName(GateRef gate, GateRef glue);
void LowerStOwnByNameWithNameSet(GateRef gate, GateRef glue, GateRef jsFunc);
void LowerLdGlobalVar(GateRef gate, GateRef glue, GateRef jsFunc);
void LowerLdObjByName(GateRef gate, GateRef glue, GateRef jsFunc);
void LowerStObjByName(GateRef gate, GateRef glue, GateRef jsFunc);
void LowerLdSuperByName(GateRef gate, GateRef glue, GateRef jsFunc);
void LowerStSuperByName(GateRef gate, GateRef glue, GateRef jsFunc);
void LowerDefineGetterSetterByValue(GateRef gate, GateRef glue);

View File

@ -287,22 +287,22 @@ inline GateRef StubBuilder::Load(VariableType type, GateRef base)
// arithmetic
inline GateRef StubBuilder::Int16Add(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryArithmetic(OpCode(OpCode::ADD), MachineType::I16, x, y);
return env_->GetBuilder()->Int16Add(x, y);
}
inline GateRef StubBuilder::Int32Add(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryArithmetic(OpCode(OpCode::ADD), MachineType::I32, x, y);
return env_->GetBuilder()->Int32Add(x, y);
}
inline GateRef StubBuilder::Int64Add(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryArithmetic(OpCode(OpCode::ADD), MachineType::I64, x, y);
return env_->GetBuilder()->Int64Add(x, y);
}
inline GateRef StubBuilder::DoubleAdd(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryArithmetic(OpCode(OpCode::ADD), MachineType::F64, x, y);
return env_->GetBuilder()->DoubleAdd(x, y);
}
inline GateRef StubBuilder::PtrAdd(GateRef x, GateRef y)
@ -313,6 +313,11 @@ inline GateRef StubBuilder::PtrAdd(GateRef x, GateRef y)
return Int64Add(x, y);
}
inline GateRef StubBuilder::PointerAdd(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryArithmetic(OpCode(OpCode::ADD), MachineType::ARCH, x, y);
}
inline GateRef StubBuilder::IntPtrAnd(GateRef x, GateRef y)
{
return env_->Is32Bit() ? Int32And(x, y) : Int64And(x, y);
@ -336,192 +341,194 @@ inline GateRef StubBuilder::PtrSub(GateRef x, GateRef y)
inline GateRef StubBuilder::PointerSub(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryArithmetic(OpCode(OpCode::SUB), MachineType::ARCH, x, y);
return env_->GetBuilder()->PointerSub(x, y);
}
inline GateRef StubBuilder::Int16Sub(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryArithmetic(OpCode(OpCode::SUB), MachineType::I16, x, y);
return env_->GetBuilder()->Int16Sub(x, y);
}
inline GateRef StubBuilder::Int32Sub(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryArithmetic(OpCode(OpCode::SUB), MachineType::I32, x, y);
return env_->GetBuilder()->Int32Sub(x, y);
}
inline GateRef StubBuilder::Int64Sub(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryArithmetic(OpCode(OpCode::SUB), MachineType::I64, x, y);
return env_->GetBuilder()->Int64Sub(x, y);
}
inline GateRef StubBuilder::DoubleSub(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryArithmetic(OpCode(OpCode::SUB), MachineType::F64, x, y);
return env_->GetBuilder()->DoubleSub(x, y);
}
inline GateRef StubBuilder::Int32Mul(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryArithmetic(OpCode(OpCode::MUL), MachineType::I32, x, y);
return env_->GetBuilder()->Int32Mul(x, y);
}
inline GateRef StubBuilder::Int64Mul(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryArithmetic(OpCode(OpCode::MUL), MachineType::I64, x, y);
return env_->GetBuilder()->Int64Mul(x, y);
}
inline GateRef StubBuilder::DoubleMul(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryArithmetic(OpCode(OpCode::MUL), MachineType::F64, x, y);
return env_->GetBuilder()->DoubleMul(x, y);
}
inline GateRef StubBuilder::DoubleDiv(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryArithmetic(OpCode(OpCode::FDIV), MachineType::F64, x, y);
return env_->GetBuilder()->DoubleDiv(x, y);
}
inline GateRef StubBuilder::Int32Div(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryArithmetic(OpCode(OpCode::SDIV), MachineType::I32, x, y);
return env_->GetBuilder()->Int32Div(x, y);
}
inline GateRef StubBuilder::Int64Div(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryArithmetic(OpCode(OpCode::SDIV), MachineType::I64, x, y);
return env_->GetBuilder()->Int64Div(x, y);
}
inline GateRef StubBuilder::IntPtrDiv(GateRef x, GateRef y)
{
return env_->Is32Bit() ? Int32Div(x, y) : Int64Div(x, y);
return env_->GetBuilder()->IntPtrDiv(x, y);
}
inline GateRef StubBuilder::Int32Mod(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryArithmetic(OpCode(OpCode::SMOD), MachineType::I32, x, y);
return env_->GetBuilder()->Int32Mod(x, y);
}
inline GateRef StubBuilder::DoubleMod(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryArithmetic(OpCode(OpCode::SMOD), MachineType::F64, x, y);
return env_->GetBuilder()->DoubleMod(x, y);
}
// bit operation
inline GateRef StubBuilder::Int32Or(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryArithmetic(OpCode(OpCode::OR), MachineType::I32, x, y);
return env_->GetBuilder()->Int32Or(x, y);
}
inline GateRef StubBuilder::Int8And(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryArithmetic(OpCode(OpCode::AND), MachineType::I8, x, y);
return env_->GetBuilder()->Int8And(x, y);
}
inline GateRef StubBuilder::Int32And(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryArithmetic(OpCode(OpCode::AND), MachineType::I32, x, y);
return env_->GetBuilder()->Int32And(x, y);
}
inline GateRef StubBuilder::BoolAnd(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryArithmetic(OpCode(OpCode::AND), MachineType::I1, x, y);
return env_->GetBuilder()->BoolAnd(x, y);
}
inline GateRef StubBuilder::BoolOr(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryArithmetic(OpCode(OpCode::OR), MachineType::I1, x, y);
return env_->GetBuilder()->BoolOr(x, y);
}
inline GateRef StubBuilder::Int32Not(GateRef x)
{
return env_->GetBuilder()->UnaryArithmetic(OpCode(OpCode::REV), MachineType::I32, x);
return env_->GetBuilder()->Int32Not(x);
}
inline GateRef StubBuilder::IntPtrNot(GateRef x)
{
return env_->Is32Bit() ? Int32Not(x) : Int64Not(x);
}
inline GateRef StubBuilder::BoolNot(GateRef x)
{
return env_->GetBuilder()->UnaryArithmetic(OpCode(OpCode::REV), MachineType::I1, x);
return env_->GetBuilder()->BoolNot(x);
}
inline GateRef StubBuilder::Int64Or(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryArithmetic(OpCode(OpCode::OR), MachineType::I64, x, y);
return env_->GetBuilder()->Int64Or(x, y);
}
inline GateRef StubBuilder::IntPtrOr(GateRef x, GateRef y)
{
auto ptrsize = env_->Is32Bit() ? MachineType::I32 : MachineType::I64;
return env_->GetBuilder()->BinaryArithmetic(OpCode(OpCode::OR), ptrsize, x, y);
return env_->GetBuilder()->IntPtrOr(x, y);
}
inline GateRef StubBuilder::Int64And(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryArithmetic(OpCode(OpCode::AND), MachineType::I64, x, y);
return env_->GetBuilder()->Int64And(x, y);
}
inline GateRef StubBuilder::Int16LSL(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryArithmetic(OpCode(OpCode::LSL), MachineType::I16, x, y);
return env_->GetBuilder()->Int16LSL(x, y);
}
inline GateRef StubBuilder::Int64Xor(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryArithmetic(OpCode(OpCode::XOR), MachineType::I64, x, y);
return env_->GetBuilder()->Int64Xor(x, y);
}
inline GateRef StubBuilder::Int32Xor(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryArithmetic(OpCode(OpCode::XOR), MachineType::I32, x, y);
return env_->GetBuilder()->Int32Xor(x, y);
}
inline GateRef StubBuilder::Int8LSR(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryArithmetic(OpCode(OpCode::LSR), MachineType::I8, x, y);
return env_->GetBuilder()->Int8LSR(x, y);
}
inline GateRef StubBuilder::Int64Not(GateRef x)
{
return env_->GetBuilder()->UnaryArithmetic(OpCode(OpCode::REV), MachineType::I64, x);
return env_->GetBuilder()->Int64Not(x);
}
inline GateRef StubBuilder::Int32LSL(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryArithmetic(OpCode(OpCode::LSL), MachineType::I32, x, y);
return env_->GetBuilder()->Int32LSL(x, y);
}
inline GateRef StubBuilder::Int64LSL(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryArithmetic(OpCode(OpCode::LSL), MachineType::I64, x, y);
return env_->GetBuilder()->Int64LSL(x, y);
}
inline GateRef StubBuilder::IntPtrLSL(GateRef x, GateRef y)
{
auto ptrSize = env_->Is32Bit() ? MachineType::I32 : MachineType::I64;
return env_->GetBuilder()->BinaryArithmetic(OpCode(OpCode::LSL), ptrSize, x, y);
return env_->GetBuilder()->IntPtrLSL(x, y);
}
inline GateRef StubBuilder::Int32ASR(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryArithmetic(OpCode(OpCode::ASR), MachineType::I32, x, y);
return env_->GetBuilder()->Int32ASR(x, y);
}
inline GateRef StubBuilder::Int32LSR(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryArithmetic(OpCode(OpCode::LSR), MachineType::I32, x, y);
return env_->GetBuilder()->Int32LSR(x, y);
}
inline GateRef StubBuilder::Int64LSR(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryArithmetic(OpCode(OpCode::LSR), MachineType::I64, x, y);
return env_->GetBuilder()->Int64LSR(x, y);
}
inline GateRef StubBuilder::IntPtrLSR(GateRef x, GateRef y)
{
auto ptrSize = env_->Is32Bit() ? MachineType::I32 : MachineType::I64;
return env_->GetBuilder()->BinaryArithmetic(OpCode(OpCode::LSR), ptrSize, x, y);
return env_->GetBuilder()->IntPtrLSR(x, y);
}
template<OpCode::Op Op, MachineType Type>
inline GateRef StubBuilder::BinaryOp(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryArithmetic(OpCode(Op), Type, x, y);
return env_->GetBuilder()->BinaryOp<Op, Type>(x, y);
}
inline GateRef StubBuilder::TaggedIsInt(GateRef x)
@ -727,7 +734,7 @@ inline GateRef StubBuilder::DoubleBuildTaggedTypeWithNoGC(GateRef x)
inline GateRef StubBuilder::CastDoubleToInt64(GateRef x)
{
return env_->GetBuilder()->UnaryArithmetic(OpCode(OpCode::BITCAST), MachineType::I64, x);
return env_->GetBuilder()->CastDoubleToInt64(x);
}
inline GateRef StubBuilder::TaggedTrue()
@ -743,112 +750,112 @@ inline GateRef StubBuilder::TaggedFalse()
// compare operation
inline GateRef StubBuilder::Int8Equal(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryLogic(OpCode(OpCode::EQ), x, y);
return env_->GetBuilder()->Int8Equal(x, y);
}
inline GateRef StubBuilder::Int32Equal(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryLogic(OpCode(OpCode::EQ), x, y);
return env_->GetBuilder()->Int32Equal(x, y);
}
inline GateRef StubBuilder::Int32NotEqual(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryLogic(OpCode(OpCode::NE), x, y);
return env_->GetBuilder()->Int32NotEqual(x, y);
}
inline GateRef StubBuilder::Int64Equal(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryLogic(OpCode(OpCode::EQ), x, y);
return env_->GetBuilder()->Int64Equal(x, y);
}
inline GateRef StubBuilder::DoubleEqual(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryLogic(OpCode(OpCode::EQ), x, y);
return env_->GetBuilder()->DoubleEqual(x, y);
}
inline GateRef StubBuilder::DoubleLessThan(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryLogic(OpCode(OpCode::SLT), x, y);
return env_->GetBuilder()->DoubleLessThan(x, y);
}
inline GateRef StubBuilder::DoubleLessThanOrEqual(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryLogic(OpCode(OpCode::SLE), x, y);
return env_->GetBuilder()->DoubleLessThanOrEqual(x, y);
}
inline GateRef StubBuilder::DoubleGreaterThan(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryLogic(OpCode(OpCode::SGT), x, y);
return env_->GetBuilder()->DoubleGreaterThan(x, y);
}
inline GateRef StubBuilder::DoubleGreaterThanOrEqual(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryLogic(OpCode(OpCode::SGE), x, y);
return env_->GetBuilder()->DoubleGreaterThanOrEqual(x, y);
}
inline GateRef StubBuilder::Int64NotEqual(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryLogic(OpCode(OpCode::NE), x, y);
return env_->GetBuilder()->Int64NotEqual(x, y);
}
inline GateRef StubBuilder::Int32GreaterThan(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryLogic(OpCode(OpCode::SGT), x, y);
return env_->GetBuilder()->Int32GreaterThan(x, y);
}
inline GateRef StubBuilder::Int32LessThan(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryLogic(OpCode(OpCode::SLT), x, y);
return env_->GetBuilder()->Int32LessThan(x, y);
}
inline GateRef StubBuilder::Int32GreaterThanOrEqual(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryLogic(OpCode(OpCode::SGE), x, y);
return env_->GetBuilder()->Int32GreaterThanOrEqual(x, y);
}
inline GateRef StubBuilder::Int32LessThanOrEqual(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryLogic(OpCode(OpCode::SLE), x, y);
return env_->GetBuilder()->Int32LessThanOrEqual(x, y);
}
inline GateRef StubBuilder::Int32UnsignedGreaterThan(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryLogic(OpCode(OpCode::UGT), x, y);
return env_->GetBuilder()->Int32UnsignedGreaterThan(x, y);
}
inline GateRef StubBuilder::Int32UnsignedLessThan(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryLogic(OpCode(OpCode::ULT), x, y);
return env_->GetBuilder()->Int32UnsignedLessThan(x, y);
}
inline GateRef StubBuilder::Int32UnsignedGreaterThanOrEqual(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryLogic(OpCode(OpCode::UGE), x, y);
return env_->GetBuilder()->Int32UnsignedGreaterThanOrEqual(x, y);
}
inline GateRef StubBuilder::Int64GreaterThan(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryLogic(OpCode(OpCode::SGT), x, y);
return env_->GetBuilder()->Int64GreaterThan(x, y);
}
inline GateRef StubBuilder::Int64LessThan(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryLogic(OpCode(OpCode::SLT), x, y);
return env_->GetBuilder()->Int64LessThan(x, y);
}
inline GateRef StubBuilder::Int64LessThanOrEqual(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryLogic(OpCode(OpCode::SLE), x, y);
return env_->GetBuilder()->Int64LessThanOrEqual(x, y);
}
inline GateRef StubBuilder::Int64GreaterThanOrEqual(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryLogic(OpCode(OpCode::SGE), x, y);
return env_->GetBuilder()->Int64GreaterThanOrEqual(x, y);
}
inline GateRef StubBuilder::Int64UnsignedLessThanOrEqual(GateRef x, GateRef y)
{
return env_->GetBuilder()->BinaryLogic(OpCode(OpCode::ULE), x, y);
return env_->GetBuilder()->Int64UnsignedLessThanOrEqual(x, y);
}
inline GateRef StubBuilder::IntPtrGreaterThan(GateRef x, GateRef y)
@ -859,7 +866,12 @@ inline GateRef StubBuilder::IntPtrGreaterThan(GateRef x, GateRef y)
// cast operation
inline GateRef StubBuilder::ChangeInt64ToInt32(GateRef val)
{
return env_->GetBuilder()->UnaryArithmetic(OpCode(OpCode::TRUNC_TO_INT32), val);
return env_->GetBuilder()->ChangeInt64ToInt32(val);
}
inline GateRef StubBuilder::ChangeInt16ToInt8(GateRef val)
{
return env_->GetBuilder()->UnaryArithmetic(OpCode(OpCode::TRUNC_TO_INT8), val);
}
inline GateRef StubBuilder::ChangeInt64ToIntPtr(GateRef val)
@ -1511,126 +1523,117 @@ inline GateRef StubBuilder::TaggedCastToWeakReferentUnChecked(GateRef x)
inline GateRef StubBuilder::ChangeInt32ToFloat64(GateRef x)
{
return env_->GetBuilder()->UnaryArithmetic(OpCode(OpCode::SIGNED_INT_TO_FLOAT), MachineType::F64, x);
return env_->GetBuilder()->ChangeInt32ToFloat64(x);
}
inline GateRef StubBuilder::ChangeUInt32ToFloat64(GateRef x)
{
return env_->GetBuilder()->UnaryArithmetic(OpCode(OpCode::UNSIGNED_INT_TO_FLOAT), MachineType::F64, x);
return env_->GetBuilder()->ChangeUInt32ToFloat64(x);
}
inline GateRef StubBuilder::ChangeFloat64ToInt32(GateRef x)
{
return env_->GetBuilder()->UnaryArithmetic(OpCode(OpCode::FLOAT_TO_SIGNED_INT), MachineType::I32, x);
return env_->GetBuilder()->ChangeFloat64ToInt32(x);
}
inline GateRef StubBuilder::ChangeTaggedPointerToInt64(GateRef x)
{
return env_->GetBuilder()->UnaryArithmetic(OpCode(OpCode::TAGGED_TO_INT64), x);
return env_->GetBuilder()->ChangeTaggedPointerToInt64(x);
}
inline GateRef StubBuilder::ChangeInt64ToTagged(GateRef x)
{
return env_->GetBuilder()->TaggedNumber(OpCode(OpCode::INT64_TO_TAGGED), x);
return env_->GetBuilder()->ChangeInt64ToTagged(x);
}
inline GateRef StubBuilder::CastInt64ToFloat64(GateRef x)
{
return env_->GetBuilder()->UnaryArithmetic(OpCode(OpCode::BITCAST), MachineType::F64, x);
return env_->GetBuilder()->CastInt64ToFloat64(x);
}
inline GateRef StubBuilder::SExtInt32ToInt64(GateRef x)
{
return env_->GetBuilder()->UnaryArithmetic(OpCode(OpCode::SEXT_TO_INT64), x);
return env_->GetBuilder()->SExtInt32ToInt64(x);
}
inline GateRef StubBuilder::SExtInt16ToInt64(GateRef x)
{
return env_->GetBuilder()->UnaryArithmetic(OpCode(OpCode::SEXT_TO_INT64), x);
return env_->GetBuilder()->SExtInt16ToInt64(x);
}
inline GateRef StubBuilder::SExtInt8ToInt64(GateRef x)
{
return env_->GetBuilder()->UnaryArithmetic(OpCode(OpCode::SEXT_TO_INT64), x);
return env_->GetBuilder()->SExtInt8ToInt64(x);
}
inline GateRef StubBuilder::SExtInt1ToInt64(GateRef x)
{
return env_->GetBuilder()->UnaryArithmetic(OpCode(OpCode::SEXT_TO_INT64), x);
return env_->GetBuilder()->SExtInt1ToInt64(x);
}
inline GateRef StubBuilder::SExtInt1ToInt32(GateRef x)
{
return env_->GetBuilder()->UnaryArithmetic(OpCode(OpCode::SEXT_TO_INT32), x);
return env_->GetBuilder()->SExtInt1ToInt32(x);
}
inline GateRef StubBuilder::ZExtInt8ToInt16(GateRef x)
{
return env_->GetBuilder()->UnaryArithmetic(OpCode(OpCode::ZEXT_TO_INT16), x);
return env_->GetBuilder()->ZExtInt8ToInt16(x);
}
inline GateRef StubBuilder::ZExtInt32ToInt64(GateRef x)
{
return env_->GetBuilder()->UnaryArithmetic(OpCode(OpCode::ZEXT_TO_INT64), x);
return env_->GetBuilder()->ZExtInt32ToInt64(x);
}
inline GateRef StubBuilder::ZExtInt1ToInt64(GateRef x)
{
return env_->GetBuilder()->UnaryArithmetic(OpCode(OpCode::ZEXT_TO_INT64), x);
return env_->GetBuilder()->ZExtInt1ToInt64(x);
}
inline GateRef StubBuilder::ZExtInt1ToInt32(GateRef x)
{
return env_->GetBuilder()->UnaryArithmetic(OpCode(OpCode::ZEXT_TO_INT32), x);
return env_->GetBuilder()->ZExtInt1ToInt32(x);
}
inline GateRef StubBuilder::ZExtInt8ToInt32(GateRef x)
{
return env_->GetBuilder()->UnaryArithmetic(OpCode(OpCode::ZEXT_TO_INT32), x);
return env_->GetBuilder()->ZExtInt8ToInt32(x);
}
inline GateRef StubBuilder::ZExtInt8ToInt64(GateRef x)
{
return env_->GetBuilder()->UnaryArithmetic(OpCode(OpCode::ZEXT_TO_INT64), x);
return env_->GetBuilder()->ZExtInt8ToInt64(x);
}
inline GateRef StubBuilder::ZExtInt8ToPtr(GateRef x)
{
if (env_->IsArch32Bit()) {
return env_->GetBuilder()->UnaryArithmetic(OpCode(OpCode::ZEXT_TO_INT32), x);
}
return env_->GetBuilder()->UnaryArithmetic(OpCode(OpCode::ZEXT_TO_INT64), x);
return env_->GetBuilder()->ZExtInt8ToPtr(x);
}
inline GateRef StubBuilder::ZExtInt16ToPtr(GateRef x)
{
if (env_->IsArch32Bit()) {
return env_->GetBuilder()->UnaryArithmetic(OpCode(OpCode::ZEXT_TO_INT32), x);
}
return env_->GetBuilder()->UnaryArithmetic(OpCode(OpCode::ZEXT_TO_INT64), x);
return env_->GetBuilder()->ZExtInt16ToPtr(x);
}
inline GateRef StubBuilder::SExtInt32ToPtr(GateRef x)
{
if (env_->IsArch32Bit()) {
return x;
}
return env_->GetBuilder()->UnaryArithmetic(OpCode(OpCode::SEXT_TO_INT64), x);
return env_->GetBuilder()->SExtInt32ToPtr(x);
}
inline GateRef StubBuilder::ZExtInt16ToInt32(GateRef x)
{
return env_->GetBuilder()->UnaryArithmetic(OpCode(OpCode::ZEXT_TO_INT32), x);
return env_->GetBuilder()->ZExtInt16ToInt32(x);
}
inline GateRef StubBuilder::ZExtInt16ToInt64(GateRef x)
{
return env_->GetBuilder()->UnaryArithmetic(OpCode(OpCode::ZEXT_TO_INT64), x);
return env_->GetBuilder()->ZExtInt16ToInt64(x);
}
inline GateRef StubBuilder::TruncInt64ToInt32(GateRef x)
{
return env_->GetBuilder()->UnaryArithmetic(OpCode(OpCode::TRUNC_TO_INT32), x);
return env_->GetBuilder()->TruncInt64ToInt32(x);
}
inline GateRef StubBuilder::TruncPtrToInt32(GateRef x)
@ -1643,12 +1646,12 @@ inline GateRef StubBuilder::TruncPtrToInt32(GateRef x)
inline GateRef StubBuilder::TruncInt64ToInt1(GateRef x)
{
return env_->GetBuilder()->UnaryArithmetic(OpCode(OpCode::TRUNC_TO_INT1), x);
return env_->GetBuilder()->TruncInt64ToInt1(x);
}
inline GateRef StubBuilder::TruncInt32ToInt1(GateRef x)
{
return env_->GetBuilder()->UnaryArithmetic(OpCode(OpCode::TRUNC_TO_INT1), x);
return env_->GetBuilder()->TruncInt32ToInt1(x);
}
inline GateRef StubBuilder::GetGlobalConstantAddr(GateRef index)
@ -1956,5 +1959,38 @@ inline GateRef StubBuilder::GetBuiltinId(GateRef method)
GateRef builtinsIdOffset = PtrAdd(IntPtr(Method::LITERAL_INFO_OFFSET), IntPtr(7));
return Load(VariableType::INT8(), method, builtinsIdOffset);
}
inline GateRef StubBuilder::ComputeSizeUtf8(GateRef length)
{
return PtrAdd(IntPtr(EcmaString::DATA_OFFSET), length);
}
inline GateRef StubBuilder::ComputeSizeUtf16(GateRef length)
{
return PtrAdd(IntPtr(EcmaString::DATA_OFFSET), PtrMul(length, IntPtr(sizeof(uint16_t))));
}
inline GateRef StubBuilder::AlignUp(GateRef x, GateRef alignment)
{
GateRef x1 = PtrAdd(x, PtrSub(alignment, IntPtr(1)));
return IntPtrAnd(x1, IntPtrNot(PtrSub(alignment, IntPtr(1))));
}
inline void StubBuilder::SetLength(GateRef glue, GateRef str, GateRef length, bool compressed)
{
GateRef len = Int32LSL(length, Int32(2));
GateRef mixLength;
if (compressed) {
mixLength = Int32Or(len, Int32(EcmaString::STRING_COMPRESSED));
} else {
mixLength = Int32Or(len, Int32(EcmaString::STRING_UNCOMPRESSED));;
}
Store(VariableType::INT32(), glue, str, IntPtr(EcmaString::MIX_LENGTH_OFFSET), mixLength);
}
inline void StubBuilder::SetRawHashcode(GateRef glue, GateRef str, GateRef rawHashcode)
{
Store(VariableType::INT32(), glue, str, IntPtr(EcmaString::HASHCODE_OFFSET), rawHashcode);
}
} // namespace panda::ecmascript::kungfu
#endif // ECMASCRIPT_COMPILER_STUB_INL_H

View File

@ -25,7 +25,6 @@
#include "ecmascript/message_string.h"
#include "ecmascript/tagged_dictionary.h"
#include "ecmascript/tagged_hash_table.h"
#include "libpandabase/macros.h"
namespace panda::ecmascript::kungfu {
void StubBuilder::Jump(Label *label)

View File

@ -105,6 +105,7 @@ public:
GateRef PtrAdd(GateRef x, GateRef y);
GateRef PtrSub(GateRef x, GateRef y);
GateRef PointerSub(GateRef x, GateRef y);
GateRef PointerAdd(GateRef x, GateRef y);
GateRef IntPtrEqual(GateRef x, GateRef y);
GateRef Int16Sub(GateRef x, GateRef y);
GateRef Int32Sub(GateRef x, GateRef y);
@ -127,6 +128,7 @@ public:
GateRef BoolAnd(GateRef x, GateRef y);
GateRef BoolOr(GateRef x, GateRef y);
GateRef Int32Not(GateRef x);
GateRef IntPtrNot(GateRef x);
GateRef BoolNot(GateRef x);
GateRef Int32Xor(GateRef x, GateRef y);
GateRef FixLoadType(GateRef x);
@ -363,6 +365,7 @@ public:
GateRef ChangeFloat64ToInt32(GateRef x);
GateRef ChangeTaggedPointerToInt64(GateRef x);
GateRef ChangeInt64ToTagged(GateRef x);
GateRef ChangeInt16ToInt8(GateRef x);
GateRef CastInt64ToFloat64(GateRef x);
GateRef SExtInt32ToInt64(GateRef x);
GateRef SExtInt16ToInt64(GateRef x);
@ -465,6 +468,11 @@ public:
GateRef jsType);
GateRef TryStringOrSymbelToElementIndex(GateRef string);
inline GateRef DispatchBuiltins(GateRef glue, GateRef builtinsId, const std::initializer_list<GateRef>& args);
GateRef ComputeSizeUtf8(GateRef length);
GateRef ComputeSizeUtf16(GateRef length);
GateRef AlignUp(GateRef x, GateRef alignment);
inline void SetLength(GateRef glue, GateRef str, GateRef length, bool compressed);
inline void SetRawHashcode(GateRef glue, GateRef str, GateRef rawHashcode);
private:
using BinaryOperation = std::function<GateRef(Environment*, GateRef, GateRef)>;
template<OpCode::Op Op>

View File

@ -13,8 +13,9 @@
* limitations under the License.
*/
#include "ecmascript/compiler/circuit_optimizer.h"
#include <random>
#include "ecmascript/compiler/circuit_optimizer.h"
#include "ecmascript/compiler/verifier.h"
#include "ecmascript/tests/test_helper.h"
@ -27,6 +28,7 @@ using ecmascript::kungfu::OpCode;
using ecmascript::kungfu::GateType;
using ecmascript::kungfu::MachineType;
using ecmascript::kungfu::GateAccessor;
using ecmascript::kungfu::GateRef;
HWTEST_F_L0(CircuitOptimizerTests, TestLatticeEquationsSystemSolverFramework)
{
@ -168,7 +170,7 @@ HWTEST_F_L0(CircuitOptimizerTests, TestSubgraphRewriteFramework)
const uint64_t numOfUses = 10;
std::random_device randomDevice;
std::mt19937_64 rng(randomDevice());
std::multimap<uint64_t, ecmascript::kungfu::GateRef> constantsSet;
std::multimap<uint64_t, GateRef> constantsSet;
for (uint64_t iter = 0; iter < numOfUses; iter++) {
for (uint64_t idx = 0; idx < numOfConstants; idx++) {
constantsSet.insert(
@ -208,4 +210,237 @@ HWTEST_F_L0(CircuitOptimizerTests, TestSubgraphRewriteFramework)
EXPECT_TRUE(acc.GetOpCode(returnValue) == OpCode(OpCode::CONSTANT));
EXPECT_TRUE(acc.GetBitField(returnValue) == (numOfUses) * (numOfConstants) * (numOfConstants - 1) / 2);
}
HWTEST_F_L0(CircuitOptimizerTests, TestSmallSizeGlobalValueNumbering) {
// construct a circuit
Circuit circuit;
GateAccessor acc(&circuit);
auto constantA = circuit.NewGate(OpCode(OpCode::CONSTANT),
MachineType::I64,
1,
{Circuit::GetCircuitRoot(OpCode(OpCode::CONSTANT_LIST))},
GateType::NJSValue());
auto constantB = circuit.NewGate(OpCode(OpCode::CONSTANT),
MachineType::I64,
1,
{Circuit::GetCircuitRoot(OpCode(OpCode::CONSTANT_LIST))},
GateType::NJSValue());
auto argA = circuit.NewGate(OpCode(OpCode::ARG),
MachineType::I64,
1,
{Circuit::GetCircuitRoot(OpCode(OpCode::ARG_LIST))},
GateType::NJSValue());
auto argB = circuit.NewGate(OpCode(OpCode::ARG),
MachineType::I64,
2,
{Circuit::GetCircuitRoot(OpCode(OpCode::ARG_LIST))},
GateType::NJSValue());
auto add1 = circuit.NewGate(OpCode(OpCode::ADD),
MachineType::I64,
0,
{constantA, argA},
GateType::NJSValue());
auto add2 = circuit.NewGate(OpCode(OpCode::ADD),
MachineType::I64,
0,
{constantB, argA},
GateType::NJSValue());
auto add3 = circuit.NewGate(OpCode(OpCode::ADD),
MachineType::I64,
0,
{constantA, argB},
GateType::NJSValue());
ecmascript::kungfu::GlobalValueNumbering(&circuit).Run();
EXPECT_FALSE(acc.GetOpCode(add3).IsNop());
EXPECT_FALSE(acc.GetOpCode(argA).IsNop());
EXPECT_FALSE(acc.GetOpCode(argB).IsNop());
EXPECT_TRUE(acc.GetOpCode(constantA).IsNop() || acc.GetOpCode(constantB).IsNop());
EXPECT_FALSE(acc.GetOpCode(constantA).IsNop() && acc.GetOpCode(constantB).IsNop());
EXPECT_TRUE(acc.GetOpCode(add1).IsNop() || acc.GetOpCode(add2).IsNop());
EXPECT_FALSE(acc.GetOpCode(add1).IsNop() && acc.GetOpCode(add2).IsNop());
}
HWTEST_F_L0(CircuitOptimizerTests, TestMultiLevelGlobalValueNumbering) {
Circuit circuit;
GateAccessor acc(&circuit);
std::random_device randomDevice;
std::mt19937_64 rng(randomDevice());
std::vector<GateRef> args;
for (uint32_t i = 0; i < 5; ++i) {
args.push_back(circuit.NewGate(OpCode(OpCode::ARG),
MachineType::I64,
i,
{Circuit::GetCircuitRoot(OpCode(OpCode::ARG_LIST))},
GateType::NJSValue()));
}
std::map<GateRef, std::vector<GateRef>> addToAdds;
std::map<GateRef, GateRef> addToAdd;
std::map<std::pair<GateRef, GateRef>, GateRef> pairToAdd;
std::vector<GateRef> adds;
for (uint32_t i = 0; i < 50; ++i) {
std::pair<GateRef, GateRef> p(args[rng() % 5], args[rng() % 5]);
auto add = circuit.NewGate(OpCode(OpCode::ADD),
MachineType::I64,
0,
{p.first, p.second},
GateType::NJSValue());
adds.push_back(add);
if (pairToAdd.count(p) == 0) {
pairToAdd[p] = add;
addToAdds[add] = std::vector<GateRef>(0);
}
addToAdd[add] = pairToAdd[p];
addToAdds[addToAdd[add]].emplace_back(add);
}
std::map<GateRef, std::vector<GateRef>> subToSubs;
std::map<GateRef, GateRef> subToSub;
std::map<std::pair<GateRef, GateRef>, GateRef> pairToSub;
std::vector<GateRef> subs;
for (uint32_t i = 0; i < 50; ++i) {
std::pair<GateRef, GateRef> p(adds[rng() % 5], adds[rng() % 5]);
auto sub = circuit.NewGate(OpCode(OpCode::SUB),
MachineType::I64,
0,
{p.first, p.second},
GateType::NJSValue());
subs.push_back(sub);
// remove redundant adds.
std::pair<GateRef, GateRef> np(addToAdd[p.first], addToAdd[p.second]);
if (pairToSub.count(np) == 0) {
pairToSub[np] = sub;
subToSubs[sub] = std::vector<GateRef>(0);
}
subToSub[sub] = pairToSub[np];
subToSubs[subToSub[sub]].emplace_back(sub);
}
ecmascript::kungfu::GlobalValueNumbering(&circuit).Run();
std::map<GateRef, GateRef> gateToKing;
for (const auto &p : addToAdds) {
uint32_t cnt = 0;
GateRef kingGate;
for (auto gate : p.second) {
if (acc.GetOpCode(gate) != OpCode::NOP) {
cnt++;
kingGate = gate;
}
}
EXPECT_TRUE(cnt == 1);
for (auto gate : p.second) {
gateToKing[gate] = kingGate;
}
}
for (const auto &p : subToSubs) {
uint32_t cnt = 0;
GateRef kingGate;
for (auto gate : p.second) {
if (acc.GetOpCode(gate) != OpCode::NOP) {
cnt++;
kingGate = gate;
}
}
EXPECT_TRUE(cnt == 1);
for (auto gate : p.second) {
gateToKing[gate] = kingGate;
}
}
std::vector<GateRef> gates;
acc.GetAllGates(gates);
for (auto gate : gates) {
if (acc.GetOpCode(gate) == OpCode::NOP) {
continue;
}
std::vector<GateRef> ins;
for (auto in : ins) {
EXPECT_TRUE(in == gateToKing[in]);
}
}
}
HWTEST_F_L0(CircuitOptimizerTests, TestSmallWorldGlobalValueNumbering) {
Circuit circuit;
GateAccessor acc(&circuit);
std::random_device randomDevice;
std::mt19937_64 rng(randomDevice());
std::vector<GateRef> args;
for (uint32_t i = 0; i < 3; ++i) {
args.push_back(circuit.NewGate(OpCode(OpCode::ARG),
MachineType::I64,
i,
{Circuit::GetCircuitRoot(OpCode(OpCode::ARG_LIST))},
GateType::NJSValue()));
}
std::map<GateRef, std::vector<GateRef>> addToAdds;
std::map<GateRef, GateRef> addToAdd;
std::map<std::pair<GateRef, GateRef>, GateRef> pairToAdd;
std::vector<GateRef> adds;
std::vector<GateRef> toBeSelect;
for (uint32_t i = 0; i < 10; ++i) {
std::pair<GateRef, GateRef> p(args[rng() % 3], args[rng() % 3]);
auto add = circuit.NewGate(OpCode(OpCode::ADD),
MachineType::I64,
0,
{p.first, p.second},
GateType::NJSValue());
adds.emplace_back(add);
toBeSelect.emplace_back(add);
toBeSelect.emplace_back(add);
if (pairToAdd.count(p) == 0) {
pairToAdd[p] = add;
addToAdds[add] = std::vector<GateRef>(0);
}
addToAdd[add] = pairToAdd[p];
addToAdds[addToAdd[add]].emplace_back(add);
}
for (uint32_t i = 0; i < 1000; ++i) {
std::pair<GateRef, GateRef> p(toBeSelect[rng() % toBeSelect.size()], toBeSelect[rng() % toBeSelect.size()]);
auto add = circuit.NewGate(OpCode(OpCode::ADD),
MachineType::I64,
0,
{p.first, p.second},
GateType::NJSValue());
adds.emplace_back(add);
toBeSelect.emplace_back(add);
toBeSelect.emplace_back(add);
toBeSelect.emplace_back(p.first);
toBeSelect.emplace_back(p.second);
std::pair<GateRef, GateRef> np(addToAdd[p.first], addToAdd[p.second]);
if (pairToAdd.count(np) == 0) {
pairToAdd[np] = add;
addToAdds[add] = std::vector<GateRef>(0);
}
addToAdd[add] = pairToAdd[np];
addToAdds[addToAdd[add]].emplace_back(add);
}
ecmascript::kungfu::GlobalValueNumbering(&circuit).Run();
std::map<GateRef, GateRef> gateToKing;
for (const auto &p : addToAdds) {
uint32_t cnt = 0;
GateRef kingGate;
for (auto gate : p.second) {
if (acc.GetOpCode(gate) != OpCode::NOP) {
cnt++;
kingGate = gate;
}
}
EXPECT_TRUE(cnt == 1);
for (auto gate : p.second) {
gateToKing[gate] = kingGate;
}
}
std::vector<GateRef> gates;
acc.GetAllGates(gates);
for (auto gate : gates) {
if (acc.GetOpCode(gate) == OpCode::NOP) {
continue;
}
std::vector<GateRef> ins;
for (auto in : ins) {
EXPECT_TRUE(in == gateToKing[in]);
}
}
}
} // namespace panda::test

View File

@ -408,6 +408,7 @@ void OptimizedCall::JSCallInternal(ExtendedAssembler *assembler, Register jsfunc
__ Add(argV, sp, Immediate(DOUBLE_SLOT_SIZE));
// asm interpreter argV = argv + 24
__ Add(argV, argV, Immediate(kungfu::ArgumentAccessor::GetFixArgsNum() * FRAME_SLOT_SIZE));
__ Sub(actualArgC, actualArgC, Immediate(kungfu::ArgumentAccessor::GetFixArgsNum()));
OptimizedCallAsmInterpreter(assembler);
}

View File

@ -436,6 +436,7 @@ void OptimizedCall::JSProxyCallInternalWithArgV(ExtendedAssembler *assembler)
__ Jb(&lCallOptimziedMethod);
__ Movq(rsp, argV);
__ Addq(TRIPLE_SLOT_SIZE, argV); // sp + 24 get aot argv
__ Subq(Immediate(kungfu::ArgumentAccessor::GetFixArgsNum()), argc);
// argv + 24 get asm interpreter argv
__ Addq(kungfu::ArgumentAccessor::GetFixArgsNum() * FRAME_SLOT_SIZE, argV);
OptimizedCallAsmInterpreter(assembler);
@ -665,6 +666,7 @@ void OptimizedCall::JSCall(ExtendedAssembler *assembler)
__ Jb(&lCallOptimziedMethod);
__ Movq(rsp, argV);
__ Addq(TRIPLE_SLOT_SIZE, argV); // sp + 24 get aot argv
__ Subq(Immediate(kungfu::ArgumentAccessor::GetFixArgsNum()), argc);
// argv + 24 get asm interpreter argv
__ Addq(kungfu::ArgumentAccessor::GetFixArgsNum() * FRAME_SLOT_SIZE, argV);
OptimizedCallAsmInterpreter(assembler);

View File

@ -15,6 +15,7 @@
#include "ecmascript/compiler/type_inference/type_infer.h"
#include "ecmascript/jspandafile/js_pandafile_manager.h"
#include "ecmascript/jspandafile/program_object.h"
namespace panda::ecmascript::kungfu {
void TypeInfer::TraverseCircuit()
@ -369,9 +370,10 @@ bool TypeInfer::InferLdObjByName(GateRef gate)
auto objType = gateAccessor_.GetGateType(gateAccessor_.GetValueIn(gate, 1));
if (objType.IsTSType()) {
// If this object has no gt type, we cannot get its internal property type
if (IsObjectOrHClass(objType)) {
if (IsObjectOrClass(objType)) {
auto constantPool = builder_->GetConstantPool().GetObject<ConstantPool>();
auto index = gateAccessor_.GetBitField(gateAccessor_.GetValueIn(gate, 0));
auto name = tsManager_->GetStringById(index);
auto name = constantPool->GetObjectFromCache(index);
auto type = GetPropType(objType, name);
return UpdateType(gate, type);
}
@ -419,7 +421,7 @@ bool TypeInfer::InferLdObjByValue(GateRef gate)
return UpdateType(gate, elementType);
}
// handle object
if (IsObjectOrHClass(objType)) {
if (IsObjectOrClass(objType)) {
auto valueGate = gateAccessor_.GetValueIn(gate, 1);
if (gateAccessor_.GetOpCode(valueGate) == OpCode::CONSTANT) {
auto value = gateAccessor_.GetBitField(valueGate);
@ -512,9 +514,10 @@ void TypeInfer::TypeCheck(GateRef gate) const
return;
}
auto funcName = gateAccessor_.GetValueIn(func, 0);
if (tsManager_->GetStdStringById(gateAccessor_.GetBitField(funcName)) == "AssertType") {
auto constantPool = builder_->GetConstantPool().GetObject<ConstantPool>();
if (constantPool->GetStdStringByIdx(gateAccessor_.GetBitField(funcName)) == "AssertType") {
GateRef expectedGate = gateAccessor_.GetValueIn(gateAccessor_.GetValueIn(gate, 2), 0);
auto expectedTypeStr = tsManager_->GetStdStringById(gateAccessor_.GetBitField(expectedGate));
auto expectedTypeStr = constantPool->GetStdStringByIdx(gateAccessor_.GetBitField(expectedGate));
GateRef valueGate = gateAccessor_.GetValueIn(gate, 1);
auto type = gateAccessor_.GetGateType(valueGate);
if (expectedTypeStr != tsManager_->GetTypeStr(type)) {

View File

@ -74,7 +74,7 @@ private:
bool InferSuperCall(GateRef gate);
bool InferTryLdGlobalByName(GateRef gate);
inline GlobalTSTypeRef GetPropType(const GateType &type, const JSHandle<EcmaString> propertyName) const
inline GlobalTSTypeRef GetPropType(const GateType &type, const JSTaggedValue propertyName) const
{
return tsManager_->GetPropType(type, propertyName);
}
@ -84,7 +84,7 @@ private:
return tsManager_->GetPropType(type, key);
}
inline bool IsObjectOrHClass(const GateType &type) const
inline bool IsObjectOrClass(const GateType &type) const
{
auto flag = tsManager_->IsObjectTypeKind(type) ||
tsManager_->IsClassTypeKind(type) ||

View File

@ -28,7 +28,7 @@ void TypeLowering::RunTypeLowering()
}
if (IsLogEnabled()) {
LOG_COMPILER(INFO) << "================== type lowering print all gates ==================";
LOG_COMPILER(INFO) << "================== type lowering print all gates Start==================";
circuit_->PrintAllGates(*bcBuilder_);
}
}
@ -46,11 +46,80 @@ void TypeLowering::Lower(GateRef gate)
case EcmaBytecode::NEWOBJRANGE:
LowerTypeNewObjRange(gate, glue);
break;
case ADD2DYN_PREF_V8:
LowerTypeAdd2Dyn(gate, glue);
break;
default:
break;
}
}
void TypeLowering::RebuildSlowpathCfg(GateRef hir, std::map<GateRef, size_t> &stateGateMap)
{
acc_.ReplaceStateIn(hir, builder_.GetState());
acc_.ReplaceDependIn(hir, builder_.GetDepend());
auto uses = acc_.Uses(hir);
GateRef stateGate = Circuit::NullGate();
for (auto useIt = uses.begin(); useIt != uses.end(); ++useIt) {
const OpCode op = acc_.GetOpCode(*useIt);
if (op == OpCode::IF_SUCCESS) {
stateGate = *useIt;
builder_.SetState(*useIt);
break;
}
}
auto nextUses = acc_.Uses(stateGate);
for (auto it = nextUses.begin(); it != nextUses.end(); ++it) {
if (it.GetOpCode().IsState()) {
stateGateMap[*it] = it.GetIndex();
}
}
builder_.SetDepend(hir);
}
void TypeLowering::GenerateSuccessMerge(std::vector<GateRef> &successControl)
{
GateRef stateMerge = builder_.GetState();
GateRef dependSelect = builder_.GetDepend();
successControl.emplace_back(stateMerge);
successControl.emplace_back(dependSelect);
}
void TypeLowering::ReplaceHirToFastPathCfg(GateRef hir, GateRef outir, const std::vector<GateRef> &successControl)
{
auto uses = acc_.Uses(hir);
for (auto useIt = uses.begin(); useIt != uses.end();) {
const OpCode op = acc_.GetOpCode(*useIt);
if (op == OpCode::JS_BYTECODE && useIt.GetIndex() == 1) {
acc_.ReplaceStateIn(*useIt, successControl[0]);
useIt = acc_.ReplaceIn(useIt, successControl[1]);
} else if (op == OpCode::RETURN) {
if (acc_.GetOpCode(acc_.GetIn(*useIt, 0)) == OpCode::IF_SUCCESS) {
acc_.ReplaceStateIn(*useIt, successControl[0]);
acc_.ReplaceDependIn(*useIt, successControl[1]);
acc_.ReplaceValueIn(*useIt, outir);
}
++useIt;
} else if (op == OpCode::IF_SUCCESS || op == OpCode::IF_EXCEPTION) {
++useIt;
} else if (op == OpCode::VALUE_SELECTOR) {
if (*useIt != outir) {
useIt = acc_.ReplaceIn(useIt, outir);
} else {
++useIt;
}
} else if (op == OpCode::DEPEND_SELECTOR) {
if (*useIt != successControl[1]) {
useIt = acc_.ReplaceIn(useIt, successControl[1]);
} else {
++useIt;
}
} else {
useIt = acc_.ReplaceIn(useIt, outir);
}
}
}
void TypeLowering::ReplaceHirToCall(GateRef hirGate, GateRef callGate, bool noThrow)
{
GateRef stateInGate = acc_.GetState(hirGate);
@ -101,6 +170,129 @@ GateRef TypeLowering::LowerCallRuntime(GateRef glue, int index, const std::vecto
}
}
template<OpCode::Op Op>
GateRef TypeLowering::FastAddOrSubOrMul(GateRef left, GateRef right)
{
auto env = builder_.GetCurrentEnvironment();
Label entry(&builder_);
env->SubCfgEntry(&entry);
DEFVAlUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant());
DEFVAlUE(doubleLeft, (&builder_), VariableType::FLOAT64(), builder_.Double(0));
DEFVAlUE(doubleRight, (&builder_), VariableType::FLOAT64(), builder_.Double(0));
Label exit(&builder_);
Label doFloatOp(&builder_);
Label doIntOp(&builder_);
Label leftIsNumber(&builder_);
Label rightIsNumber(&builder_);
Label leftIsIntRightIsDouble(&builder_);
Label rightIsInt(&builder_);
Label rightIsDouble(&builder_);
builder_.Branch(builder_.TaggedIsNumber(left), &leftIsNumber, &exit);
builder_.Bind(&leftIsNumber);
{
builder_.Branch(builder_.TaggedIsNumber(right), &rightIsNumber, &exit);
builder_.Bind(&rightIsNumber);
{
Label leftIsInt(&builder_);
Label leftIsDouble(&builder_);
builder_.Branch(builder_.TaggedIsInt(left), &leftIsInt, &leftIsDouble);
builder_.Bind(&leftIsInt);
{
builder_.Branch(builder_.TaggedIsInt(right), &doIntOp, &leftIsIntRightIsDouble);
builder_.Bind(&leftIsIntRightIsDouble);
{
doubleLeft = ChangeInt32ToFloat64(builder_.TaggedCastToInt32(left));
doubleRight = builder_.TaggedCastToDouble(right);
builder_.Jump(&doFloatOp);
}
}
builder_.Bind(&leftIsDouble);
{
builder_.Branch(builder_.TaggedIsInt(right), &rightIsInt, &rightIsDouble);
builder_.Bind(&rightIsInt);
{
doubleLeft = builder_.TaggedCastToDouble(left);
doubleRight = ChangeInt32ToFloat64(builder_.TaggedCastToInt32(right));
builder_.Jump(&doFloatOp);
}
builder_.Bind(&rightIsDouble);
{
doubleLeft = builder_.TaggedCastToDouble(left);
doubleRight = builder_.TaggedCastToDouble(right);
builder_.Jump(&doFloatOp);
}
}
}
}
builder_.Bind(&doIntOp);
{
Label overflow(&builder_);
Label notOverflow(&builder_);
// handle left is int and right is int
GateRef res = BinaryOp<Op, MachineType::I64>(builder_.TaggedCastToInt64(left),
builder_.TaggedCastToInt64(right));
GateRef max = builder_.Int64(INT32_MAX);
GateRef min = builder_.Int64(INT32_MIN);
Label greaterZero(&builder_);
Label notGreaterZero(&builder_);
builder_.Branch(builder_.Int32GreaterThan(builder_.TaggedCastToInt32(left), builder_.Int32(0)),
&greaterZero, &notGreaterZero);
builder_.Bind(&greaterZero);
{
builder_.Branch(builder_.Int64GreaterThan(res, max), &overflow, &notOverflow);
}
builder_.Bind(&notGreaterZero);
{
Label lessZero(&builder_);
builder_.Branch(builder_.Int32LessThan(builder_.TaggedCastToInt32(left), builder_.Int32(0)),
&lessZero, &notOverflow);
builder_.Bind(&lessZero);
builder_.Branch(builder_.Int64LessThan(res, min), &overflow, &notOverflow);
}
builder_.Bind(&overflow);
{
GateRef newDoubleLeft = ChangeInt32ToFloat64(builder_.TaggedCastToInt32(left));
GateRef newDoubleRight = ChangeInt32ToFloat64(builder_.TaggedCastToInt32(right));
GateRef middleRet = BinaryOp<Op, MachineType::F64>(newDoubleLeft, newDoubleRight);
result = DoubleBuildTaggedWithNoGC(middleRet);
builder_.Jump(&exit);
}
builder_.Bind(&notOverflow);
{
result = builder_.TaggedNGC(res);
builder_.Jump(&exit);
}
}
builder_.Bind(&doFloatOp);
{
// Other situations
auto res = BinaryOp<Op, MachineType::F64>(*doubleLeft, *doubleRight);
result = DoubleBuildTaggedWithNoGC(res);
builder_.Jump(&exit);
}
builder_.Bind(&exit);
auto ret = *result;
env->SubCfgExit();
return ret;
}
template<OpCode::Op Op, MachineType Type>
GateRef TypeLowering::BinaryOp(GateRef x, GateRef y)
{
return builder_.BinaryArithmetic(OpCode(Op), Type, x, y);
}
GateRef TypeLowering::DoubleBuildTaggedWithNoGC(GateRef gate)
{
return builder_.DoubleToTaggedNGC(gate);
}
GateRef TypeLowering::ChangeInt32ToFloat64(GateRef gate)
{
return builder_.UnaryArithmetic(OpCode(OpCode::SIGNED_INT_TO_FLOAT), MachineType::F64, gate);
}
void TypeLowering::LowerTypeNewObjRange(GateRef gate, GateRef glue)
{
GateRef ctor = acc_.GetValueIn(gate, 0);
@ -130,4 +322,40 @@ void TypeLowering::LowerTypeNewObjRange(GateRef gate, GateRef glue)
GateRef newGate = LowerCallRuntime(glue, id, args);
ReplaceHirToCall(gate, newGate);
}
} // namespace panda::ecmascript
void TypeLowering::LowerTypeAdd2Dyn(GateRef gate, [[maybe_unused]]GateRef glue)
{
GateRef left = acc_.GetValueIn(gate, 0);
GateType leftType = acc_.GetGateType(left);
GateRef right = acc_.GetValueIn(gate, 1);
GateType rightType = acc_.GetGateType(right);
if (!leftType.IsTSType() || !rightType.IsTSType()) {
return;
}
if (!leftType.IsNumberType() || !rightType.IsNumberType()) {
return;
}
std::map<GateRef, size_t> stateGateMap;
DEFVAlUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant());
result = FastAddOrSubOrMul<OpCode::ADD>(left, right);
Label successExit(&builder_);
Label slowPath(&builder_);
builder_.Branch(builder_.IsSpecial(*result, JSTaggedValue::VALUE_HOLE),
&slowPath, &successExit);
builder_.Bind(&slowPath);
{
// slow path
result = gate;
RebuildSlowpathCfg(gate, stateGateMap);
builder_.Jump(&successExit);
}
builder_.Bind(&successExit);
for (auto [state, index] : stateGateMap) {
acc_.ReplaceIn(state, index, builder_.GetState());
}
std::vector<GateRef> successControl;
GenerateSuccessMerge(successControl);
ReplaceHirToFastPathCfg(gate, *result, successControl);
}
} // namespace panda::ecmascript

View File

@ -25,6 +25,80 @@
#include "ecmascript/ts_types/ts_manager.h"
namespace panda::ecmascript::kungfu {
// TypeLowering Process
// SW: state wire, DW: depend wire, VW: value wire
// Before Type Lowering:
// SW DW VW
// | | |
// | | |
// v v v
// +-------------------+
// | (HIR) | SW +--------------+
// --DW| JS_BYTECODE |---------->| IF_EXCEPTION |
// | +-------------------+ +--------------+
// | SW VW
// | | |
// | v |
// | +--------------+ |
// | | IF_SUCCESS | |
// | +--------------+ |
// | SW |
// | | |
// | v v
// | +-------------------+
// | | (HIR) |
// --->| JS_BYTECODE |
// +-------------------+
//
// After Type Lowering:
// SW
// |
// v
// +-------------------+
// | IF_BRANCH |
// | (Type Check) |
// +-------------------+
// SW SW
// | |
// V V
// +--------------+ +--------------+
// | IF_TRUE | | IF_FALSE |
// +--------------+ +--------------+
// VW DW SW SW DW VW
// | | | | | |
// | | V V | |
// | | +---------------+ +---------------------+ | |
// ------->| FAST PATH | | (HIR) |<-------
// +---------------+ | JS_BYTECODE |
// VW DW SW +---------------------+
// | | | SW VW DW
// | | | | | |
// | | | v | |
// | | | +--------------+ | |
// | | | | IF_SUCCESS | | |
// | | | +--------------+ | |
// | | | SW | |
// | | | | | |
// | | v v | |
// | | +---------------------+ | |
// | | | MERGE | | |
// | | +---------------------+ | |
// | | SW SW SW | |
// ----|----|----------|-----|-- | |
// ---|----|----------|-----|-|-------|----
// | | | | | | |
// v v v | v v v
// +-----------------+ | +----------------+
// | DEPEND_SELECTOR | | | VALUE_SELECTOR |
// +-----------------+ | +----------------+
// DW | VW
// | | |
// v v v
// +------------------------+
// | (HIR) |
// | JS_BYTECODE |
// +------------------------+
class TypeLowering {
public:
TypeLowering(BytecodeCircuitBuilder *bcBuilder, Circuit *circuit, CompilationConfig *cmpCfg, TSManager *tsManager,
@ -43,12 +117,21 @@ private:
}
void Lower(GateRef gate);
void GenerateSuccessMerge(std::vector<GateRef> &successControl);
void RebuildSlowpathCfg(GateRef hir, std::map<GateRef, size_t> &stateGateMap);
void ReplaceHirToCall(GateRef hirGate, GateRef callGate, bool noThrow = false);
void ReplaceHirToFastPathCfg(GateRef hir, GateRef outir, const std::vector<GateRef> &successControl);
GateRef LowerCallRuntime(GateRef glue, int index, const std::vector<GateRef> &args, bool useLabel = false);
template<OpCode::Op Op>
GateRef FastAddOrSubOrMul(GateRef left, GateRef right);
template<OpCode::Op Op, MachineType Type>
GateRef BinaryOp(GateRef x, GateRef y);
GateRef DoubleBuildTaggedWithNoGC(GateRef gate);
GateRef ChangeInt32ToFloat64(GateRef gate);
void LowerTypeNewObjRange(GateRef gate, GateRef glue);
void LowerTypeAdd2Dyn(GateRef gate, GateRef glue);
BytecodeCircuitBuilder *bcBuilder_;
Circuit *circuit_;

View File

@ -254,6 +254,8 @@ CString *HeapSnapshot::GenerateNodeName(TaggedObject *entry)
return GetString("Uri Error");
case JSType::JS_SYNTAX_ERROR:
return GetString("Syntax Error");
case JSType::JS_OOM_ERROR:
return GetString("OutOfMemory Error");
case JSType::JS_REG_EXP:
return GetString("Regexp");
case JSType::JS_SET:

View File

@ -26,6 +26,7 @@
namespace panda::ecmascript {
static const std::string LIB_UNWIND_SO_NAME = "libunwind.so";
static const std::string LIB_UNWIND_Z_SO_NAME = "libunwind.z.so";
static const int MAX_STACK_SIZE = 16;
static const int ALIGN_WIDTH = 2;
@ -37,8 +38,11 @@ void PrintBacktrace(uintptr_t value)
if (!unwBackTrace) {
void *handle = dlopen(LIB_UNWIND_SO_NAME.c_str(), RTLD_NOW);
if (handle == nullptr) {
LOG_ECMA(ERROR) << "dlopen libunwind.so failed";
return;
handle = dlopen(LIB_UNWIND_Z_SO_NAME.c_str(), RTLD_NOW);
if (handle == nullptr) {
LOG_ECMA(ERROR) << "dlopen libunwind.so failed";
return;
}
}
unwBackTrace = reinterpret_cast<UnwBackTraceFunc>(dlsym(handle, "unw_backtrace"));
if (unwBackTrace == nullptr) {

View File

@ -164,6 +164,8 @@ CString JSHClass::DumpJSType(JSType type)
return "Uri Error";
case JSType::JS_SYNTAX_ERROR:
return "Syntax Error";
case JSType::JS_OOM_ERROR:
return "OutOfMemory Error";
case JSType::JS_REG_EXP:
return "Regexp";
case JSType::JS_SET:
@ -560,6 +562,7 @@ static void DumpObject(TaggedObject *obj, std::ostream &os)
case JSType::JS_REFERENCE_ERROR:
case JSType::JS_URI_ERROR:
case JSType::JS_SYNTAX_ERROR:
case JSType::JS_OOM_ERROR:
case JSType::JS_ARGUMENTS:
JSObject::Cast(obj)->Dump(os);
break;
@ -1338,6 +1341,9 @@ void JSFunction::Dump(std::ostream &os) const
os << " - Module: ";
GetModule().Dump(os);
os << "\n";
os << " - Method: ";
GetMethod().Dump(os);
os << "\n";
JSObject::Dump(os);
}
@ -2135,6 +2141,8 @@ void GlobalEnv::Dump(std::ostream &os) const
GetSyntaxErrorFunction().GetTaggedValue().Dump(os);
os << " - EvalErrorFunction: ";
GetEvalErrorFunction().GetTaggedValue().Dump(os);
os << " - OOMErrorFunction: ";
GetOOMErrorFunction().GetTaggedValue().Dump(os);
os << " - RegExpFunction: ";
GetRegExpFunction().GetTaggedValue().Dump(os);
os << " - BuiltinsSetFunction: ";
@ -2301,6 +2309,8 @@ void GlobalEnv::Dump(std::ostream &os) const
GetPromiseReactionJob().GetTaggedValue().Dump(os);
os << " - PromiseResolveThenableJob: ";
GetPromiseResolveThenableJob().GetTaggedValue().Dump(os);
os << " - DynamicImportJob: ";
GetDynamicImportJob().GetTaggedValue().Dump(os);
os << " - ScriptJobString: ";
globalConst->GetScriptJobString().Dump(os);
os << " - PromiseString: ";
@ -3240,9 +3250,6 @@ void ResolvedBinding::Dump(std::ostream &os) const
void ModuleNamespace::Dump(std::ostream &os) const
{
os << " - Module: ";
GetModule().Dump(os);
os << "\n";
os << " - Exports: ";
GetExports().Dump(os);
os << "\n";
@ -3319,6 +3326,9 @@ void JSFunctionBase::Dump(std::ostream &os) const
void Method::Dump(std::ostream &os) const
{
os << " - MethodName: ";
os << GetMethodName();
os << "\n";
os << " - ConstantPool: ";
GetConstantPool().Dump(os);
os << "\n";
@ -3382,6 +3392,7 @@ static void DumpObject(TaggedObject *obj,
case JSType::JS_REFERENCE_ERROR:
case JSType::JS_URI_ERROR:
case JSType::JS_SYNTAX_ERROR:
case JSType::JS_OOM_ERROR:
case JSType::JS_ARGUMENTS:
case JSType::JS_GLOBAL_OBJECT:
JSObject::Cast(obj)->DumpForSnapshot(vec);
@ -4329,6 +4340,7 @@ void GlobalEnv::DumpForSnapshot(std::vector<std::pair<CString, JSTaggedValue>> &
vec.push_back(std::make_pair(CString("URIErrorFunction"), GetURIErrorFunction().GetTaggedValue()));
vec.push_back(std::make_pair(CString("SyntaxErrorFunction"), GetSyntaxErrorFunction().GetTaggedValue()));
vec.push_back(std::make_pair(CString("EvalErrorFunction"), GetEvalErrorFunction().GetTaggedValue()));
vec.push_back(std::make_pair(CString("OOMErrorFunction"), GetOOMErrorFunction().GetTaggedValue()));
vec.push_back(std::make_pair(CString("RegExpFunction"), GetRegExpFunction().GetTaggedValue()));
vec.push_back(std::make_pair(CString("BuiltinsSetFunction"), GetBuiltinsSetFunction().GetTaggedValue()));
vec.push_back(std::make_pair(CString("BuiltinsMapFunction"), GetBuiltinsMapFunction().GetTaggedValue()));
@ -4415,6 +4427,8 @@ void GlobalEnv::DumpForSnapshot(std::vector<std::pair<CString, JSTaggedValue>> &
vec.push_back(std::make_pair(CString("PromiseReactionJob"), GetPromiseReactionJob().GetTaggedValue()));
vec.push_back(
std::make_pair(CString("PromiseResolveThenableJob"), GetPromiseResolveThenableJob().GetTaggedValue()));
vec.push_back(
std::make_pair(CString("DynamicImportJob"), GetDynamicImportJob().GetTaggedValue()));
vec.push_back(std::make_pair(CString("ScriptJobString"), globalConst->GetScriptJobString()));
vec.push_back(std::make_pair(CString("PromiseString"), globalConst->GetPromiseString()));
vec.push_back(std::make_pair(CString("IdentityString"), globalConst->GetIdentityString()));

View File

@ -17,7 +17,7 @@
#define ECMASCRIPT_ECMA_GLOBAL_STORAGE_H
#include "ecmascript/mem/native_area_allocator.h"
#if ECMASCRIPT_ENABLE_HANDLE_LEAK_CHECK
#ifdef ECMASCRIPT_ENABLE_GLOBAL_LEAK_CHECK
#include "ecmascript/dfx/native_dfx/backtrace.h"
#endif
#include "ecmascript/mem/c_containers.h"
@ -138,7 +138,7 @@ public:
SetNext(next);
SetObject(value);
SetUsing(isUsing);
#if ECMASCRIPT_ENABLE_HANDLE_LEAK_CHECK
#ifdef ECMASCRIPT_ENABLE_GLOBAL_LEAK_CHECK
ResetMarkCount();
if (isUsing) {
IncGlobalNumber();
@ -147,14 +147,14 @@ public:
static const int GLOBAL_NUMBER_COUNT = 10000;
if (globalNumber_ > START_GLOBAL_NUMBER && globalNumber_ < START_GLOBAL_NUMBER + GLOBAL_NUMBER_COUNT
&& JSTaggedValue(value).IsHeapObject()) {
LOG_ECMA(ERROR) << "---------------Global Number:" << globalNumber_ << "-------------------";
LOG_ECMA(INFO) << "---------------Global Number:" << globalNumber_ << "-------------------";
PrintBacktrace(value);
}
}
#endif
}
#if ECMASCRIPT_ENABLE_HANDLE_LEAK_CHECK
#ifdef ECMASCRIPT_ENABLE_GLOBAL_LEAK_CHECK
int32_t GetMarkCount() const
{
return markCount_;
@ -189,7 +189,7 @@ public:
int32_t index_ {-1};
bool isUsing_ {false};
bool isWeak_ {false};
#if ECMASCRIPT_ENABLE_HANDLE_LEAK_CHECK
#ifdef ECMASCRIPT_ENABLE_GLOBAL_LEAK_CHECK
int32_t markCount_ {0};
// A number generated in the order of distribution.It Used to help locate global memory leaks.
int32_t globalNumber_ {0};

View File

@ -18,6 +18,11 @@
#include "ecmascript/js_tagged_value.h"
#include "ecmascript/js_thread.h"
#ifdef ECMASCRIPT_ENABLE_HANDLE_LEAK_CHECK
#include "ecmascript/dfx/native_dfx/backtrace.h"
#include "ecmascript/log_wrapper.h"
#include "ecmascript/mem/clock_scope.h"
#endif
namespace panda::ecmascript {
/*
@ -30,12 +35,20 @@ public:
thread_(thread), prevNext_(thread->handleScopeStorageNext_), prevEnd_(thread->handleScopeStorageEnd_),
prevHandleStorageIndex_(thread->currentHandleStorageIndex_)
{
thread->HandleScopeCountAdd();
#ifdef ECMASCRIPT_ENABLE_HANDLE_LEAK_CHECK
thread_->HandleScopeCountAdd();
prevHandleScope_ = thread->GetLastHandleScope();
thread_->SetLastHandleScope(this);
#endif
}
inline ~EcmaHandleScope()
{
#ifdef ECMASCRIPT_ENABLE_HANDLE_LEAK_CHECK
thread_->HandleScopeCountDec();
thread_->SetLastHandleScope(prevHandleScope_);
prevHandleScope_ = nullptr;
#endif
thread_->handleScopeStorageNext_ = prevNext_;
if (thread_->handleScopeStorageEnd_ != prevEnd_) {
thread_->handleScopeStorageEnd_ = prevEnd_;
@ -45,8 +58,21 @@ public:
static inline uintptr_t PUBLIC_API NewHandle(JSThread *thread, JSTaggedType value)
{
#ifdef ECMASCRIPT_ENABLE_HANDLE_LEAK_CHECK
// Each Handle must be managed by HandleScope, otherwise it may cause Handle leakage.
ASSERT(thread->handleScopeCount_ > 0);
if (thread->handleScopeCount_ <= 0) {
LOG_ECMA(ERROR) << "New handle must be in handlescope" << thread->handleScopeCount_;
}
static const long MAYBE_HANDLE_LEAK_TIME_MS = 5000;
if (thread->GetLastHandleScope() != nullptr) {
float totalSpentTime = thread->GetLastHandleScope()->scope_.TotalSpentTime();
if (totalSpentTime >= MAYBE_HANDLE_LEAK_TIME_MS) {
LOG_ECMA(INFO) << "New handle in scope count:" << thread->handleScopeCount_
<< ", time:" << totalSpentTime << "ms";
PrintBacktrace(value);
}
}
#endif
#if ECMASCRIPT_ENABLE_NEW_HANDLE_CHECK
thread->CheckJSTaggedType(value);
#endif
@ -69,7 +95,11 @@ private:
JSThread *thread_;
JSTaggedType *prevNext_;
JSTaggedType *prevEnd_;
int prevHandleStorageIndex_{-1};
int prevHandleStorageIndex_ {-1};
#ifdef ECMASCRIPT_ENABLE_HANDLE_LEAK_CHECK
ClockScope scope_;
EcmaHandleScope *prevHandleScope_ {nullptr};
#endif
NO_COPY_SEMANTIC(EcmaHandleScope);
NO_MOVE_SEMANTIC(EcmaHandleScope);

View File

@ -617,3 +617,7 @@ groups:
prefix: ecma
format: [pref_op_id_16_imm_16_v_8]
properties: [method_id]
- sig: ecma.dynamicimport v:in:top
acc: out:top
prefix: ecma
format: [pref_op_v_8]

View File

@ -349,6 +349,10 @@
#define THROW_TYPE_ERROR(thread, message) \
THROW_ERROR(thread, ErrorType::TYPE_ERROR, message)
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define THROW_OOM_ERROR(thread, message) \
THROW_ERROR(thread, ErrorType::OOM_ERROR, message)
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define RETURN_REJECT_PROMISE_IF_ABRUPT(thread, value, capability) \
do { \

View File

@ -54,6 +54,7 @@ public:
defaultMachineCodeSpaceSize_ = 2_MB;
semiSpaceTriggerConcurrentMark_ = 1_MB;
semiSpaceOvershootSize_ = 2_MB;
outOfMemoryOvershootSize_ = 2_MB;
minAllocLimitGrowingStep_ = 2_MB;
minGrowingStep_ = 4_MB;
maxStackSize_ = 128_KB;
@ -66,6 +67,7 @@ public:
defaultMachineCodeSpaceSize_ = 2_MB;
semiSpaceTriggerConcurrentMark_ = 1.5_MB;
semiSpaceOvershootSize_ = 2_MB;
outOfMemoryOvershootSize_ = 2_MB;
minAllocLimitGrowingStep_ = 4_MB;
minGrowingStep_ = 8_MB;
maxStackSize_ = 128_KB;
@ -78,6 +80,7 @@ public:
defaultMachineCodeSpaceSize_ = 8_MB;
semiSpaceTriggerConcurrentMark_ = 1.5_MB;
semiSpaceOvershootSize_ = 2_MB;
outOfMemoryOvershootSize_ = 2_MB;
minAllocLimitGrowingStep_ = 8_MB;
minGrowingStep_ = 16_MB;
maxStackSize_ = 128_KB;
@ -129,6 +132,11 @@ public:
return semiSpaceOvershootSize_;
}
size_t GetOutOfMemoryOvershootSize() const
{
return outOfMemoryOvershootSize_;
}
size_t GetMinAllocLimitGrowingStep() const
{
return minAllocLimitGrowingStep_;
@ -149,7 +157,7 @@ public:
return DEFAULT_STACK_SIZE;
}
static size_t GetDefalutReservedStackSize()
static size_t GetDefaultReservedStackSize()
{
return DEFAULT_RESERVED_STACK_SIZE;
}
@ -170,6 +178,7 @@ private:
size_t defaultMachineCodeSpaceSize_ {0};
size_t semiSpaceTriggerConcurrentMark_ {0};
size_t semiSpaceOvershootSize_ {0};
size_t outOfMemoryOvershootSize_ {0};
size_t minAllocLimitGrowingStep_ {0};
size_t minGrowingStep_ {0};
uint32_t maxStackSize_ {0};

View File

@ -16,7 +16,7 @@
#include "ecmascript/ecma_vm.h"
#include "ecmascript/base/string_helper.h"
#include "ecmascript/builtins.h"
#include "ecmascript/builtins/builtins.h"
#include "ecmascript/builtins/builtins_collator.h"
#include "ecmascript/builtins/builtins_date_time_format.h"
#include "ecmascript/builtins/builtins_global.h"
@ -49,6 +49,7 @@
#include "ecmascript/jspandafile/constpool_value.h"
#include "ecmascript/jspandafile/js_pandafile.h"
#include "ecmascript/jspandafile/js_pandafile_manager.h"
#include "ecmascript/jspandafile/js_patch_manager.h"
#include "ecmascript/jspandafile/module_data_extractor.h"
#include "ecmascript/jspandafile/panda_file_translator.h"
#include "ecmascript/jspandafile/program_object.h"
@ -209,6 +210,7 @@ bool EcmaVM::Initialize()
debuggerManager_->Initialize(this);
tsManager_ = new TSManager(this);
tsManager_->Initialize();
patchManager_ = new JSPatchManager();
snapshotEnv_ = new SnapshotEnv(this);
if (!WIN_OR_MAC_PLATFORM) {
snapshotEnv_->Initialize();
@ -336,6 +338,11 @@ EcmaVM::~EcmaVM()
tsManager_ = nullptr;
}
if (patchManager_ != nullptr) {
delete patchManager_;
patchManager_ = nullptr;
}
if (snapshotEnv_ != nullptr) {
delete snapshotEnv_;
snapshotEnv_ = nullptr;
@ -735,7 +742,7 @@ void EcmaVM::LoadStubFile()
void EcmaVM::LoadAOTFiles()
{
std::string file = options_.GetAOTOutputFile() + ".aot";
std::string file = options_.GetAOTOutputFile() + ".an";
LOG_ECMA(INFO) << "Try to load aot file" << file.c_str();
fileLoader_->LoadAOTFile(file);
fileLoader_->LoadSnapshotFile();
@ -793,7 +800,7 @@ void EcmaVM::GenerateInternalNativeMethods()
size_t length = static_cast<size_t>(MethodIndex::METHOD_END);
for (size_t i = 0; i < length; i++) {
uint32_t numArgs = 2; // function object and this
auto method = factory_->NewJSMethod(nullptr);
auto method = factory_->NewMethod(nullptr);
method->SetNativePointer(InternalMethodTable[i]);
method->SetNativeBit(true);
method->SetNumArgsWithCallField(numArgs);

View File

@ -77,6 +77,7 @@ class CjsModuleCache;
class SlowRuntimeStub;
class RequireManager;
struct CJSInfo;
class JSPatchManager;
enum class MethodIndex : uint8_t {
BUILTINS_GLOBAL_CALL_JS_BOUND_FUNCTION = 0,
@ -114,6 +115,7 @@ using PromiseRejectCallback = void (*)(void* info);
using NativePtrGetter = void* (*)(void* info);
using ResolvePathCallback = std::function<std::string(std::string dirPath, std::string requestPath)>;
using ResolveBufferCallback = std::function<std::vector<uint8_t>(std::string dirPath, std::string requestPath)>;
class EcmaVM {
public:
@ -364,6 +366,16 @@ public:
return resolvePathCallback_;
}
void SetResolveBufferCallback(ResolveBufferCallback cb)
{
resolveBufferCallback_ = cb;
}
ResolveBufferCallback GetResolveBufferCallback() const
{
return resolveBufferCallback_;
}
void AddConstpool(const JSPandaFile *jsPandaFile, JSTaggedValue constpool, int32_t index, int32_t total = 0);
JSTaggedValue FindConstpool(const JSPandaFile *jsPandaFile, int32_t index);
@ -407,6 +419,11 @@ public:
// For Internal Native MethodLiteral.
JSTaggedValue GetMethodByIndex(MethodIndex idx);
JSPatchManager *GetPatchManager() const
{
return patchManager_;
}
protected:
void HandleUncaughtException(TaggedObject *exception);
@ -507,6 +524,7 @@ private:
// CJS resolve path Callbacks
ResolvePathCallback resolvePathCallback_ {nullptr};
ResolveBufferCallback resolveBufferCallback_ {nullptr};
// vm parameter configurations
EcmaParamConfiguration ecmaParamConfiguration_;
@ -518,6 +536,9 @@ private:
static void *InternalMethodTable[static_cast<uint8_t>(MethodIndex::METHOD_END)];
CVector<JSTaggedValue> internalNativeMethods_;
// For repair patch.
JSPatchManager *patchManager_;
friend class Snapshot;
friend class SnapshotProcessor;
friend class ObjectFactory;

View File

@ -34,8 +34,8 @@
#include "ecmascript/mem/region.h"
#include "ecmascript/base/mem_mmap.h"
extern const uint8_t _binary_stub_aot_start[];
extern const uint32_t _binary_stub_aot_length;
extern const uint8_t _binary_stub_an_start[];
extern const uint32_t _binary_stub_an_length;
namespace panda::ecmascript {
void ModuleSectionDes::SaveSectionsInfo(std::ofstream &file)
@ -164,11 +164,11 @@ bool StubModulePackInfo::Load(EcmaVM *vm)
// by calling NewMachineCodeObject.
// then MachineCode will support movable, code is saved to MachineCode and stackmap is saved
// to different heap which will be freed when stackmap is parsed by EcmaVM is started.
if (_binary_stub_aot_length <= 1) {
LOG_FULL(FATAL) << "stub.aot length <= 1, is default and invalid.";
if (_binary_stub_an_length <= 1) {
LOG_FULL(FATAL) << "stub.an length <= 1, is default and invalid.";
return false;
}
BinaryBufferParser binBufparser((uint8_t *)_binary_stub_aot_start, _binary_stub_aot_length);
BinaryBufferParser binBufparser((uint8_t *)_binary_stub_an_start, _binary_stub_an_length);
binBufparser.ParseBuffer(&entryNum_, sizeof(entryNum_));
entries_.resize(entryNum_);
binBufparser.ParseBuffer(entries_.data(), sizeof(FuncEntryDes) * entryNum_);
@ -315,7 +315,7 @@ void FileLoader::LoadSnapshotFile()
CString snapshotPath = snapshotArg + ".etso";
Snapshot snapshot(vm_);
#if !defined(PANDA_TARGET_WINDOWS) && !defined(PANDA_TARGET_MACOS)
snapshot.Deserialize(SnapshotType::TS_LOADER, snapshotPath);
snapshot.Deserialize(SnapshotType::ETSO, snapshotPath);
#endif
}
@ -331,7 +331,7 @@ void FileLoader::UpdateJSMethods(JSHandle<JSFunction> mainFunc, const JSPandaFil
auto mainFuncMethodId = jsPandaFile->GetMainMethodIndex();
auto fileHash = jsPandaFile->GetFileUniqId();
auto mainEntry = GetAOTFuncEntry(fileHash, mainFuncMethodId);
MethodLiteral *mainMethod = jsPandaFile->FindMethods(mainFuncMethodId);
MethodLiteral *mainMethod = jsPandaFile->FindMethodLiteral(mainFuncMethodId);
mainMethod->SetAotCodeBit(true);
mainMethod->SetNativeBit(false);
mainFunc->SetCodeEntry(reinterpret_cast<uintptr_t>(mainEntry));
@ -462,6 +462,30 @@ FileLoader::FileLoader(EcmaVM *vm) : vm_(vm), factory_(vm->GetFactory())
arkStackMapParser_ = new kungfu::ArkStackMapParser(enableLog);
}
JSTaggedValue FileLoader::GetAbsolutePath(JSThread *thread, JSTaggedValue relativePathVal)
{
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
CString relativePath = ConvertToString(relativePathVal);
CString absPath;
if (!GetAbsolutePath(relativePath, absPath)) {
LOG_FULL(FATAL) << "Get Absolute Path failed";
return JSTaggedValue::Hole();
}
JSTaggedValue absPathVal = factory->NewFromUtf8(absPath).GetTaggedValue();
return absPathVal;
}
bool FileLoader::GetAbsolutePath(const CString &relativePathCstr, CString &absPathCstr)
{
std::string relativePath = CstringConvertToStdString(relativePathCstr);
std::string absPath = "";
if (GetAbsolutePath(relativePath, absPath)) {
absPathCstr = ConvertToString(absPath);
return true;
}
return false;
}
bool FileLoader::GetAbsolutePath(const std::string &relativePath, std::string &absPath)
{
if (relativePath.size() >= PATH_MAX) {

View File

@ -425,7 +425,10 @@ public:
void SetAOTFuncEntryForLiteral(const JSPandaFile *jsPandaFile, const JSHandle<TaggedArray> &obj);
void LoadSnapshotFile();
kungfu::ArkStackMapParser* GetStackMapParser() const;
static JSTaggedValue GetAbsolutePath(JSThread *thread, JSTaggedValue relativePathVal);
static bool GetAbsolutePath(const std::string &relativePath, std::string &absPath);
static bool GetAbsolutePath(const CString &relativePathCstr, CString &absPathCstr);
bool RewriteDataSection(uintptr_t dataSec, size_t size, uintptr_t newData, size_t newSize);
void RuntimeRelocate();
private:

View File

@ -20,7 +20,7 @@
#include "ecmascript/mem/barriers.h"
#include "ecmascript/mem/tagged_object-inl.h"
#define INVALID_OBJECT ((FreeObject *)NULL_POINTER)
#define INVALID_OBJECT ((FreeObject *) JSTaggedValue::NULL_POINTER)
namespace panda::ecmascript {
class FreeObject : public TaggedObject {

View File

@ -65,6 +65,7 @@ class JSThread;
V(JSTaggedValue, URIErrorFunction, URI_ERROR_FUNCTION_INDEX) \
V(JSTaggedValue, SyntaxErrorFunction, SYNTAX_ERROR_FUNCTION_INDEX) \
V(JSTaggedValue, EvalErrorFunction, EVAL_ERROR_FUNCTION_INDEX) \
V(JSTaggedValue, OOMErrorFunction, OOM_ERROR_FUNCTION_INDEX) \
V(JSTaggedValue, IntlFunction, INTL_FUNCTION_INDEX) \
V(JSTaggedValue, LocaleFunction, LOCALE_FUNCTION_INDEX) \
V(JSTaggedValue, DateTimeFormatFunction, DATE_TIME_FORMAT_FUNCTION_INDEX) \
@ -129,6 +130,7 @@ class JSThread;
V(JSTaggedValue, PromiseFunction, PROMISE_FUNCTION_INDEX) \
V(JSTaggedValue, PromiseReactionJob, PROMISE_REACTION_JOB_INDEX) \
V(JSTaggedValue, PromiseResolveThenableJob, PROMISE_REACTION_THENABLE_JOB_INDEX) \
V(JSTaggedValue, DynamicImportJob, DYNAMIC_IMPORT_JOB_INDEX) \
V(JSTaggedValue, TemplateMap, TEMPLATE_MAP_INDEX) \
V(JSTaggedValue, FunctionClassWithProto, FUNCTION_CLASS_WITH_PROTO) \
V(JSTaggedValue, FunctionClassWithoutProto, FUNCTION_CLASS_WITHOUT_PROTO) \

View File

@ -16,7 +16,7 @@
#include "ecmascript/global_env_constants.h"
#include "ecmascript/accessor_data.h"
#include "ecmascript/builtins.h"
#include "ecmascript/builtins/builtins.h"
#include "ecmascript/builtins/builtins_global.h"
#include "ecmascript/ecma_vm.h"
#include "ecmascript/free_object.h"
@ -155,7 +155,7 @@ void GlobalEnvConstants::InitRootsClass([[maybe_unused]] JSThread *thread, JSHCl
SetConstant(
ConstantIndex::INDIRECT_EXPORT_ENTRY_CLASS_INDEX,
factory->NewEcmaReadOnlyHClass(hClass, IndirectExportEntry::SIZE,
JSType::INDIRECT_EXPORTENTRY_RECORD));
JSType::INDIRECT_EXPORTENTRY_RECORD));
SetConstant(
ConstantIndex::STAR_EXPORT_ENTRY_CLASS_INDEX,
factory->NewEcmaReadOnlyHClass(hClass, StarExportEntry::SIZE, JSType::STAR_EXPORTENTRY_RECORD));
@ -362,6 +362,7 @@ void GlobalEnvConstants::InitGlobalConstant(JSThread *thread)
SetConstant(ConstantIndex::URI_ERROR_STRING_INDEX, factory->NewFromASCIINonMovable("URIError"));
SetConstant(ConstantIndex::SYNTAX_ERROR_STRING_INDEX, factory->NewFromASCIINonMovable("SyntaxError"));
SetConstant(ConstantIndex::EVAL_ERROR_STRING_INDEX, factory->NewFromASCIINonMovable("EvalError"));
SetConstant(ConstantIndex::OOM_ERROR_STRING_INDEX, factory->NewFromASCIINonMovable("OutOfMemoryError"));
SetConstant(ConstantIndex::ERROR_FUNC_STRING_INDEX, factory->NewFromASCIINonMovable("errorfunc"));
SetConstant(ConstantIndex::STACK_STRING_INDEX, factory->NewFromASCIINonMovable("stack"));
SetConstant(ConstantIndex::STACK_EMPTY_STRING_INDEX, factory->NewFromASCIINonMovable("stackisempty"));

View File

@ -105,7 +105,7 @@ class JSThread;
V(JSTaggedValue, CellRecordClass, CELL_RECORD_CLASS_INDEX, ecma_roots_class) \
V(JSTaggedValue, ObjectClass, OBJECT_HCLASS_INDEX, initial_object_hclass) \
V(JSTaggedValue, IteratorResultClass, ITERATOR_RESULT_CLASS, ecma_roots_class) \
V(JSTaggedValue, JSMethodClass, JS_METHOD_CLASS_INDEX, ecma_roots_class)
V(JSTaggedValue, MethodClass, JS_METHOD_CLASS_INDEX, ecma_roots_class)
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define GLOBAL_ENV_CONSTANT_SPECIAL(V) \
@ -225,6 +225,7 @@ class JSThread;
V(JSTaggedValue, URIErrorString, URI_ERROR_STRING_INDEX, URIError) \
V(JSTaggedValue, SyntaxErrorString, SYNTAX_ERROR_STRING_INDEX, SyntaxError) \
V(JSTaggedValue, EvalErrorString, EVAL_ERROR_STRING_INDEX, EvalError) \
V(JSTaggedValue, OOMErrorString, OOM_ERROR_STRING_INDEX, OOMError) \
V(JSTaggedValue, ErrorFuncString, ERROR_FUNC_STRING_INDEX, errorfunc) \
V(JSTaggedValue, StackString, STACK_STRING_INDEX, stack) \
V(JSTaggedValue, StackEmptyString, STACK_EMPTY_STRING_INDEX, stackisempty) \

View File

@ -137,7 +137,7 @@ void ICRuntime::TraceIC([[maybe_unused]] JSHandle<JSTaggedValue> receiver,
JSTaggedValue LoadICRuntime::LoadMiss(JSHandle<JSTaggedValue> receiver, JSHandle<JSTaggedValue> key)
{
if (receiver->IsTypedArray() || !receiver->IsJSObject() || receiver->IsSpecialContainer()) {
if (!receiver->IsJSObject() || receiver->HasOrdinaryGet()) {
icAccessor_.SetAsMega();
return JSTaggedValue::GetProperty(thread_, receiver, key).GetValue().GetTaggedValue();
}
@ -179,7 +179,7 @@ JSTaggedValue LoadICRuntime::LoadMiss(JSHandle<JSTaggedValue> receiver, JSHandle
JSTaggedValue StoreICRuntime::StoreMiss(JSHandle<JSTaggedValue> receiver, JSHandle<JSTaggedValue> key,
JSHandle<JSTaggedValue> value)
{
if (receiver->IsTypedArray() || !receiver->IsJSObject() || receiver->IsSpecialContainer()) {
if (!receiver->IsJSObject() || receiver->HasOrdinaryGet()) {
icAccessor_.SetAsMega();
bool success = JSTaggedValue::SetProperty(GetThread(), receiver, key, value, true);
return success ? JSTaggedValue::Undefined() : JSTaggedValue::Exception();

View File

@ -453,6 +453,7 @@ void FrameBcCollector::CollectBCOffsetInfo()
case FrameType::BUILTIN_CALL_LEAVE_FRAME:
case FrameType::LEAVE_FRAME:
case FrameType::OPTIMIZED_ENTRY_FRAME:
case FrameType::ASM_INTERPRETER_BRIDGE_FRAME:
case FrameType::ASM_INTERPRETER_ENTRY_FRAME:
case FrameType::ASM_INTERPRETER_FRAME:
case FrameType::INTERPRETER_CONSTRUCTOR_FRAME:

View File

@ -6539,6 +6539,18 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, const uint8_t
LOG_FULL(FATAL) << "not implement";
DISPATCH(STPATCHVAR_IMM8_V8);
}
HANDLE_OPCODE(DYNAMICIMPORT_V8) {
uint16_t v0 = READ_INST_8_0();
LOG_INST() << "intrinsics::dynamicimport"
<< " v" << v0;
JSTaggedValue specifier = GET_VREG_VALUE(v0);
SAVE_PC();
JSTaggedValue res = SlowRuntimeStub::DynamicImport(thread, specifier);
INTERPRETER_RETURN_IF_ABRUPT(res);
SET_ACC(res);
DISPATCH(DYNAMICIMPORT_V8);
}
#include "templates/debugger_instruction_handler.inl"
}
@ -6831,6 +6843,7 @@ std::string GetEcmaOpcodeStr(EcmaOpcode opcode)
{EcmaOpcode::STTHISBYVALUE_IMM16_V8, "STTHISBYVALUE_IMM16_V8"},
{EcmaOpcode::LDPATCHVAR_IMM8, "LDPATCHVAR_IMM8"},
{EcmaOpcode::STPATCHVAR_IMM8_V8, "STPATCHVAR_IMM8_V8"},
{EcmaOpcode::DYNAMICIMPORT_V8, "DYNAMICIMPORT_V8"},
{EcmaOpcode::DEFINECLASSWITHBUFFER_IMM8_ID16_ID16_IMM16_V8, "DEFINECLASSWITHBUFFER_IMM8_ID16_ID16_IMM16_V8"},
{EcmaOpcode::DEFINECLASSWITHBUFFER_IMM16_ID16_ID16_IMM16_V8, "DEFINECLASSWITHBUFFER_IMM16_ID16_ID16_IMM16_V8"},
{EcmaOpcode::RESUMEGENERATOR, "RESUMEGENERATOR"},

View File

@ -3825,6 +3825,33 @@ void InterpreterAssembly::HandleDeprecatedDefineclasswithbufferPrefId16Imm16Imm1
JSThread *thread, const uint8_t *pc, JSTaggedType *sp, JSTaggedValue constpool, JSTaggedValue profileTypeInfo,
JSTaggedValue acc, int16_t hotnessCounter)
{
uint16_t methodId = READ_INST_16_1();
uint16_t length = READ_INST_16_5();
uint16_t v0 = READ_INST_8_7();
uint16_t v1 = READ_INST_8_8();
LOG_INST() << "intrinsics::defineclasswithbuffer"
<< " method id:" << methodId << " lexenv: v" << v0 << " parent: v" << v1;
JSTaggedValue lexenv = GET_VREG_VALUE(v0);
JSTaggedValue proto = GET_VREG_VALUE(v1);
SAVE_PC();
JSTaggedValue res = SlowRuntimeStub::CreateClassWithBuffer(thread, proto, lexenv, constpool, methodId);
INTERPRETER_RETURN_IF_ABRUPT(res);
ASSERT(res.IsClassConstructor());
JSFunction *cls = JSFunction::Cast(res.GetTaggedObject());
lexenv = GET_VREG_VALUE(v0); // slow runtime may gc
cls->SetLexicalEnv(thread, lexenv);
JSFunction *currentFunc = JSFunction::Cast((GET_ASM_FRAME(sp)->function).GetTaggedObject());
cls->SetModule(thread, currentFunc->GetModule());
SlowRuntimeStub::SetClassConstructorLength(thread, res, JSTaggedValue(length));
SET_ACC(res);
DISPATCH(DEPRECATED_DEFINECLASSWITHBUFFER_PREF_ID16_IMM16_IMM16_V8_V8);
}
void InterpreterAssembly::HandleDeprecatedDefinemethodPrefId16Imm16V8(
JSThread *thread, const uint8_t *pc, JSTaggedType *sp, JSTaggedValue constpool, JSTaggedValue profileTypeInfo,
@ -4289,6 +4316,20 @@ void InterpreterAssembly::HandleCallrangeImm8Imm8V8(
JSTaggedValue acc, int16_t hotnessCounter)
{
}
void InterpreterAssembly::HandleDynamicimportV8(
JSThread *thread, const uint8_t *pc, JSTaggedType *sp, JSTaggedValue constpool, JSTaggedValue profileTypeInfo,
JSTaggedValue acc, int16_t hotnessCounter)
{
uint16_t v0 = READ_INST_8_0();
LOG_INST() << "intrinsics::dynamicimport"
<< " v" << v0;
JSTaggedValue specifier = GET_VREG_VALUE(v0);
JSTaggedValue res = SlowRuntimeStub::DynamicImport(thread, specifier);
INTERPRETER_RETURN_IF_ABRUPT(res);
SET_ACC(res);
DISPATCH(DYNAMICIMPORT_V8);
}
void InterpreterAssembly::HandleCallargs3Imm8V8V8V8(
JSThread *thread, const uint8_t *pc, JSTaggedType *sp, JSTaggedValue constpool, JSTaggedValue profileTypeInfo,
JSTaggedValue acc, int16_t hotnessCounter)

View File

@ -22,6 +22,7 @@
#include "ecmascript/interpreter/frame_handler.h"
#include "ecmascript/interpreter/interpreter-inl.h"
#include "ecmascript/interpreter/slow_runtime_helper.h"
#include "ecmascript/jobs/micro_job_queue.h"
#include "ecmascript/jspandafile/program_object.h"
#include "ecmascript/jspandafile/scope_info_extractor.h"
#include "ecmascript/js_arguments.h"
@ -1033,6 +1034,61 @@ JSTaggedValue SlowRuntimeStub::SuperCall(JSThread *thread, JSTaggedValue func, J
return RuntimeStubs::RuntimeSuperCall(thread, funcHandle, newTargetHandle, firstVRegIdx, length);
}
// specifier = "./test.js"
JSTaggedValue SlowRuntimeStub::DynamicImport(JSThread *thread, JSTaggedValue specifier)
{
INTERPRETER_TRACE(thread, DynamicImport);
[[maybe_unused]] EcmaHandleScope handleScope(thread);
EcmaVM *ecmaVm = thread->GetEcmaVM();
JSHandle<GlobalEnv> env = ecmaVm->GetGlobalEnv();
ObjectFactory *factory = ecmaVm->GetFactory();
// 5. Let specifierString be Completion(ToString(specifier))
JSHandle<EcmaString> specifierString = JSTaggedValue::ToString(thread, specifier);
// get current filename
std::string filename;
JSTaggedType *sp = const_cast<JSTaggedType *>(thread->GetCurrentInterpretedFrame());
if (thread->IsAsmInterpreter()) {
AsmInterpretedFrame *state = (reinterpret_cast<AsmInterpretedFrame *>(sp) - 1);
Method *method = ECMAObject::Cast(state->function.GetTaggedObject())->GetCallTarget();
filename = method->GetJSPandaFile()->GetPandaFile()->GetFilename();
} else {
InterpretedFrame *state = (reinterpret_cast<InterpretedFrame *>(sp) - 1);
Method *method = JSFunction::Cast(state->function.GetTaggedObject())->GetCallTarget();
filename = method->GetJSPandaFile()->GetPandaFile()->GetFilename();
}
// parse dirPath from filename
CString fullName = CString(filename);
int foundPos = static_cast<int>(fullName.find_last_of("/\\"));
if (foundPos == -1) {
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Hole());
}
CString dirPathStr = fullName.substr(0, foundPos + 1);
JSHandle<EcmaString> dirPath = factory->NewFromUtf8(dirPathStr);
// 4. Let promiseCapability be !NewPromiseCapability(%Promise%).
JSHandle<JSTaggedValue> promiseFunc = env->GetPromiseFunction();
JSHandle<PromiseCapability> promiseCapability = JSPromise::NewPromiseCapability(thread, promiseFunc);
// 6. IfAbruptRejectPromise(specifierString, promiseCapability).
RETURN_REJECT_PROMISE_IF_ABRUPT(thread, specifierString, promiseCapability);
JSHandle<JSTaggedValue> currentModule(thread, thread->GetEcmaVM()->GetModuleManager()->GetCurrentModule());
JSHandle<job::MicroJobQueue> job = ecmaVm->GetMicroJobQueue();
JSHandle<TaggedArray> argv = factory->NewTaggedArray(4); // 4: 4 means two args stored in array
argv->Set(thread, 0, promiseCapability->GetResolve());
argv->Set(thread, 1, promiseCapability->GetReject()); // 1 : first argument
argv->Set(thread, 2, dirPath); // 2: second argument
argv->Set(thread, 3, specifierString); // 3 : third argument
JSHandle<JSFunction> dynamicImportJob(env->GetDynamicImportJob());
job::MicroJobQueue::EnqueueJob(thread, job, job::QueueType::QUEUE_PROMISE, dynamicImportJob, argv);
return promiseCapability->GetPromise();
}
JSTaggedValue SlowRuntimeStub::SuperCallSpread(JSThread *thread, JSTaggedValue func, JSTaggedValue newTarget,
JSTaggedValue array)
{
@ -1126,6 +1182,19 @@ JSTaggedValue SlowRuntimeStub::CloneClassFromTemplate(JSThread *thread, JSTagged
return RuntimeStubs::RuntimeCloneClassFromTemplate(thread, cls, baseHandle, lexenvHandle);
}
// clone class may need re-set inheritance relationship due to extends may be a variable.
JSTaggedValue SlowRuntimeStub::CreateClassWithBuffer(JSThread *thread, JSTaggedValue base,
JSTaggedValue lexenv, JSTaggedValue constpool,
const uint16_t methodId)
{
[[maybe_unused]] EcmaHandleScope handleScope(thread);
JSHandle<JSTaggedValue> baseHandle(thread, base);
JSHandle<JSTaggedValue> lexenvHandle(thread, lexenv);
JSHandle<JSTaggedValue> constpoolHandle(thread, constpool);
return RuntimeStubs::RuntimeCreateClassWithBuffer(thread, baseHandle, lexenvHandle, constpoolHandle, methodId);
}
JSTaggedValue SlowRuntimeStub::SetClassInheritanceRelationship(JSThread *thread, JSTaggedValue ctor, JSTaggedValue base)
{
[[maybe_unused]] EcmaHandleScope handleScope(thread);

View File

@ -151,6 +151,7 @@ public:
uint16_t length);
static JSTaggedValue SuperCallSpread(JSThread *thread, JSTaggedValue func, JSTaggedValue newTarget,
JSTaggedValue array);
static JSTaggedValue DynamicImport(JSThread *thread, JSTaggedValue specifier);
static JSTaggedValue DefineMethod(JSThread *thread, JSFunction *func, JSTaggedValue homeObject);
static JSTaggedValue LdSuperByValue(JSThread *thread, JSTaggedValue obj, JSTaggedValue key, JSTaggedValue thisFunc);
static JSTaggedValue StSuperByValue(JSThread *thread, JSTaggedValue obj, JSTaggedValue key, JSTaggedValue value,
@ -162,10 +163,14 @@ public:
JSTaggedValue lexenv);
static JSTaggedValue CloneClassFromTemplate(JSThread *thread, JSTaggedValue ctor, JSTaggedValue base,
JSTaggedValue lexenv);
static JSTaggedValue CreateClassWithBuffer(JSThread *thread, JSTaggedValue base,
JSTaggedValue lexenv, JSTaggedValue constpool,
const uint16_t methodId);
static JSTaggedValue SetClassConstructorLength(JSThread *thread, JSTaggedValue ctor, JSTaggedValue length);
static JSTaggedValue GetModuleNamespace(JSThread *thread, JSTaggedValue localName);
static JSTaggedValue LdBigInt(JSThread *thread, JSTaggedValue numberBigInt);
static JSTaggedValue ThrowTypeError(JSThread *thread, const char *message);
static JSTaggedValue SetClassInheritanceRelationship(JSThread *thread, JSTaggedValue ctor, JSTaggedValue base);
static JSTaggedValue AsyncGeneratorResolve(JSThread *thread, JSTaggedValue asyncFuncObj,
const JSTaggedValue value, JSTaggedValue flag);
@ -174,7 +179,6 @@ public:
private:
static JSTaggedValue ThrowSyntaxError(JSThread *thread, const char *message);
static JSTaggedValue GetCallSpreadArgs(JSThread *thread, JSTaggedValue array);
static JSTaggedValue SetClassInheritanceRelationship(JSThread *thread, JSTaggedValue ctor, JSTaggedValue base);
};
} // namespace panda::ecmascript
#endif // ECMASCRIPT_INTERPRETER_SLOW_RUNTIME_STUB_H

View File

@ -115,6 +115,7 @@
&&DEBUG_HANDLE_STTHISBYVALUE_IMM16_V8,
&&DEBUG_HANDLE_LDPATCHVAR_IMM8,
&&DEBUG_HANDLE_STPATCHVAR_IMM8_V8,
&&DEBUG_HANDLE_DYNAMICIMPORT_V8,
&&DEBUG_HANDLE_JEQZ_IMM8,
&&DEBUG_HANDLE_DEFINECLASSWITHBUFFER_IMM8_ID16_ID16_IMM16_V8,
&&DEBUG_HANDLE_DEFINECLASSWITHBUFFER_IMM16_ID16_ID16_IMM16_V8,
@ -264,7 +265,6 @@
&&DEBUG_HANDLE_OVERFLOW,
&&DEBUG_HANDLE_OVERFLOW,
&&DEBUG_HANDLE_OVERFLOW,
&&DEBUG_HANDLE_OVERFLOW,
&&DEBUG_HANDLE_DEPRECATED,
&&DEBUG_HANDLE_WIDE,
&&DEBUG_HANDLE_THROW,

View File

@ -713,6 +713,11 @@
NOTIFY_DEBUGGER_EVENT();
REAL_GOTO_DISPATCH_OPCODE(EcmaOpcode::STLEXVAR_IMM4_IMM4);
}
DEBUG_HANDLE_OPCODE(DYNAMICIMPORT_V8)
{
NOTIFY_DEBUGGER_EVENT();
REAL_GOTO_DISPATCH_OPCODE(EcmaOpcode::DYNAMICIMPORT_V8);
}
DEBUG_HANDLE_OPCODE(GETMODULENAMESPACE_IMM8)
{
NOTIFY_DEBUGGER_EVENT();

View File

@ -115,6 +115,7 @@
&&HANDLE_STTHISBYVALUE_IMM16_V8,
&&HANDLE_LDPATCHVAR_IMM8,
&&HANDLE_STPATCHVAR_IMM8_V8,
&&HANDLE_DYNAMICIMPORT_V8,
&&HANDLE_JEQZ_IMM8,
&&HANDLE_DEFINECLASSWITHBUFFER_IMM8_ID16_ID16_IMM16_V8,
&&HANDLE_DEFINECLASSWITHBUFFER_IMM16_ID16_ID16_IMM16_V8,
@ -264,7 +265,6 @@
&&HANDLE_OVERFLOW,
&&HANDLE_OVERFLOW,
&&HANDLE_OVERFLOW,
&&HANDLE_OVERFLOW,
&&HANDLE_DEPRECATED,
&&HANDLE_WIDE,
&&HANDLE_THROW,

View File

@ -623,7 +623,7 @@ int64_t JSDate::GetLocalOffsetFromOS([[maybe_unused]] int64_t timeMs, bool isLoc
#else
TIME_ZONE_INFORMATION tmp;
GetTimeZoneInformation(&tmp);
int64_t res = tmp.Bias / SEC_PER_MINUTE;
int64_t res = -tmp.Bias;
return res;
#endif
}

View File

@ -91,7 +91,8 @@ class ProtoChangeDetails;
JS_TYPE_ERROR, /* ////////////////////////////////////////////////////////////////////////////-PADDING */ \
JS_AGGREGATE_ERROR, /* ////////////////////////////////////////////////////////////////////////////-PADDING */ \
JS_URI_ERROR, /* ////////////////////////////////////////////////////////////////////////////-PADDING */ \
JS_SYNTAX_ERROR, /* JS_ERROR_LAST /////////////////////////////////////////////////////////////////////// */\
JS_SYNTAX_ERROR, /* ////////////////////////////////////////////////////////////////////////////-PADDING */ \
JS_OOM_ERROR, /* JS_ERROR_LAST /////////////////////////////////////////////////////////////////////// */\
\
JS_REG_EXP, /* ///////////////////////////////////////////////////////////////////////////////////-PADDING */ \
JS_SET, /* ///////////////////////////////////////////////////////////////////////////////////-PADDING */ \
@ -242,7 +243,7 @@ class ProtoChangeDetails;
ECMA_OBJECT_LAST = JS_PROXY, /* /////////////////////////////////////////////////////////////////-PADDING */\
\
JS_ERROR_FIRST = JS_ERROR, /* ////////////////////////////////////////////////////////////////-PADDING */ \
JS_ERROR_LAST = JS_SYNTAX_ERROR, /* ////////////////////////////////////////////////////////////////-PADDING */\
JS_ERROR_LAST = JS_OOM_ERROR, /* ////////////////////////////////////////////////////////////////-PADDING */\
\
JS_ITERATOR_FIRST = JS_ITERATOR, /* //////////////////////////////////////////////////////////-PADDING */ \
JS_ITERATOR_LAST = JS_STRING_ITERATOR, /* //////////////////////////////////////////////////////////-PADDING */\
@ -489,6 +490,11 @@ public:
return (JSType::JS_TYPED_ARRAY_FIRST < jsType && jsType <= JSType::JS_TYPED_ARRAY_LAST);
}
inline bool HasOrdinaryGet() const
{
return (IsTypedArray() || IsSpecialContainer() || IsModuleNamespace());
}
inline bool IsJSTypedArray() const
{
return GetObjectType() == JSType::JS_TYPED_ARRAY;

View File

@ -672,8 +672,8 @@ private:
PandArg<bool> enableCpuprofiler_ {"enable-cpuprofiler", false,
R"(Enable cpuprofiler to sample call stack and output to json file. Default: false)"};
PandArg<std::string> stubFile_ {"stub-file",
R"(stub.aot)",
R"(Path of file includes common stubs module compiled by stub compiler. Default: "stub.aot")"};
R"(stub.an)",
R"(Path of file includes common stubs module compiled by stub compiler. Default: "stub.an")"};
PandArg<bool> enableForceGc_ {"enable-force-gc", true, R"(enable force gc when allocating object)"};
PandArg<bool> forceFullGc_ {"force-full-gc",
true,

View File

@ -260,6 +260,7 @@ bool JSSerializer::WriteTaggedObject(const JSHandle<JSTaggedValue> &value)
case JSType::JS_AGGREGATE_ERROR:
case JSType::JS_URI_ERROR:
case JSType::JS_SYNTAX_ERROR:
case JSType::JS_OOM_ERROR:
return WriteJSError(value);
case JSType::JS_DATE:
return WriteJSDate(value);
@ -344,6 +345,8 @@ bool JSSerializer::WriteJSErrorHeader(JSType type)
return WriteType(SerializationUID::URI_ERROR);
case JSType::JS_SYNTAX_ERROR:
return WriteType(SerializationUID::SYNTAX_ERROR);
case JSType::JS_OOM_ERROR:
return WriteType(SerializationUID::OOM_ERROR);
default:
UNREACHABLE();
}
@ -969,6 +972,7 @@ JSHandle<JSTaggedValue> JSDeserializer::DeserializeJSTaggedValue()
case SerializationUID::AGGREGATE_ERROR:
case SerializationUID::URI_ERROR:
case SerializationUID::SYNTAX_ERROR:
case SerializationUID::OOM_ERROR:
return ReadJSError(uid);
case SerializationUID::JS_DATE:
return ReadJSDate();
@ -1046,7 +1050,10 @@ JSHandle<JSTaggedValue> JSDeserializer::ReadJSError(SerializationUID uid)
errorType = base::ErrorType::URI_ERROR;
break;
case SerializationUID::SYNTAX_ERROR:
errorType = base::ErrorType::URI_ERROR;
errorType = base::ErrorType::SYNTAX_ERROR;
break;
case SerializationUID::OOM_ERROR:
errorType = base::ErrorType::OOM_ERROR;
break;
default:
UNREACHABLE();

View File

@ -85,6 +85,7 @@ enum class SerializationUID : uint8_t {
AGGREGATE_ERROR,
URI_ERROR,
SYNTAX_ERROR,
OOM_ERROR,
ERROR_MESSAGE_BEGIN,
ERROR_MESSAGE_END,
// NativeFunctionPointer

View File

@ -420,4 +420,153 @@ JSTaggedValue JSStableArray::IndexOf(JSThread *thread, JSHandle<JSTaggedValue> r
}
return JSTaggedValue(-1);
}
JSTaggedValue JSStableArray::Filter(JSHandle<JSObject> newArrayHandle, JSHandle<JSObject> thisObjHandle,
EcmaRuntimeCallInfo *argv, uint32_t &k, double &toIndex)
{
JSThread *thread = argv->GetThread();
JSHandle<JSTaggedValue> callbackFnHandle = base::BuiltinsBase::GetCallArg(argv, 0);
JSHandle<JSTaggedValue> thisArgHandle = base::BuiltinsBase::GetCallArg(argv, 1);
JSHandle<JSTaggedValue> thisObjVal(thisObjHandle);
JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
JSMutableHandle<JSTaggedValue> toIndexHandle(thread, JSTaggedValue::Undefined());
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
const int32_t argsLength = 3; // 3: ?kValue, k, O?
double len = base::ArrayHelper::GetArrayLength(thread, thisObjVal);
JSHandle<TaggedArray> array(thread, thisObjHandle->GetElements());
while (k < len) {
JSTaggedValue kValue = array->Get(k);
if (!kValue.IsHole()) {
key.Update(JSTaggedValue(k));
EcmaRuntimeCallInfo *info =
EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, thisArgHandle, undefined, argsLength);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
info->SetCallArg(kValue, key.GetTaggedValue(), thisObjVal.GetTaggedValue());
JSTaggedValue callResult = JSFunction::Call(info);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
if (array->GetLength() < len) {
len = array->GetLength();
}
bool boolResult = callResult.ToBoolean();
if (boolResult) {
toIndexHandle.Update(JSTaggedValue(toIndex));
JSObject::CreateDataPropertyOrThrow(thread, newArrayHandle,
toIndexHandle, JSHandle<JSTaggedValue>(thread, kValue));
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
toIndex++;
}
}
k++;
if (!thisObjVal->IsStableJSArray(thread)) {
break;
}
}
return base::BuiltinsBase::GetTaggedDouble(true);
}
JSTaggedValue JSStableArray::Map(JSHandle<JSObject> newArrayHandle, JSHandle<JSObject> thisObjHandle,
EcmaRuntimeCallInfo *argv, uint32_t &k, uint32_t len)
{
JSThread *thread = argv->GetThread();
JSHandle<JSTaggedValue> callbackFnHandle = base::BuiltinsBase::GetCallArg(argv, 0);
JSHandle<JSTaggedValue> thisArgHandle = base::BuiltinsBase::GetCallArg(argv, 1);
JSHandle<JSTaggedValue> thisObjVal(thisObjHandle);
JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
JSMutableHandle<JSTaggedValue> mapResultHandle(thread, JSTaggedValue::Undefined());
const int32_t argsLength = 3; // 3: ?kValue, k, O?
JSHandle<TaggedArray> array(thread, thisObjHandle->GetElements());
while (k < len) {
JSTaggedValue kValue = array->Get(k);
if (!kValue.IsHole()) {
key.Update(JSTaggedValue(k));
EcmaRuntimeCallInfo *info =
EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, thisArgHandle, undefined, argsLength);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
info->SetCallArg(kValue, key.GetTaggedValue(), thisObjVal.GetTaggedValue());
JSTaggedValue mapResult = JSFunction::Call(info);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
mapResultHandle.Update(mapResult);
JSObject::CreateDataPropertyOrThrow(thread, newArrayHandle, k, mapResultHandle);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
if (array->GetLength() < len) {
len = array->GetLength();
}
}
k++;
if (!thisObjVal->IsStableJSArray(thread)) {
break;
}
}
return base::BuiltinsBase::GetTaggedDouble(true);
}
JSTaggedValue JSStableArray::Reverse(JSThread *thread, JSHandle<JSObject> thisObjHandle,
JSHandle<JSTaggedValue> thisHandle, double &lower, uint32_t len)
{
JSHandle<JSTaggedValue> thisObjVal(thisObjHandle);
JSHandle<TaggedArray> array(thread, thisObjHandle->GetElements());
JSMutableHandle<JSTaggedValue> lowerP(thread, JSTaggedValue::Undefined());
JSMutableHandle<JSTaggedValue> upperP(thread, JSTaggedValue::Undefined());
JSMutableHandle<JSTaggedValue> lowerValueHandle(thread, JSTaggedValue::Undefined());
JSMutableHandle<JSTaggedValue> upperValueHandle(thread, JSTaggedValue::Undefined());
double middle = std::floor(len / 2);
while (lower != middle) {
if (array->GetLength() != len) {
break;
}
double upper = len - lower - 1;
lowerP.Update(JSTaggedValue(lower));
upperP.Update(JSTaggedValue(upper));
bool lowerExists = (thisHandle->IsTypedArray() || JSTaggedValue::HasProperty(thread, thisObjVal, lowerP));
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
if (lowerExists) {
lowerValueHandle.Update(array->Get(lower));
}
bool upperExists = (thisHandle->IsTypedArray() || JSTaggedValue::HasProperty(thread, thisObjVal, upperP));
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
if (upperExists) {
upperValueHandle.Update(array->Get(upper));
}
if (lowerExists && upperExists) {
array->Set(thread, lower, upperValueHandle.GetTaggedValue());
array->Set(thread, upper, lowerValueHandle.GetTaggedValue());
} else if (upperExists) {
array->Set(thread, lower, upperValueHandle.GetTaggedValue());
JSTaggedValue::SetProperty(thread, thisObjVal, lowerP, upperValueHandle, true);
JSTaggedValue::DeletePropertyOrThrow(thread, thisObjVal, upperP);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
} else if (lowerExists) {
array->Set(thread, upper, lowerValueHandle.GetTaggedValue());
JSTaggedValue::SetProperty(thread, thisObjVal, upperP, lowerValueHandle, true);
JSTaggedValue::DeletePropertyOrThrow(thread, thisObjVal, lowerP);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
}
lower++;
}
return base::BuiltinsBase::GetTaggedDouble(true);
}
JSTaggedValue JSStableArray::Concat(JSThread *thread, JSHandle<JSObject> newArrayHandle,
JSHandle<JSObject> thisObjHandle, double &k, double &n)
{
JSHandle<JSTaggedValue> thisObjVal(thisObjHandle);
double thisLen = base::ArrayHelper::GetArrayLength(thread, thisObjVal);
JSHandle<TaggedArray> arrayFrom(thread, thisObjHandle->GetElements());
JSMutableHandle<JSTaggedValue> toKey(thread, JSTaggedValue::Undefined());
while (k < thisLen) {
if (arrayFrom->GetLength() != thisLen) {
break;
}
toKey.Update(JSTaggedValue(n));
JSTaggedValue kValue = arrayFrom->Get(k);
if (!kValue.IsHole()) {
JSObject::CreateDataPropertyOrThrow(thread, newArrayHandle, toKey, JSHandle<JSTaggedValue>(thread, kValue));
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
}
n++;
k++;
}
return base::BuiltinsBase::GetTaggedDouble(true);
}
} // namespace panda::ecmascript

View File

@ -42,6 +42,14 @@ public:
JSHandle<JSTaggedValue> thisArgHandle, uint32_t &k);
static JSTaggedValue IndexOf(JSThread *thread, JSHandle<JSTaggedValue> receiver,
JSHandle<JSTaggedValue> searchElement, uint32_t from, uint32_t len);
static JSTaggedValue Filter(JSHandle<JSObject> newArrayHandle, JSHandle<JSObject> thisObjHandle,
EcmaRuntimeCallInfo *argv, uint32_t &k, double &toIndex);
static JSTaggedValue Map(JSHandle<JSObject> newArrayHandle, JSHandle<JSObject> thisObjHandle,
EcmaRuntimeCallInfo *argv, uint32_t &k, uint32_t len);
static JSTaggedValue Reverse(JSThread *thread, JSHandle<JSObject> thisObjHandle,
JSHandle<JSTaggedValue> thisHandle, double &lower, uint32_t len);
static JSTaggedValue Concat(JSThread *thread, JSHandle<JSObject> newArrayHandle,
JSHandle<JSObject> thisObjHandle, double &k, double &n);
};
} // namespace panda::ecmascript
#endif // ECMASCRIPT_JS_STABLE_ARRAY_H

View File

@ -698,6 +698,11 @@ inline bool JSTaggedValue::IsSpecialContainer() const
return IsHeapObject() && GetTaggedObject()->GetClass()->IsSpecialContainer();
}
inline bool JSTaggedValue::HasOrdinaryGet() const
{
return IsHeapObject() && GetTaggedObject()->GetClass()->HasOrdinaryGet();
}
inline bool JSTaggedValue::IsPromiseIteratorRecord() const
{
return IsHeapObject() && GetTaggedObject()->GetClass()->IsPromiseIteratorRecord();

View File

@ -388,6 +388,12 @@ JSTaggedValue JSTaggedValue::OrdinaryToPrimitive(JSThread *thread, const JSHandl
THROW_TYPE_ERROR_AND_RETURN(thread, "Cannot convert a illegal value to a Primitive", JSTaggedValue::Undefined());
}
JSHandle<EcmaString> JSTaggedValue::ToString(JSThread *thread, JSTaggedValue val)
{
JSHandle<JSTaggedValue> tagged(thread, val);
return ToString(thread, tagged);
}
JSHandle<EcmaString> JSTaggedValue::ToString(JSThread *thread, const JSHandle<JSTaggedValue> &tagged)
{
if (tagged->IsString()) {

View File

@ -16,8 +16,6 @@
#ifndef ECMASCRIPT_JS_TAGGED_VALUE_H
#define ECMASCRIPT_JS_TAGGED_VALUE_H
#include <limits.h>
#include "ecmascript/base/bit_helper.h"
#include "ecmascript/mem/c_string.h"
#include "ecmascript/mem/mem_common.h"
@ -47,22 +45,8 @@ enum class ComparisonResult {
UNDEFINED // at least one of x or y was undefined or NaN
};
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define RETURN_TAGGED_VALUE_IF_ABRUPT(thread) RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Undefined());
using JSTaggedType = uint64_t;
static const JSTaggedType NULL_POINTER = 0x05ULL;
static inline JSTaggedType ReinterpretDoubleToTaggedType(double value)
{
return base::bit_cast<JSTaggedType>(value);
}
static inline double ReinterpretTaggedTypeToDouble(JSTaggedType value)
{
return base::bit_cast<double>(value);
}
// Every double with all of its exponent bits set and its highest mantissa bit set is a quiet NaN.
// That leaves 51 bits unaccounted for. Well avoid one of those so that we dont step on Intels
// “QNaN Floating-Point Indefinite” value, leaving us 50 bits. Those remaining bits can be anything.
@ -86,9 +70,10 @@ static inline double ReinterpretTaggedTypeToDouble(JSTaggedType value)
class JSTaggedValue {
public:
static constexpr size_t BIT_PER_BYTE = 8;
static constexpr size_t TAG_BITS_SIZE = 16; // 16 means bit numbers of 0xFFFF
static constexpr size_t TAG_BITS_SHIFT = base::BitNumbers<JSTaggedType>() - TAG_BITS_SIZE;
static_assert((TAG_BITS_SHIFT + TAG_BITS_SIZE) == sizeof(JSTaggedType) * CHAR_BIT, "Insufficient bits!");
static_assert((TAG_BITS_SHIFT + TAG_BITS_SIZE) == sizeof(JSTaggedType) * BIT_PER_BYTE, "Insufficient bits!");
static constexpr JSTaggedType TAG_MARK = 0xFFFFULL << TAG_BITS_SHIFT;
// int tag
static constexpr JSTaggedType TAG_INT = TAG_MARK;
@ -123,6 +108,19 @@ public:
return JSTaggedValue(object);
}
static const JSTaggedType NULL_POINTER = VALUE_HOLE;
static const JSTaggedType INVALID_VALUE_LIMIT = 0x40000ULL;
static inline JSTaggedType CastDoubleToTagged(double value)
{
return base::bit_cast<JSTaggedType>(value);
}
static inline double CastTaggedToDouble(JSTaggedType value)
{
return base::bit_cast<double>(value);
}
static inline constexpr size_t TaggedTypeSize()
{
return sizeof(JSTaggedType);
@ -134,7 +132,7 @@ public:
explicit JSTaggedValue(void *) = delete;
constexpr JSTaggedValue() : value_(NULL_POINTER) {}
constexpr JSTaggedValue() : value_(JSTaggedValue::NULL_POINTER) {}
constexpr explicit JSTaggedValue(JSTaggedType v) : value_(v) {}
@ -155,8 +153,8 @@ public:
explicit JSTaggedValue(double v)
{
ASSERT_PRINT(!IsImpureNaN(v), "pureNaN will break the encoding of tagged double: "
<< std::hex << ReinterpretDoubleToTaggedType(v));
value_ = ReinterpretDoubleToTaggedType(v) + DOUBLE_ENCODE_OFFSET;
<< std::hex << CastDoubleToTagged(v));
value_ = CastDoubleToTagged(v) + DOUBLE_ENCODE_OFFSET;
}
explicit JSTaggedValue(const TaggedObject *v) : value_(static_cast<JSTaggedType>(ToUintPtr(v))) {}
@ -229,10 +227,15 @@ public:
return ((value_ & TAG_HEAPOBJECT_MASK) == 0U);
}
inline bool IsInvalidValue() const
{
return value_ <= INVALID_VALUE_LIMIT;
}
inline double GetDouble() const
{
ASSERT_PRINT(IsDouble(), "can not convert JSTaggedValue to Double : " << std::hex << value_);
return ReinterpretTaggedTypeToDouble(value_ - DOUBLE_ENCODE_OFFSET);
return CastTaggedToDouble(value_ - DOUBLE_ENCODE_OFFSET);
}
inline int GetInt() const
@ -402,6 +405,7 @@ public:
static uint8_t ToUint8(JSThread *thread, const JSHandle<JSTaggedValue> &tagged);
static uint8_t ToUint8Clamp(JSThread *thread, const JSHandle<JSTaggedValue> &tagged);
static JSHandle<EcmaString> ToString(JSThread *thread, const JSHandle<JSTaggedValue> &tagged);
static JSHandle<EcmaString> ToString(JSThread *thread, JSTaggedValue val);
static JSHandle<JSObject> ToObject(JSThread *thread, const JSHandle<JSTaggedValue> &tagged);
static JSHandle<JSTaggedValue> ToPropertyKey(JSThread *thread, const JSHandle<JSTaggedValue> &tagged);
static JSTaggedNumber ToLength(JSThread *thread, const JSHandle<JSTaggedValue> &tagged);
@ -612,7 +616,7 @@ public:
bool IsJSAPIListIterator() const;
bool IsJSAPILinkedListIterator() const;
bool IsSpecialContainer() const;
bool HasOrdinaryGet() const;
bool IsPrototypeHandler() const;
bool IsTransitionHandler() const;
bool IsPropertyBox() const;

View File

@ -47,17 +47,7 @@ JSThread *JSThread::Create(EcmaVM *vm)
EcmaInterpreter::InitStackFrame(jsThread);
if (jsThread->IsAsmInterpreter()) {
size_t stackSize = GetAsmStackSize();
if (stackSize <= EcmaParamConfiguration::GetDefalutReservedStackSize()) {
LOG_ECMA(FATAL) << "Too small stackSize to run jsvm:" << stackSize;
}
// init stack limit of asm interpreter
ASSERT(GetCurrentStackPosition() > (stackSize - EcmaParamConfiguration::GetDefalutReservedStackSize()));
// To avoid too much times of stack overflow checking, we only check stack overflow before push vregs or
// parameters of variable length. So we need a reserved size of stack to make sure stack won't be overflowed
// when push other data.
jsThread->glueData_.stackLimit_ =
GetCurrentStackPosition() - (stackSize - EcmaParamConfiguration::GetDefalutReservedStackSize());
jsThread->glueData_.stackLimit_ = GetAsmStackLimit();
}
return jsThread;
}
@ -153,7 +143,7 @@ void JSThread::Iterate(const RootVisitor &visitor, const RootRangeVisitor &range
FrameHandler frameHandler(this);
frameHandler.Iterate(visitor, rangeVisitor, derivedVisitor);
// visit tagged handle storage roots
#if ECMASCRIPT_ENABLE_HANDLE_LEAK_CHECK
#ifdef ECMASCRIPT_ENABLE_GLOBAL_LEAK_CHECK
IterateHandleWithCheck(visitor, rangeVisitor);
#else
if (currentHandleStorageIndex_ != -1) {
@ -175,7 +165,7 @@ void JSThread::Iterate(const RootVisitor &visitor, const RootRangeVisitor &range
#endif
}
#if ECMASCRIPT_ENABLE_HANDLE_LEAK_CHECK
#ifdef ECMASCRIPT_ENABLE_GLOBAL_LEAK_CHECK
void JSThread::IterateHandleWithCheck(const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor)
{
size_t handleCount = 0;
@ -399,30 +389,53 @@ void JSThread::CollectBCOffsetInfo()
}
// static
size_t JSThread::GetAsmStackSize()
size_t JSThread::GetAsmStackLimit()
{
size_t result = EcmaParamConfiguration::GetDefalutStackSize();
#if !defined(PANDA_TARGET_WINDOWS) && !defined(PANDA_TARGET_MACOS)
// js stack limit
size_t result = GetCurrentStackPosition() - EcmaParamConfiguration::GetDefalutStackSize();
pthread_attr_t attr;
int ret = pthread_attr_init(&attr);
int ret = pthread_getattr_np(pthread_self(), &attr);
if (ret != 0) {
LOG_ECMA(ERROR) << "Get current thread attr failed";
return result;
}
void *stackAddr = nullptr;
size_t size = 0;
ret = pthread_attr_getstacksize(&attr, &size);
ret = pthread_attr_getstack(&attr, &stackAddr, &size);
if (ret != 0) {
LOG_ECMA(ERROR) << "Get current thread stack size failed";
if (pthread_attr_destroy(&attr) != 0) {
LOG_ECMA(ERROR) << "Destroy current thread attr failed";
}
return result;
}
if (size < result) {
result = size;
uintptr_t threadStackLimit = reinterpret_cast<uintptr_t>(stackAddr);
if (result < threadStackLimit) {
result = threadStackLimit;
}
LOG_ECMA(INFO) << "Current thread asm stack size:" << result;
uintptr_t threadStackStart = threadStackLimit + size;
LOG_ECMA(INFO) << "Current thread stack start:" << threadStackStart
<< " Used stack before js stack start:" << (threadStackStart - GetCurrentStackPosition())
<< " Current thread asm stack limit:" << result;
ret = pthread_attr_destroy(&attr);
if (ret != 0) {
LOG_ECMA(ERROR) << "Destroy current thread attr failed";
}
// To avoid too much times of stack overflow checking, we only check stack overflow before push vregs or
// parameters of variable length. So we need a reserved size of stack to make sure stack won't be overflowed
// when push other data.
result += EcmaParamConfiguration::GetDefaultReservedStackSize();
if (threadStackStart <= result) {
LOG_ECMA(FATAL) << "Too small stackSize to run jsvm";
}
return result;
#else
return 0;
#endif
}
} // namespace panda::ecmascript

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