mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2025-02-26 15:28:33 +00:00
Merge remote-tracking branch 'origin/master' into wcc_0808
Change-Id: I1566e28d02d931b390ac5d7c3cb11c3485aed5de
This commit is contained in:
commit
447847cb1d
13
BUILD.gn
13
BUILD.gn
@ -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",
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -28,6 +28,7 @@ enum class ErrorType : uint8_t {
|
||||
TYPE_ERROR,
|
||||
URI_ERROR,
|
||||
AGGREGATE_ERROR,
|
||||
OOM_ERROR,
|
||||
};
|
||||
} // namespace panda::ecmascript::base
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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));
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 ] ] )
|
||||
|
@ -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();
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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" ]
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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) \
|
||||
|
@ -25,6 +25,8 @@ namespace panda::ecmascript::kungfu {
|
||||
#define BUILTINS_STUB_LIST(V) \
|
||||
V(CharCodeAt) \
|
||||
V(IndexOf) \
|
||||
V(Substring) \
|
||||
V(CharAt) \
|
||||
|
||||
class BuiltinsStubCSigns {
|
||||
public:
|
||||
|
567
ecmascript/compiler/builtins/builtins_string_stub_builder.cpp
Normal file
567
ecmascript/compiler/builtins/builtins_string_stub_builder.cpp
Normal 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
|
46
ecmascript/compiler/builtins/builtins_string_stub_builder.h
Normal file
46
ecmascript/compiler/builtins/builtins_string_stub_builder.h
Normal 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
|
@ -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
|
@ -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
|
@ -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) \
|
||||
|
@ -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)) {
|
||||
|
@ -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};
|
||||
|
@ -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()
|
||||
|
@ -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();
|
||||
|
@ -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};
|
||||
|
@ -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
|
||||
|
@ -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_
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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"},
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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>
|
||||
|
@ -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
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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)) {
|
||||
|
@ -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) ||
|
||||
|
@ -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, ¬GreaterZero);
|
||||
builder_.Bind(&greaterZero);
|
||||
{
|
||||
builder_.Branch(builder_.Int64GreaterThan(res, max), &overflow, ¬Overflow);
|
||||
}
|
||||
builder_.Bind(¬GreaterZero);
|
||||
{
|
||||
Label lessZero(&builder_);
|
||||
builder_.Branch(builder_.Int32LessThan(builder_.TaggedCastToInt32(left), builder_.Int32(0)),
|
||||
&lessZero, ¬Overflow);
|
||||
builder_.Bind(&lessZero);
|
||||
builder_.Branch(builder_.Int64LessThan(res, min), &overflow, ¬Overflow);
|
||||
}
|
||||
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(¬Overflow);
|
||||
{
|
||||
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
|
@ -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_;
|
||||
|
@ -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:
|
||||
|
@ -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) {
|
||||
|
@ -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()));
|
||||
|
@ -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};
|
||||
|
@ -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);
|
||||
|
@ -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]
|
||||
|
@ -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 { \
|
||||
|
@ -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};
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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:
|
||||
|
@ -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 {
|
||||
|
@ -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) \
|
||||
|
@ -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"));
|
||||
|
@ -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) \
|
||||
|
@ -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();
|
||||
|
@ -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:
|
||||
|
@ -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"},
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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();
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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();
|
||||
|
@ -85,6 +85,7 @@ enum class SerializationUID : uint8_t {
|
||||
AGGREGATE_ERROR,
|
||||
URI_ERROR,
|
||||
SYNTAX_ERROR,
|
||||
OOM_ERROR,
|
||||
ERROR_MESSAGE_BEGIN,
|
||||
ERROR_MESSAGE_END,
|
||||
// NativeFunctionPointer
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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()) {
|
||||
|
@ -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. We’ll avoid one of those so that we don’t step on Intel’s
|
||||
// “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;
|
||||
|
@ -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
Loading…
x
Reference in New Issue
Block a user