mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-10-06 23:54:03 +00:00
Merge branch 'master' of gitee.com:openharmony/arkcompiler_ets_runtime into master
Signed-off-by: 查维 <zhawei@kaihong.com>
This commit is contained in:
commit
ca768d783d
1
BUILD.gn
1
BUILD.gn
@ -793,6 +793,7 @@ if (is_ohos && is_standard_system && enable_hitrace) {
|
||||
ecma_debugger_source = [
|
||||
"ecmascript/debugger/debugger_api.cpp",
|
||||
"ecmascript/debugger/js_debugger.cpp",
|
||||
"ecmascript/debugger/dropframe_manager.cpp",
|
||||
"ecmascript/debugger/hot_reload_manager.cpp",
|
||||
]
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
#include "ecmascript/js_dataview.h"
|
||||
|
||||
namespace panda::ecmascript::base {
|
||||
enum class BytesSize : int32_t {ONEBYTES = 1, TWOBYTES = 2, FOURBYTES = 4, EIGHTBYTES = 8};
|
||||
enum class BytesSize : uint32_t {ONEBYTES = 1, TWOBYTES = 2, FOURBYTES = 4, EIGHTBYTES = 8};
|
||||
|
||||
class AtomicHelper final {
|
||||
public:
|
||||
@ -101,4 +101,4 @@ public:
|
||||
};
|
||||
} // namespace panda::ecmascript::base
|
||||
|
||||
#endif // ECMASCRIPT_BASE_ATOMIC_HELPER_H
|
||||
#endif // ECMASCRIPT_BASE_ATOMIC_HELPER_H
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <type_traits>
|
||||
|
||||
namespace panda::ecmascript::base {
|
||||
constexpr uint64_t pureNaN = 0x7FF8ULL << 48U; // Be sure return the NaN that is safe.
|
||||
template <class S, class R>
|
||||
union Data {
|
||||
S src;
|
||||
|
@ -192,7 +192,7 @@ JSTaggedValue ErrorHelper::ErrorCommonConstructor(EcmaRuntimeCallInfo *argv,
|
||||
ASSERT_PRINT(status == true, "return result exception!");
|
||||
}
|
||||
|
||||
bool isOOMError = errorType == ErrorType::OOM_ERROR ? true : false;
|
||||
bool isOOMError = errorType == ErrorType::OOM_ERROR;
|
||||
JSHandle<EcmaString> handleStack = BuildEcmaStackTrace(thread, isOOMError);
|
||||
JSHandle<JSTaggedValue> stackkey = globalConst->GetHandledStackString();
|
||||
PropertyDescriptor stackDesc(thread, JSHandle<JSTaggedValue>::Cast(handleStack), true, false, true);
|
||||
|
@ -57,7 +57,7 @@ JSHandle<JSTaggedValue> Internalize::InternalizeJsonProperty(JSThread *thread, c
|
||||
}
|
||||
|
||||
// Return ? Call(receiver, holder, « name, val »).
|
||||
const int32_t argsLength = 2; // 2: « name, val »
|
||||
const uint32_t argsLength = 2; // 2: « name, val »
|
||||
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
|
||||
EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, receiver, objHandle, undefined, argsLength);
|
||||
RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
|
||||
|
@ -313,7 +313,7 @@ JSTaggedValue JsonStringifier::GetSerializeValue(const JSHandle<JSTaggedValue> &
|
||||
if (UNLIKELY(replacer->IsCallable())) {
|
||||
handleValue_.Update(tagValue);
|
||||
// a. Let value be Call(ReplacerFunction, holder, «key, value»).
|
||||
const int32_t argsLength = 2; // 2: «key, value»
|
||||
const uint32_t argsLength = 2; // 2: «key, value»
|
||||
EcmaRuntimeCallInfo *info =
|
||||
EcmaInterpreter::NewRuntimeCallInfo(thread_, replacer, object, undefined, argsLength);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread_);
|
||||
|
@ -46,6 +46,7 @@ static constexpr double MAX_VALUE = std::numeric_limits<double>::max();
|
||||
static constexpr double MIN_VALUE = std::numeric_limits<double>::min();
|
||||
static constexpr double POSITIVE_INFINITY = std::numeric_limits<double>::infinity();
|
||||
static constexpr double NAN_VALUE = std::numeric_limits<double>::quiet_NaN();
|
||||
static constexpr uint64_t MAX_UINT64_VALUE = std::numeric_limits<uint64_t>::max();
|
||||
|
||||
// Helper defines for double
|
||||
static constexpr int DOUBLE_MAX_PRECISION = 17;
|
||||
|
@ -68,8 +68,8 @@ public:
|
||||
}
|
||||
|
||||
/*
|
||||
* Before: @xxx:****
|
||||
* After: ****
|
||||
* Before: @***:xxxx
|
||||
* After: xxxx
|
||||
*/
|
||||
inline static CString GetStrippedModuleName(const CString &moduleRequestName)
|
||||
{
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "ecmascript/js_array_iterator.h"
|
||||
#include "ecmascript/js_function.h"
|
||||
#include "ecmascript/js_handle.h"
|
||||
#include "ecmascript/js_map_iterator.h"
|
||||
#include "ecmascript/js_stable_array.h"
|
||||
#include "ecmascript/js_tagged_number.h"
|
||||
#include "ecmascript/object_factory.h"
|
||||
@ -167,6 +168,11 @@ JSTaggedValue BuiltinsArray::From(EcmaRuntimeCallInfo *argv)
|
||||
// 6. If usingIterator is not undefined, then
|
||||
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
|
||||
if (!usingIterator->IsUndefined()) {
|
||||
// Fast path for MapIterator
|
||||
if (!mapping && items->IsJSMapIterator()) {
|
||||
return JSMapIterator::MapIteratorToList(thread, items, usingIterator);
|
||||
}
|
||||
|
||||
// a. If IsConstructor(C) is true, then
|
||||
// i. Let A be Construct(C).
|
||||
// b. Else,
|
||||
@ -221,7 +227,7 @@ JSTaggedValue BuiltinsArray::From(EcmaRuntimeCallInfo *argv)
|
||||
// 3. Let mappedValue be mappedValue.[[value]].
|
||||
// viii. Else, let mappedValue be nextValue.
|
||||
if (mapping) {
|
||||
const int32_t argsLength = 2; // 2: «nextValue, k»
|
||||
const uint32_t argsLength = 2; // 2: «nextValue, k»
|
||||
EcmaRuntimeCallInfo *info =
|
||||
EcmaInterpreter::NewRuntimeCallInfo(thread, mapfn, thisArgHandle, undefined, argsLength);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
@ -982,7 +988,7 @@ JSTaggedValue BuiltinsArray::Find(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»
|
||||
const uint32_t argsLength = 3; // 3: «kValue, k, O»
|
||||
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
|
||||
EcmaRuntimeCallInfo *info =
|
||||
EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, thisArgHandle, undefined, argsLength);
|
||||
@ -1115,7 +1121,7 @@ JSTaggedValue BuiltinsArray::ForEach(EcmaRuntimeCallInfo *argv)
|
||||
JSStableArray::HandleforEachOfStable(thread, thisObjHandle, callbackFnHandle, thisArgHandle, k);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
}
|
||||
const int32_t argsLength = 3; // 3: «kValue, k, O»
|
||||
const uint32_t argsLength = 3; // 3: «kValue, k, O»
|
||||
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
|
||||
while (k < len) {
|
||||
bool exists = JSTaggedValue::HasProperty(thread, thisObjVal, k);
|
||||
@ -1231,6 +1237,12 @@ JSTaggedValue BuiltinsArray::Join(EcmaRuntimeCallInfo *argv)
|
||||
JSThread *thread = argv->GetThread();
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
||||
JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
|
||||
auto factory = thread->GetEcmaVM()->GetFactory();
|
||||
auto context = thread->GetCurrentEcmaContext();
|
||||
bool noCircular = context->JoinStackPushFastPath(thisHandle);
|
||||
if (!noCircular) {
|
||||
return factory->GetEmptyString().GetTaggedValue();
|
||||
}
|
||||
if (thisHandle->IsStableJSArray(thread)) {
|
||||
return JSStableArray::Join(JSHandle<JSArray>::Cast(thisHandle), argv);
|
||||
}
|
||||
@ -1238,13 +1250,13 @@ JSTaggedValue BuiltinsArray::Join(EcmaRuntimeCallInfo *argv)
|
||||
// 1. Let O be ToObject(this value).
|
||||
JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle);
|
||||
// 2. ReturnIfAbrupt(O).
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
RETURN_EXCEPTION_AND_POP_JOINSTACK(thread, thisHandle);
|
||||
JSHandle<JSTaggedValue> thisObjVal(thisObjHandle);
|
||||
|
||||
// 3. Let len be ToLength(Get(O, "length")).
|
||||
int64_t len = ArrayHelper::GetLength(thread, thisObjVal);
|
||||
// 4. ReturnIfAbrupt(len).
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
RETURN_EXCEPTION_AND_POP_JOINSTACK(thread, thisHandle);
|
||||
|
||||
// 5. If separator is undefined, let separator be the single-element String ",".
|
||||
// 6. Let sep be ToString(separator).
|
||||
@ -1257,7 +1269,7 @@ JSTaggedValue BuiltinsArray::Join(EcmaRuntimeCallInfo *argv)
|
||||
|
||||
JSHandle<EcmaString> sepStringHandle = JSTaggedValue::ToString(thread, sepHandle);
|
||||
// 7. ReturnIfAbrupt(sep).
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
RETURN_EXCEPTION_AND_POP_JOINSTACK(thread, thisHandle);
|
||||
std::u16string sepStr = EcmaStringAccessor(sepStringHandle).ToU16String();
|
||||
|
||||
// 8. If len is zero, return the empty String.
|
||||
@ -1277,22 +1289,19 @@ JSTaggedValue BuiltinsArray::Join(EcmaRuntimeCallInfo *argv)
|
||||
// e. Let R be a String value produced by concatenating S and next.
|
||||
// f. Increase k by 1.
|
||||
std::u16string concatStr;
|
||||
std::u16string concatStrNew;
|
||||
for (int64_t k = 0; k < len; k++) {
|
||||
std::u16string nextStr;
|
||||
JSHandle<JSTaggedValue> element = JSArray::FastGetPropertyByValue(thread, thisObjVal, k);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
RETURN_EXCEPTION_AND_POP_JOINSTACK(thread, thisHandle);
|
||||
if (!element->IsUndefined() && !element->IsNull()) {
|
||||
JSHandle<EcmaString> nextStringHandle = JSTaggedValue::ToString(thread, element);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
RETURN_EXCEPTION_AND_POP_JOINSTACK(thread, thisHandle);
|
||||
nextStr = EcmaStringAccessor(nextStringHandle).ToU16String();
|
||||
}
|
||||
if (k > 0) {
|
||||
concatStrNew = base::StringHelper::Append(concatStr, sepStr);
|
||||
concatStr = base::StringHelper::Append(concatStrNew, nextStr);
|
||||
continue;
|
||||
concatStr.append(sepStr);
|
||||
}
|
||||
concatStr = base::StringHelper::Append(concatStr, nextStr);
|
||||
concatStr.append(nextStr);
|
||||
}
|
||||
|
||||
// 14. Return R.
|
||||
@ -1300,7 +1309,7 @@ JSTaggedValue BuiltinsArray::Join(EcmaRuntimeCallInfo *argv)
|
||||
auto *char16tData = const_cast<char16_t *>(constChar16tData);
|
||||
auto *uint16tData = reinterpret_cast<uint16_t *>(char16tData);
|
||||
uint32_t u16strSize = concatStr.size();
|
||||
auto factory = thread->GetEcmaVM()->GetFactory();
|
||||
context->JoinStackPopFastPath(thisHandle);
|
||||
return factory->NewFromUtf16Literal(uint16tData, u16strSize).GetTaggedValue();
|
||||
}
|
||||
|
||||
@ -1663,6 +1672,10 @@ JSTaggedValue BuiltinsArray::Reduce(EcmaRuntimeCallInfo *argv)
|
||||
}
|
||||
}
|
||||
|
||||
if (thisObjVal->IsStableJSArray(thread)) {
|
||||
JSStableArray::Reduce(thread, thisObjHandle, callbackFnHandle, accumulator, k, len);
|
||||
}
|
||||
|
||||
// 10. Repeat, while k < len
|
||||
// a. Let Pk be ToString(k).
|
||||
// b. Let kPresent be HasProperty(O, Pk).
|
||||
|
@ -87,7 +87,7 @@ JSTaggedValue BuiltinsArrayBuffer::GetByteLength(EcmaRuntimeCallInfo *argv)
|
||||
JSThread *thread = argv->GetThread();
|
||||
BUILTINS_API_TRACE(thread, ArrayBuffer, GetByteLength);
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
||||
|
||||
|
||||
// 1. Let O be the this value.
|
||||
JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
|
||||
// 2. If Type(O) is not Object, throw a TypeError exception.
|
||||
@ -507,7 +507,11 @@ JSTaggedValue BuiltinsArrayBuffer::GetValueFromBufferForFloat(uint8_t *block, ui
|
||||
}
|
||||
if (!littleEndian) {
|
||||
uint64_t res = LittleEndianToBigEndian64Bit(unionValue.uValue);
|
||||
return GetTaggedDouble(base::bit_cast<T>(res));
|
||||
T d = base::bit_cast<T>(res);
|
||||
if (JSTaggedValue::IsImpureNaN(d)) {
|
||||
return GetTaggedDouble(base::bit_cast<T>(base::pureNaN));
|
||||
}
|
||||
return GetTaggedDouble(d);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,6 +43,7 @@ JSTaggedValue BuiltinsCjsRequire::CjsRequireConstructor(EcmaRuntimeCallInfo *arg
|
||||
}
|
||||
JSHandle<EcmaString> requestName = JSHandle<EcmaString>::Cast(GetCallArg(argv, 0));
|
||||
result = CjsModule::Load(thread, requestName);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
return result.GetTaggedValue();
|
||||
}
|
||||
|
||||
|
@ -347,7 +347,8 @@ JSTaggedValue BuiltinsDataView::SetBigUint64(EcmaRuntimeCallInfo *argv)
|
||||
|
||||
// 24.2.1.1
|
||||
JSTaggedValue BuiltinsDataView::GetViewValue(JSThread *thread, const JSHandle<JSTaggedValue> &view,
|
||||
const JSHandle<JSTaggedValue> &requestIndex, JSTaggedValue littleEndian,
|
||||
const JSHandle<JSTaggedValue> &requestIndex,
|
||||
const JSHandle<JSTaggedValue> &littleEndian,
|
||||
DataViewType type)
|
||||
{
|
||||
BUILTINS_API_TRACE(thread, DataView, GetViewValue);
|
||||
@ -371,10 +372,10 @@ JSTaggedValue BuiltinsDataView::GetViewValue(JSThread *thread, const JSHandle<JS
|
||||
uint32_t index = static_cast<uint32_t>(indexInt);
|
||||
// 7. Let isLittleEndian be ToBoolean(isLittleEndian).
|
||||
bool isLittleEndian = false;
|
||||
if (littleEndian.IsUndefined()) {
|
||||
if (littleEndian->IsUndefined()) {
|
||||
isLittleEndian = false;
|
||||
} else {
|
||||
isLittleEndian = littleEndian.ToBoolean();
|
||||
isLittleEndian = littleEndian->ToBoolean();
|
||||
}
|
||||
// 8. Let buffer be the value of view’s [[ViewedArrayBuffer]] internal slot.
|
||||
JSHandle<JSDataView> dataView(view);
|
||||
@ -401,7 +402,8 @@ JSTaggedValue BuiltinsDataView::GetViewValue(JSThread *thread, const JSHandle<JS
|
||||
|
||||
// 24.2.1.2
|
||||
JSTaggedValue BuiltinsDataView::SetViewValue(JSThread *thread, const JSHandle<JSTaggedValue> &view,
|
||||
const JSHandle<JSTaggedValue> &requestIndex, JSTaggedValue littleEndian,
|
||||
const JSHandle<JSTaggedValue> &requestIndex,
|
||||
const JSHandle<JSTaggedValue> &littleEndian,
|
||||
DataViewType type, const JSHandle<JSTaggedValue> &value)
|
||||
{
|
||||
// 1. If Type(view) is not Object, throw a TypeError exception.
|
||||
@ -426,10 +428,10 @@ JSTaggedValue BuiltinsDataView::SetViewValue(JSThread *thread, const JSHandle<JS
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
// 7. Let isLittleEndian be ToBoolean(isLittleEndian).
|
||||
bool isLittleEndian = false;
|
||||
if (littleEndian.IsUndefined()) {
|
||||
if (littleEndian->IsUndefined()) {
|
||||
isLittleEndian = false;
|
||||
} else {
|
||||
isLittleEndian = littleEndian.ToBoolean();
|
||||
isLittleEndian = littleEndian->ToBoolean();
|
||||
}
|
||||
// 8. Let buffer be the value of view’s [[ViewedArrayBuffer]] internal slot.
|
||||
JSHandle<JSDataView> dataView(view);
|
||||
@ -461,11 +463,12 @@ JSTaggedValue BuiltinsDataView::GetTypedValue(EcmaRuntimeCallInfo *argv, DataVie
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
||||
JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
|
||||
JSHandle<JSTaggedValue> offsetHandle = GetCallArg(argv, 0);
|
||||
JSHandle<JSTaggedValue> trueHandle(thread, JSTaggedValue::True());
|
||||
if (type == DataViewType::UINT8 || type == DataViewType::INT8) {
|
||||
return GetViewValue(thread, thisHandle, offsetHandle, JSTaggedValue::True(), type);
|
||||
return GetViewValue(thread, thisHandle, offsetHandle, trueHandle, type);
|
||||
}
|
||||
JSHandle<JSTaggedValue> littleEndianHandle = GetCallArg(argv, 1);
|
||||
return GetViewValue(thread, thisHandle, offsetHandle, littleEndianHandle.GetTaggedValue(), type);
|
||||
return GetViewValue(thread, thisHandle, offsetHandle, littleEndianHandle, type);
|
||||
}
|
||||
|
||||
JSTaggedValue BuiltinsDataView::SetTypedValue(EcmaRuntimeCallInfo *argv, DataViewType type)
|
||||
@ -476,10 +479,11 @@ JSTaggedValue BuiltinsDataView::SetTypedValue(EcmaRuntimeCallInfo *argv, DataVie
|
||||
JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
|
||||
JSHandle<JSTaggedValue> offsetHandle = GetCallArg(argv, 0);
|
||||
JSHandle<JSTaggedValue> value = GetCallArg(argv, 1);
|
||||
JSHandle<JSTaggedValue> trueHandle(thread, JSTaggedValue::True());
|
||||
if (type == DataViewType::UINT8 || type == DataViewType::INT8) {
|
||||
return SetViewValue(thread, thisHandle, offsetHandle, JSTaggedValue::True(), type, value);
|
||||
return SetViewValue(thread, thisHandle, offsetHandle, trueHandle, type, value);
|
||||
}
|
||||
JSHandle<JSTaggedValue> littleEndianHandle = GetCallArg(argv, BuiltinsBase::ArgsPosition::THIRD);
|
||||
return SetViewValue(thread, thisHandle, offsetHandle, littleEndianHandle.GetTaggedValue(), type, value);
|
||||
return SetViewValue(thread, thisHandle, offsetHandle, littleEndianHandle, type, value);
|
||||
}
|
||||
} // namespace panda::ecmascript::builtins
|
||||
|
@ -75,10 +75,12 @@ public:
|
||||
private:
|
||||
// 24.2.1.1 GetViewValue ( view, requestIndex, isLittleEndian, type )
|
||||
static JSTaggedValue GetViewValue(JSThread *thread, const JSHandle<JSTaggedValue> &view,
|
||||
const JSHandle<JSTaggedValue> &requestIndex, JSTaggedValue littleEndian,
|
||||
const JSHandle<JSTaggedValue> &requestIndex,
|
||||
const JSHandle<JSTaggedValue> &littleEndian,
|
||||
DataViewType type);
|
||||
static JSTaggedValue SetViewValue(JSThread *thread, const JSHandle<JSTaggedValue> &view,
|
||||
const JSHandle<JSTaggedValue> &requestIndex, JSTaggedValue littleEndian,
|
||||
const JSHandle<JSTaggedValue> &requestIndex,
|
||||
const JSHandle<JSTaggedValue> &littleEndian,
|
||||
DataViewType type, const JSHandle<JSTaggedValue> &value);
|
||||
|
||||
static JSTaggedValue GetTypedValue(EcmaRuntimeCallInfo *argv, DataViewType type);
|
||||
|
@ -75,19 +75,19 @@ JSTaggedValue BuiltinsFinalizationRegistry::Register(EcmaRuntimeCallInfo *argv)
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "thisValue is not object or does not have an internalSlot internal slot",
|
||||
JSTaggedValue::Exception());
|
||||
}
|
||||
// 3. If Type(target) is not Object, throw a TypeError exception.
|
||||
if (!target->IsECMAObject()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "target is not object", JSTaggedValue::Exception());
|
||||
// 3. If CanBeHeldWeakly(target) is false, throw a TypeError exception.
|
||||
if (!JSTaggedValue::CanBeHeldWeakly(thread, target)) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "target invalid", JSTaggedValue::Exception());
|
||||
}
|
||||
// 4. If SameValue(target, heldValue) is true, throw a TypeError exception.
|
||||
if (JSTaggedValue::SameValue(target, heldValue)) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "target and heldValue should not be equal", JSTaggedValue::Exception());
|
||||
}
|
||||
// 5. If Type(unregisterToken) is not Object, then
|
||||
// 5. If CanBeHeldWeakly(unregisterToken) is false, then
|
||||
// a. If unregisterToken is not undefined, throw a TypeError exception.
|
||||
// b. Set unregisterToken to empty.
|
||||
if (!unregisterToken->IsECMAObject() && !unregisterToken->IsUndefined()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "unregisterToken should be object", JSTaggedValue::Exception());
|
||||
if (!JSTaggedValue::CanBeHeldWeakly(thread, unregisterToken) && !unregisterToken->IsUndefined()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "unregisterToken invalid", JSTaggedValue::Exception());
|
||||
}
|
||||
// 6. Let cell be the Record { [[WeakRefTarget]]: target,
|
||||
// [[HeldValue]]: heldValue, [[UnregisterToken]]: unregisterToken }.
|
||||
@ -112,9 +112,9 @@ JSTaggedValue BuiltinsFinalizationRegistry::Unregister(EcmaRuntimeCallInfo *argv
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "thisValue is not object or does not have an internalSlot internal slot",
|
||||
JSTaggedValue::Exception());
|
||||
}
|
||||
// 3. If Type(unregisterToken) is not Object, throw a TypeError exception.
|
||||
if (!unregisterToken->IsECMAObject()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "unregisterToken should be object", JSTaggedValue::Exception());
|
||||
// 3. If CanBeHeldWeakly(unregisterToken) is false, throw a TypeError exception.
|
||||
if (!JSTaggedValue::CanBeHeldWeakly(thread, unregisterToken)) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "unregisterToken invalid", JSTaggedValue::Exception());
|
||||
}
|
||||
// 4. Let removed be false.
|
||||
// 5. For each Record { [[WeakRefTarget]], [[HeldValue]], [[UnregisterToken]] } cell of
|
||||
|
@ -125,14 +125,14 @@ JSTaggedValue BuiltinsFunction::FunctionPrototypeApply(EcmaRuntimeCallInfo *argv
|
||||
JSObject::CreateListFromArrayLike(thread, arrayObj));
|
||||
// 4. ReturnIfAbrupt(argList).
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
const int32_t argsLength = static_cast<int32_t>(argList->GetLength());
|
||||
const uint32_t argsLength = argList->GetLength();
|
||||
EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, func, thisArg, undefined, argsLength);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
info->SetCallArg(argsLength, argList);
|
||||
return JSFunction::Call(info);
|
||||
}
|
||||
// 6. Return Call(func, thisArg, argList).
|
||||
const int32_t argsLength = static_cast<int32_t>(argumentsList.second);
|
||||
const uint32_t argsLength = static_cast<uint32_t>(argumentsList.second);
|
||||
EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, func, thisArg, undefined, argsLength);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
info->SetCallArg(argsLength, argumentsList.first);
|
||||
|
@ -180,7 +180,7 @@ JSTaggedValue BuiltinsMap::ForEach(EcmaRuntimeCallInfo *argv)
|
||||
JSHandle<JSTaggedValue> thisArg = GetCallArg(argv, 1);
|
||||
|
||||
JSMutableHandle<LinkedHashMap> hashMap(thread, map->GetLinkedMap());
|
||||
const int32_t argsLength = 3;
|
||||
const uint32_t argsLength = 3;
|
||||
int index = 0;
|
||||
int totalElements = hashMap->NumberOfElements() + hashMap->NumberOfDeletedElements();
|
||||
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
|
||||
@ -314,7 +314,7 @@ JSTaggedValue BuiltinsMap::AddEntriesFromIterable(JSThread *thread, const JSHand
|
||||
if (thread->HasPendingException()) {
|
||||
return JSIterator::IteratorCloseAndReturn(thread, iter);
|
||||
}
|
||||
const int32_t argsLength = 2; // 2: key and value pair
|
||||
const uint32_t argsLength = 2; // 2: key and value pair
|
||||
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
|
||||
EcmaRuntimeCallInfo *info =
|
||||
EcmaInterpreter::NewRuntimeCallInfo(thread, adder, JSHandle<JSTaggedValue>(target), undefined, argsLength);
|
||||
|
@ -73,7 +73,7 @@ JSTaggedValue BuiltinsPromise::PromiseConstructor(EcmaRuntimeCallInfo *argv)
|
||||
auto resolveFunc = resolvingFunction->GetResolveFunction();
|
||||
auto rejectFunc = resolvingFunction->GetRejectFunction();
|
||||
JSHandle<JSTaggedValue> undefined = globalConst->GetHandledUndefined();
|
||||
const int32_t argsLength = 2; // 2: «resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]]»
|
||||
const uint32_t argsLength = 2; // 2: «resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]]»
|
||||
EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, executor, undefined, undefined, argsLength);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
info->SetCallArg(resolveFunc, rejectFunc);
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "libpandabase/macros.h"
|
||||
|
||||
namespace panda::ecmascript::builtins {
|
||||
using JSRecordInfo = ecmascript::JSPandaFile::JSRecordInfo;
|
||||
|
||||
JSTaggedValue BuiltinsPromiseJob::PromiseReactionJob(EcmaRuntimeCallInfo *argv)
|
||||
{
|
||||
@ -52,7 +53,7 @@ JSTaggedValue BuiltinsPromiseJob::PromiseReactionJob(EcmaRuntimeCallInfo *argv)
|
||||
// 3. Let handler be reaction.[[Handler]].
|
||||
JSHandle<JSTaggedValue> handler(thread, reaction->GetHandler());
|
||||
JSHandle<JSTaggedValue> call(thread, capability->GetResolve());
|
||||
const int32_t argsLength = 1;
|
||||
const uint32_t argsLength = 1;
|
||||
JSHandle<JSTaggedValue> undefined = globalConst->GetHandledUndefined();
|
||||
EcmaRuntimeCallInfo *runtimeInfo =
|
||||
EcmaInterpreter::NewRuntimeCallInfo(thread, call, undefined, undefined, argsLength);
|
||||
@ -104,7 +105,7 @@ JSTaggedValue BuiltinsPromiseJob::PromiseResolveThenableJob(EcmaRuntimeCallInfo
|
||||
JSHandle<JSTaggedValue> then = GetCallArg(argv, BuiltinsBase::ArgsPosition::THIRD);
|
||||
|
||||
// 2. Let thenCallResult be Call(then, thenable, «resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]]»).
|
||||
const int32_t argsLength = 2; // 2: «resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]]»
|
||||
const uint32_t argsLength = 2; // 2: «resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]]»
|
||||
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
|
||||
EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, then, thenable, undefined, argsLength);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
@ -200,11 +201,16 @@ JSTaggedValue BuiltinsPromiseJob::DynamicImportJob(EcmaRuntimeCallInfo *argv)
|
||||
}
|
||||
|
||||
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, CatchException(thread, reject));
|
||||
bool isModule = jsPandaFile->IsModule(thread, entryPoint);
|
||||
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, CatchException(thread, reject));
|
||||
JSRecordInfo recordInfo;
|
||||
bool hasRecord = jsPandaFile->CheckAndGetRecordInfo(entryPoint, recordInfo);
|
||||
if (!hasRecord) {
|
||||
LOG_FULL(ERROR) << "cannot find record '" << entryPoint <<"' in basefileName " << fileNameStr << ".";
|
||||
CString msg = "cannot find record '" + entryPoint + "', please check the request path.";
|
||||
THROW_REFERENCE_ERROR_AND_RETURN(thread, msg.c_str(), CatchException(thread, reject));
|
||||
}
|
||||
JSMutableHandle<JSTaggedValue> moduleNamespace(thread, JSTaggedValue::Undefined());
|
||||
// only support importing es module, or return a default object.
|
||||
if (!isModule) {
|
||||
if (!jsPandaFile->IsModule(recordInfo)) {
|
||||
moduleNamespace.Update(vm->GetGlobalEnv()->GetExportOfScript());
|
||||
} else {
|
||||
// b. Let moduleRecord be ! HostResolveImportedModule(referencingScriptOrModule, specifier).
|
||||
|
@ -40,7 +40,7 @@ JSTaggedValue BuiltinsReflect::ReflectApply(EcmaRuntimeCallInfo *argv)
|
||||
|
||||
// 3. Perform PrepareForTailCall().
|
||||
// 4. Return ? Call(target, thisArgument, args).
|
||||
const int32_t argsLength = static_cast<int32_t>(args->GetLength());
|
||||
const uint32_t argsLength = args->GetLength();
|
||||
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
|
||||
EcmaRuntimeCallInfo *info =
|
||||
EcmaInterpreter::NewRuntimeCallInfo(thread, target, thisArgument, undefined, argsLength);
|
||||
@ -75,7 +75,7 @@ JSTaggedValue BuiltinsReflect::ReflectConstruct(EcmaRuntimeCallInfo *argv)
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
JSHandle<TaggedArray> args = JSHandle<TaggedArray>::Cast(argOrAbrupt);
|
||||
// 5. Return ? Construct(target, args, newTarget).
|
||||
const int32_t argsLength = static_cast<int32_t>(args->GetLength());
|
||||
const uint32_t argsLength = args->GetLength();
|
||||
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
|
||||
EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, target, undefined, newTarget, argsLength);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
|
@ -961,7 +961,7 @@ JSTaggedValue BuiltinsRegExp::Replace(EcmaRuntimeCallInfo *argv)
|
||||
replacerArgs->Set(thread, index + 3, namedCaptures.GetTaggedValue()); // 3: position of groups
|
||||
}
|
||||
// iv. Let replValue be Call(replaceValue, undefined, replacerArgs).
|
||||
const int32_t argsLength = static_cast<int32_t>(replacerArgs->GetLength());
|
||||
const uint32_t argsLength = replacerArgs->GetLength();
|
||||
JSHandle<JSTaggedValue> undefined = globalConst->GetHandledUndefined();
|
||||
EcmaRuntimeCallInfo *info =
|
||||
EcmaInterpreter::NewRuntimeCallInfo(thread, inputReplaceValue, undefined, undefined, argsLength);
|
||||
|
@ -205,7 +205,7 @@ JSTaggedValue BuiltinsSet::ForEach(EcmaRuntimeCallInfo *argv)
|
||||
|
||||
// 6.Let entries be the List that is the value of S’s [[SetData]] internal slot.
|
||||
JSMutableHandle<LinkedHashSet> hashSet(thread, set->GetLinkedSet());
|
||||
const int32_t argsLength = 3;
|
||||
const uint32_t argsLength = 3;
|
||||
int index = 0;
|
||||
int totalElements = hashSet->NumberOfElements() + hashSet->NumberOfDeletedElements();
|
||||
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
|
||||
|
@ -859,7 +859,7 @@ JSTaggedValue BuiltinsString::Replace(EcmaRuntimeCallInfo *argv)
|
||||
// If replacer is not undefined, then
|
||||
if (!replaceMethod->IsUndefined()) {
|
||||
// Return Call(replacer, searchValue, «O, replaceValue»).
|
||||
const int32_t argsLength = 2;
|
||||
const uint32_t argsLength = 2;
|
||||
JSHandle<JSTaggedValue> undefined = globalConst->GetHandledUndefined();
|
||||
EcmaRuntimeCallInfo *info =
|
||||
EcmaInterpreter::NewRuntimeCallInfo(thread, replaceMethod, searchTag, undefined, argsLength);
|
||||
@ -897,7 +897,7 @@ JSTaggedValue BuiltinsString::Replace(EcmaRuntimeCallInfo *argv)
|
||||
// If functionalReplace is true, then
|
||||
if (replaceTag->IsCallable()) {
|
||||
// Let replValue be Call(replaceValue, undefined,«matched, pos, and string»).
|
||||
const int32_t argsLength = 3; // 3: «matched, pos, and string»
|
||||
const uint32_t argsLength = 3; // 3: «matched, pos, and string»
|
||||
EcmaRuntimeCallInfo *info =
|
||||
EcmaInterpreter::NewRuntimeCallInfo(thread, replaceTag, undefined, undefined, argsLength);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
@ -1022,7 +1022,7 @@ JSTaggedValue BuiltinsString::ReplaceAll(EcmaRuntimeCallInfo *argv)
|
||||
// If functionalReplace is true, then
|
||||
if (replaceTag->IsCallable()) {
|
||||
// Let replValue be Call(replaceValue, undefined,«matched, pos, and string»).
|
||||
const int32_t argsLength = 3; // 3: «matched, pos, and string»
|
||||
const uint32_t argsLength = 3; // 3: «matched, pos, and string»
|
||||
EcmaRuntimeCallInfo *info =
|
||||
EcmaInterpreter::NewRuntimeCallInfo(thread, replaceTag, undefined, undefined, argsLength);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
@ -1370,7 +1370,7 @@ JSTaggedValue BuiltinsString::Split(EcmaRuntimeCallInfo *argv)
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
if (!splitter->IsUndefined()) {
|
||||
// Return Call(splitter, separator, «O, limit»).
|
||||
const int32_t argsLength = 2;
|
||||
const uint32_t argsLength = 2;
|
||||
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
|
||||
EcmaRuntimeCallInfo *info =
|
||||
EcmaInterpreter::NewRuntimeCallInfo(thread, splitter, seperatorTag, undefined, argsLength);
|
||||
|
@ -222,7 +222,7 @@ JSTaggedValue BuiltinsTypedArray::From(EcmaRuntimeCallInfo *argv)
|
||||
// vi. Set k to k + 1.
|
||||
JSMutableHandle<JSTaggedValue> tKey(thread, JSTaggedValue::Undefined());
|
||||
JSMutableHandle<JSTaggedValue> mapValue(thread, JSTaggedValue::Undefined());
|
||||
const int32_t argsLength = 2;
|
||||
const uint32_t argsLength = 2;
|
||||
uint32_t k = 0;
|
||||
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
|
||||
while (k < len) {
|
||||
@ -277,7 +277,7 @@ JSTaggedValue BuiltinsTypedArray::From(EcmaRuntimeCallInfo *argv)
|
||||
// e. Perform ? Set(targetObj, Pk, mappedValue, true).
|
||||
// f. Set k to k + 1.
|
||||
JSMutableHandle<JSTaggedValue> tKey(thread, JSTaggedValue::Undefined());
|
||||
const int32_t argsLength = 2;
|
||||
const uint32_t argsLength = 2;
|
||||
int64_t k = 0;
|
||||
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
|
||||
JSMutableHandle<JSTaggedValue> kValue(thread, JSTaggedValue::Undefined());
|
||||
@ -521,7 +521,7 @@ JSTaggedValue BuiltinsTypedArray::Every(EcmaRuntimeCallInfo *argv)
|
||||
// v. If testResult is false, return false.
|
||||
// e. Increase k by 1.
|
||||
JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
|
||||
const int32_t argsLength = 3;
|
||||
const uint32_t argsLength = 3;
|
||||
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
|
||||
uint32_t k = 0;
|
||||
while (k < len) {
|
||||
@ -708,7 +708,7 @@ JSTaggedValue BuiltinsTypedArray::ForEach(EcmaRuntimeCallInfo *argv)
|
||||
// iv. ReturnIfAbrupt(funcResult).
|
||||
// e. Increase k by 1.
|
||||
JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
|
||||
const int32_t argsLength = 3;
|
||||
const uint32_t argsLength = 3;
|
||||
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
|
||||
uint32_t k = 0;
|
||||
while (k < len) {
|
||||
@ -936,7 +936,7 @@ JSTaggedValue BuiltinsTypedArray::Map(EcmaRuntimeCallInfo *argv)
|
||||
JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
|
||||
JSMutableHandle<JSTaggedValue> mapValue(thread, JSTaggedValue::Undefined());
|
||||
JSMutableHandle<JSTaggedValue> kValue(thread, JSTaggedValue::Undefined());
|
||||
const int32_t argsLength = 3;
|
||||
const uint32_t argsLength = 3;
|
||||
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
|
||||
for (uint32_t k = 0; k < len; k++) {
|
||||
key.Update(JSTaggedValue(k));
|
||||
@ -1513,7 +1513,7 @@ JSTaggedValue BuiltinsTypedArray::Subarray(EcmaRuntimeCallInfo *argv)
|
||||
// 21. Let argumentsList be «buffer, beginByteOffset, newLength».
|
||||
// 5. Let buffer be the value of O’s [[ViewedArrayBuffer]] internal slot.
|
||||
// 22. Return Construct(constructor, argumentsList).
|
||||
const int32_t argsLength = 3;
|
||||
const uint32_t argsLength = 3;
|
||||
JSTaggedType args[argsLength] = {
|
||||
buffer.GetRawData(),
|
||||
JSTaggedValue(beginByteOffset).GetRawData(),
|
||||
|
@ -87,8 +87,8 @@ JSTaggedValue BuiltinsWeakMap::Delete(EcmaRuntimeCallInfo *argv)
|
||||
|
||||
JSHandle<JSWeakMap> weakMap(self);
|
||||
JSHandle<JSTaggedValue> key = GetCallArg(argv, 0);
|
||||
// 5.if Type(key) is not Object, return false.
|
||||
if (!key->IsHeapObject()) {
|
||||
// 5.If CanBeHeldWeakly(key) is false, return false.
|
||||
if (!JSTaggedValue::CanBeHeldWeakly(thread, key)) {
|
||||
return GetTaggedBoolean(false);
|
||||
}
|
||||
return GetTaggedBoolean(JSWeakMap::Delete(thread, weakMap, key));
|
||||
@ -109,8 +109,8 @@ JSTaggedValue BuiltinsWeakMap::Has(EcmaRuntimeCallInfo *argv)
|
||||
JSWeakMap *jsWeakMap = JSWeakMap::Cast(*JSTaggedValue::ToObject(thread, self));
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
JSHandle<JSTaggedValue> key = GetCallArg(argv, 0);
|
||||
// 5.if Type(key) is not Object, return false.
|
||||
if (!key->IsHeapObject()) {
|
||||
// 5.If CanBeHeldWeakly(key) is false, return false.
|
||||
if (!JSTaggedValue::CanBeHeldWeakly(thread, key)) {
|
||||
return GetTaggedBoolean(false);
|
||||
}
|
||||
return GetTaggedBoolean(jsWeakMap->Has(key.GetTaggedValue()));
|
||||
@ -131,7 +131,8 @@ JSTaggedValue BuiltinsWeakMap::Get(EcmaRuntimeCallInfo *argv)
|
||||
JSWeakMap *jsWeakMap = JSWeakMap::Cast(*JSTaggedValue::ToObject(thread, self));
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
JSHandle<JSTaggedValue> key = GetCallArg(argv, 0);
|
||||
if (!key->IsHeapObject()) {
|
||||
// 4.If CanBeHeldWeakly(key) is false, return undefined.
|
||||
if (!JSTaggedValue::CanBeHeldWeakly(thread, key)) {
|
||||
return JSTaggedValue::Undefined();
|
||||
}
|
||||
return jsWeakMap->Get(key.GetTaggedValue());
|
||||
@ -152,11 +153,9 @@ JSTaggedValue BuiltinsWeakMap::Set(EcmaRuntimeCallInfo *argv)
|
||||
}
|
||||
|
||||
JSHandle<JSTaggedValue> key = GetCallArg(argv, 0);
|
||||
if (!key->IsHeapObject()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not an object.", JSTaggedValue::Exception());
|
||||
}
|
||||
if (key->IsSymbol() || key->IsString()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "key is Symblol or String", JSTaggedValue::Exception());
|
||||
// 4.If CanBeHeldWeakly(key) is false, throw a TypeError exception.
|
||||
if (!JSTaggedValue::CanBeHeldWeakly(thread, key)) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "invalid value used as weak map key.", JSTaggedValue::Exception());
|
||||
}
|
||||
|
||||
JSHandle<JSTaggedValue> value = GetCallArg(argv, 1);
|
||||
|
@ -32,10 +32,10 @@ JSTaggedValue BuiltinsWeakRef::WeakRefConstructor(EcmaRuntimeCallInfo *argv)
|
||||
if (newTarget->IsUndefined()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "new target can't be undefined", JSTaggedValue::Exception());
|
||||
}
|
||||
// 2. If Type(target) is not Object, throw a TypeError exception.
|
||||
// 2. If CanBeHeldWeakly(target) is false, throw a TypeError exception.
|
||||
JSHandle<JSTaggedValue> target = GetCallArg(argv, 0);
|
||||
if (!target->IsECMAObject()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "target is not object", JSTaggedValue::Exception());
|
||||
if (!JSTaggedValue::CanBeHeldWeakly(thread, target)) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "target invalid", JSTaggedValue::Exception());
|
||||
}
|
||||
// 3. Let weakRef be ? OrdinaryCreateFromConstructor(NewTarget, "%WeakRef.prototype%", « [[WeakRefTarget]] »).
|
||||
JSHandle<JSTaggedValue> constructor = GetConstructor(argv);
|
||||
|
@ -120,11 +120,9 @@ JSTaggedValue BuiltinsWeakSet::Add(EcmaRuntimeCallInfo *argv)
|
||||
}
|
||||
|
||||
JSHandle<JSTaggedValue> value(GetCallArg(argv, 0));
|
||||
if (!value->IsHeapObject()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "value is not an object", JSTaggedValue::Exception());
|
||||
}
|
||||
if (value->IsSymbol() || value->IsString()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "value is Symblol or String", JSTaggedValue::Exception());
|
||||
// 4.If CanBeHeldWeakly(value) is false, throw a TypeError exception.
|
||||
if (!JSTaggedValue::CanBeHeldWeakly(thread, value)) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "invalid value used in weak set", JSTaggedValue::Exception());
|
||||
}
|
||||
|
||||
JSHandle<JSWeakSet> weakSet(thread, JSWeakSet::Cast(*JSTaggedValue::ToObject(thread, self)));
|
||||
@ -149,7 +147,8 @@ JSTaggedValue BuiltinsWeakSet::Delete(EcmaRuntimeCallInfo *argv)
|
||||
JSHandle<JSWeakSet> weakSet(thread, JSWeakSet::Cast(*JSTaggedValue::ToObject(thread, self)));
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);
|
||||
if (!value->IsHeapObject()) {
|
||||
// 4.If CanBeHeldWeakly(value) is false, return false.
|
||||
if (!JSTaggedValue::CanBeHeldWeakly(thread, value)) {
|
||||
GetTaggedBoolean(false);
|
||||
}
|
||||
return GetTaggedBoolean(JSWeakSet::Delete(thread, weakSet, value));
|
||||
@ -170,7 +169,8 @@ JSTaggedValue BuiltinsWeakSet::Has(EcmaRuntimeCallInfo *argv)
|
||||
JSWeakSet *jsWeakSet = JSWeakSet::Cast(*JSTaggedValue::ToObject(thread, self));
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);
|
||||
if (!value->IsHeapObject()) {
|
||||
// 4.If CanBeHeldWeakly(value) is false, return false.
|
||||
if (!JSTaggedValue::CanBeHeldWeakly(thread, value)) {
|
||||
GetTaggedBoolean(false);
|
||||
}
|
||||
return GetTaggedBoolean(jsWeakSet->Has(value.GetTaggedValue()));
|
||||
|
@ -441,4 +441,96 @@ HWTEST_F_L0(BuiltinsFinalizationRegistryTest, Unregister2)
|
||||
vm->SetEnableForceGC(true);
|
||||
ASSERT_EQ(testValue, 0);
|
||||
}
|
||||
|
||||
// finalizationRegistry.Register(target, heldValue [ , unregisterToken ]) target and unregisterToken Symbol
|
||||
HWTEST_F_L0(BuiltinsFinalizationRegistryTest, RegisterTargetSymbol)
|
||||
{
|
||||
testValue = 0;
|
||||
EcmaVM *vm = thread->GetEcmaVM();
|
||||
|
||||
JSTaggedValue result = CreateFinalizationRegistryConstructor(thread);
|
||||
JSHandle<JSFinalizationRegistry> jsfinalizationRegistry(thread, result);
|
||||
|
||||
vm->SetEnableForceGC(false);
|
||||
JSTaggedValue target = JSTaggedValue::Undefined();
|
||||
JSTaggedValue target1 = JSTaggedValue::Undefined();
|
||||
{
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
||||
JSHandle<JSSymbol> symbol1 = thread->GetEcmaVM()->GetFactory()->NewJSSymbol();
|
||||
JSHandle<JSSymbol> symbol2 = thread->GetEcmaVM()->GetFactory()->NewJSSymbol();
|
||||
target = symbol1.GetTaggedValue();
|
||||
target1 = symbol2.GetTaggedValue();
|
||||
auto ecmaRuntimeCallInfo =
|
||||
TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10); // 10 means 3 call args
|
||||
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetThis(jsfinalizationRegistry.GetTaggedValue());
|
||||
ecmaRuntimeCallInfo->SetCallArg(0, target);
|
||||
ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(10));
|
||||
ecmaRuntimeCallInfo->SetCallArg(2, target); // 2 means the unregisterToken arg
|
||||
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
|
||||
BuiltinsFinalizationRegistry::Register(ecmaRuntimeCallInfo);
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
|
||||
auto ecmaRuntimeCallInfo1 =
|
||||
TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10); // 10 means 3 call args
|
||||
ecmaRuntimeCallInfo1->SetFunction(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo1->SetThis(jsfinalizationRegistry.GetTaggedValue());
|
||||
ecmaRuntimeCallInfo1->SetCallArg(0, target1);
|
||||
ecmaRuntimeCallInfo1->SetCallArg(1, JSTaggedValue(10));
|
||||
ecmaRuntimeCallInfo1->SetCallArg(2, target1); // 2 means the unregisterToken arg
|
||||
|
||||
[[maybe_unused]] auto prev1 = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1);
|
||||
BuiltinsFinalizationRegistry::Register(ecmaRuntimeCallInfo1);
|
||||
TestHelper::TearDownFrame(thread, prev1);
|
||||
}
|
||||
vm->CollectGarbage(TriggerGCType::FULL_GC);
|
||||
if (!thread->HasPendingException()) {
|
||||
job::MicroJobQueue::ExecutePendingJob(thread, vm->GetJSThread()->GetCurrentEcmaContext()->GetMicroJobQueue());
|
||||
}
|
||||
vm->SetEnableForceGC(true);
|
||||
ASSERT_EQ(testValue, 2);
|
||||
}
|
||||
|
||||
// finalizationRegistry.Unregister(unregisterToken) unregisterToken Symbol
|
||||
HWTEST_F_L0(BuiltinsFinalizationRegistryTest, UnregisterTokenSymbol)
|
||||
{
|
||||
testValue = 0;
|
||||
EcmaVM *vm = thread->GetEcmaVM();
|
||||
|
||||
JSTaggedValue result = CreateFinalizationRegistryConstructor(thread);
|
||||
JSHandle<JSFinalizationRegistry> jsfinalizationRegistry(thread, result);
|
||||
vm->SetEnableForceGC(false);
|
||||
JSTaggedValue target = JSTaggedValue::Undefined();
|
||||
{
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
||||
JSHandle<JSSymbol> symbol = thread->GetEcmaVM()->GetFactory()->NewJSSymbol();
|
||||
target = symbol.GetTaggedValue();
|
||||
auto ecmaRuntimeCallInfo =
|
||||
TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10); // 10 means 3 call args
|
||||
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetThis(jsfinalizationRegistry.GetTaggedValue());
|
||||
ecmaRuntimeCallInfo->SetCallArg(0, target);
|
||||
ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(10));
|
||||
ecmaRuntimeCallInfo->SetCallArg(2, target);
|
||||
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
|
||||
BuiltinsFinalizationRegistry::Register(ecmaRuntimeCallInfo);
|
||||
|
||||
auto ecmaRuntimeCallInfo1 =
|
||||
TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); // 6 means 1 call args
|
||||
ecmaRuntimeCallInfo1->SetFunction(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo1->SetThis(jsfinalizationRegistry.GetTaggedValue());
|
||||
ecmaRuntimeCallInfo1->SetCallArg(0, target);
|
||||
|
||||
BuiltinsFinalizationRegistry::Unregister(ecmaRuntimeCallInfo1);
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
}
|
||||
vm->CollectGarbage(TriggerGCType::FULL_GC);
|
||||
if (!thread->HasPendingException()) {
|
||||
job::MicroJobQueue::ExecutePendingJob(thread, vm->GetJSThread()->GetCurrentEcmaContext()->GetMicroJobQueue());
|
||||
}
|
||||
vm->SetEnableForceGC(true);
|
||||
ASSERT_EQ(testValue, 0);
|
||||
}
|
||||
} // namespace panda::test
|
||||
|
@ -213,4 +213,55 @@ HWTEST_F_L0(BuiltinsWeakMapTest, DeleteAndRemove)
|
||||
|
||||
EXPECT_EQ(result4.GetRawData(), JSTaggedValue::False().GetRawData());
|
||||
}
|
||||
|
||||
HWTEST_F_L0(BuiltinsWeakMapTest, SymbolKey)
|
||||
{
|
||||
// create jsWeakMap
|
||||
JSHandle<JSWeakMap> weakMap(thread, CreateBuiltinsWeakMap(thread));
|
||||
|
||||
// add 2 symbol keys
|
||||
JSTaggedValue lastKey(JSTaggedValue::Undefined());
|
||||
for (int i = 0; i < 2; i++) {
|
||||
JSHandle<JSSymbol> symbolKey = thread->GetEcmaVM()->GetFactory()->NewJSSymbol();
|
||||
JSHandle<JSTaggedValue> key(symbolKey);
|
||||
auto ecmaRuntimeCallInfo =
|
||||
TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); // 8 means 2 call args
|
||||
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetThis(weakMap.GetTaggedValue());
|
||||
ecmaRuntimeCallInfo->SetCallArg(0, key.GetTaggedValue());
|
||||
ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(static_cast<int32_t>(i)));
|
||||
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
|
||||
// set
|
||||
JSTaggedValue result1 = BuiltinsWeakMap::Set(ecmaRuntimeCallInfo);
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
|
||||
EXPECT_TRUE(result1.IsECMAObject());
|
||||
JSWeakMap *jsWeakMap = JSWeakMap::Cast(reinterpret_cast<TaggedObject *>(result1.GetRawData()));
|
||||
EXPECT_EQ(jsWeakMap->GetSize(), static_cast<int>(i) + 1);
|
||||
lastKey = key.GetTaggedValue();
|
||||
}
|
||||
|
||||
// check whether jsWeakMap can get and delete lastKey
|
||||
|
||||
auto ecmaRuntimeCallInfo1 =
|
||||
TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); // 6 means 1 call arg
|
||||
ecmaRuntimeCallInfo1->SetFunction(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo1->SetThis(weakMap.GetTaggedValue());
|
||||
ecmaRuntimeCallInfo1->SetCallArg(0, lastKey);
|
||||
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1);
|
||||
// get
|
||||
JSTaggedValue result2 = BuiltinsWeakMap::Get(ecmaRuntimeCallInfo1);
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
EXPECT_EQ(result2, JSTaggedValue(1));
|
||||
|
||||
// delete
|
||||
JSTaggedValue result3 = BuiltinsWeakMap::Delete(ecmaRuntimeCallInfo1);
|
||||
EXPECT_EQ(result3.GetRawData(), JSTaggedValue::True().GetRawData());
|
||||
|
||||
// check deleteKey is deleted
|
||||
JSTaggedValue result4 = BuiltinsWeakMap::Has(ecmaRuntimeCallInfo1);
|
||||
EXPECT_EQ(result4.GetRawData(), JSTaggedValue::False().GetRawData());
|
||||
}
|
||||
} // namespace panda::test
|
||||
|
@ -188,4 +188,38 @@ HWTEST_F_L0(BuiltinsWeakRefTest, Deref3)
|
||||
vm->SetEnableForceGC(true);
|
||||
ASSERT_TRUE(!result2.IsUndefined());
|
||||
}
|
||||
|
||||
// symbol target
|
||||
HWTEST_F_L0(BuiltinsWeakRefTest, SymbolTarget)
|
||||
{
|
||||
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
|
||||
JSHandle<JSSymbol> symbolTarget = thread->GetEcmaVM()->GetFactory()->NewJSSymbol();
|
||||
JSHandle<JSTaggedValue> target(symbolTarget);
|
||||
|
||||
JSHandle<JSFunction> weakRef(env->GetBuiltinsWeakRefFunction());
|
||||
|
||||
auto ecmaRuntimeCallInfo1 =
|
||||
TestHelper::CreateEcmaRuntimeCallInfo(thread, weakRef.GetTaggedValue(), 6); // 6 means 1 call arg
|
||||
ecmaRuntimeCallInfo1->SetFunction(weakRef.GetTaggedValue());
|
||||
ecmaRuntimeCallInfo1->SetThis(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo1->SetCallArg(0, target.GetTaggedValue());
|
||||
|
||||
// constructor
|
||||
[[maybe_unused]] auto prev1 = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1);
|
||||
JSTaggedValue result1 = BuiltinsWeakRef::WeakRefConstructor(ecmaRuntimeCallInfo1);
|
||||
TestHelper::TearDownFrame(thread, prev1);
|
||||
ASSERT_TRUE(result1.IsECMAObject());
|
||||
|
||||
JSHandle<JSWeakRef> jsWeakRef(thread, JSWeakRef::Cast(reinterpret_cast<TaggedObject *>(result1.GetRawData())));
|
||||
auto ecmaRuntimeCallInfo2 =
|
||||
TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4); // 4 means 0 call arg
|
||||
ecmaRuntimeCallInfo2->SetFunction(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo2->SetThis(jsWeakRef.GetTaggedValue());
|
||||
|
||||
// weakRef.Deref()
|
||||
[[maybe_unused]] auto prev2 = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo2);
|
||||
JSTaggedValue result2 = BuiltinsWeakRef::Deref(ecmaRuntimeCallInfo2);
|
||||
TestHelper::TearDownFrame(thread, prev2);
|
||||
ASSERT_EQ(result2, target.GetTaggedValue());
|
||||
}
|
||||
} // namespace panda::test
|
||||
|
@ -207,4 +207,54 @@ HWTEST_F_L0(BuiltinsWeakSetTest, DeleteAndRemove)
|
||||
|
||||
EXPECT_EQ(result4.GetRawData(), JSTaggedValue::False().GetRawData());
|
||||
}
|
||||
|
||||
HWTEST_F_L0(BuiltinsWeakSetTest, SymbolKey)
|
||||
{
|
||||
// create jsSet
|
||||
JSHandle<JSWeakSet> weakSet(thread, CreateBuiltinsWeakSet(thread));
|
||||
|
||||
// add 2 keys
|
||||
JSTaggedValue lastKey(JSTaggedValue::Undefined());
|
||||
for (int i = 0; i < 2; i++) {
|
||||
JSHandle<JSSymbol> symbolKey = thread->GetEcmaVM()->GetFactory()->NewJSSymbol();
|
||||
JSHandle<JSTaggedValue> key(symbolKey);
|
||||
|
||||
auto ecmaRuntimeCallInfo =
|
||||
TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); // 6 means 1 call arg
|
||||
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetThis(weakSet.GetTaggedValue());
|
||||
ecmaRuntimeCallInfo->SetCallArg(0, key.GetTaggedValue());
|
||||
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
|
||||
// add
|
||||
JSTaggedValue result1 = BuiltinsWeakSet::Add(ecmaRuntimeCallInfo);
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
|
||||
EXPECT_TRUE(result1.IsECMAObject());
|
||||
JSWeakSet *jsWeakSet = JSWeakSet::Cast(reinterpret_cast<TaggedObject *>(result1.GetRawData()));
|
||||
EXPECT_EQ(jsWeakSet->GetSize(), static_cast<int>(i) + 1);
|
||||
lastKey = key.GetTaggedValue();
|
||||
}
|
||||
// whether jsWeakSet has delete lastKey
|
||||
|
||||
auto ecmaRuntimeCallInfo1 =
|
||||
TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); // 6 means 1 call arg
|
||||
ecmaRuntimeCallInfo1->SetFunction(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo1->SetThis(weakSet.GetTaggedValue());
|
||||
ecmaRuntimeCallInfo1->SetCallArg(0, lastKey);
|
||||
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1);
|
||||
// has
|
||||
JSTaggedValue result2 = BuiltinsWeakSet::Has(ecmaRuntimeCallInfo1);
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
EXPECT_EQ(result2.GetRawData(), JSTaggedValue::True().GetRawData());
|
||||
|
||||
// delete
|
||||
JSTaggedValue result3 = BuiltinsWeakSet::Delete(ecmaRuntimeCallInfo1);
|
||||
EXPECT_EQ(result3.GetRawData(), JSTaggedValue::True().GetRawData());
|
||||
|
||||
// check deleteKey is deleted
|
||||
JSTaggedValue result4 = BuiltinsWeakSet::Has(ecmaRuntimeCallInfo1);
|
||||
EXPECT_EQ(result4.GetRawData(), JSTaggedValue::False().GetRawData());
|
||||
}
|
||||
} // namespace panda::test
|
||||
|
@ -65,6 +65,7 @@ ohos_source_set("libark_jsoptimizer_set") {
|
||||
"assembler/x64/extended_assembler_x64.cpp",
|
||||
"assembler_module.cpp",
|
||||
"async_function_lowering.cpp",
|
||||
"base/depend_chain_helper.cpp",
|
||||
"bc_call_signature.cpp",
|
||||
"builtins/builtins_call_signature.cpp",
|
||||
"builtins/builtins_string_stub_builder.cpp",
|
||||
@ -104,6 +105,7 @@ ohos_source_set("libark_jsoptimizer_set") {
|
||||
"number_speculative_lowering.cpp",
|
||||
"number_speculative_retype.cpp",
|
||||
"number_speculative_runner.cpp",
|
||||
"object_access_helper.cpp",
|
||||
"operations_stub_builder.cpp",
|
||||
"pass_manager.cpp",
|
||||
"profiler_stub_builder.cpp",
|
||||
|
@ -34,11 +34,11 @@ GateRef AccessObjectStubBuilder::LoadObjByName(GateRef glue, GateRef receiver, G
|
||||
GateRef value = 0;
|
||||
ICStubBuilder builder(this);
|
||||
builder.SetParameters(glue, receiver, profileTypeInfo, value, slotId);
|
||||
builder.LoadICByName(&result, &tryFastPath, &slowPath, &exit);
|
||||
builder.LoadICByName(&result, &tryFastPath, &slowPath, &exit, callback);
|
||||
Bind(&tryFastPath);
|
||||
{
|
||||
GateRef propKey = ResolvePropKey(glue, prop, info);
|
||||
result = GetPropertyByName(glue, receiver, propKey);
|
||||
result = GetPropertyByName(glue, receiver, propKey, callback);
|
||||
Label notHole(env);
|
||||
Branch(TaggedIsHole(*result), &slowPath, ¬Hole);
|
||||
Bind(¬Hole);
|
||||
@ -75,7 +75,7 @@ GateRef AccessObjectStubBuilder::DeprecatedLoadObjByName(GateRef glue, GateRef r
|
||||
Branch(TaggedIsHeapObject(receiver), &fastPath, &slowPath);
|
||||
Bind(&fastPath);
|
||||
{
|
||||
result = GetPropertyByName(glue, receiver, propKey);
|
||||
result = GetPropertyByName(glue, receiver, propKey, ProfileOperation());
|
||||
Branch(TaggedIsHole(*result), &slowPath, &exit);
|
||||
}
|
||||
Bind(&slowPath);
|
||||
@ -129,8 +129,8 @@ GateRef AccessObjectStubBuilder::StoreObjByName(GateRef glue, GateRef receiver,
|
||||
GateRef AccessObjectStubBuilder::ResolvePropKey(GateRef glue, GateRef prop, const StringIdInfo &info)
|
||||
{
|
||||
if (jsFunc_ != Circuit::NullGate()) {
|
||||
GateRef key = LoadObjectFromConstPool(jsFunc_, prop);
|
||||
return key;
|
||||
GateRef constpool = GetConstPoolFromFunction(jsFunc_);
|
||||
return GetStringFromConstPool(glue, constpool, ChangeIntPtrToInt32(prop));
|
||||
}
|
||||
if (!info.IsValid()) {
|
||||
return prop;
|
||||
@ -142,7 +142,7 @@ GateRef AccessObjectStubBuilder::ResolvePropKey(GateRef glue, GateRef prop, cons
|
||||
}
|
||||
|
||||
GateRef AccessObjectStubBuilder::LoadObjByValue(GateRef glue, GateRef receiver, GateRef key, GateRef profileTypeInfo,
|
||||
GateRef slotId)
|
||||
GateRef slotId, ProfileOperation callback)
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
Label entry(env);
|
||||
@ -155,10 +155,10 @@ GateRef AccessObjectStubBuilder::LoadObjByValue(GateRef glue, GateRef receiver,
|
||||
GateRef value = 0;
|
||||
ICStubBuilder builder(this);
|
||||
builder.SetParameters(glue, receiver, profileTypeInfo, value, slotId, key);
|
||||
builder.LoadICByValue(&result, &tryFastPath, &slowPath, &exit);
|
||||
builder.LoadICByValue(&result, &tryFastPath, &slowPath, &exit, callback);
|
||||
Bind(&tryFastPath);
|
||||
{
|
||||
result = GetPropertyByValue(glue, receiver, key);
|
||||
result = GetPropertyByValue(glue, receiver, key, callback);
|
||||
Branch(TaggedIsHole(*result), &slowPath, &exit);
|
||||
}
|
||||
Bind(&slowPath);
|
||||
@ -187,7 +187,7 @@ GateRef AccessObjectStubBuilder::DeprecatedLoadObjByValue(GateRef glue, GateRef
|
||||
Branch(TaggedIsHeapObject(receiver), &fastPath, &slowPath);
|
||||
Bind(&fastPath);
|
||||
{
|
||||
result = GetPropertyByValue(glue, receiver, key);
|
||||
result = GetPropertyByValue(glue, receiver, key, ProfileOperation());
|
||||
Branch(TaggedIsHole(*result), &slowPath, &exit);
|
||||
}
|
||||
Bind(&slowPath);
|
||||
@ -234,7 +234,8 @@ GateRef AccessObjectStubBuilder::StoreObjByValue(GateRef glue, GateRef receiver,
|
||||
}
|
||||
|
||||
GateRef AccessObjectStubBuilder::TryLoadGlobalByName(GateRef glue, GateRef prop, const StringIdInfo &info,
|
||||
GateRef profileTypeInfo, GateRef slotId)
|
||||
GateRef profileTypeInfo, GateRef slotId,
|
||||
ProfileOperation callback)
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
Label entry(env);
|
||||
@ -264,7 +265,7 @@ GateRef AccessObjectStubBuilder::TryLoadGlobalByName(GateRef glue, GateRef prop,
|
||||
Bind(¬FoundInRecord);
|
||||
{
|
||||
GateRef globalObject = GetGlobalObject(glue);
|
||||
result = GetGlobalOwnProperty(glue, globalObject, propKey);
|
||||
result = GetGlobalOwnProperty(glue, globalObject, propKey, callback);
|
||||
Branch(TaggedIsHole(*result), &slowPath, &exit);
|
||||
}
|
||||
}
|
||||
@ -283,7 +284,8 @@ GateRef AccessObjectStubBuilder::TryLoadGlobalByName(GateRef glue, GateRef prop,
|
||||
}
|
||||
|
||||
GateRef AccessObjectStubBuilder::TryStoreGlobalByName(GateRef glue, GateRef prop, const StringIdInfo &info,
|
||||
GateRef value, GateRef profileTypeInfo, GateRef slotId)
|
||||
GateRef value, GateRef profileTypeInfo, GateRef slotId,
|
||||
ProfileOperation callback)
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
Label entry(env);
|
||||
@ -312,7 +314,7 @@ GateRef AccessObjectStubBuilder::TryStoreGlobalByName(GateRef glue, GateRef prop
|
||||
Bind(¬FoundInRecord);
|
||||
{
|
||||
GateRef globalObject = GetGlobalObject(glue);
|
||||
result = GetGlobalOwnProperty(glue, globalObject, propKey);
|
||||
result = GetGlobalOwnProperty(glue, globalObject, propKey, callback);
|
||||
Label isFoundInGlobal(env);
|
||||
Label notFoundInGlobal(env);
|
||||
Branch(TaggedIsHole(*result), ¬FoundInGlobal, &isFoundInGlobal);
|
||||
@ -345,7 +347,7 @@ GateRef AccessObjectStubBuilder::TryStoreGlobalByName(GateRef glue, GateRef prop
|
||||
}
|
||||
|
||||
GateRef AccessObjectStubBuilder::LoadGlobalVar(GateRef glue, GateRef prop, const StringIdInfo &info,
|
||||
GateRef profileTypeInfo, GateRef slotId)
|
||||
GateRef profileTypeInfo, GateRef slotId, ProfileOperation callback)
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
Label entry(env);
|
||||
@ -364,7 +366,7 @@ GateRef AccessObjectStubBuilder::LoadGlobalVar(GateRef glue, GateRef prop, const
|
||||
{
|
||||
GateRef globalObject = GetGlobalObject(glue);
|
||||
GateRef propKey = ResolvePropKey(glue, prop, info);
|
||||
result = GetGlobalOwnProperty(glue, globalObject, propKey);
|
||||
result = GetGlobalOwnProperty(glue, globalObject, propKey, callback);
|
||||
Branch(TaggedIsHole(*result), &slowPath, &exit);
|
||||
}
|
||||
Bind(&slowPath);
|
||||
|
@ -38,16 +38,17 @@ public:
|
||||
GateRef DeprecatedLoadObjByName(GateRef glue, GateRef receiver, GateRef propKey);
|
||||
GateRef StoreObjByName(GateRef glue, GateRef receiver, GateRef prop, const StringIdInfo &info, GateRef value,
|
||||
GateRef profileTypeInfo, GateRef slotId, ProfileOperation callback = ProfileOperation());
|
||||
GateRef LoadObjByValue(GateRef glue, GateRef receiver, GateRef key, GateRef profileTypeInfo, GateRef slotId);
|
||||
GateRef LoadObjByValue(GateRef glue, GateRef receiver, GateRef key, GateRef profileTypeInfo, GateRef slotId,
|
||||
ProfileOperation callback = ProfileOperation());
|
||||
GateRef StoreObjByValue(GateRef glue, GateRef receiver, GateRef key, GateRef value, GateRef profileTypeInfo,
|
||||
GateRef slotId, ProfileOperation callback = ProfileOperation());
|
||||
GateRef DeprecatedLoadObjByValue(GateRef glue, GateRef receiver, GateRef key);
|
||||
GateRef TryLoadGlobalByName(GateRef glue, GateRef prop, const StringIdInfo &info,
|
||||
GateRef profileTypeInfo, GateRef slotId);
|
||||
GateRef profileTypeInfo, GateRef slotId, ProfileOperation callback);
|
||||
GateRef TryStoreGlobalByName(GateRef glue, GateRef prop, const StringIdInfo &info,
|
||||
GateRef value, GateRef profileTypeInfo, GateRef slotId);
|
||||
GateRef value, GateRef profileTypeInfo, GateRef slotId, ProfileOperation callback);
|
||||
GateRef LoadGlobalVar(GateRef glue, GateRef prop, const StringIdInfo &info,
|
||||
GateRef profileTypeInfo, GateRef slotId);
|
||||
GateRef profileTypeInfo, GateRef slotId, ProfileOperation callback);
|
||||
GateRef StoreGlobalVar(GateRef glue, GateRef prop, const StringIdInfo &info,
|
||||
GateRef value, GateRef profileTypeInfo, GateRef slotId);
|
||||
private:
|
||||
|
@ -157,22 +157,19 @@ int Main(const int argc, const char **argv)
|
||||
size_t maxMethodsInModule = runtimeOptions.GetCompilerModuleMethods();
|
||||
bool isEnableTypeLowering = runtimeOptions.IsEnableTypeLowering();
|
||||
bool isEnableEarlyElimination = runtimeOptions.IsEnableEarlyElimination();
|
||||
bool isEnableRangeGuard = runtimeOptions.IsEnableRangeGuard();
|
||||
bool isEnableLaterElimination = runtimeOptions.IsEnableLaterElimination();
|
||||
bool isEnableValueNumbering = runtimeOptions.IsEnableValueNumbering();
|
||||
bool isEnableOptInlining = runtimeOptions.IsEnableOptInlining();
|
||||
bool isEnableOptStaticMethod = runtimeOptions.IsEnableOptStaticMethod();
|
||||
bool isEnableTypeInfer = isEnableTypeLowering ||
|
||||
vm->GetJSThread()->GetCurrentEcmaContext()->GetTSManager()->AssertTypes();
|
||||
bool isEnableOptPGOType = runtimeOptions.IsEnableOptPGOType();
|
||||
bool isEnableOptTrackField = runtimeOptions.IsEnableOptTrackField();
|
||||
bool isEnableOptLoopPeeling = runtimeOptions.IsEnableOptLoopPeeling();
|
||||
|
||||
PassOptions passOptions(isEnableTypeLowering, isEnableEarlyElimination, isEnableRangeGuard, isEnableLaterElimination,
|
||||
PassOptions passOptions(isEnableTypeLowering, isEnableEarlyElimination, isEnableLaterElimination,
|
||||
isEnableValueNumbering, isEnableTypeInfer, isEnableOptInlining,
|
||||
isEnableOptStaticMethod, isEnableOptPGOType,
|
||||
isEnableOptTrackField, isEnableOptLoopPeeling);
|
||||
|
||||
isEnableOptPGOType, isEnableOptTrackField, isEnableOptLoopPeeling);
|
||||
|
||||
uint32_t hotnessThreshold = runtimeOptions.GetPGOHotnessThreshold();
|
||||
AOTInitialize(vm);
|
||||
|
||||
|
@ -32,8 +32,9 @@ public:
|
||||
AOTFileInfo() = default;
|
||||
virtual ~AOTFileInfo() = default;
|
||||
|
||||
static constexpr uint32_t TEXT_SEC_ALIGN = 16;
|
||||
static constexpr uint32_t DATA_SEC_ALIGN = 8;
|
||||
static constexpr uint32_t TEXT_SEC_ALIGN = 4096;
|
||||
static constexpr uint32_t PAGE_ALIGN = 4096;
|
||||
|
||||
struct FuncEntryDes {
|
||||
uint64_t codeAddr_ {};
|
||||
@ -149,7 +150,7 @@ public:
|
||||
des.SetArkStackMapSize(size);
|
||||
}
|
||||
|
||||
size_t GetCodeUnitsNum()
|
||||
size_t GetCodeUnitsNum() const
|
||||
{
|
||||
return des_.size();
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ class JSThread;
|
||||
* | AOT Function Entry Index | |
|
||||
* +--------------------------------+----
|
||||
* | AOT Instance Hclass (IHC) |
|
||||
* | AOT Constructor Hclass (CHC) |
|
||||
* +--------------------------------+
|
||||
*/
|
||||
class AOTLiteralInfo : public TaggedArray {
|
||||
@ -64,6 +65,7 @@ public:
|
||||
{
|
||||
TaggedArray::InitializeWithSpecialValue(initValue, capacity + RESERVED_LENGTH, extraLength);
|
||||
SetIhc(JSTaggedValue::Undefined());
|
||||
SetChc(JSTaggedValue::Undefined());
|
||||
}
|
||||
|
||||
inline uint32_t GetCacheLength() const
|
||||
@ -81,6 +83,16 @@ public:
|
||||
return JSTaggedValue(Barriers::GetValue<JSTaggedType>(GetData(), GetIhcOffset()));
|
||||
}
|
||||
|
||||
inline void SetChc(JSTaggedValue value)
|
||||
{
|
||||
Barriers::SetPrimitive(GetData(), GetChcOffset(), value.GetRawData());
|
||||
}
|
||||
|
||||
inline JSTaggedValue GetChc() const
|
||||
{
|
||||
return JSTaggedValue(Barriers::GetValue<JSTaggedType>(GetData(), GetChcOffset()));
|
||||
}
|
||||
|
||||
inline void SetObjectToCache(JSThread *thread, uint32_t index, JSTaggedValue value)
|
||||
{
|
||||
Set(thread, index, value);
|
||||
@ -91,13 +103,19 @@ public:
|
||||
return Get(index);
|
||||
}
|
||||
private:
|
||||
static constexpr size_t AOT_IHC_INDEX = 1;
|
||||
static constexpr size_t AOT_CHC_INDEX = 1;
|
||||
static constexpr size_t AOT_IHC_INDEX = 2;
|
||||
static constexpr size_t RESERVED_LENGTH = AOT_IHC_INDEX;
|
||||
|
||||
inline size_t GetIhcOffset() const
|
||||
{
|
||||
return JSTaggedValue::TaggedTypeSize() * (GetLength() - AOT_IHC_INDEX);
|
||||
}
|
||||
|
||||
inline size_t GetChcOffset() const
|
||||
{
|
||||
return JSTaggedValue::TaggedTypeSize() * (GetLength() - AOT_CHC_INDEX);
|
||||
}
|
||||
};
|
||||
|
||||
class AOTFileManager {
|
||||
|
@ -27,8 +27,8 @@ public:
|
||||
// 4.0 4.0.0.x
|
||||
static constexpr base::FileHeaderBase::VersionType AN_VERSION = {4, 0, 0, 4};
|
||||
static constexpr bool AN_STRICT_MATCH = true;
|
||||
static constexpr base::FileHeaderBase::VersionType AI_VERSION = {4, 0, 0, 1};
|
||||
static constexpr base::FileHeaderBase::VersionType AI_VERSION = {4, 0, 0, 2};
|
||||
static constexpr bool AI_STRICT_MATCH = true;
|
||||
};
|
||||
} // namespace panda::ecmascript
|
||||
#endif // ECMASCRIPT_AOT_VERSION_H
|
||||
#endif // ECMASCRIPT_AOT_VERSION_H
|
||||
|
@ -83,12 +83,7 @@ void ElfBuilder::Initialize()
|
||||
des_[i].AddArkStackMapSection();
|
||||
}
|
||||
sectionToAlign_ = {
|
||||
{ElfSecName::RODATA, AOTFileInfo::TEXT_SEC_ALIGN},
|
||||
{ElfSecName::RODATA_CST4, AOTFileInfo::TEXT_SEC_ALIGN},
|
||||
{ElfSecName::RODATA_CST8, AOTFileInfo::TEXT_SEC_ALIGN},
|
||||
{ElfSecName::RODATA_CST16, AOTFileInfo::TEXT_SEC_ALIGN},
|
||||
{ElfSecName::RODATA_CST32, AOTFileInfo::TEXT_SEC_ALIGN},
|
||||
{ElfSecName::TEXT, AOTFileInfo::TEXT_SEC_ALIGN},
|
||||
{ElfSecName::TEXT, AOTFileInfo::PAGE_ALIGN},
|
||||
{ElfSecName::STRTAB, 1},
|
||||
{ElfSecName::SYMTAB, AOTFileInfo::DATA_SEC_ALIGN},
|
||||
{ElfSecName::SHSTRTAB, AOTFileInfo::DATA_SEC_ALIGN},
|
||||
@ -331,20 +326,19 @@ void ElfBuilder::MergeTextSections(std::ofstream &file,
|
||||
ModuleSectionDes::ModuleRegionInfo &curInfo = moduleInfo[i];
|
||||
uint32_t curSecSize = des.GetSecSize(ElfSecName::TEXT);
|
||||
uint64_t curSecAddr = des.GetSecAddr(ElfSecName::TEXT);
|
||||
curSecOffset = AlignUp(curSecOffset, AOTFileInfo::TEXT_SEC_ALIGN);
|
||||
curSecOffset = AlignUp(curSecOffset, AOTFileInfo::PAGE_ALIGN);
|
||||
file.seekp(curSecOffset);
|
||||
auto curModuleSec = des.GetSectionsInfo();
|
||||
uint32_t rodataSize = 0;
|
||||
uint64_t rodataAddr = 0;
|
||||
curInfo.rodataAfterText = 0;
|
||||
if (curModuleSec.find(ElfSecName::RODATA_CST8) != curModuleSec.end()) {
|
||||
rodataSize = des.GetSecSize(ElfSecName::RODATA_CST8);
|
||||
rodataAddr = des.GetSecAddr(ElfSecName::RODATA_CST8);
|
||||
}
|
||||
std::tie(rodataAddr, rodataSize) = des.GetMergedRODataAddrAndSize();
|
||||
if (rodataSize != 0 && rodataAddr < curSecAddr) {
|
||||
file.write(reinterpret_cast<char *>(rodataAddr), rodataSize);
|
||||
curInfo.rodataSize = rodataSize;
|
||||
curSecOffset += rodataSize;
|
||||
curSecOffset = AlignUp(curSecOffset, AOTFileInfo::TEXT_SEC_ALIGN);
|
||||
file.seekp(curSecOffset);
|
||||
}
|
||||
file.write(reinterpret_cast<char *>(curSecAddr), curSecSize);
|
||||
curInfo.textSize = curSecSize;
|
||||
@ -441,7 +435,7 @@ void ElfBuilder::PackELFSections(std::ofstream &file)
|
||||
std::string secNameStr = ModuleSectionDes::GetSecName(secName);
|
||||
// text section address needs 16 bytes alignment
|
||||
if (secName == ElfSecName::TEXT) {
|
||||
curSecOffset = AlignUp(curSecOffset, AOTFileInfo::TEXT_SEC_ALIGN);
|
||||
curSecOffset = AlignUp(curSecOffset, AOTFileInfo::PAGE_ALIGN);
|
||||
file.seekp(curSecOffset);
|
||||
}
|
||||
llvm::ELF::Elf64_Word shName = FindShName(secNameStr, shStrTab.first, shStrTab.second);
|
||||
|
@ -256,18 +256,19 @@ void ElfReader::SeparateTextSections(std::vector<ModuleSectionDes> &des,
|
||||
{
|
||||
for (size_t i = 0; i < des.size(); ++i) {
|
||||
auto moduleInfo = GetCurModuleInfo(i, moduleInfoOffset);
|
||||
secOffset = AlignUp(secOffset, TEXT_SEC_ALIGN);
|
||||
secOffset = AlignUp(secOffset, AOTFileInfo::PAGE_ALIGN);
|
||||
uint32_t rodataSize = moduleInfo->rodataSize;
|
||||
uint32_t rodataAfterText = moduleInfo->rodataAfterText;
|
||||
if (rodataSize > 0 && rodataAfterText == 0) {
|
||||
des[i].SetSecAddrAndSize(ElfSecName::RODATA_CST8, secAddr + secOffset, rodataSize);
|
||||
secOffset += rodataSize;
|
||||
secOffset = AlignUp(secOffset, AOTFileInfo::TEXT_SEC_ALIGN);
|
||||
}
|
||||
uint32_t textSize = moduleInfo->textSize;
|
||||
des[i].SetSecAddrAndSize(ElfSecName::TEXT, secAddr + secOffset, textSize);
|
||||
secOffset += textSize;
|
||||
if (rodataSize > 0 && rodataAfterText == 1) {
|
||||
secOffset = AlignUp(secOffset, DATA_SEC_ALIGN);
|
||||
secOffset = AlignUp(secOffset, AOTFileInfo::DATA_SEC_ALIGN);
|
||||
des[i].SetSecAddrAndSize(ElfSecName::RODATA_CST8, secAddr + secOffset, rodataSize);
|
||||
secOffset += rodataSize;
|
||||
}
|
||||
@ -300,20 +301,21 @@ void ElfReader::SeparateTextSections(BinaryBufferParser &parser,
|
||||
{
|
||||
for (size_t i = 0; i < des.size(); ++i) {
|
||||
auto moduleInfo = moduleInfo_[i];
|
||||
secOffset = AlignUp(secOffset, TEXT_SEC_ALIGN);
|
||||
secOffset = AlignUp(secOffset, AOTFileInfo::PAGE_ALIGN);
|
||||
uint32_t rodataSize = moduleInfo.rodataSize;
|
||||
uint32_t rodataAfterText = moduleInfo.rodataAfterText;
|
||||
if (rodataSize > 0 && rodataAfterText == 0) {
|
||||
parser.ParseBuffer(reinterpret_cast<void *>(secAddr + secOffset), rodataSize, curShOffset + secOffset);
|
||||
des[i].SetSecAddrAndSize(ElfSecName::RODATA_CST8, secAddr + secOffset, rodataSize);
|
||||
secOffset += rodataSize;
|
||||
secOffset = AlignUp(secOffset, AOTFileInfo::TEXT_SEC_ALIGN);
|
||||
}
|
||||
uint32_t textSize = moduleInfo.textSize;
|
||||
parser.ParseBuffer(reinterpret_cast<void *>(secAddr + secOffset), textSize, curShOffset + secOffset);
|
||||
des[i].SetSecAddrAndSize(ElfSecName::TEXT, secAddr + secOffset, textSize);
|
||||
secOffset += textSize;
|
||||
if (rodataSize > 0 && rodataAfterText == 1) {
|
||||
secOffset = AlignUp(secOffset, DATA_SEC_ALIGN);
|
||||
secOffset = AlignUp(secOffset, AOTFileInfo::DATA_SEC_ALIGN);
|
||||
parser.ParseBuffer(reinterpret_cast<void *>(secAddr + secOffset), rodataSize, curShOffset + secOffset);
|
||||
des[i].SetSecAddrAndSize(ElfSecName::RODATA_CST8, secAddr + secOffset, rodataSize);
|
||||
secOffset += rodataSize;
|
||||
|
@ -53,8 +53,6 @@ private:
|
||||
return moduleInfoSize / sizeof(ModuleSectionDes::ModuleRegionInfo);
|
||||
}
|
||||
|
||||
static constexpr uint32_t TEXT_SEC_ALIGN = 4096;
|
||||
static constexpr uint32_t DATA_SEC_ALIGN = 8;
|
||||
static constexpr uint32_t ASMSTUB_MODULE_NUM = 3;
|
||||
ExecutedMemoryAllocator::ExeMem stubsMem_ {};
|
||||
MemMap fileMapMem_ {};
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
#include "ecmascript/base/number_helper.h"
|
||||
#include "ecmascript/compiler/aot_file/binary_buffer_parser.h"
|
||||
#include "ecmascript/compiler/binary_section.h"
|
||||
|
||||
@ -34,6 +35,28 @@ public:
|
||||
};
|
||||
static std::string GetSecName(ElfSecName idx);
|
||||
|
||||
void UpdateRODataInfo(uint64_t &addr, uint32_t &size, ElfSecName sec) const
|
||||
{
|
||||
if (sectionsInfo_.find(sec) == sectionsInfo_.end()) {
|
||||
return;
|
||||
}
|
||||
uint64_t curSectionAddr = GetSecAddr(sec);
|
||||
addr = curSectionAddr < addr ? curSectionAddr : addr;
|
||||
size += GetSecSize(sec);
|
||||
}
|
||||
|
||||
std::tuple<uint64_t, uint32_t> GetMergedRODataAddrAndSize() const
|
||||
{
|
||||
uint64_t addr = base::MAX_UINT64_VALUE;
|
||||
uint32_t size = 0;
|
||||
UpdateRODataInfo(addr, size, ElfSecName::RODATA);
|
||||
UpdateRODataInfo(addr, size, ElfSecName::RODATA_CST4);
|
||||
UpdateRODataInfo(addr, size, ElfSecName::RODATA_CST8);
|
||||
UpdateRODataInfo(addr, size, ElfSecName::RODATA_CST16);
|
||||
UpdateRODataInfo(addr, size, ElfSecName::RODATA_CST32);
|
||||
return std::make_tuple(addr, size);
|
||||
}
|
||||
|
||||
void SetArkStackMapPtr(std::shared_ptr<uint8_t> ptr)
|
||||
{
|
||||
arkStackMapPtr_ = std::move(ptr);
|
||||
|
@ -41,7 +41,7 @@ void AsyncFunctionLowering::ProcessJumpTable()
|
||||
GateRef ifBranchCondition = builder_.Branch(stateEntry_, isEqual);
|
||||
GateRef ifTrueCondition = builder_.IfTrue(ifBranchCondition);
|
||||
GateRef ifFalseCondition = builder_.IfFalse(ifBranchCondition);
|
||||
if (accessor_.GetOpCode(*firstUse) == OpCode::STATE_SPLIT) {
|
||||
while (accessor_.GetOpCode(*firstUse) == OpCode::STATE_SPLIT) {
|
||||
firstUse++;
|
||||
}
|
||||
accessor_.ReplaceStateIn(*firstUse, ifTrueCondition);
|
||||
@ -81,8 +81,7 @@ void AsyncFunctionLowering::RebuildGeneratorCfg(GateRef resumeGate, GateRef rest
|
||||
GateRef loopBeginStateIn = Circuit::NullGate();
|
||||
GateRef prevBcOffsetPhiGate = Circuit::NullGate();
|
||||
while (true) {
|
||||
auto opcode = accessor_.GetOpCode(stateInGate);
|
||||
if (opcode == OpCode::STATE_ENTRY) {
|
||||
if (stateInGate == GetEntryBBStateOut()) { // from state entry
|
||||
GateRef condition = builder_.Equal(offsetConstantGate, restoreOffsetGate);
|
||||
GateRef ifBranch = circuit_->NewGate(circuit_->IfBranch(), { ifFalseCondition, condition });
|
||||
GateRef ifTrue = circuit_->NewGate(circuit_->IfTrue(), {ifBranch});
|
||||
@ -110,7 +109,7 @@ void AsyncFunctionLowering::RebuildGeneratorCfg(GateRef resumeGate, GateRef rest
|
||||
}
|
||||
firstState = ifBranch;
|
||||
}
|
||||
|
||||
auto opcode = accessor_.GetOpCode(stateInGate);
|
||||
if (opcode == OpCode::LOOP_BEGIN) {
|
||||
bool resumeInLoopBody = false;
|
||||
CheckResumeInLoopBody(stateInGate, resumeInLoopBody);
|
||||
@ -158,7 +157,7 @@ void AsyncFunctionLowering::RebuildGeneratorCfg(GateRef resumeGate, GateRef rest
|
||||
UpdateValueSelector(prevLoopBeginGate, loopBeginStateIn, prevBcOffsetPhiGate);
|
||||
break;
|
||||
}
|
||||
if (accessor_.GetOpCode(stateInGate) == OpCode::STATE_ENTRY) {
|
||||
if (stateInGate == GetEntryBBStateOut()) {
|
||||
break;
|
||||
}
|
||||
stateInGate = accessor_.GetState(stateInGate);
|
||||
@ -192,9 +191,16 @@ void AsyncFunctionLowering::UpdateValueSelector(GateRef prevLoopBeginGate,
|
||||
if (accessor_.GetOpCode(use) == OpCode::VALUE_SELECTOR && use != prevBcOffsetPhiGate) {
|
||||
auto machineType = accessor_.GetMachineType(use);
|
||||
auto gateType = accessor_.GetGateType(use);
|
||||
GateRef undefinedGate =
|
||||
GateRef undefinedGate = Circuit::NullGate();
|
||||
if (gateType.IsNumberType()) {
|
||||
undefinedGate =
|
||||
circuit_->NewGate(circuit_->GetMetaBuilder()->Constant(JSTaggedValue::VALUE_ZERO),
|
||||
machineType, GateType::IntType());
|
||||
} else {
|
||||
undefinedGate =
|
||||
circuit_->NewGate(circuit_->GetMetaBuilder()->Constant(JSTaggedValue::VALUE_UNDEFINED),
|
||||
machineType, gateType);
|
||||
}
|
||||
auto firstValueGate = accessor_.GetValueIn(use, 0);
|
||||
auto newValueSelector = circuit_->NewGate(circuit_->ValueSelector(2), machineType, // 2: valuesIn
|
||||
{newGate, undefinedGate, firstValueGate},
|
||||
@ -279,5 +285,27 @@ GateRef AsyncFunctionLowering::GetDependPhiFromLoopBegin(GateRef gate) const
|
||||
LOG_COMPILER(FATAL) << "Can not find depend-selector from loopbegin";
|
||||
return Circuit::NullGate();
|
||||
}
|
||||
|
||||
GateRef AsyncFunctionLowering::GetEntryBBStateOut() const
|
||||
{
|
||||
auto bb = bcBuilder_->GetBasicBlockById(1); // 1 : First Block Id
|
||||
auto state = bb.stateCurrent;
|
||||
if (accessor_.IsCFGMerge(state)) {
|
||||
return accessor_.GetState(state);
|
||||
} else {
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
GateRef AsyncFunctionLowering::GetEntryBBDependOut() const
|
||||
{
|
||||
auto bb = bcBuilder_->GetBasicBlockById(1); // 1 : First Block Id
|
||||
auto depend = bb.dependCurrent;
|
||||
if (accessor_.IsDependSelector(depend)) {
|
||||
return accessor_.GetDep(depend);
|
||||
} else {
|
||||
return depend;
|
||||
}
|
||||
}
|
||||
} // panda::ecmascript::kungfu
|
||||
|
||||
|
@ -29,9 +29,8 @@ public:
|
||||
AsyncFunctionLowering(BytecodeCircuitBuilder *bcBuilder, Circuit *circuit, CompilationConfig *cmpCfg,
|
||||
bool enableLog, const std::string& name)
|
||||
: bcBuilder_(bcBuilder), circuit_(circuit), builder_(circuit, cmpCfg), enableLog_(enableLog),
|
||||
stateEntry_(circuit->GetStateRoot()),
|
||||
dependEntry_(circuit->GetDependRoot()),
|
||||
accessor_(circuit), argAccessor_(circuit), methodName_(name)
|
||||
accessor_(circuit), argAccessor_(circuit), stateEntry_(GetEntryBBStateOut()),
|
||||
dependEntry_(GetEntryBBDependOut()), methodName_(name)
|
||||
{
|
||||
}
|
||||
|
||||
@ -66,14 +65,18 @@ private:
|
||||
|
||||
GateRef GetDependPhiFromLoopBegin(GateRef loopbegin) const;
|
||||
|
||||
GateRef GetEntryBBStateOut() const;
|
||||
|
||||
GateRef GetEntryBBDependOut() const;
|
||||
|
||||
BytecodeCircuitBuilder *bcBuilder_;
|
||||
Circuit *circuit_;
|
||||
CircuitBuilder builder_;
|
||||
bool enableLog_ {false};
|
||||
GateRef stateEntry_ {Circuit::NullGate()};
|
||||
GateRef dependEntry_ {Circuit::NullGate()};
|
||||
GateAccessor accessor_;
|
||||
ArgumentAccessor argAccessor_;
|
||||
GateRef stateEntry_ {Circuit::NullGate()};
|
||||
GateRef dependEntry_ {Circuit::NullGate()};
|
||||
std::string methodName_;
|
||||
};
|
||||
} // panda::ecmascript::kungfu
|
||||
|
106
ecmascript/compiler/base/depend_chain_helper.cpp
Normal file
106
ecmascript/compiler/base/depend_chain_helper.cpp
Normal file
@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (c) 2023 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/base/depend_chain_helper.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
|
||||
void DependChains::Merge(DependChains* that)
|
||||
{
|
||||
// find common sub list
|
||||
while (size_ > that->size_) {
|
||||
head_ = head_->next;
|
||||
size_--;
|
||||
}
|
||||
|
||||
auto lhs = this->head_;
|
||||
auto rhs = that->head_;
|
||||
size_t rhsSize = that->size_;
|
||||
while (rhsSize > size_) {
|
||||
rhs = rhs->next;
|
||||
rhsSize--;
|
||||
}
|
||||
while (lhs != rhs) {
|
||||
ASSERT(lhs != nullptr);
|
||||
lhs = lhs->next;
|
||||
rhs = rhs->next;
|
||||
size_--;
|
||||
}
|
||||
head_ = lhs;
|
||||
}
|
||||
|
||||
bool DependChains::Equals(DependChains* that)
|
||||
{
|
||||
if (that == nullptr) {
|
||||
return false;
|
||||
}
|
||||
if (size_ != that->size_) {
|
||||
return false;
|
||||
}
|
||||
auto lhs = this->head_;
|
||||
auto rhs = that->head_;
|
||||
while (lhs != rhs) {
|
||||
if (lhs->gate != rhs->gate) {
|
||||
return false;
|
||||
}
|
||||
lhs = lhs->next;
|
||||
rhs = rhs->next;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t DependChains::FoundIndexCheckedForLength(RangeGuard* rangeGuard, GateRef input)
|
||||
{
|
||||
for (Node* node = head_; node != nullptr; node = node->next) {
|
||||
uint32_t length = rangeGuard->CheckIndexCheckLengthInput(node->gate, input);
|
||||
if(length > 0) { // found !!!
|
||||
return length;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t DependChains::FoundIndexCheckedForIndex(RangeGuard* rangeGuard, GateRef input)
|
||||
{
|
||||
for (Node* node = head_; node != nullptr; node = node->next) {
|
||||
uint32_t length = rangeGuard->CheckIndexCheckIndexInput(node->gate, input);
|
||||
if(length > 0) { // found !!!
|
||||
return length;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
GateRef DependChains::LookupNode(LaterElimination* elimination, GateRef gate)
|
||||
{
|
||||
for (Node* node = head_; node != nullptr; node = node->next) {
|
||||
if (elimination->CheckReplacement(node->gate, gate)) {
|
||||
return node->gate;
|
||||
}
|
||||
}
|
||||
return Circuit::NullGate();
|
||||
}
|
||||
|
||||
DependChains* DependChains::UpdateNode(GateRef gate)
|
||||
{
|
||||
// assign node->next to head
|
||||
Node* node = chunk_->New<Node>(gate, head_);
|
||||
DependChains* that = new (chunk_) DependChains(chunk_);
|
||||
// assign head to node
|
||||
that->head_ = node;
|
||||
that->size_ = size_ + 1;
|
||||
return that;
|
||||
}
|
||||
} // namespace panda::ecmascript::kungfu
|
57
ecmascript/compiler/base/depend_chain_helper.h
Normal file
57
ecmascript/compiler/base/depend_chain_helper.h
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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_DEPEND_CHAIN_HELPER_H
|
||||
#define ECMASCRIPT_COMPILER_DEPEND_CHAIN_HELPER_H
|
||||
|
||||
#include "ecmascript/compiler/circuit_builder.h"
|
||||
#include "ecmascript/compiler/gate_accessor.h"
|
||||
#include "ecmascript/compiler/graph_visitor.h"
|
||||
#include "ecmascript/compiler/later_elimination.h"
|
||||
#include "ecmascript/compiler/range_guard.h"
|
||||
#include "ecmascript/mem/chunk_containers.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
class LaterElimination;
|
||||
class RangeGuard;
|
||||
class DependChains : public ChunkObject {
|
||||
public:
|
||||
DependChains(Chunk* chunk) : chunk_(chunk) {}
|
||||
~DependChains() = default;
|
||||
|
||||
DependChains* UpdateNode(GateRef gate);
|
||||
bool Equals(DependChains* that);
|
||||
void Merge(DependChains* that);
|
||||
void CopyFrom(DependChains *other)
|
||||
{
|
||||
head_ = other->head_;
|
||||
size_ = other->size_;
|
||||
}
|
||||
uint32_t FoundIndexCheckedForLength(RangeGuard* rangeGuard, GateRef input);
|
||||
uint32_t FoundIndexCheckedForIndex(RangeGuard* rangeGuard, GateRef input);
|
||||
GateRef LookupNode(LaterElimination* elimination, GateRef gate);
|
||||
private:
|
||||
struct Node {
|
||||
Node(GateRef gate, Node* next) : gate(gate), next(next) {}
|
||||
GateRef gate;
|
||||
Node *next;
|
||||
};
|
||||
|
||||
Node *head_{nullptr};
|
||||
size_t size_ {0};
|
||||
Chunk* chunk_;
|
||||
};
|
||||
} // panda::ecmascript::kungfu
|
||||
#endif // ECMASCRIPT_COMPILER_DEPEND_CHAIN_HELPER_H
|
@ -453,7 +453,13 @@ namespace panda::ecmascript::kungfu {
|
||||
APPEND_SUFFIX(HandleCallthis3Imm8V8V8V8V8, V) \
|
||||
APPEND_SUFFIX(HandleNewobjrangeImm8Imm8V8, V) \
|
||||
APPEND_SUFFIX(HandleNewobjrangeImm16Imm8V8, V) \
|
||||
APPEND_SUFFIX(HandleWideNewobjrangePrefImm16V8, V)
|
||||
APPEND_SUFFIX(HandleWideNewobjrangePrefImm16V8, V) \
|
||||
APPEND_SUFFIX(HandleInstanceofImm8V8, V) \
|
||||
APPEND_SUFFIX(HandleTryldglobalbynameImm8Id16, V) \
|
||||
APPEND_SUFFIX(HandleTryldglobalbynameImm16Id16, V) \
|
||||
APPEND_SUFFIX(HandleTrystglobalbynameImm8Id16, V) \
|
||||
APPEND_SUFFIX(HandleTrystglobalbynameImm16Id16, V) \
|
||||
APPEND_SUFFIX(HandleLdglobalvarImm16Id16, V)
|
||||
|
||||
#define ASM_INTERPRETER_BC_LAYOUT_PROFILER_STUB_LIST(V) \
|
||||
APPEND_SUFFIX(HandleDefineclasswithbufferImm8Id16Id16Imm16V8, V) \
|
||||
|
@ -212,7 +212,7 @@ public:
|
||||
// RO data section needs 16 bytes alignment
|
||||
bool InRodataSection() const
|
||||
{
|
||||
return ElfSecName::RODATA <= value_ && value_ <= ElfSecName::RODATA_CST8;
|
||||
return ElfSecName::RODATA <= value_ && value_ <= ElfSecName::RODATA_CST32;
|
||||
}
|
||||
private:
|
||||
static int const FIX_SIZE = 24; // 24:Elf_Rel
|
||||
|
@ -36,7 +36,7 @@ void BytecodeCircuitBuilder::BytecodeToCircuit()
|
||||
void BytecodeCircuitBuilder::BuildRegionInfo()
|
||||
{
|
||||
uint32_t size = pcOffsets_.size();
|
||||
uint32_t end = size - 1; // 1: end
|
||||
uint32_t end = size - 2; // 1: end
|
||||
BytecodeIterator iterator(this, 0, end);
|
||||
|
||||
infoData_.resize(size);
|
||||
@ -1055,8 +1055,8 @@ void BytecodeCircuitBuilder::BuildSubCircuit()
|
||||
ASSERT(stateCur != Circuit::NullGate());
|
||||
ASSERT(dependCur != Circuit::NullGate());
|
||||
if (IsEntryBlock(bb.id)) {
|
||||
if (NeedUpdateHotness()) {
|
||||
stateCur = circuit_->NewGate(circuit_->UpdateHotness(), {stateCur, dependCur});
|
||||
if (NeedCheckSafePointAndStackOver()) {
|
||||
stateCur = circuit_->NewGate(circuit_->CheckSafePointAndStackOver(), {stateCur, dependCur});
|
||||
dependCur = stateCur;
|
||||
}
|
||||
auto &bbNext = graph_[bb.id + 1];
|
||||
@ -1420,9 +1420,7 @@ void BytecodeCircuitBuilder::BuildCircuit()
|
||||
}
|
||||
|
||||
auto type = typeRecorder_.GetType(bcIndex);
|
||||
if (HasValidType(type)) {
|
||||
gateAcc_.SetGateType(gate, type);
|
||||
}
|
||||
gateAcc_.SetGateType(gate, type);
|
||||
auto pgoType = typeRecorder_.GetOrUpdatePGOType(tsManager_, gateAcc_.TryGetPcOffset(gate), type);
|
||||
gateAcc_.TrySetPGOType(gate, pgoType);
|
||||
|
||||
@ -1458,6 +1456,15 @@ void BytecodeCircuitBuilder::BuildCircuit()
|
||||
gateAcc_.NewIn(gate, inIdx, defVreg);
|
||||
} else {
|
||||
GateRef defAcc = ResolveDef(bb, bcIndex, 0, true);
|
||||
if (!Bytecodes::IsCallOp(bytecodeInfo.GetOpcode())) {
|
||||
gateAcc_.NewIn(gate, inIdx, defAcc);
|
||||
continue;
|
||||
}
|
||||
auto oldGt = gateAcc_.GetGateType(defAcc).GetGTRef();
|
||||
GateType callTargetType = typeRecorder_.GetCallTargetType(bcIndex);
|
||||
if (!tsManager_->MethodOffsetIsVaild(oldGt) && !callTargetType.IsAnyType()) {
|
||||
gateAcc_.SetGateType(defAcc, callTargetType);
|
||||
}
|
||||
gateAcc_.NewIn(gate, inIdx, defAcc);
|
||||
}
|
||||
}
|
||||
|
@ -317,7 +317,7 @@ public:
|
||||
return jsGatesToByteCode_.at(gate);
|
||||
}
|
||||
|
||||
bool NeedUpdateHotness() const
|
||||
bool NeedCheckSafePointAndStackOver() const
|
||||
{
|
||||
return !isInline_ && !method_->IsNoGC();
|
||||
}
|
||||
@ -585,11 +585,6 @@ private:
|
||||
return (IsFirstBasicBlock(bbId) && bcIndex == 0 && reg == GetNumberVRegs());
|
||||
}
|
||||
|
||||
inline bool HasValidType(GateType type)
|
||||
{
|
||||
return HasTypes() && !type.IsAnyType() && !tsManager_->IsPGOGT(type.GetGTRef());
|
||||
}
|
||||
|
||||
TSManager *tsManager_;
|
||||
Circuit *circuit_;
|
||||
std::vector<std::vector<GateRef>> byteCodeToJSGates_;
|
||||
|
@ -67,7 +67,7 @@ void BytecodeInfoCollector::ProcessClasses()
|
||||
MethodLiteral *methods = jsPandaFile_->GetMethodLiterals();
|
||||
const panda_file::File *pf = jsPandaFile_->GetPandaFile();
|
||||
size_t methodIdx = 0;
|
||||
std::map<const uint8_t *, std::pair<size_t, uint32_t>> processedInsns;
|
||||
std::map<uint32_t, std::pair<size_t, uint32_t>> processedMethod;
|
||||
Span<const uint32_t> classIndexes = jsPandaFile_->GetClasses();
|
||||
|
||||
auto &recordNames = bytecodeInfo_.GetRecordNames();
|
||||
@ -82,7 +82,7 @@ void BytecodeInfoCollector::ProcessClasses()
|
||||
panda_file::ClassDataAccessor cda(*pf, classId);
|
||||
CString desc = utf::Mutf8AsCString(cda.GetDescriptor());
|
||||
const CString recordName = JSPandaFile::ParseEntryPoint(desc);
|
||||
cda.EnumerateMethods([this, methods, &methodIdx, pf, &processedInsns,
|
||||
cda.EnumerateMethods([this, methods, &methodIdx, pf, &processedMethod,
|
||||
&recordNames, &methodPcInfos, &recordName,
|
||||
&methodIndexes, &classConstructIndexes] (panda_file::MethodDataAccessor &mda) {
|
||||
auto methodId = mda.GetMethodId();
|
||||
@ -114,19 +114,19 @@ void BytecodeInfoCollector::ProcessClasses()
|
||||
panda_file::CodeDataAccessor codeDataAccessor(*pf, codeId.value());
|
||||
uint32_t codeSize = codeDataAccessor.GetCodeSize();
|
||||
const uint8_t *insns = codeDataAccessor.GetInstructions();
|
||||
auto it = processedInsns.find(insns);
|
||||
if (it == processedInsns.end()) {
|
||||
auto it = processedMethod.find(methodOffset);
|
||||
if (it == processedMethod.end()) {
|
||||
std::vector<std::string> classNameVec;
|
||||
CollectMethodPcsFromBC(codeSize, insns, methodLiteral, classNameVec,
|
||||
recordName, methodOffset, classConstructIndexes);
|
||||
processedInsns[insns] = std::make_pair(methodPcInfos.size() - 1, methodOffset);
|
||||
processedMethod[methodOffset] = std::make_pair(methodPcInfos.size() - 1, methodOffset);
|
||||
// collect className and literal offset for type infer
|
||||
if (EnableCollectLiteralInfo()) {
|
||||
CollectClassLiteralInfo(methodLiteral, classNameVec);
|
||||
}
|
||||
}
|
||||
|
||||
SetMethodPcInfoIndex(methodOffset, processedInsns[insns]);
|
||||
SetMethodPcInfoIndex(methodOffset, processedMethod[methodOffset]);
|
||||
jsPandaFile_->SetMethodLiteralToMap(methodLiteral);
|
||||
pfDecoder_.MatchAndMarkMethod(recordName, name.c_str(), methodId);
|
||||
});
|
||||
@ -251,7 +251,7 @@ void BytecodeInfoCollector::CollectMethodPcsFromBC(const uint32_t insSz, const u
|
||||
canFastCall = false;
|
||||
}
|
||||
CollectModuleInfoFromBC(bcIns, method, recordName);
|
||||
CollectConstantPoolIndexInfoFromBC(bcIns, method);
|
||||
CollectConstantPoolIndexInfoFromBC(bcIns, method, bcIndex);
|
||||
pgoBCInfo_.Record(bcIns, bcIndex, recordName, method);
|
||||
if (noGC && !bytecodes_.GetBytecodeMetaData(curPc).IsNoGC()) {
|
||||
noGC = false;
|
||||
@ -262,6 +262,7 @@ void BytecodeInfoCollector::CollectMethodPcsFromBC(const uint32_t insSz, const u
|
||||
pcOffsets.emplace_back(curPc);
|
||||
bcIndex++;
|
||||
}
|
||||
pcOffsets.emplace_back(bcInsLast.GetAddress());
|
||||
bytecodeInfo_.SetMethodOffsetToFastCallInfo(methodOffset, canFastCall, noGC);
|
||||
method->SetIsFastCall(canFastCall);
|
||||
method->SetNoGCBit(noGC);
|
||||
@ -625,7 +626,8 @@ void BytecodeInfoCollector::CollectRecordReferenceREL()
|
||||
{
|
||||
auto &recordNames = bytecodeInfo_.GetRecordNames();
|
||||
for (auto &record : recordNames) {
|
||||
if (jsPandaFile_->HasTSTypes(record) && jsPandaFile_->IsModule(vm_->GetJSThread(), record)) {
|
||||
JSRecordInfo info = jsPandaFile_->FindRecordInfo(record);
|
||||
if (jsPandaFile_->HasTSTypes(info)|| jsPandaFile_->IsModule(info)) {
|
||||
CollectRecordImportInfo(record);
|
||||
CollectRecordExportInfo(record);
|
||||
}
|
||||
@ -709,7 +711,7 @@ void BytecodeInfoCollector::RearrangeInnerMethods()
|
||||
}
|
||||
|
||||
void BytecodeInfoCollector::CollectConstantPoolIndexInfoFromBC(const BytecodeInstruction &bcIns,
|
||||
const MethodLiteral *method)
|
||||
const MethodLiteral *method, uint32_t bcIndex)
|
||||
{
|
||||
BytecodeInstruction::Opcode opcode = static_cast<BytecodeInstruction::Opcode>(bcIns.GetOpcode());
|
||||
uint32_t methodOffset = method->GetMethodId().GetOffset();
|
||||
@ -743,7 +745,7 @@ void BytecodeInfoCollector::CollectConstantPoolIndexInfoFromBC(const BytecodeIns
|
||||
case BytecodeInstruction::Opcode::STGLOBALVAR_IMM16_ID16:
|
||||
case BytecodeInstruction::Opcode::LDBIGINT_ID16: {
|
||||
auto index = bcIns.GetId().AsRawValue();
|
||||
AddConstantPoolIndexToBCInfo(ConstantPoolInfo::ItemType::STRING, index, methodOffset);
|
||||
AddConstantPoolIndexToBCInfo(ConstantPoolInfo::ItemType::STRING, index, methodOffset, bcIndex);
|
||||
break;
|
||||
}
|
||||
case BytecodeInstruction::Opcode::DEFINEFUNC_IMM8_ID16_IMM8:
|
||||
@ -751,33 +753,35 @@ void BytecodeInfoCollector::CollectConstantPoolIndexInfoFromBC(const BytecodeIns
|
||||
case BytecodeInstruction::Opcode::DEFINEMETHOD_IMM8_ID16_IMM8:
|
||||
case BytecodeInstruction::Opcode::DEFINEMETHOD_IMM16_ID16_IMM8: {
|
||||
auto index = bcIns.GetId().AsRawValue();
|
||||
AddConstantPoolIndexToBCInfo(ConstantPoolInfo::ItemType::METHOD, index, methodOffset);
|
||||
AddConstantPoolIndexToBCInfo(ConstantPoolInfo::ItemType::METHOD, index, methodOffset, bcIndex);
|
||||
break;
|
||||
}
|
||||
case BytecodeInstruction::Opcode::CREATEOBJECTWITHBUFFER_IMM8_ID16:
|
||||
case BytecodeInstruction::Opcode::CREATEOBJECTWITHBUFFER_IMM16_ID16: {
|
||||
auto index = bcIns.GetId().AsRawValue();
|
||||
AddConstantPoolIndexToBCInfo(ConstantPoolInfo::ItemType::OBJECT_LITERAL, index, methodOffset);
|
||||
AddConstantPoolIndexToBCInfo(ConstantPoolInfo::ItemType::OBJECT_LITERAL, index, methodOffset, bcIndex);
|
||||
break;
|
||||
}
|
||||
case BytecodeInstruction::Opcode::CREATEARRAYWITHBUFFER_IMM8_ID16:
|
||||
case BytecodeInstruction::Opcode::CREATEARRAYWITHBUFFER_IMM16_ID16: {
|
||||
auto index = bcIns.GetId().AsRawValue();
|
||||
AddConstantPoolIndexToBCInfo(ConstantPoolInfo::ItemType::ARRAY_LITERAL, index, methodOffset);
|
||||
AddConstantPoolIndexToBCInfo(ConstantPoolInfo::ItemType::ARRAY_LITERAL, index, methodOffset, bcIndex);
|
||||
break;
|
||||
}
|
||||
case BytecodeInstruction::Opcode::DEFINECLASSWITHBUFFER_IMM8_ID16_ID16_IMM16_V8: {
|
||||
auto methodIndex = (bcIns.GetId <BytecodeInstruction::Format::IMM8_ID16_ID16_IMM16_V8, 0>()).AsRawValue();
|
||||
AddConstantPoolIndexToBCInfo(ConstantPoolInfo::ItemType::METHOD, methodIndex, methodOffset);
|
||||
AddConstantPoolIndexToBCInfo(ConstantPoolInfo::ItemType::METHOD, methodIndex, methodOffset, bcIndex);
|
||||
auto literalIndex = (bcIns.GetId <BytecodeInstruction::Format::IMM8_ID16_ID16_IMM16_V8, 1>()).AsRawValue();
|
||||
AddConstantPoolIndexToBCInfo(ConstantPoolInfo::ItemType::CLASS_LITERAL, literalIndex, methodOffset);
|
||||
AddConstantPoolIndexToBCInfo(ConstantPoolInfo::ItemType::CLASS_LITERAL, literalIndex,
|
||||
methodOffset, bcIndex);
|
||||
break;
|
||||
}
|
||||
case BytecodeInstruction::Opcode::DEFINECLASSWITHBUFFER_IMM16_ID16_ID16_IMM16_V8: {
|
||||
auto methodIndex = (bcIns.GetId <BytecodeInstruction::Format::IMM16_ID16_ID16_IMM16_V8, 0>()).AsRawValue();
|
||||
AddConstantPoolIndexToBCInfo(ConstantPoolInfo::ItemType::METHOD, methodIndex, methodOffset);
|
||||
AddConstantPoolIndexToBCInfo(ConstantPoolInfo::ItemType::METHOD, methodIndex, methodOffset, bcIndex);
|
||||
auto literalIndex = (bcIns.GetId <BytecodeInstruction::Format::IMM16_ID16_ID16_IMM16_V8, 1>()).AsRawValue();
|
||||
AddConstantPoolIndexToBCInfo(ConstantPoolInfo::ItemType::CLASS_LITERAL, literalIndex, methodOffset);
|
||||
AddConstantPoolIndexToBCInfo(ConstantPoolInfo::ItemType::CLASS_LITERAL, literalIndex,
|
||||
methodOffset, bcIndex);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -826,12 +830,12 @@ uint32_t LexEnvManager::GetTargetLexEnv(uint32_t methodId, uint32_t level) const
|
||||
return offset;
|
||||
}
|
||||
|
||||
void ConstantPoolInfo::AddIndexToCPItem(ItemType type, uint32_t index, uint32_t methodOffset)
|
||||
void ConstantPoolInfo::AddIndexToCPItem(ItemType type, uint32_t index, uint32_t methodOffset, uint32_t bcIndex)
|
||||
{
|
||||
Item &item = GetCPItem(type);
|
||||
if (item.find(index) != item.end()) {
|
||||
return;
|
||||
}
|
||||
item.insert({index, ItemData {index, methodOffset, nullptr}});
|
||||
item.insert({index, ItemData {index, methodOffset, nullptr, bcIndex}});
|
||||
}
|
||||
} // namespace panda::ecmascript::kungfu
|
||||
|
@ -408,6 +408,7 @@ public:
|
||||
uint32_t index {0};
|
||||
uint32_t outerMethodOffset {0};
|
||||
CString *recordName {nullptr};
|
||||
uint32_t bcIndex {0};
|
||||
};
|
||||
|
||||
// key:constantpool index, value:ItemData
|
||||
@ -421,7 +422,7 @@ public:
|
||||
return items_[type];
|
||||
}
|
||||
|
||||
void AddIndexToCPItem(ItemType type, uint32_t index, uint32_t methodOffset);
|
||||
void AddIndexToCPItem(ItemType type, uint32_t index, uint32_t methodOffset, uint32_t bcIndex);
|
||||
private:
|
||||
std::vector<Item> items_;
|
||||
};
|
||||
@ -505,9 +506,9 @@ public:
|
||||
return skippedMethods_.size();
|
||||
}
|
||||
|
||||
void AddIndexToCPInfo(ConstantPoolInfo::ItemType type, uint32_t index, uint32_t methodOffset)
|
||||
void AddIndexToCPInfo(ConstantPoolInfo::ItemType type, uint32_t index, uint32_t methodOffset, uint32_t bcIndex)
|
||||
{
|
||||
cpInfo_.AddIndexToCPItem(type, index, methodOffset);
|
||||
cpInfo_.AddIndexToCPItem(type, index, methodOffset, bcIndex);
|
||||
}
|
||||
|
||||
template <class Callback>
|
||||
@ -761,9 +762,9 @@ private:
|
||||
}
|
||||
|
||||
void AddConstantPoolIndexToBCInfo(ConstantPoolInfo::ItemType type,
|
||||
uint32_t index, uint32_t methodOffset)
|
||||
uint32_t index, uint32_t methodOffset, uint32_t bcIndex)
|
||||
{
|
||||
bytecodeInfo_.AddIndexToCPInfo(type, index, methodOffset);
|
||||
bytecodeInfo_.AddIndexToCPInfo(type, index, methodOffset, bcIndex);
|
||||
}
|
||||
|
||||
inline std::string GetClassName(const EntityId entityId)
|
||||
@ -795,7 +796,8 @@ private:
|
||||
bool *canFastCall);
|
||||
void CollectModuleInfoFromBC(const BytecodeInstruction &bcIns, const MethodLiteral *method,
|
||||
const CString &recordName);
|
||||
void CollectConstantPoolIndexInfoFromBC(const BytecodeInstruction &bcIns, const MethodLiteral *method);
|
||||
void CollectConstantPoolIndexInfoFromBC(const BytecodeInstruction &bcIns, const MethodLiteral *method,
|
||||
uint32_t bcIndex);
|
||||
void IterateLiteral(const MethodLiteral *method, std::vector<uint32_t> &classOffsetVector);
|
||||
void StoreClassTypeOffset(const uint32_t typeOffset, std::vector<uint32_t> &classOffsetVector);
|
||||
void CollectClassLiteralInfo(const MethodLiteral *method, const std::vector<std::string> &classNameVec);
|
||||
|
@ -232,7 +232,6 @@ BytecodeMetaData BytecodeMetaData::InitBytecodeMetaData(const uint8_t *pc)
|
||||
kind = BytecodeKind::SUSPEND;
|
||||
break;
|
||||
case EcmaOpcode::RESUMEGENERATOR:
|
||||
case EcmaOpcode::CREATEOBJECTWITHEXCLUDEDKEYS_IMM8_V8_V8:
|
||||
kind = BytecodeKind::RESUME;
|
||||
break;
|
||||
case EcmaOpcode::DEBUGGER:
|
||||
|
@ -314,6 +314,49 @@ public:
|
||||
return bytecodes_[primary];
|
||||
}
|
||||
|
||||
static bool IsCallOp(EcmaOpcode opcode)
|
||||
{
|
||||
switch (opcode) {
|
||||
case EcmaOpcode::CALLARG0_IMM8:
|
||||
case EcmaOpcode::CALLARG1_IMM8_V8:
|
||||
case EcmaOpcode::CALLARGS2_IMM8_V8_V8:
|
||||
case EcmaOpcode::CALLARGS3_IMM8_V8_V8_V8:
|
||||
case EcmaOpcode::CALLRANGE_IMM8_IMM8_V8:
|
||||
case EcmaOpcode::WIDE_CALLRANGE_PREF_IMM16_V8:
|
||||
case EcmaOpcode::CALLTHIS0_IMM8_V8:
|
||||
case EcmaOpcode::CALLTHIS1_IMM8_V8_V8:
|
||||
case EcmaOpcode::CALLTHIS2_IMM8_V8_V8_V8:
|
||||
case EcmaOpcode::CALLTHIS3_IMM8_V8_V8_V8_V8:
|
||||
case EcmaOpcode::CALLTHISRANGE_IMM8_IMM8_V8:
|
||||
case EcmaOpcode::WIDE_CALLTHISRANGE_PREF_IMM16_V8:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool IsCreateObjectWithBufferOp(EcmaOpcode opcode)
|
||||
{
|
||||
switch (opcode) {
|
||||
case EcmaOpcode::CREATEOBJECTWITHBUFFER_IMM8_ID16:
|
||||
case EcmaOpcode::CREATEOBJECTWITHBUFFER_IMM16_ID16:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool IsCreateArrayWithBufferOp(EcmaOpcode opcode)
|
||||
{
|
||||
switch (opcode) {
|
||||
case EcmaOpcode::CREATEARRAYWITHBUFFER_IMM8_ID16:
|
||||
case EcmaOpcode::CREATEARRAYWITHBUFFER_IMM16_ID16:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static uint8_t ReadByte(const uint8_t *pc)
|
||||
{
|
||||
|
@ -1411,13 +1411,15 @@ DEF_CALL_SIGNATURE(Comment)
|
||||
|
||||
DEF_CALL_SIGNATURE(ProfileCall)
|
||||
{
|
||||
// 2 : 2 input parameters
|
||||
CallSignature callProfilerInstruction("ProfileCall", 0, 2, ArgumentsOrder::DEFAULT_ORDER, VariableType::VOID());
|
||||
// 4 : 4 input parameters
|
||||
CallSignature callProfilerInstruction("ProfileCall", 0, 4, ArgumentsOrder::DEFAULT_ORDER, VariableType::VOID());
|
||||
*callSign = callProfilerInstruction;
|
||||
// 2 : 2 input parameters
|
||||
std::array<VariableType, 2> params = {
|
||||
// 4 : 4 input parameters
|
||||
std::array<VariableType, 4> params = {
|
||||
VariableType::NATIVE_POINTER(),
|
||||
VariableType::JS_ANY(),
|
||||
VariableType::JS_ANY(),
|
||||
VariableType::INT32(),
|
||||
};
|
||||
callSign->SetVariadicArgs(true);
|
||||
callSign->SetParameters(params.data());
|
||||
|
@ -127,20 +127,38 @@ GateRef CircuitBuilder::DependRelay(GateRef state, GateRef depend)
|
||||
return circuit_->NewGate(circuit_->DependRelay(), { state, depend });
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::ReadSp()
|
||||
{
|
||||
return circuit_->NewGate(circuit_->ReadSp(), MachineType::I64, GateType::NJSValue());
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::Arguments(size_t index)
|
||||
{
|
||||
auto argListOfCircuit = circuit_->GetArgRoot();
|
||||
return GetCircuit()->NewArg(MachineType::I64, index, GateType::NJSValue(), argListOfCircuit);
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::ObjectTypeCheck(GateType type, GateRef gate, GateRef index)
|
||||
GateRef CircuitBuilder::ObjectTypeCheck(GateType type, GateRef gate, GateRef hclassIndex)
|
||||
{
|
||||
auto currentLabel = env_->GetCurrentLabel();
|
||||
auto currentControl = currentLabel->GetControl();
|
||||
auto currentDepend = currentLabel->GetDepend();
|
||||
auto frameState = acc_.FindNearestFrameState(currentDepend);
|
||||
GateRef ret = GetCircuit()->NewGate(circuit_->ObjectTypeCheck(static_cast<size_t>(type.Value())),
|
||||
MachineType::I1, {currentControl, currentDepend, gate, index, frameState}, GateType::NJSValue());
|
||||
GateRef ret = GetCircuit()->NewGate(circuit_->ObjectTypeCheck(static_cast<size_t>(type.Value())), MachineType::I1,
|
||||
{currentControl, currentDepend, gate, hclassIndex, frameState}, GateType::NJSValue());
|
||||
currentLabel->SetControl(ret);
|
||||
currentLabel->SetDepend(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::ObjectTypeCompare(GateType type, GateRef gate, GateRef hclassIndex)
|
||||
{
|
||||
auto currentLabel = env_->GetCurrentLabel();
|
||||
auto currentControl = currentLabel->GetControl();
|
||||
auto currentDepend = currentLabel->GetDepend();
|
||||
auto frameState = acc_.FindNearestFrameState(currentDepend);
|
||||
GateRef ret = GetCircuit()->NewGate(circuit_->ObjectTypeCompare(static_cast<size_t>(type.Value())), MachineType::I1,
|
||||
{currentControl, currentDepend, gate, hclassIndex, frameState}, GateType::NJSValue());
|
||||
currentLabel->SetControl(ret);
|
||||
currentLabel->SetDepend(ret);
|
||||
return ret;
|
||||
@ -233,12 +251,13 @@ GateRef CircuitBuilder::LoadTypedArrayLength(GateType type, GateRef gate)
|
||||
return ret;
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::RangeGuard(GateRef gate)
|
||||
GateRef CircuitBuilder::RangeGuard(GateRef gate, uint32_t left, uint32_t right)
|
||||
{
|
||||
auto currentLabel = env_->GetCurrentLabel();
|
||||
auto currentControl = currentLabel->GetControl();
|
||||
auto currentDepend = currentLabel->GetDepend();
|
||||
GateRef ret = GetCircuit()->NewGate(circuit_->RangeGuard(),
|
||||
UInt32PairAccessor accessor(left, right);
|
||||
GateRef ret = GetCircuit()->NewGate(circuit_->RangeGuard(accessor.ToValue()),
|
||||
MachineType::I64, {currentControl, currentDepend, gate}, GateType::IntType());
|
||||
currentLabel->SetControl(ret);
|
||||
currentLabel->SetDepend(ret);
|
||||
@ -319,15 +338,17 @@ GateType CircuitBuilder::GetGateTypeOfValueType(ValueType type)
|
||||
GateRef CircuitBuilder::CheckAndConvert(GateRef gate, ValueType src, ValueType dst, ConvertSupport support)
|
||||
{
|
||||
auto currentLabel = env_->GetCurrentLabel();
|
||||
auto currentControl = currentLabel->GetControl();
|
||||
auto currentDepend = currentLabel->GetDepend();
|
||||
auto stateSplit = acc_.FindNearestStateSplit(currentDepend);
|
||||
auto frameState = acc_.GetFrameState(stateSplit);
|
||||
GateRef state = acc_.GetState(stateSplit);
|
||||
MachineType machineType = GetMachineTypeOfValueType(dst);
|
||||
GateType gateType = GetGateTypeOfValueType(dst);
|
||||
uint64_t value = ValuePairTypeAccessor::ToValue(src, dst, support);
|
||||
GateRef ret = GetCircuit()->NewGate(circuit_->CheckAndConvert(value),
|
||||
machineType, {state, gate, frameState}, gateType);
|
||||
machineType, {currentControl, currentDepend, gate, frameState}, gateType);
|
||||
currentLabel->SetControl(ret);
|
||||
currentLabel->SetDepend(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -355,6 +376,11 @@ GateRef CircuitBuilder::ConvertInt32ToFloat64(GateRef gate)
|
||||
return Convert(gate, ValueType::INT32, ValueType::FLOAT64);
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::ConvertUInt32ToFloat64(GateRef gate)
|
||||
{
|
||||
return Convert(gate, ValueType::UINT32, ValueType::FLOAT64);
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::ConvertFloat64ToInt32(GateRef gate)
|
||||
{
|
||||
return Convert(gate, ValueType::FLOAT64, ValueType::INT32);
|
||||
@ -375,11 +401,21 @@ GateRef CircuitBuilder::ConvertInt32ToTaggedInt(GateRef gate)
|
||||
return Convert(gate, ValueType::INT32, ValueType::TAGGED_INT);
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::ConvertUInt32ToTaggedNumber(GateRef gate)
|
||||
{
|
||||
return Convert(gate, ValueType::UINT32, ValueType::TAGGED_NUMBER);
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::ConvertInt32ToBool(GateRef gate)
|
||||
{
|
||||
return Convert(gate, ValueType::INT32, ValueType::BOOL);
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::ConvertUInt32ToBool(GateRef gate)
|
||||
{
|
||||
return Convert(gate, ValueType::UINT32, ValueType::BOOL);
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::ConvertFloat64ToBool(GateRef gate)
|
||||
{
|
||||
return Convert(gate, ValueType::FLOAT64, ValueType::BOOL);
|
||||
@ -400,6 +436,11 @@ GateRef CircuitBuilder::ConvertFloat64ToTaggedDouble(GateRef gate)
|
||||
return Convert(gate, ValueType::FLOAT64, ValueType::TAGGED_DOUBLE);
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::CheckUInt32AndConvertToInt32(GateRef gate)
|
||||
{
|
||||
return CheckAndConvert(gate, ValueType::UINT32, ValueType::INT32);
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::CheckTaggedIntAndConvertToInt32(GateRef gate)
|
||||
{
|
||||
return CheckAndConvert(gate, ValueType::TAGGED_INT, ValueType::INT32);
|
||||
@ -615,32 +656,6 @@ GateRef CircuitBuilder::ValueCheckNegOverflow(GateRef value)
|
||||
return ret;
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::NegativeIndexCheck(GateRef index)
|
||||
{
|
||||
auto currentLabel = env_->GetCurrentLabel();
|
||||
auto currentControl = currentLabel->GetControl();
|
||||
auto currentDepend = currentLabel->GetDepend();
|
||||
auto frameState = acc_.FindNearestFrameState(currentDepend);
|
||||
GateRef ret = GetCircuit()->NewGate(circuit_->NegativeIndexCheck(),
|
||||
MachineType::I1, {currentControl, currentDepend, index, frameState}, GateType::NJSValue());
|
||||
currentLabel->SetControl(ret);
|
||||
currentLabel->SetDepend(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::LargeIndexCheck(GateRef index, GateRef length)
|
||||
{
|
||||
auto currentLabel = env_->GetCurrentLabel();
|
||||
auto currentControl = currentLabel->GetControl();
|
||||
auto currentDepend = currentLabel->GetDepend();
|
||||
auto frameState = acc_.FindNearestFrameState(currentDepend);
|
||||
GateRef ret = GetCircuit()->NewGate(circuit_->LargeIndexCheck(),
|
||||
MachineType::I1, {currentControl, currentDepend, index, length, frameState}, GateType::IntType());
|
||||
currentLabel->SetControl(ret);
|
||||
currentLabel->SetDepend(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::OverflowCheck(GateRef value)
|
||||
{
|
||||
auto currentLabel = env_->GetCurrentLabel();
|
||||
@ -1044,15 +1059,14 @@ GateRef CircuitBuilder::Call(const CallSignature* cs, GateRef glue, GateRef targ
|
||||
return result;
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::StoreMemory(MemoryType Op, VariableType type, GateRef receiver, GateRef index, GateRef value)
|
||||
GateRef CircuitBuilder::StoreMemory(MemoryType Op, VariableType type, GateRef receiver, GateRef index, GateRef value)
|
||||
{
|
||||
auto opIdx = static_cast<uint64_t>(Op);
|
||||
auto currentLabel = env_->GetCurrentLabel();
|
||||
auto currentControl = currentLabel->GetControl();
|
||||
auto currentDepend = currentLabel->GetDepend();
|
||||
auto ret =
|
||||
GetCircuit()->NewGate(GetCircuit()->StoreMemory(opIdx), type.GetMachineType(),
|
||||
{currentControl, currentDepend, receiver, index, value}, type.GetGateType());
|
||||
auto ret = GetCircuit()->NewGate(GetCircuit()->StoreMemory(opIdx), type.GetMachineType(),
|
||||
{currentControl, currentDepend, receiver, index, value}, type.GetGateType());
|
||||
currentLabel->SetControl(ret);
|
||||
currentLabel->SetDepend(ret);
|
||||
return ret;
|
||||
@ -1536,6 +1550,23 @@ GateRef CircuitBuilder::CreateArray(size_t arraySize)
|
||||
return newGate;
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::CreateArrayWithBuffer(size_t arraySize, GateRef constPoolIndex,
|
||||
GateRef elementIndex)
|
||||
{
|
||||
auto currentLabel = env_->GetCurrentLabel();
|
||||
auto currentControl = currentLabel->GetControl();
|
||||
auto currentDepend = currentLabel->GetDepend();
|
||||
auto frameState = acc_.FindNearestFrameState(currentDepend);
|
||||
GateRef newGate = GetCircuit()->NewGate(circuit_->CreateArrayWithBuffer(arraySize),
|
||||
MachineType::I64,
|
||||
{ currentControl, currentDepend, constPoolIndex,
|
||||
elementIndex, frameState },
|
||||
GateType::NJSValue());
|
||||
currentLabel->SetControl(newGate);
|
||||
currentLabel->SetDepend(newGate);
|
||||
return newGate;
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::StartAllocate()
|
||||
{
|
||||
auto currentLabel = env_->GetCurrentLabel();
|
||||
|
@ -40,6 +40,9 @@ class Environment;
|
||||
class Label;
|
||||
class Variable;
|
||||
class StubBuilder;
|
||||
class TSHCRLowering;
|
||||
class NTypeHCRLowering;
|
||||
class SlowPathLowering;
|
||||
|
||||
#define BINARY_ARITHMETIC_METHOD_LIST_WITH_BITWIDTH(V) \
|
||||
V(Int16Add, Add, MachineType::I16) \
|
||||
@ -253,9 +256,10 @@ public:
|
||||
GateRef ArrayGuardianCheck(GateRef frameState);
|
||||
GateRef TypedArrayCheck(GateType type, GateRef gate);
|
||||
GateRef LoadTypedArrayLength(GateType type, GateRef gate);
|
||||
GateRef RangeGuard(GateRef gate);
|
||||
GateRef RangeGuard(GateRef gate, uint32_t left, uint32_t right);
|
||||
GateRef IndexCheck(GateType type, GateRef gate, GateRef index);
|
||||
GateRef ObjectTypeCheck(GateType type, GateRef gate, GateRef hclassOffset);
|
||||
GateRef ObjectTypeCheck(GateType type, GateRef gate, GateRef hclassIndex);
|
||||
GateRef ObjectTypeCompare(GateType type, GateRef gate, GateRef hclassIndex);
|
||||
GateRef TryPrimitiveTypeCheck(GateType type, GateRef gate);
|
||||
GateRef CallTargetCheck(GateRef gate, GateRef function, GateRef id, GateRef param, const char* comment = nullptr);
|
||||
GateRef JSCallTargetFromDefineFuncCheck(GateType type, GateRef func, GateRef gate);
|
||||
@ -279,8 +283,6 @@ public:
|
||||
GateRef Int32CheckRightIsZero(GateRef right);
|
||||
GateRef Float64CheckRightIsZero(GateRef right);
|
||||
GateRef ValueCheckNegOverflow(GateRef value);
|
||||
GateRef NegativeIndexCheck(GateRef index);
|
||||
GateRef LargeIndexCheck(GateRef index, GateRef length);
|
||||
GateRef OverflowCheck(GateRef value);
|
||||
GateRef LexVarIsHoleCheck(GateRef value);
|
||||
GateRef Int32UnsignedUpperBoundCheck(GateRef value, GateRef upperBound);
|
||||
@ -301,9 +303,13 @@ public:
|
||||
GateRef ConvertInt32ToFloat64(GateRef gate);
|
||||
GateRef ConvertBoolToInt32(GateRef gate, ConvertSupport support);
|
||||
GateRef ConvertBoolToFloat64(GateRef gate, ConvertSupport support);
|
||||
GateRef ConvertUInt32ToBool(GateRef gate);
|
||||
GateRef ConvertUInt32ToTaggedNumber(GateRef gate);
|
||||
GateRef ConvertUInt32ToFloat64(GateRef gate);
|
||||
GateRef CheckAndConvert(
|
||||
GateRef gate, ValueType src, ValueType dst, ConvertSupport support = ConvertSupport::ENABLE);
|
||||
GateRef ConvertHoleAsUndefined(GateRef receiver);
|
||||
GateRef CheckUInt32AndConvertToInt32(GateRef gate);
|
||||
GateRef CheckTaggedIntAndConvertToInt32(GateRef gate);
|
||||
GateRef CheckTaggedDoubleAndConvertToInt32(GateRef gate);
|
||||
GateRef CheckTaggedNumberAndConvertToInt32(GateRef gate);
|
||||
@ -350,6 +356,7 @@ public:
|
||||
GateRef SwitchCase(GateRef switchBranch, int64_t value);
|
||||
GateRef DefaultCase(GateRef switchBranch);
|
||||
GateRef DependRelay(GateRef state, GateRef depend);
|
||||
GateRef ReadSp();
|
||||
GateRef BinaryArithmetic(const GateMetaData* meta, MachineType machineType,
|
||||
GateRef left, GateRef right, GateType gateType = GateType::Empty());
|
||||
GateRef BinaryCmp(const GateMetaData* meta, GateRef left, GateRef right);
|
||||
@ -612,6 +619,7 @@ public:
|
||||
GateRef FinishAllocate();
|
||||
GateRef HeapAlloc(GateRef size, GateType type, RegionSpaceFlag flag);
|
||||
GateRef CreateArray(size_t arraySize);
|
||||
GateRef CreateArrayWithBuffer(size_t arraySize, GateRef constPoolIndex, GateRef elementIndex);
|
||||
|
||||
void SetEnvironment(Environment *env)
|
||||
{
|
||||
@ -650,8 +658,6 @@ public:
|
||||
inline GateRef GetState() const;
|
||||
inline GateRef GetDepend() const;
|
||||
inline StateDepend GetStateDepend() const;
|
||||
inline void SetDepend(GateRef depend);
|
||||
inline void SetState(GateRef state);
|
||||
|
||||
GateRef GetGlobalEnvValue(VariableType type, GateRef env, size_t index);
|
||||
GateRef IsBase(GateRef ctor);
|
||||
@ -660,6 +666,9 @@ public:
|
||||
inline GateRef StoreToTaggedArray(GateRef array, size_t index, GateRef value);
|
||||
|
||||
private:
|
||||
inline void SetDepend(GateRef depend);
|
||||
inline void SetState(GateRef state);
|
||||
|
||||
#define ARITHMETIC_UNARY_OP_WITH_BITWIDTH(NAME, OPCODEID, MACHINETYPEID) \
|
||||
inline GateRef NAME(GateRef x) \
|
||||
{ \
|
||||
@ -674,6 +683,9 @@ private:
|
||||
Environment *env_ {nullptr};
|
||||
CompilationConfig *cmpCfg_ {nullptr};
|
||||
friend StubBuilder;
|
||||
friend TSHCRLowering;
|
||||
friend NTypeHCRLowering;
|
||||
friend SlowPathLowering;
|
||||
};
|
||||
|
||||
class Label {
|
||||
|
@ -216,7 +216,7 @@ void InstanceofStubBuilder::GenerateCircuit()
|
||||
GateRef jsFunc = TaggedArgument(3); // 3 : 4th para
|
||||
GateRef slotId = Int32Argument(4); // 4 : 5th pars
|
||||
GateRef profileTypeInfo = UpdateProfileTypeInfo(glue, jsFunc);
|
||||
Return(InstanceOf(glue, object, target, profileTypeInfo, slotId));
|
||||
Return(InstanceOf(glue, object, target, profileTypeInfo, slotId, ProfileOperation()));
|
||||
}
|
||||
|
||||
void IncStubBuilder::GenerateCircuit()
|
||||
@ -307,7 +307,7 @@ void GetPropertyByIndexStubBuilder::GenerateCircuit()
|
||||
GateRef glue = PtrArgument(0);
|
||||
GateRef receiver = TaggedArgument(1);
|
||||
GateRef index = Int32Argument(2); /* 2 : 3rd parameter is index */
|
||||
Return(GetPropertyByIndex(glue, receiver, index));
|
||||
Return(GetPropertyByIndex(glue, receiver, index, ProfileOperation()));
|
||||
}
|
||||
|
||||
void SetPropertyByIndexStubBuilder::GenerateCircuit()
|
||||
@ -399,7 +399,7 @@ void DeprecatedGetPropertyByValueStubBuilder::GenerateCircuit()
|
||||
GateRef glue = PtrArgument(0);
|
||||
GateRef receiver = TaggedArgument(1);
|
||||
GateRef key = TaggedArgument(2); // 2 : 3rd para
|
||||
Return(GetPropertyByValue(glue, receiver, key));
|
||||
Return(GetPropertyByValue(glue, receiver, key, ProfileOperation()));
|
||||
}
|
||||
|
||||
void SetPropertyByValueStubBuilder::GenerateCircuit()
|
||||
@ -442,7 +442,7 @@ void TryLdGlobalByNameStubBuilder::GenerateCircuit()
|
||||
AccessObjectStubBuilder builder(this, jsFunc);
|
||||
StringIdInfo info = { 0, 0, StringIdInfo::Offset::INVALID, StringIdInfo::Length::INVALID };
|
||||
GateRef profileTypeInfo = UpdateProfileTypeInfo(glue, jsFunc);
|
||||
Return(builder.TryLoadGlobalByName(glue, id, info, profileTypeInfo, slotId));
|
||||
Return(builder.TryLoadGlobalByName(glue, id, info, profileTypeInfo, slotId, ProfileOperation()));
|
||||
}
|
||||
|
||||
void TryStGlobalByNameStubBuilder::GenerateCircuit()
|
||||
@ -455,7 +455,7 @@ void TryStGlobalByNameStubBuilder::GenerateCircuit()
|
||||
AccessObjectStubBuilder builder(this, jsFunc);
|
||||
StringIdInfo info = { 0, 0, StringIdInfo::Offset::INVALID, StringIdInfo::Length::INVALID };
|
||||
GateRef profileTypeInfo = UpdateProfileTypeInfo(glue, jsFunc);
|
||||
Return(builder.TryStoreGlobalByName(glue, id, info, value, profileTypeInfo, slotId));
|
||||
Return(builder.TryStoreGlobalByName(glue, id, info, value, profileTypeInfo, slotId, ProfileOperation()));
|
||||
}
|
||||
|
||||
void LdGlobalVarStubBuilder::GenerateCircuit()
|
||||
@ -467,7 +467,7 @@ void LdGlobalVarStubBuilder::GenerateCircuit()
|
||||
AccessObjectStubBuilder builder(this, jsFunc);
|
||||
StringIdInfo info = { 0, 0, StringIdInfo::Offset::INVALID, StringIdInfo::Length::INVALID };
|
||||
GateRef profileTypeInfo = UpdateProfileTypeInfo(glue, jsFunc);
|
||||
Return(builder.LoadGlobalVar(glue, id, info, profileTypeInfo, slotId));
|
||||
Return(builder.LoadGlobalVar(glue, id, info, profileTypeInfo, slotId, ProfileOperation()));
|
||||
}
|
||||
|
||||
void StGlobalVarStubBuilder::GenerateCircuit()
|
||||
@ -505,7 +505,7 @@ void TryLoadICByNameStubBuilder::GenerateCircuit()
|
||||
&hclassNotEqualFirstValue);
|
||||
Bind(&hclassEqualFirstValue);
|
||||
{
|
||||
Return(LoadICWithHandler(glue, receiver, receiver, secondValue));
|
||||
Return(LoadICWithHandler(glue, receiver, receiver, secondValue, ProfileOperation()));
|
||||
}
|
||||
Bind(&hclassNotEqualFirstValue);
|
||||
{
|
||||
@ -513,7 +513,7 @@ void TryLoadICByNameStubBuilder::GenerateCircuit()
|
||||
Branch(TaggedIsHole(cachedHandler), &receiverNotHeapObject, &cachedHandlerNotHole);
|
||||
Bind(&cachedHandlerNotHole);
|
||||
{
|
||||
Return(LoadICWithHandler(glue, receiver, receiver, cachedHandler));
|
||||
Return(LoadICWithHandler(glue, receiver, receiver, cachedHandler, ProfileOperation()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -555,7 +555,7 @@ void TryLoadICByValueStubBuilder::GenerateCircuit()
|
||||
auto cachedHandler = CheckPolyHClass(secondValue, hclass);
|
||||
Branch(TaggedIsHole(cachedHandler), &receiverNotHeapObject, &cachedHandlerNotHole);
|
||||
Bind(&cachedHandlerNotHole);
|
||||
Return(LoadICWithHandler(glue, receiver, receiver, cachedHandler));
|
||||
Return(LoadICWithHandler(glue, receiver, receiver, cachedHandler, ProfileOperation()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -85,6 +85,7 @@ GateRef EarlyElimination::VisitGate(GateRef gate)
|
||||
case OpCode::LOAD_TYPED_ARRAY_LENGTH:
|
||||
case OpCode::TYPED_ARRAY_CHECK:
|
||||
case OpCode::OBJECT_TYPE_CHECK:
|
||||
case OpCode::OBJECT_TYPE_COMPARE:
|
||||
case OpCode::STABLE_ARRAY_CHECK:
|
||||
case OpCode::INDEX_CHECK:
|
||||
case OpCode::TYPED_CALL_CHECK:
|
||||
@ -92,6 +93,7 @@ GateRef EarlyElimination::VisitGate(GateRef gate)
|
||||
case OpCode::TYPED_BINARY_OP:
|
||||
case OpCode::TYPED_UNARY_OP:
|
||||
case OpCode::JSINLINETARGET_TYPE_CHECK:
|
||||
case OpCode::INLINE_ACCESSOR_CHECK:
|
||||
return TryEliminateGate(gate);
|
||||
case OpCode::STATE_SPLIT:
|
||||
return TryEliminateFrameState(gate);
|
||||
@ -249,8 +251,14 @@ bool EarlyElimination::MayAccessOneMemory(GateRef lhs, GateRef rhs)
|
||||
case OpCode::STORE_MEMORY:
|
||||
ASSERT(acc_.GetMemoryType(rhs) == MemoryType::ELEMENT_TYPE);
|
||||
return acc_.GetOpCode(lhs) == OpCode::LOAD_ELEMENT;
|
||||
case OpCode::STORE_ELEMENT:
|
||||
return lop == OpCode::LOAD_ELEMENT;
|
||||
case OpCode::STORE_ELEMENT: {
|
||||
if(lop == OpCode::LOAD_ELEMENT) {
|
||||
auto lopIsTypedArray = static_cast<uint8_t>(acc_.GetTypedLoadOp(lhs)) > 0;
|
||||
auto ropIsTypedArray = static_cast<uint8_t>(acc_.GetTypedStoreOp(rhs)) > 0;
|
||||
return lopIsTypedArray == ropIsTypedArray;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
case OpCode::STORE_PROPERTY:
|
||||
case OpCode::STORE_PROPERTY_NO_BARRIER: {
|
||||
if (lop == OpCode::LOAD_PROPERTY) {
|
||||
@ -322,6 +330,7 @@ bool EarlyElimination::CheckReplacement(GateRef lhs, GateRef rhs)
|
||||
}
|
||||
case OpCode::TYPED_ARRAY_CHECK:
|
||||
case OpCode::OBJECT_TYPE_CHECK:
|
||||
case OpCode::OBJECT_TYPE_COMPARE:
|
||||
case OpCode::INDEX_CHECK: {
|
||||
if (acc_.GetParamGateType(lhs) != acc_.GetParamGateType(rhs)) {
|
||||
return false;
|
||||
|
@ -122,11 +122,13 @@ void Module::CollectFuncEntryInfo(std::map<uintptr_t, std::string> &addr2name, A
|
||||
// 2.After all functions compiled, the module sections would be fixed
|
||||
uintptr_t textAddr = GetTextAddr();
|
||||
uint32_t textSize = GetTextSize();
|
||||
uintptr_t rodataAddr = GetRODataAddr();
|
||||
uint32_t rodataSize = GetRODataSize();
|
||||
aotInfo.AlignTextSec(AOTFileInfo::TEXT_SEC_ALIGN);
|
||||
uintptr_t rodataAddr = 0;
|
||||
uint32_t rodataSize = 0;
|
||||
std::tie(rodataAddr, rodataSize) = GetMergedRODataAddrAndSize();
|
||||
aotInfo.AlignTextSec(AOTFileInfo::PAGE_ALIGN);
|
||||
if (rodataAddr < textAddr) {
|
||||
aotInfo.UpdateCurTextSecOffset(rodataSize);
|
||||
aotInfo.AlignTextSec(AOTFileInfo::TEXT_SEC_ALIGN);
|
||||
}
|
||||
|
||||
const size_t funcCount = funcInfo.size();
|
||||
@ -270,10 +272,11 @@ void StubFileGenerator::DisassembleAsmStubs(std::map<uintptr_t, std::string> &ad
|
||||
|
||||
uint64_t AOTFileGenerator::RollbackTextSize(Module *module)
|
||||
{
|
||||
uintptr_t textAddr = module->GetSectionAddr(ElfSecName::TEXT);
|
||||
uintptr_t rodataAddr = module->GetSectionAddr(ElfSecName::RODATA_CST8);
|
||||
uint64_t textAddr = module->GetSectionAddr(ElfSecName::TEXT);
|
||||
uint32_t textSize = module->GetSectionSize(ElfSecName::TEXT);
|
||||
uint32_t rodataSize = module->GetSectionSize(ElfSecName::RODATA_CST8);
|
||||
uint64_t rodataAddr = 0;
|
||||
uint32_t rodataSize = 0;
|
||||
std::tie(rodataAddr, rodataSize) = module->GetMergedRODataAddrAndSize();
|
||||
uint64_t textStart = 0;
|
||||
if (textAddr > rodataAddr) {
|
||||
textStart = aotInfo_.GetCurTextSecOffset() - textSize;
|
||||
|
@ -16,6 +16,7 @@
|
||||
#ifndef ECMASCRIPT_COMPILER_FILE_GENERATORS_H
|
||||
#define ECMASCRIPT_COMPILER_FILE_GENERATORS_H
|
||||
|
||||
#include "ecmascript/base/number_helper.h"
|
||||
#include "ecmascript/compiler/aot_file/aot_file_manager.h"
|
||||
#include "ecmascript/compiler/assembler_module.h"
|
||||
#include "ecmascript/compiler/compiler_log.h"
|
||||
@ -58,6 +59,18 @@ public:
|
||||
|
||||
uintptr_t GetSectionAddr(ElfSecName sec) const;
|
||||
|
||||
std::tuple<uint64_t, uint32_t> GetMergedRODataAddrAndSize() const
|
||||
{
|
||||
uint64_t addr = base::MAX_UINT64_VALUE;
|
||||
uint32_t size = 0;
|
||||
UpdateRODataInfo(addr, size, ElfSecName::RODATA);
|
||||
UpdateRODataInfo(addr, size, ElfSecName::RODATA_CST4);
|
||||
UpdateRODataInfo(addr, size, ElfSecName::RODATA_CST8);
|
||||
UpdateRODataInfo(addr, size, ElfSecName::RODATA_CST16);
|
||||
UpdateRODataInfo(addr, size, ElfSecName::RODATA_CST32);
|
||||
return std::make_tuple(addr, size);
|
||||
}
|
||||
|
||||
void RunAssembler(const CompilerLog &log, bool fastCompileMode);
|
||||
|
||||
void DisassemblerFunc(std::map<uintptr_t, std::string> &addr2name, uint64_t textOffset, const CompilerLog &log,
|
||||
@ -81,14 +94,11 @@ private:
|
||||
return assembler_->GetSectionSize(ElfSecName::TEXT);
|
||||
}
|
||||
|
||||
uintptr_t GetRODataAddr() const
|
||||
void UpdateRODataInfo(uint64_t &addr, uint32_t &size, ElfSecName sec) const
|
||||
{
|
||||
return assembler_->GetSectionAddr(ElfSecName::RODATA_CST8);
|
||||
}
|
||||
|
||||
uint32_t GetRODataSize() const
|
||||
{
|
||||
return assembler_->GetSectionSize(ElfSecName::RODATA_CST8);
|
||||
uint64_t curSectionAddr = GetSectionAddr(sec);
|
||||
addr = ((curSectionAddr != 0) && (curSectionAddr < addr)) ? curSectionAddr : addr;
|
||||
size += GetSectionSize(sec);
|
||||
}
|
||||
|
||||
LLVMModule *llvmModule_ {nullptr};
|
||||
|
@ -520,6 +520,9 @@ void FrameStateBuilder::BindBBStateSplit()
|
||||
if (builder_->IsFirstBasicBlock(bb.id)) {
|
||||
BuildStateSplitBefore(bb, bb.start);
|
||||
}
|
||||
if (builder_->IsEntryBlock(bb.id)) {
|
||||
BuildStateSplitBefore(bb, bb.start);
|
||||
}
|
||||
ASSERT(!bb.isDead);
|
||||
builder_->EnumerateBlock(bb, [&](const BytecodeInfo &bytecodeInfo) -> bool {
|
||||
auto &iterator = bb.GetBytecodeIterator();
|
||||
|
@ -127,8 +127,27 @@ private:
|
||||
}
|
||||
return currentInfo;
|
||||
}
|
||||
FrameStateInfo *GetBBBeginStateInfo(size_t bbId) const
|
||||
FrameStateInfo *GetEntryBBBeginStateInfo()
|
||||
{
|
||||
auto entry = CreateEmptyStateInfo();
|
||||
auto first = bbBeginStateInfos_.at(1); // 1: first block
|
||||
for (size_t i = 0; i < numVregs_; ++i) {
|
||||
auto value = first->ValuesAt(i);
|
||||
if (value == Circuit::NullGate()) {
|
||||
continue;
|
||||
}
|
||||
if (gateAcc_.IsValueSelector(value)) {
|
||||
value = gateAcc_.GetValueIn(value);
|
||||
}
|
||||
entry->SetValuesAt(i, value);
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
FrameStateInfo *GetBBBeginStateInfo(size_t bbId)
|
||||
{
|
||||
if (bbId == 0) { // 0: entry block
|
||||
return GetEntryBBBeginStateInfo();
|
||||
}
|
||||
return bbBeginStateInfos_.at(bbId);
|
||||
}
|
||||
void UpdateVirtualRegistersOfSuspend(GateRef gate);
|
||||
|
@ -107,14 +107,16 @@ size_t GateAccessor::GetIndex(GateRef gate) const
|
||||
|
||||
size_t GateAccessor::GetArraySize(GateRef gate) const
|
||||
{
|
||||
ASSERT(GetOpCode(gate) == OpCode::CREATE_ARRAY);
|
||||
ASSERT(GetOpCode(gate) == OpCode::CREATE_ARRAY ||
|
||||
GetOpCode(gate) == OpCode::CREATE_ARRAY_WITH_BUFFER);
|
||||
Gate *gatePtr = circuit_->LoadGatePtr(gate);
|
||||
return gatePtr->GetOneParameterMetaData()->GetValue();
|
||||
}
|
||||
|
||||
void GateAccessor::SetArraySize(GateRef gate, size_t size)
|
||||
{
|
||||
ASSERT(GetOpCode(gate) == OpCode::CREATE_ARRAY);
|
||||
ASSERT(GetOpCode(gate) == OpCode::CREATE_ARRAY ||
|
||||
GetOpCode(gate) == OpCode::CREATE_ARRAY_WITH_BUFFER);
|
||||
Gate *gatePtr = circuit_->LoadGatePtr(gate);
|
||||
const_cast<OneParameterMetaData *>(gatePtr->GetOneParameterMetaData())->SetValue(size);
|
||||
}
|
||||
@ -203,9 +205,11 @@ GateType GateAccessor::GetParamGateType(GateRef gate) const
|
||||
{
|
||||
ASSERT(GetOpCode(gate) == OpCode::PRIMITIVE_TYPE_CHECK ||
|
||||
GetOpCode(gate) == OpCode::OBJECT_TYPE_CHECK ||
|
||||
GetOpCode(gate) == OpCode::OBJECT_TYPE_COMPARE ||
|
||||
GetOpCode(gate) == OpCode::TYPED_ARRAY_CHECK ||
|
||||
GetOpCode(gate) == OpCode::INDEX_CHECK ||
|
||||
GetOpCode(gate) == OpCode::TYPED_CALLTARGETCHECK_OP);
|
||||
GetOpCode(gate) == OpCode::TYPED_CALLTARGETCHECK_OP ||
|
||||
GetOpCode(gate) == OpCode::CREATE_ARRAY_WITH_BUFFER);
|
||||
Gate *gatePtr = circuit_->LoadGatePtr(gate);
|
||||
GateTypeAccessor accessor(gatePtr->GetOneParameterMetaData()->GetValue());
|
||||
return accessor.GetGateType();
|
||||
@ -257,6 +261,22 @@ GateType GateAccessor::GetRightType(GateRef gate) const
|
||||
return accessor.GetRightType();
|
||||
}
|
||||
|
||||
uint32_t GateAccessor::GetFirstValue(GateRef gate) const
|
||||
{
|
||||
ASSERT(GetOpCode(gate) == OpCode::RANGE_GUARD);
|
||||
Gate *gatePtr = circuit_->LoadGatePtr(gate);
|
||||
UInt32PairAccessor accessor(gatePtr->GetOneParameterMetaData()->GetValue());
|
||||
return accessor.GetFirstValue();
|
||||
}
|
||||
|
||||
uint32_t GateAccessor::GetSecondValue(GateRef gate) const
|
||||
{
|
||||
ASSERT(GetOpCode(gate) == OpCode::RANGE_GUARD);
|
||||
Gate *gatePtr = circuit_->LoadGatePtr(gate);
|
||||
UInt32PairAccessor accessor(gatePtr->GetOneParameterMetaData()->GetValue());
|
||||
return accessor.GetSecondValue();
|
||||
}
|
||||
|
||||
size_t GateAccessor::GetVirtualRegisterIndex(GateRef gate) const
|
||||
{
|
||||
ASSERT(GetOpCode(gate) == OpCode::SAVE_REGISTER ||
|
||||
@ -326,7 +346,7 @@ uint32_t GateAccessor::TryGetPcOffset(GateRef gate) const
|
||||
return static_cast<uint32_t>(gatePtr->GetOneParameterMetaData()->GetValue());
|
||||
case OpCode::TYPEDCALL:
|
||||
case OpCode::TYPEDFASTCALL:
|
||||
return static_cast<uint32_t>(gatePtr->GetTypedCallMetaData()->GetValue());
|
||||
return static_cast<uint32_t>(gatePtr->GetTypedCallMetaData()->GetValue());
|
||||
case OpCode::FRAME_STATE: {
|
||||
UInt32PairAccessor accessor(gatePtr->GetOneParameterMetaData()->GetValue());
|
||||
return accessor.GetFirstValue();
|
||||
@ -842,55 +862,7 @@ void GateAccessor::ReplaceHirAndDeleteIfException(GateRef hirGate,
|
||||
|
||||
void GateAccessor::EliminateRedundantPhi()
|
||||
{
|
||||
std::vector<GateRef> gateList;
|
||||
GetAllGates(gateList);
|
||||
std::queue<GateRef> workList;
|
||||
std::set<GateRef> inList;
|
||||
for (auto gate : gateList) {
|
||||
if (IsValueSelector(gate)) {
|
||||
workList.push(gate);
|
||||
inList.insert(gate);
|
||||
}
|
||||
}
|
||||
|
||||
while (!workList.empty()) {
|
||||
auto cur = workList.front();
|
||||
workList.pop();
|
||||
ASSERT(IsValueSelector(cur));
|
||||
GateRef first = GetValueIn(cur, 0);
|
||||
bool sameIns = true;
|
||||
bool selfUse = first == cur;
|
||||
auto valueNum = GetNumValueIn(cur);
|
||||
for (size_t i = 1; i < valueNum; ++i) {
|
||||
GateRef input = GetValueIn(cur, i);
|
||||
if (input != first) {
|
||||
sameIns = false;
|
||||
}
|
||||
if (input == cur) {
|
||||
ASSERT(IsLoopHead(GetState(cur)));
|
||||
selfUse = true;
|
||||
}
|
||||
}
|
||||
if ((!sameIns) && (!selfUse)) {
|
||||
inList.erase(cur);
|
||||
continue;
|
||||
}
|
||||
auto use = Uses(cur);
|
||||
for (auto it = use.begin(); it != use.end(); ++it) {
|
||||
if (((*it) == cur) || (!IsValueSelector(*it)) || inList.count(*it)) {
|
||||
// selfUse or notPhi or inListPhi
|
||||
continue;
|
||||
}
|
||||
workList.push(*it);
|
||||
inList.insert(*it);
|
||||
}
|
||||
UpdateAllUses(cur, first);
|
||||
}
|
||||
for (auto phi : inList) {
|
||||
ASSERT(IsValueSelector(phi));
|
||||
DeleteGate(phi);
|
||||
}
|
||||
return;
|
||||
GraphEditor::EliminateRedundantPhi(circuit_);
|
||||
}
|
||||
|
||||
UseIterator GateAccessor::DeleteGate(const UseIterator &useIt)
|
||||
|
@ -488,6 +488,8 @@ public:
|
||||
void ReplaceGate(GateRef gate, GateRef state, GateRef depend, GateRef value);
|
||||
GateType GetLeftType(GateRef gate) const;
|
||||
GateType GetRightType(GateRef gate) const;
|
||||
uint32_t GetFirstValue(GateRef gate) const;
|
||||
uint32_t GetSecondValue(GateRef gate) const;
|
||||
GateRef GetGlueFromArgList() const;
|
||||
void GetArgsOuts(std::vector<GateRef>& outs) const;
|
||||
void GetReturnOuts(std::vector<GateRef>& outs) const;
|
||||
|
@ -230,7 +230,6 @@ bool GateMetaData::IsVirtualState() const
|
||||
switch (opcode_) {
|
||||
case OpCode::GET_EXCEPTION:
|
||||
case OpCode::STATE_SPLIT:
|
||||
case OpCode::CHECK_AND_CONVERT:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
@ -107,12 +107,11 @@ enum class TypedJumpOp : uint8_t {
|
||||
V(NotJSCallTarget, NOTJSCALLTGT) \
|
||||
V(CowArray, COWARRAY) \
|
||||
V(DivideZero, DIVZERO) \
|
||||
V(NegativeIndex, NEGTIVEINDEX) \
|
||||
V(LargeIndex, LARGEINDEX) \
|
||||
V(InlineFail, INLINEFAIL) \
|
||||
V(NotJSFastCallTarget, NOTJSFASTCALLTGT) \
|
||||
V(LexVarIsHole, LEXVARISHOLE) \
|
||||
V(ModZero, MODZERO)
|
||||
V(ModZero, MODZERO) \
|
||||
V(Int32Overflow, INT32OVERFLOW)
|
||||
|
||||
enum class DeoptType : uint8_t {
|
||||
NOTCHECK = 0,
|
||||
@ -210,14 +209,11 @@ std::string MachineTypeToStr(MachineType machineType);
|
||||
V(Int32CheckRightIsZero, INT32_CHECK_RIGHT_IS_ZERO, GateFlags::CHECKABLE, 1, 1, 1) \
|
||||
V(Float64CheckRightIsZero, FLOAT64_CHECK_RIGHT_IS_ZERO, GateFlags::CHECKABLE, 1, 1, 1) \
|
||||
V(ValueCheckNegOverflow, VALUE_CHECK_NEG_OVERFLOW, GateFlags::CHECKABLE, 1, 1, 1) \
|
||||
V(NegativeIndexCheck, NEGATIVE_INDEX_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
|
||||
V(LargeIndexCheck, LARGE_INDEX_CHECK, GateFlags::CHECKABLE, 1, 1, 2) \
|
||||
V(OverflowCheck, OVERFLOW_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
|
||||
V(Int32UnsignedUpperBoundCheck, INT32_UNSIGNED_UPPER_BOUND_CHECK, GateFlags::CHECKABLE, 1, 1, 2) \
|
||||
V(Int32DivWithCheck, INT32_DIV_WITH_CHECK, GateFlags::CHECKABLE, 1, 1, 2) \
|
||||
V(LexVarIsHoleCheck, LEX_VAR_IS_HOLE_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
|
||||
V(RangeGuard, RANGE_GUARD, GateFlags::NO_WRITE, 1, 1, 1) \
|
||||
|
||||
V(LexVarIsHoleCheck, LEX_VAR_IS_HOLE_CHECK, GateFlags::CHECKABLE, 1, 1, 1)
|
||||
|
||||
#define UNARY_GATE_META_DATA_CACHE_LIST(V) \
|
||||
V(Zext, ZEXT, GateFlags::NONE_FLAG, 0, 0, 1) \
|
||||
V(Sext, SEXT, GateFlags::NONE_FLAG, 0, 0, 1) \
|
||||
@ -235,56 +231,59 @@ std::string MachineTypeToStr(MachineType machineType);
|
||||
V(UnsignedFloatToInt, UNSIGNED_FLOAT_TO_INT, GateFlags::NONE_FLAG, 0, 0, 1) \
|
||||
V(Bitcast, BITCAST, GateFlags::NONE_FLAG, 0, 0, 1)
|
||||
|
||||
#define IMMUTABLE_META_DATA_CACHE_LIST(V) \
|
||||
V(CircuitRoot, CIRCUIT_ROOT, GateFlags::NONE_FLAG, 0, 0, 0) \
|
||||
V(StateEntry, STATE_ENTRY, GateFlags::ROOT, 0, 0, 0) \
|
||||
V(DependEntry, DEPEND_ENTRY, GateFlags::ROOT, 0, 0, 0) \
|
||||
V(ReturnList, RETURN_LIST, GateFlags::ROOT, 0, 0, 0) \
|
||||
V(ArgList, ARG_LIST, GateFlags::ROOT, 0, 0, 0) \
|
||||
V(Return, RETURN, GateFlags::HAS_ROOT, 1, 1, 1) \
|
||||
V(ReturnVoid, RETURN_VOID, GateFlags::HAS_ROOT, 1, 1, 0) \
|
||||
V(Throw, THROW, GateFlags::CONTROL, 1, 1, 1) \
|
||||
V(OrdinaryBlock, ORDINARY_BLOCK, GateFlags::CONTROL, 1, 0, 0) \
|
||||
V(IfBranch, IF_BRANCH, GateFlags::CONTROL, 1, 0, 1) \
|
||||
V(IfTrue, IF_TRUE, GateFlags::CONTROL, 1, 0, 0) \
|
||||
V(IfFalse, IF_FALSE, GateFlags::CONTROL, 1, 0, 0) \
|
||||
V(LoopBegin, LOOP_BEGIN, GateFlags::CONTROL, 2, 0, 0) \
|
||||
V(LoopBack, LOOP_BACK, GateFlags::CONTROL, 1, 0, 0) \
|
||||
V(LoopExit, LOOP_EXIT, GateFlags::CONTROL, 1, 0, 0) \
|
||||
V(LoopExitDepend, LOOP_EXIT_DEPEND, GateFlags::FIXED, 1, 1, 0) \
|
||||
V(LoopExitValue, LOOP_EXIT_VALUE, GateFlags::FIXED, 1, 0, 1) \
|
||||
V(DependRelay, DEPEND_RELAY, GateFlags::FIXED, 1, 1, 0) \
|
||||
V(IfSuccess, IF_SUCCESS, GateFlags::CONTROL, 1, 0, 0) \
|
||||
V(IfException, IF_EXCEPTION, GateFlags::CONTROL, 1, 1, 0) \
|
||||
V(GetException, GET_EXCEPTION, GateFlags::NONE_FLAG, 1, 1, 0) \
|
||||
V(GetConstPool, GET_CONSTPOOL, GateFlags::NO_WRITE, 0, 1, 1) \
|
||||
V(GetGlobalEnv, GET_GLOBAL_ENV, GateFlags::NO_WRITE, 0, 1, 0) \
|
||||
V(StateSplit, STATE_SPLIT, GateFlags::CHECKABLE, 1, 1, 0) \
|
||||
V(Load, LOAD, GateFlags::NO_WRITE, 0, 1, 1) \
|
||||
V(Store, STORE, GateFlags::NONE_FLAG, 0, 1, 2) \
|
||||
V(TypedCallCheck, TYPED_CALL_CHECK, GateFlags::CHECKABLE, 1, 1, 3) \
|
||||
V(HeapObjectCheck, HEAP_OBJECT_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
|
||||
V(StableArrayCheck, STABLE_ARRAY_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
|
||||
V(COWArrayCheck, COW_ARRAY_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
|
||||
V(ArrayGuardianCheck, ARRAY_GUARDIAN_CHECK, GateFlags::CHECKABLE, 1, 1, 0) \
|
||||
V(HClassStableArrayCheck, HCLASS_STABLE_ARRAY_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
|
||||
V(DeoptCheck, DEOPT_CHECK, GateFlags::NO_WRITE, 1, 1, 3) \
|
||||
V(StoreProperty, STORE_PROPERTY, GateFlags::NONE_FLAG, 1, 1, 3) \
|
||||
V(StorePropertyNoBarrier, STORE_PROPERTY_NO_BARRIER, GateFlags::NONE_FLAG, 1, 1, 3) \
|
||||
V(ToLength, TO_LENGTH, GateFlags::NONE_FLAG, 1, 1, 1) \
|
||||
V(DefaultCase, DEFAULT_CASE, GateFlags::CONTROL, 1, 0, 0) \
|
||||
V(LoadArrayLength, LOAD_ARRAY_LENGTH, GateFlags::NO_WRITE, 1, 1, 1) \
|
||||
V(TypedNewAllocateThis, TYPED_NEW_ALLOCATE_THIS, GateFlags::CHECKABLE, 1, 1, 2) \
|
||||
V(TypedSuperAllocateThis, TYPED_SUPER_ALLOCATE_THIS, GateFlags::CHECKABLE, 1, 1, 2) \
|
||||
V(GetSuperConstructor, GET_SUPER_CONSTRUCTOR, GateFlags::NO_WRITE, 1, 1, 1) \
|
||||
V(UpdateHotness, UPDATE_HOTNESS, GateFlags::NO_WRITE, 1, 1, 0) \
|
||||
V(Dead, DEAD, GateFlags::NONE_FLAG, 0, 0, 0) \
|
||||
V(FrameArgs, FRAME_ARGS, GateFlags::NONE_FLAG, 0, 0, 4) \
|
||||
V(GetEnv, GET_ENV, GateFlags::NONE_FLAG, 0, 0, 1) \
|
||||
V(ConvertHoleAsUndefined, CONVERT_HOLE_AS_UNDEFINED, GateFlags::NO_WRITE, 1, 1, 1) \
|
||||
V(StartAllocate, START_ALLOCATE, GateFlags::NONE_FLAG, 0, 1, 0) \
|
||||
V(FinishAllocate, FINISH_ALLOCATE, GateFlags::NONE_FLAG, 0, 1, 0) \
|
||||
BINARY_GATE_META_DATA_CACHE_LIST(V) \
|
||||
#define IMMUTABLE_META_DATA_CACHE_LIST(V) \
|
||||
V(CircuitRoot, CIRCUIT_ROOT, GateFlags::NONE_FLAG, 0, 0, 0) \
|
||||
V(StateEntry, STATE_ENTRY, GateFlags::ROOT, 0, 0, 0) \
|
||||
V(DependEntry, DEPEND_ENTRY, GateFlags::ROOT, 0, 0, 0) \
|
||||
V(ReturnList, RETURN_LIST, GateFlags::ROOT, 0, 0, 0) \
|
||||
V(ArgList, ARG_LIST, GateFlags::ROOT, 0, 0, 0) \
|
||||
V(Return, RETURN, GateFlags::HAS_ROOT, 1, 1, 1) \
|
||||
V(ReturnVoid, RETURN_VOID, GateFlags::HAS_ROOT, 1, 1, 0) \
|
||||
V(Throw, THROW, GateFlags::CONTROL, 1, 1, 1) \
|
||||
V(OrdinaryBlock, ORDINARY_BLOCK, GateFlags::CONTROL, 1, 0, 0) \
|
||||
V(IfBranch, IF_BRANCH, GateFlags::CONTROL, 1, 0, 1) \
|
||||
V(IfTrue, IF_TRUE, GateFlags::CONTROL, 1, 0, 0) \
|
||||
V(IfFalse, IF_FALSE, GateFlags::CONTROL, 1, 0, 0) \
|
||||
V(LoopBegin, LOOP_BEGIN, GateFlags::CONTROL, 2, 0, 0) \
|
||||
V(LoopBack, LOOP_BACK, GateFlags::CONTROL, 1, 0, 0) \
|
||||
V(LoopExit, LOOP_EXIT, GateFlags::CONTROL, 1, 0, 0) \
|
||||
V(LoopExitDepend, LOOP_EXIT_DEPEND, GateFlags::FIXED, 1, 1, 0) \
|
||||
V(LoopExitValue, LOOP_EXIT_VALUE, GateFlags::FIXED, 1, 0, 1) \
|
||||
V(DependRelay, DEPEND_RELAY, GateFlags::FIXED, 1, 1, 0) \
|
||||
V(IfSuccess, IF_SUCCESS, GateFlags::CONTROL, 1, 0, 0) \
|
||||
V(IfException, IF_EXCEPTION, GateFlags::CONTROL, 1, 1, 0) \
|
||||
V(GetException, GET_EXCEPTION, GateFlags::NONE_FLAG, 1, 1, 0) \
|
||||
V(GetConstPool, GET_CONSTPOOL, GateFlags::NO_WRITE, 0, 1, 1) \
|
||||
V(GetGlobalEnv, GET_GLOBAL_ENV, GateFlags::NO_WRITE, 0, 1, 0) \
|
||||
V(StateSplit, STATE_SPLIT, GateFlags::CHECKABLE, 1, 1, 0) \
|
||||
V(Load, LOAD, GateFlags::NO_WRITE, 0, 1, 1) \
|
||||
V(Store, STORE, GateFlags::NONE_FLAG, 0, 1, 2) \
|
||||
V(TypedCallCheck, TYPED_CALL_CHECK, GateFlags::CHECKABLE, 1, 1, 3) \
|
||||
V(HeapObjectCheck, HEAP_OBJECT_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
|
||||
V(StableArrayCheck, STABLE_ARRAY_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
|
||||
V(COWArrayCheck, COW_ARRAY_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
|
||||
V(ArrayGuardianCheck, ARRAY_GUARDIAN_CHECK, GateFlags::CHECKABLE, 1, 1, 0) \
|
||||
V(HClassStableArrayCheck, HCLASS_STABLE_ARRAY_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
|
||||
V(DeoptCheck, DEOPT_CHECK, GateFlags::NO_WRITE, 1, 1, 3) \
|
||||
V(StoreProperty, STORE_PROPERTY, GateFlags::NONE_FLAG, 1, 1, 3) \
|
||||
V(StorePropertyNoBarrier, STORE_PROPERTY_NO_BARRIER, GateFlags::NONE_FLAG, 1, 1, 3) \
|
||||
V(ToLength, TO_LENGTH, GateFlags::NONE_FLAG, 1, 1, 1) \
|
||||
V(DefaultCase, DEFAULT_CASE, GateFlags::CONTROL, 1, 0, 0) \
|
||||
V(LoadArrayLength, LOAD_ARRAY_LENGTH, GateFlags::NO_WRITE, 1, 1, 1) \
|
||||
V(TypedNewAllocateThis, TYPED_NEW_ALLOCATE_THIS, GateFlags::CHECKABLE, 1, 1, 2) \
|
||||
V(TypedSuperAllocateThis, TYPED_SUPER_ALLOCATE_THIS, GateFlags::CHECKABLE, 1, 1, 2) \
|
||||
V(GetSuperConstructor, GET_SUPER_CONSTRUCTOR, GateFlags::NO_WRITE, 1, 1, 1) \
|
||||
V(CheckSafePointAndStackOver, CHECK_SAFEPOINT_AND_STACKOVER, GateFlags::NO_WRITE, 1, 1, 0) \
|
||||
V(Dead, DEAD, GateFlags::NONE_FLAG, 0, 0, 0) \
|
||||
V(FrameArgs, FRAME_ARGS, GateFlags::NONE_FLAG, 0, 0, 4) \
|
||||
V(GetEnv, GET_ENV, GateFlags::NONE_FLAG, 0, 0, 1) \
|
||||
V(ConvertHoleAsUndefined, CONVERT_HOLE_AS_UNDEFINED, GateFlags::NO_WRITE, 1, 1, 1) \
|
||||
V(StartAllocate, START_ALLOCATE, GateFlags::NONE_FLAG, 0, 1, 0) \
|
||||
V(FinishAllocate, FINISH_ALLOCATE, GateFlags::NONE_FLAG, 0, 1, 0) \
|
||||
V(LoadGetter, LOAD_GETTER, GateFlags::NONE_FLAG, 0, 1, 2) \
|
||||
V(LoadSetter, LOAD_SETTER, GateFlags::NONE_FLAG, 0, 1, 2) \
|
||||
V(ReadSp, READSP, GateFlags::NONE_FLAG, 0, 0, 0) \
|
||||
BINARY_GATE_META_DATA_CACHE_LIST(V) \
|
||||
UNARY_GATE_META_DATA_CACHE_LIST(V)
|
||||
|
||||
#define GATE_META_DATA_LIST_WITH_VALUE_IN(V) \
|
||||
@ -312,23 +311,25 @@ std::string MachineTypeToStr(MachineType machineType);
|
||||
V(CallGetter, CALL_GETTER, GateFlags::NONE_FLAG, 1, 1, 2) \
|
||||
V(CallSetter, CALL_SETTER, GateFlags::NONE_FLAG, 1, 1, 3)
|
||||
|
||||
#define GATE_META_DATA_LIST_WITH_SIZE(V) \
|
||||
V(Merge, MERGE, GateFlags::CONTROL, value, 0, 0) \
|
||||
V(DependSelector, DEPEND_SELECTOR, GateFlags::FIXED, 1, value, 0) \
|
||||
#define GATE_META_DATA_LIST_WITH_SIZE(V) \
|
||||
V(Merge, MERGE, GateFlags::CONTROL, value, 0, 0) \
|
||||
V(DependSelector, DEPEND_SELECTOR, GateFlags::FIXED, 1, value, 0) \
|
||||
GATE_META_DATA_LIST_WITH_VALUE_IN(V)
|
||||
|
||||
#define GATE_META_DATA_LIST_WITH_GATE_TYPE(V) \
|
||||
V(PrimitiveTypeCheck, PRIMITIVE_TYPE_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
|
||||
V(ObjectTypeCheck, OBJECT_TYPE_CHECK, GateFlags::CHECKABLE, 1, 1, 2) \
|
||||
V(TypedArrayCheck, TYPED_ARRAY_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
|
||||
V(LoadTypedArrayLength, LOAD_TYPED_ARRAY_LENGTH, GateFlags::NO_WRITE, 1, 1, 1) \
|
||||
V(IndexCheck, INDEX_CHECK, GateFlags::CHECKABLE, 1, 1, 2) \
|
||||
V(TypedUnaryOp, TYPED_UNARY_OP, GateFlags::NO_WRITE, 1, 1, 1) \
|
||||
V(TypedConditionJump, TYPED_CONDITION_JUMP, GateFlags::NO_WRITE, 1, 1, 1) \
|
||||
V(TypedConvert, TYPE_CONVERT, GateFlags::NO_WRITE, 1, 1, 1) \
|
||||
V(CheckAndConvert, CHECK_AND_CONVERT, GateFlags::CHECKABLE, 1, 0, 1) \
|
||||
V(Convert, CONVERT, GateFlags::NONE_FLAG, 0, 0, 1) \
|
||||
V(JSInlineTargetTypeCheck, JSINLINETARGET_TYPE_CHECK, GateFlags::CHECKABLE, 1, 1, 2)
|
||||
#define GATE_META_DATA_LIST_WITH_GATE_TYPE(V) \
|
||||
V(PrimitiveTypeCheck, PRIMITIVE_TYPE_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
|
||||
V(ObjectTypeCheck, OBJECT_TYPE_CHECK, GateFlags::CHECKABLE, 1, 1, 2) \
|
||||
V(ObjectTypeCompare, OBJECT_TYPE_COMPARE, GateFlags::CHECKABLE, 1, 1, 2) \
|
||||
V(TypedArrayCheck, TYPED_ARRAY_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
|
||||
V(LoadTypedArrayLength, LOAD_TYPED_ARRAY_LENGTH, GateFlags::NO_WRITE, 1, 1, 1) \
|
||||
V(IndexCheck, INDEX_CHECK, GateFlags::CHECKABLE, 1, 1, 2) \
|
||||
V(TypedUnaryOp, TYPED_UNARY_OP, GateFlags::NO_WRITE, 1, 1, 1) \
|
||||
V(TypedConditionJump, TYPED_CONDITION_JUMP, GateFlags::NO_WRITE, 1, 1, 1) \
|
||||
V(TypedConvert, TYPE_CONVERT, GateFlags::NO_WRITE, 1, 1, 1) \
|
||||
V(CheckAndConvert, CHECK_AND_CONVERT, GateFlags::CHECKABLE, 1, 1, 1) \
|
||||
V(Convert, CONVERT, GateFlags::NONE_FLAG, 0, 0, 1) \
|
||||
V(JSInlineTargetTypeCheck, JSINLINETARGET_TYPE_CHECK, GateFlags::CHECKABLE, 1, 1, 2) \
|
||||
V(InlineAccessorCheck, INLINE_ACCESSOR_CHECK, GateFlags::CHECKABLE, 1, 1, 2)
|
||||
|
||||
#define GATE_META_DATA_LIST_WITH_VALUE(V) \
|
||||
V(Icmp, ICMP, GateFlags::NONE_FLAG, 0, 0, 2) \
|
||||
@ -348,7 +349,9 @@ std::string MachineTypeToStr(MachineType machineType);
|
||||
V(GetGlobalEnvObjHClass, GET_GLOBAL_ENV_OBJ_HCLASS, GateFlags::NO_WRITE, 0, 1, 1) \
|
||||
V(GetGlobalConstantValue, GET_GLOBAL_CONSTANT_VALUE, GateFlags::NO_WRITE, 0, 1, 0) \
|
||||
V(FrameState, FRAME_STATE, GateFlags::HAS_FRAME_STATE, 0, 0, 2) \
|
||||
V(CreateArray, CREATE_ARRAY, GateFlags::NONE_FLAG, 1, 1, 0)
|
||||
V(CreateArray, CREATE_ARRAY, GateFlags::NONE_FLAG, 1, 1, 0) \
|
||||
V(CreateArrayWithBuffer, CREATE_ARRAY_WITH_BUFFER, GateFlags::CHECKABLE, 1, 1, 2) \
|
||||
V(RangeGuard, RANGE_GUARD, GateFlags::NO_WRITE, 1, 1, 1)
|
||||
|
||||
#define GATE_META_DATA_LIST_WITH_ONE_PARAMETER(V) \
|
||||
V(Arg, ARG, GateFlags::HAS_ROOT, 0, 0, 0) \
|
||||
|
@ -26,6 +26,12 @@ void GraphEditor::RemoveDeadState(Circuit* circuit, GateRef gate)
|
||||
editor.RemoveGate();
|
||||
}
|
||||
|
||||
void GraphEditor::EliminateRedundantPhi(Circuit* circuit)
|
||||
{
|
||||
GraphEditor editor(circuit);
|
||||
editor.EliminatePhi();
|
||||
}
|
||||
|
||||
void GraphEditor::ReplaceGate(GateRef gate)
|
||||
{
|
||||
auto uses = acc_.Uses(gate);
|
||||
@ -108,4 +114,57 @@ void GraphEditor::PropagateMerge(const Edge& edge)
|
||||
acc_.DecreaseIn(gate, edge.GetIndex());
|
||||
}
|
||||
}
|
||||
} // namespace panda::ecmascript::kungfu
|
||||
|
||||
void GraphEditor::EliminatePhi()
|
||||
{
|
||||
std::vector<GateRef> gateList;
|
||||
acc_.GetAllGates(gateList);
|
||||
std::queue<GateRef> workList;
|
||||
std::set<GateRef> inList;
|
||||
for (auto gate : gateList) {
|
||||
if (acc_.IsValueSelector(gate)) {
|
||||
workList.push(gate);
|
||||
inList.insert(gate);
|
||||
}
|
||||
}
|
||||
|
||||
while (!workList.empty()) {
|
||||
auto cur = workList.front();
|
||||
workList.pop();
|
||||
ASSERT(acc_.IsValueSelector(cur));
|
||||
GateRef first = acc_.GetValueIn(cur, 0);
|
||||
auto use = acc_.Uses(cur);
|
||||
bool sameIns = true;
|
||||
bool selfUse = first == cur;
|
||||
bool noUses = use.begin() == use.end();
|
||||
auto valueNum = acc_.GetNumValueIn(cur);
|
||||
for (size_t i = 1; i < valueNum; ++i) {
|
||||
GateRef input = acc_.GetValueIn(cur, i);
|
||||
if (input != first) {
|
||||
sameIns = false;
|
||||
}
|
||||
if (input == cur) {
|
||||
ASSERT(acc_.IsLoopHead(acc_.GetState(cur)));
|
||||
selfUse = true;
|
||||
}
|
||||
}
|
||||
if ((!sameIns) && (!selfUse) && (!noUses)) {
|
||||
inList.erase(cur);
|
||||
continue;
|
||||
}
|
||||
for (auto it = use.begin(); it != use.end(); ++it) {
|
||||
if (((*it) == cur) || (!acc_.IsValueSelector(*it)) || inList.count(*it)) {
|
||||
// selfUse or notPhi or inListPhi
|
||||
continue;
|
||||
}
|
||||
workList.push(*it);
|
||||
inList.insert(*it);
|
||||
}
|
||||
acc_.UpdateAllUses(cur, first);
|
||||
}
|
||||
for (auto phi : inList) {
|
||||
ASSERT(acc_.IsValueSelector(phi));
|
||||
acc_.DeleteGate(phi);
|
||||
}
|
||||
}
|
||||
} // namespace panda::ecmascript::kungfu
|
||||
|
@ -31,11 +31,13 @@ public:
|
||||
~GraphEditor() = default;
|
||||
|
||||
static void RemoveDeadState(Circuit* circuit, GateRef gate);
|
||||
static void EliminateRedundantPhi(Circuit* circuit);
|
||||
private:
|
||||
void ReplaceGate(GateRef gate);
|
||||
void RemoveGate();
|
||||
void PropagateGate(const Edge& edge);
|
||||
void PropagateMerge(const Edge& edge);
|
||||
void EliminatePhi();
|
||||
|
||||
Circuit *circuit_ {nullptr};
|
||||
GateAccessor acc_;
|
||||
@ -43,4 +45,4 @@ private:
|
||||
ChunkVector<Edge> workList_;
|
||||
};
|
||||
} // panda::ecmascript::kungfu
|
||||
#endif // ECMASCRIPT_COMPILER_GRAPH_VISITOR_H
|
||||
#endif // ECMASCRIPT_COMPILER_GRAPH_VISITOR_H
|
||||
|
@ -96,7 +96,8 @@ void ICStubBuilder::ValuedICAccessor(Variable* cachedHandler, Label *tryICHandle
|
||||
}
|
||||
}
|
||||
|
||||
void ICStubBuilder::LoadICByName(Variable* result, Label* tryFastPath, Label *slowPath, Label *success)
|
||||
void ICStubBuilder::LoadICByName(
|
||||
Variable *result, Label *tryFastPath, Label *slowPath, Label *success, ProfileOperation callback)
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
Label loadWithHandler(env);
|
||||
@ -108,7 +109,7 @@ void ICStubBuilder::LoadICByName(Variable* result, Label* tryFastPath, Label *sl
|
||||
NamedICAccessor(&cachedHandler, &loadWithHandler);
|
||||
Bind(&loadWithHandler);
|
||||
{
|
||||
GateRef ret = LoadICWithHandler(glue_, receiver_, receiver_, *cachedHandler);
|
||||
GateRef ret = LoadICWithHandler(glue_, receiver_, receiver_, *cachedHandler, callback);
|
||||
result->WriteVariable(ret);
|
||||
Branch(TaggedIsHole(ret), slowPath_, success_);
|
||||
}
|
||||
@ -132,7 +133,8 @@ void ICStubBuilder::StoreICByName(Variable* result, Label* tryFastPath, Label *s
|
||||
}
|
||||
}
|
||||
|
||||
void ICStubBuilder::LoadICByValue(Variable* result, Label* tryFastPath, Label *slowPath, Label *success)
|
||||
void ICStubBuilder::LoadICByValue(
|
||||
Variable *result, Label *tryFastPath, Label *slowPath, Label *success, ProfileOperation callback)
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
Label loadWithHandler(env);
|
||||
@ -151,7 +153,7 @@ void ICStubBuilder::LoadICByValue(Variable* result, Label* tryFastPath, Label *s
|
||||
}
|
||||
Bind(&loadWithHandler);
|
||||
{
|
||||
GateRef ret = LoadICWithHandler(glue_, receiver_, receiver_, *cachedHandler);
|
||||
GateRef ret = LoadICWithHandler(glue_, receiver_, receiver_, *cachedHandler, callback);
|
||||
result->WriteVariable(ret);
|
||||
Branch(TaggedIsHole(ret), slowPath_, success_);
|
||||
}
|
||||
|
@ -44,9 +44,11 @@ public:
|
||||
propKey_ = propKey;
|
||||
}
|
||||
|
||||
void LoadICByName(Variable* result, Label* tryFastPath, Label *slowPath, Label *success);
|
||||
void LoadICByName(Variable* result, Label* tryFastPath, Label *slowPath, Label *success,
|
||||
ProfileOperation callback);
|
||||
void StoreICByName(Variable* result, Label* tryFastPath, Label *slowPath, Label *success);
|
||||
void LoadICByValue(Variable* result, Label* tryFastPath, Label *slowPath, Label *success);
|
||||
void LoadICByValue(Variable* result, Label* tryFastPath, Label *slowPath, Label *success,
|
||||
ProfileOperation callback);
|
||||
void StoreICByValue(Variable* result, Label* tryFastPath, Label *slowPath, Label *success);
|
||||
void TryLoadGlobalICByName(Variable* result, Label* tryFastPath, Label *slowPath, Label *success);
|
||||
void TryStoreGlobalICByName(Variable* result, Label* tryFastPath, Label *slowPath, Label *success);
|
||||
|
@ -128,7 +128,7 @@ void name##StubBuilder::GenerateCircuitImpl(GateRef glue, GateRef sp, GateRef pc
|
||||
Int8(VmThreadControl::VM_NEED_SUSPENSION))), &callRuntime, &dispatch); \
|
||||
Bind(&callRuntime); \
|
||||
{ \
|
||||
if (callback.IsEmpty()) { \
|
||||
if (!(callback).IsEmpty()) { \
|
||||
varProfileTypeInfo = CallRuntime(glue, RTSTUB_ID(UpdateHotnessCounterWithProf), { func }); \
|
||||
} else { \
|
||||
varProfileTypeInfo = CallRuntime(glue, RTSTUB_ID(UpdateHotnessCounter), { func }); \
|
||||
@ -922,7 +922,7 @@ DECLARE_ASM_HANDLER(HandleInstanceofImm8V8)
|
||||
GateRef slotId = ZExtInt8ToInt32(ReadInst8_0(pc));
|
||||
GateRef target = acc;
|
||||
AccessObjectStubBuilder builder(this);
|
||||
GateRef result = InstanceOf(glue, obj, target, profileTypeInfo, slotId);
|
||||
GateRef result = InstanceOf(glue, obj, target, profileTypeInfo, slotId, callback);
|
||||
CHECK_PENDING_EXCEPTION(result, INT_PTR(INSTANCEOF_IMM8_V8));
|
||||
}
|
||||
|
||||
@ -2578,7 +2578,7 @@ DECLARE_ASM_HANDLER(HandleTryldglobalbynameImm8Id16)
|
||||
GateRef slotId = ZExtInt8ToInt32(ReadInst8_0(pc));
|
||||
AccessObjectStubBuilder builder(this);
|
||||
StringIdInfo info = { constpool, pc, StringIdInfo::Offset::BYTE_1, StringIdInfo::Length::BITS_16 };
|
||||
GateRef result = builder.TryLoadGlobalByName(glue, 0, info, profileTypeInfo, slotId);
|
||||
GateRef result = builder.TryLoadGlobalByName(glue, 0, info, profileTypeInfo, slotId, callback);
|
||||
CHECK_EXCEPTION_WITH_VARACC(result, INT_PTR(TRYLDGLOBALBYNAME_IMM8_ID16));
|
||||
}
|
||||
|
||||
@ -2589,7 +2589,7 @@ DECLARE_ASM_HANDLER(HandleTryldglobalbynameImm16Id16)
|
||||
GateRef slotId = ZExtInt16ToInt32(ReadInst16_0(pc));
|
||||
AccessObjectStubBuilder builder(this);
|
||||
StringIdInfo info = { constpool, pc, StringIdInfo::Offset::BYTE_2, StringIdInfo::Length::BITS_16 };
|
||||
GateRef result = builder.TryLoadGlobalByName(glue, 0, info, profileTypeInfo, slotId);
|
||||
GateRef result = builder.TryLoadGlobalByName(glue, 0, info, profileTypeInfo, slotId, callback);
|
||||
CHECK_EXCEPTION_WITH_VARACC(result, INT_PTR(TRYLDGLOBALBYNAME_IMM16_ID16));
|
||||
}
|
||||
|
||||
@ -2598,7 +2598,7 @@ DECLARE_ASM_HANDLER(HandleTrystglobalbynameImm8Id16)
|
||||
GateRef slotId = ZExtInt16ToInt32(ReadInst8_0(pc));
|
||||
AccessObjectStubBuilder builder(this);
|
||||
StringIdInfo info = { constpool, pc, StringIdInfo::Offset::BYTE_1, StringIdInfo::Length::BITS_16 };
|
||||
GateRef result = builder.TryStoreGlobalByName(glue, 0, info, acc, profileTypeInfo, slotId);
|
||||
GateRef result = builder.TryStoreGlobalByName(glue, 0, info, acc, profileTypeInfo, slotId, callback);
|
||||
CHECK_EXCEPTION(result, INT_PTR(TRYSTGLOBALBYNAME_IMM8_ID16));
|
||||
}
|
||||
|
||||
@ -2607,7 +2607,7 @@ DECLARE_ASM_HANDLER(HandleTrystglobalbynameImm16Id16)
|
||||
GateRef slotId = ZExtInt16ToInt32(ReadInst16_0(pc));
|
||||
AccessObjectStubBuilder builder(this);
|
||||
StringIdInfo info = { constpool, pc, StringIdInfo::Offset::BYTE_2, StringIdInfo::Length::BITS_16 };
|
||||
GateRef result = builder.TryStoreGlobalByName(glue, 0, info, acc, profileTypeInfo, slotId);
|
||||
GateRef result = builder.TryStoreGlobalByName(glue, 0, info, acc, profileTypeInfo, slotId, callback);
|
||||
CHECK_EXCEPTION(result, INT_PTR(TRYSTGLOBALBYNAME_IMM16_ID16));
|
||||
}
|
||||
|
||||
@ -2618,7 +2618,7 @@ DECLARE_ASM_HANDLER(HandleLdglobalvarImm16Id16)
|
||||
GateRef slotId = ZExtInt16ToInt32(ReadInst16_0(pc));
|
||||
AccessObjectStubBuilder builder(this);
|
||||
StringIdInfo info = { constpool, pc, StringIdInfo::Offset::BYTE_2, StringIdInfo::Length::BITS_16 };
|
||||
GateRef result = builder.LoadGlobalVar(glue, 0, info, profileTypeInfo, slotId);
|
||||
GateRef result = builder.LoadGlobalVar(glue, 0, info, profileTypeInfo, slotId, callback);
|
||||
CHECK_EXCEPTION_WITH_VARACC(result, INT_PTR(LDGLOBALVAR_IMM16_ID16));
|
||||
}
|
||||
|
||||
@ -3016,7 +3016,7 @@ DECLARE_ASM_HANDLER(HandleLdobjbyvalueImm8V8)
|
||||
GateRef slotId = ZExtInt8ToInt32(ReadInst8_0(pc));
|
||||
|
||||
AccessObjectStubBuilder builder(this);
|
||||
GateRef result = builder.LoadObjByValue(glue, receiver, propKey, profileTypeInfo, slotId);
|
||||
GateRef result = builder.LoadObjByValue(glue, receiver, propKey, profileTypeInfo, slotId, callback);
|
||||
CHECK_EXCEPTION_WITH_VARACC(result, INT_PTR(LDOBJBYVALUE_IMM8_V8));
|
||||
}
|
||||
|
||||
@ -3030,7 +3030,7 @@ DECLARE_ASM_HANDLER(HandleLdobjbyvalueImm16V8)
|
||||
GateRef slotId = ZExtInt8ToInt32(ReadInst16_0(pc));
|
||||
|
||||
AccessObjectStubBuilder builder(this);
|
||||
GateRef result = builder.LoadObjByValue(glue, receiver, propKey, profileTypeInfo, slotId);
|
||||
GateRef result = builder.LoadObjByValue(glue, receiver, propKey, profileTypeInfo, slotId, callback);
|
||||
CHECK_EXCEPTION_WITH_VARACC(result, INT_PTR(LDOBJBYVALUE_IMM16_V8));
|
||||
}
|
||||
|
||||
@ -3093,7 +3093,7 @@ DECLARE_ASM_HANDLER(HandleLdobjbyindexImm8Imm16)
|
||||
Branch(TaggedIsHeapObject(receiver), &fastPath, &slowPath);
|
||||
Bind(&fastPath);
|
||||
{
|
||||
GateRef result = GetPropertyByIndex(glue, receiver, index);
|
||||
GateRef result = GetPropertyByIndex(glue, receiver, index, callback);
|
||||
Label notHole(env);
|
||||
Branch(TaggedIsHole(result), &slowPath, ¬Hole);
|
||||
Bind(¬Hole);
|
||||
@ -3118,7 +3118,7 @@ DECLARE_ASM_HANDLER(HandleLdobjbyindexImm16Imm16)
|
||||
Branch(TaggedIsHeapObject(receiver), &fastPath, &slowPath);
|
||||
Bind(&fastPath);
|
||||
{
|
||||
GateRef result = GetPropertyByIndex(glue, receiver, index);
|
||||
GateRef result = GetPropertyByIndex(glue, receiver, index, callback);
|
||||
Label notHole(env);
|
||||
Branch(TaggedIsHole(result), &slowPath, ¬Hole);
|
||||
Bind(¬Hole);
|
||||
@ -3143,7 +3143,7 @@ DECLARE_ASM_HANDLER(HandleWideLdobjbyindexPrefImm32)
|
||||
Branch(TaggedIsHeapObject(receiver), &fastPath, &slowPath);
|
||||
Bind(&fastPath);
|
||||
{
|
||||
GateRef result = GetPropertyByIndex(glue, receiver, index);
|
||||
GateRef result = GetPropertyByIndex(glue, receiver, index, callback);
|
||||
Label notHole(env);
|
||||
Branch(TaggedIsHole(result), &slowPath, ¬Hole);
|
||||
Bind(¬Hole);
|
||||
@ -3169,7 +3169,7 @@ DECLARE_ASM_HANDLER(HandleDeprecatedLdobjbyindexPrefV8Imm32)
|
||||
Branch(TaggedIsHeapObject(receiver), &fastPath, &slowPath);
|
||||
Bind(&fastPath);
|
||||
{
|
||||
GateRef result = GetPropertyByIndex(glue, receiver, index);
|
||||
GateRef result = GetPropertyByIndex(glue, receiver, index, callback);
|
||||
Label notHole(env);
|
||||
Branch(TaggedIsHole(result), &slowPath, ¬Hole);
|
||||
Bind(¬Hole);
|
||||
@ -3695,8 +3695,7 @@ DECLARE_ASM_HANDLER(HandleWideCallrangePrefImm16V8)
|
||||
GateRef jumpSize = INT_PTR(WIDE_CALLRANGE_PREF_IMM16_V8);
|
||||
GateRef numArgs = ZExtInt32ToPtr(actualNumArgs);
|
||||
GateRef res = JSCallDispatch(glue, func, actualNumArgs, jumpSize, hotnessCounter,
|
||||
JSCallMode::CALL_WITH_ARGV, { numArgs, argv }, callback,
|
||||
BytecodeInstruction::Format::IMM16);
|
||||
JSCallMode::CALL_WITH_ARGV, { numArgs, argv }, callback);
|
||||
CHECK_PENDING_EXCEPTION(res, jumpSize);
|
||||
}
|
||||
|
||||
@ -3710,8 +3709,7 @@ DECLARE_ASM_HANDLER(HandleDeprecatedCallrangePrefImm16V8)
|
||||
GateRef jumpSize = INT_PTR(DEPRECATED_CALLRANGE_PREF_IMM16_V8);
|
||||
GateRef numArgs = ZExtInt32ToPtr(actualNumArgs);
|
||||
GateRef res = JSCallDispatch(glue, func, actualNumArgs, jumpSize, hotnessCounter,
|
||||
JSCallMode::DEPRECATED_CALL_WITH_ARGV, { numArgs, argv }, callback,
|
||||
BytecodeInstruction::Format::IMM16);
|
||||
JSCallMode::DEPRECATED_CALL_WITH_ARGV, { numArgs, argv }, callback);
|
||||
CHECK_PENDING_EXCEPTION(res, jumpSize);
|
||||
}
|
||||
|
||||
@ -3741,8 +3739,7 @@ DECLARE_ASM_HANDLER(HandleWideCallthisrangePrefImm16V8)
|
||||
GateRef jumpSize = INT_PTR(WIDE_CALLTHISRANGE_PREF_IMM16_V8);
|
||||
GateRef numArgs = ZExtInt32ToPtr(actualNumArgs);
|
||||
GateRef res = JSCallDispatch(glue, func, actualNumArgs, jumpSize, hotnessCounter,
|
||||
JSCallMode::CALL_THIS_WITH_ARGV, { numArgs, argv, thisValue },
|
||||
callback, BytecodeInstruction::Format::IMM16);
|
||||
JSCallMode::CALL_THIS_WITH_ARGV, { numArgs, argv, thisValue }, callback);
|
||||
CHECK_PENDING_EXCEPTION(res, jumpSize);
|
||||
}
|
||||
|
||||
@ -3758,8 +3755,7 @@ DECLARE_ASM_HANDLER(HandleDeprecatedCallthisrangePrefImm16V8)
|
||||
GateRef jumpSize = INT_PTR(DEPRECATED_CALLTHISRANGE_PREF_IMM16_V8);
|
||||
GateRef numArgs = ZExtInt32ToPtr(actualNumArgs);
|
||||
GateRef res = JSCallDispatch(glue, func, actualNumArgs, jumpSize, hotnessCounter,
|
||||
JSCallMode::DEPRECATED_CALL_THIS_WITH_ARGV, { numArgs, argv, thisValue },
|
||||
callback, BytecodeInstruction::Format::IMM16);
|
||||
JSCallMode::DEPRECATED_CALL_THIS_WITH_ARGV, { numArgs, argv, thisValue }, callback);
|
||||
CHECK_PENDING_EXCEPTION(res, jumpSize);
|
||||
}
|
||||
|
||||
@ -3996,8 +3992,7 @@ DECLARE_ASM_HANDLER(HandleNewobjrangeImm16Imm8V8)
|
||||
IntPtr(-static_cast<int64_t>(BytecodeInstruction::Size(BytecodeInstruction::Format::IMM16_IMM8_V8)));
|
||||
res = JSCallDispatch(glue, ctor, actualNumArgs, jumpSize, hotnessCounter,
|
||||
JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV,
|
||||
{ ZExtInt32ToPtr(actualNumArgs), argv, *thisObj }, callback,
|
||||
BytecodeInstruction::Format::IMM16);
|
||||
{ ZExtInt32ToPtr(actualNumArgs), argv, *thisObj }, callback);
|
||||
Jump(&threadCheck);
|
||||
}
|
||||
Bind(&slowPath);
|
||||
@ -4066,8 +4061,7 @@ DECLARE_ASM_HANDLER(HandleWideNewobjrangePrefImm16V8)
|
||||
GateRef jumpSize = IntPtr(-BytecodeInstruction::Size(BytecodeInstruction::Format::PREF_IMM16_V8));
|
||||
res = JSCallDispatch(glue, ctor, actualNumArgs, jumpSize, hotnessCounter,
|
||||
JSCallMode::DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV,
|
||||
{ ZExtInt32ToPtr(actualNumArgs), argv, *thisObj }, callback,
|
||||
BytecodeInstruction::Format::IMM16);
|
||||
{ ZExtInt32ToPtr(actualNumArgs), argv, *thisObj }, callback);
|
||||
Jump(&threadCheck);
|
||||
}
|
||||
Bind(&slowPath);
|
||||
@ -4364,7 +4358,7 @@ DECLARE_ASM_HANDLER(HandleLdthisbyvalueImm16)
|
||||
GateRef slotId = ZExtInt16ToInt32(ReadInst16_0(pc));
|
||||
|
||||
AccessObjectStubBuilder builder(this);
|
||||
GateRef result = builder.LoadObjByValue(glue, receiver, propKey, profileTypeInfo, slotId);
|
||||
GateRef result = builder.LoadObjByValue(glue, receiver, propKey, profileTypeInfo, slotId, callback);
|
||||
CHECK_EXCEPTION_WITH_VARACC(result, INT_PTR(LDTHISBYVALUE_IMM16));
|
||||
}
|
||||
DECLARE_ASM_HANDLER(HandleLdthisbyvalueImm8)
|
||||
@ -4376,7 +4370,7 @@ DECLARE_ASM_HANDLER(HandleLdthisbyvalueImm8)
|
||||
GateRef slotId = ZExtInt8ToInt32(ReadInst8_0(pc));
|
||||
|
||||
AccessObjectStubBuilder builder(this);
|
||||
GateRef result = builder.LoadObjByValue(glue, receiver, propKey, profileTypeInfo, slotId);
|
||||
GateRef result = builder.LoadObjByValue(glue, receiver, propKey, profileTypeInfo, slotId, callback);
|
||||
CHECK_EXCEPTION_WITH_VARACC(result, INT_PTR(LDTHISBYVALUE_IMM8));
|
||||
}
|
||||
DECLARE_ASM_HANDLER(HandleStthisbynameImm16Id16)
|
||||
|
@ -37,7 +37,7 @@ void LaterElimination::Run()
|
||||
|
||||
GateRef LaterElimination::VisitDependEntry(GateRef gate)
|
||||
{
|
||||
auto empty = new (chunk_) DependChainNodes(chunk_);
|
||||
auto empty = new (chunk_) DependChains(chunk_);
|
||||
return UpdateDependChain(gate, empty);
|
||||
}
|
||||
|
||||
@ -54,14 +54,13 @@ GateRef LaterElimination::VisitGate(GateRef gate)
|
||||
case OpCode::HEAP_OBJECT_CHECK:
|
||||
case OpCode::INT32_UNSIGNED_UPPER_BOUND_CHECK:
|
||||
case OpCode::OVERFLOW_CHECK:
|
||||
case OpCode::LARGE_INDEX_CHECK:
|
||||
case OpCode::NEGATIVE_INDEX_CHECK:
|
||||
case OpCode::VALUE_CHECK_NEG_OVERFLOW:
|
||||
case OpCode::FLOAT64_CHECK_RIGHT_IS_ZERO:
|
||||
case OpCode::INT32_CHECK_RIGHT_IS_ZERO:
|
||||
case OpCode::INT32_DIV_WITH_CHECK:
|
||||
case OpCode::LEX_VAR_IS_HOLE_CHECK:
|
||||
case OpCode::COW_ARRAY_CHECK:
|
||||
case OpCode::CHECK_AND_CONVERT:
|
||||
return TryEliminateGate(gate);
|
||||
case OpCode::DEPEND_SELECTOR:
|
||||
return TryEliminateDependSelector(gate);
|
||||
@ -123,7 +122,7 @@ GateRef LaterElimination::TryEliminateDependSelector(GateRef gate)
|
||||
// all depend done.
|
||||
auto depend = acc_.GetDep(gate);
|
||||
auto dependChain = GetDependChain(depend);
|
||||
DependChainNodes* copy = new (chunk_) DependChainNodes(chunk_);
|
||||
DependChains* copy = new (chunk_) DependChains(chunk_);
|
||||
copy->CopyFrom(dependChain);
|
||||
for (size_t i = 1; i < dependCount; ++i) { // 1: second in
|
||||
auto dependIn = acc_.GetDep(gate, i);
|
||||
@ -133,7 +132,7 @@ GateRef LaterElimination::TryEliminateDependSelector(GateRef gate)
|
||||
return UpdateDependChain(gate, copy);
|
||||
}
|
||||
|
||||
GateRef LaterElimination::UpdateDependChain(GateRef gate, DependChainNodes* dependChain)
|
||||
GateRef LaterElimination::UpdateDependChain(GateRef gate, DependChains* dependChain)
|
||||
{
|
||||
ASSERT(dependChain != nullptr);
|
||||
auto oldDependChain = GetDependChain(gate);
|
||||
@ -158,77 +157,26 @@ bool LaterElimination::CheckReplacement(GateRef lhs, GateRef rhs)
|
||||
}
|
||||
}
|
||||
auto opcode = acc_.GetOpCode(lhs);
|
||||
if (opcode == OpCode::GET_GLOBAL_ENV_OBJ_HCLASS ||
|
||||
opcode == OpCode::GET_GLOBAL_CONSTANT_VALUE) {
|
||||
if (acc_.GetIndex(lhs) != acc_.GetIndex(rhs)) {
|
||||
return false;
|
||||
switch (opcode) {
|
||||
case OpCode::GET_GLOBAL_ENV_OBJ_HCLASS:
|
||||
case OpCode::GET_GLOBAL_CONSTANT_VALUE: {
|
||||
if (acc_.GetIndex(lhs) != acc_.GetIndex(rhs)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OpCode::CHECK_AND_CONVERT: {
|
||||
if (acc_.GetSrcType(lhs) != acc_.GetSrcType(rhs)) {
|
||||
return false;
|
||||
}
|
||||
if (acc_.GetDstType(lhs) != acc_.GetDstType(rhs)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void DependChainNodes::Merge(DependChainNodes* that)
|
||||
{
|
||||
// find common sub list
|
||||
while (size_ > that->size_) {
|
||||
head_ = head_->next;
|
||||
size_--;
|
||||
}
|
||||
|
||||
auto lhs = this->head_;
|
||||
auto rhs = that->head_;
|
||||
size_t rhsSize = that->size_;
|
||||
while (rhsSize > size_) {
|
||||
rhs = rhs->next;
|
||||
rhsSize--;
|
||||
}
|
||||
while (lhs != rhs) {
|
||||
ASSERT(lhs != nullptr);
|
||||
lhs = lhs->next;
|
||||
rhs = rhs->next;
|
||||
size_--;
|
||||
}
|
||||
head_ = lhs;
|
||||
}
|
||||
|
||||
bool DependChainNodes::Equals(DependChainNodes* that)
|
||||
{
|
||||
if (that == nullptr) {
|
||||
return false;
|
||||
}
|
||||
if (size_ != that->size_) {
|
||||
return false;
|
||||
}
|
||||
auto lhs = this->head_;
|
||||
auto rhs = that->head_;
|
||||
while (lhs != rhs) {
|
||||
if (lhs->gate != rhs->gate) {
|
||||
return false;
|
||||
}
|
||||
lhs = lhs->next;
|
||||
rhs = rhs->next;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
GateRef DependChainNodes::LookupNode(LaterElimination* elimination, GateRef gate)
|
||||
{
|
||||
for (Node* node = head_; node != nullptr; node = node->next) {
|
||||
if (elimination->CheckReplacement(node->gate, gate)) {
|
||||
return node->gate;
|
||||
}
|
||||
}
|
||||
return Circuit::NullGate();
|
||||
}
|
||||
|
||||
DependChainNodes* DependChainNodes::UpdateNode(GateRef gate)
|
||||
{
|
||||
// assign node->next to head
|
||||
Node* node = chunk_->New<Node>(gate, head_);
|
||||
DependChainNodes* that = new (chunk_) DependChainNodes(chunk_);
|
||||
// assign head to node
|
||||
that->head_ = node;
|
||||
that->size_ = size_ + 1;
|
||||
return that;
|
||||
}
|
||||
} // namespace panda::ecmascript::kungfu
|
||||
|
@ -19,37 +19,11 @@
|
||||
#include "ecmascript/compiler/circuit_builder.h"
|
||||
#include "ecmascript/compiler/gate_accessor.h"
|
||||
#include "ecmascript/compiler/graph_visitor.h"
|
||||
#include "ecmascript/compiler/base/depend_chain_helper.h"
|
||||
#include "ecmascript/mem/chunk_containers.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
class LaterElimination;
|
||||
|
||||
class DependChainNodes : public ChunkObject {
|
||||
public:
|
||||
DependChainNodes(Chunk* chunk) : chunk_(chunk) {}
|
||||
~DependChainNodes() = default;
|
||||
|
||||
GateRef LookupNode(LaterElimination* elimination, GateRef gate);
|
||||
DependChainNodes* UpdateNode(GateRef gate);
|
||||
bool Equals(DependChainNodes* that);
|
||||
void Merge(DependChainNodes* that);
|
||||
void CopyFrom(DependChainNodes *other)
|
||||
{
|
||||
head_ = other->head_;
|
||||
size_ = other->size_;
|
||||
}
|
||||
private:
|
||||
struct Node {
|
||||
Node(GateRef gate, Node* next) : gate(gate), next(next) {}
|
||||
GateRef gate;
|
||||
Node *next;
|
||||
};
|
||||
|
||||
Node *head_{nullptr};
|
||||
size_t size_ {0};
|
||||
Chunk* chunk_;
|
||||
};
|
||||
|
||||
class DependChains;
|
||||
class LaterElimination : public GraphVisitor {
|
||||
public:
|
||||
LaterElimination(Circuit *circuit, bool enableLog, const std::string& name, Chunk* chunk)
|
||||
@ -73,7 +47,7 @@ private:
|
||||
return methodName_;
|
||||
}
|
||||
|
||||
DependChainNodes* GetDependChain(GateRef dependIn)
|
||||
DependChains* GetDependChain(GateRef dependIn)
|
||||
{
|
||||
size_t idx = acc_.GetId(dependIn);
|
||||
ASSERT(idx <= circuit_->GetMaxGateId());
|
||||
@ -81,14 +55,14 @@ private:
|
||||
}
|
||||
|
||||
GateRef VisitDependEntry(GateRef gate);
|
||||
GateRef UpdateDependChain(GateRef gate, DependChainNodes* dependInfo);
|
||||
GateRef UpdateDependChain(GateRef gate, DependChains* dependInfo);
|
||||
GateRef TryEliminateGate(GateRef gate);
|
||||
GateRef TryEliminateOther(GateRef gate);
|
||||
GateRef TryEliminateDependSelector(GateRef gate);
|
||||
|
||||
bool enableLog_ {false};
|
||||
std::string methodName_;
|
||||
ChunkVector<DependChainNodes*> dependChains_;
|
||||
ChunkVector<DependChains*> dependChains_;
|
||||
};
|
||||
} // panda::ecmascript::kungfu
|
||||
#endif // ECMASCRIPT_COMPILER_LATER_ELIMINATION_H
|
@ -71,12 +71,6 @@ void LCRLowering::Run()
|
||||
case OpCode::VALUE_CHECK_NEG_OVERFLOW:
|
||||
LowerValueCheckNegOverflow(gate);
|
||||
break;
|
||||
case OpCode::NEGATIVE_INDEX_CHECK:
|
||||
LowerNegativeIndexCheck(gate);
|
||||
break;
|
||||
case OpCode::LARGE_INDEX_CHECK:
|
||||
LowerLargeIndexCheck(gate);
|
||||
break;
|
||||
case OpCode::OVERFLOW_CHECK:
|
||||
LowerOverflowCheck(gate);
|
||||
break;
|
||||
@ -92,6 +86,9 @@ void LCRLowering::Run()
|
||||
case OpCode::STORE_MEMORY:
|
||||
LowerStoreMemory(gate);
|
||||
break;
|
||||
case OpCode::CHECK_AND_CONVERT:
|
||||
LowerCheckAndConvert(gate);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -227,6 +224,16 @@ StateDepend LCRLowering::LowerConvert(StateDepend stateDepend, GateRef gate)
|
||||
result = builder_.NotEqual(value, builder_.Int32(0));
|
||||
}
|
||||
break;
|
||||
case ValueType::UINT32:
|
||||
if (dstType == ValueType::TAGGED_NUMBER) {
|
||||
result = ConvertUInt32ToTaggedNumber(value, &exit);
|
||||
} else if (dstType == ValueType::FLOAT64) {
|
||||
result = ConvertUInt32ToFloat64(value);
|
||||
} else {
|
||||
ASSERT(dstType == ValueType::BOOL);
|
||||
result = builder_.NotEqual(value,builder_.Int32(0));
|
||||
}
|
||||
break;
|
||||
case ValueType::FLOAT64:
|
||||
if (dstType == ValueType::TAGGED_DOUBLE) {
|
||||
result = ConvertFloat64ToTaggedDouble(value);
|
||||
@ -313,12 +320,16 @@ GateRef LCRLowering::ConvertTaggedNumberToFloat64(GateRef gate, Label *exit)
|
||||
return *result;
|
||||
}
|
||||
|
||||
StateDepend LCRLowering::LowerCheckAndConvert(StateDepend stateDepend, GateRef gate, GateRef frameState)
|
||||
void LCRLowering::LowerCheckAndConvert(GateRef gate)
|
||||
{
|
||||
Environment env(stateDepend.State(), stateDepend.Depend(), {}, circuit_, &builder_);
|
||||
Environment env(gate, circuit_, &builder_);
|
||||
GateRef frameState = acc_.GetFrameState(gate);
|
||||
ValueType srcType = acc_.GetSrcType(gate);
|
||||
Label exit(&builder_);
|
||||
switch (srcType) {
|
||||
case ValueType::UINT32:
|
||||
LowerCheckUInt32AndConvert(gate, frameState);
|
||||
break;
|
||||
case ValueType::TAGGED_INT:
|
||||
LowerCheckTaggedIntAndConvert(gate, frameState);
|
||||
break;
|
||||
@ -337,7 +348,15 @@ StateDepend LCRLowering::LowerCheckAndConvert(StateDepend stateDepend, GateRef g
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
return builder_.GetStateDepend();
|
||||
}
|
||||
|
||||
void LCRLowering::LowerCheckUInt32AndConvert(GateRef gate, GateRef frameState)
|
||||
{
|
||||
GateRef value = acc_.GetValueIn(gate, 0);
|
||||
GateRef upperBound = builder_.Int32(INT32_MAX);
|
||||
GateRef check = builder_.Int32UnsignedLessThanOrEqual(value, upperBound);
|
||||
builder_.DeoptCheck(check, frameState, DeoptType::INT32OVERFLOW);
|
||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), value);
|
||||
}
|
||||
|
||||
void LCRLowering::LowerCheckTaggedIntAndConvert(GateRef gate, GateRef frameState)
|
||||
@ -434,11 +453,33 @@ GateRef LCRLowering::ConvertInt32ToFloat64(GateRef gate)
|
||||
return builder_.ChangeInt32ToFloat64(gate);
|
||||
}
|
||||
|
||||
GateRef LCRLowering::ConvertUInt32ToFloat64(GateRef gate)
|
||||
{
|
||||
return builder_.ChangeUInt32ToFloat64(gate);
|
||||
}
|
||||
|
||||
GateRef LCRLowering::ConvertInt32ToTaggedInt(GateRef gate)
|
||||
{
|
||||
return builder_.Int32ToTaggedPtr(gate);
|
||||
}
|
||||
|
||||
GateRef LCRLowering::ConvertUInt32ToTaggedNumber(GateRef gate, Label *exit)
|
||||
{
|
||||
Label isOverFlow(&builder_);
|
||||
Label notOverFlow(&builder_);
|
||||
GateRef upperBound = builder_.Int32(INT32_MAX);
|
||||
DEFVAlUE(taggedVal, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant());
|
||||
builder_.Branch(builder_.Int32UnsignedLessThanOrEqual(gate, upperBound), ¬OverFlow, &isOverFlow);
|
||||
builder_.Bind(¬OverFlow);
|
||||
taggedVal = builder_.Int32ToTaggedPtr(gate);
|
||||
builder_.Jump(exit);
|
||||
builder_.Bind(&isOverFlow);
|
||||
taggedVal = builder_.DoubleToTaggedDoublePtr(builder_.ChangeUInt32ToFloat64(gate));
|
||||
builder_.Jump(exit);
|
||||
builder_.Bind(exit);
|
||||
return *taggedVal;
|
||||
}
|
||||
|
||||
GateRef LCRLowering::ConvertFloat64ToInt32(GateRef gate, Label *exit)
|
||||
{
|
||||
return builder_.DoubleToInt(gate, exit);
|
||||
@ -594,27 +635,6 @@ void LCRLowering::LowerValueCheckNegOverflow(GateRef gate)
|
||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
|
||||
}
|
||||
|
||||
void LCRLowering::LowerNegativeIndexCheck(GateRef gate)
|
||||
{
|
||||
Environment env(gate, circuit_, &builder_);
|
||||
GateRef frameState = acc_.GetFrameState(gate);
|
||||
GateRef index = acc_.GetValueIn(gate, 0);
|
||||
GateRef condition = builder_.Int32LessThanOrEqual(builder_.Int32(0), index);
|
||||
builder_.DeoptCheck(condition, frameState, DeoptType::NEGTIVEINDEX);
|
||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
|
||||
}
|
||||
|
||||
void LCRLowering::LowerLargeIndexCheck(GateRef gate)
|
||||
{
|
||||
Environment env(gate, circuit_, &builder_);
|
||||
GateRef frameState = acc_.GetFrameState(gate);
|
||||
GateRef index = acc_.GetValueIn(gate, 0);
|
||||
GateRef length = acc_.GetValueIn(gate, 1);
|
||||
GateRef condition = builder_.Int32LessThan(index, length);
|
||||
builder_.DeoptCheck(condition, frameState, DeoptType::LARGEINDEX);
|
||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
|
||||
}
|
||||
|
||||
void LCRLowering::LowerOverflowCheck(GateRef gate)
|
||||
{
|
||||
Environment env(gate, circuit_, &builder_);
|
||||
@ -649,13 +669,15 @@ void LCRLowering::LowerInt32DivWithCheck(GateRef gate)
|
||||
GateRef condition = builder_.BoolOr(rightGreaterZero, builder_.BoolAnd(rightLessZero, leftNotZero));
|
||||
builder_.DeoptCheck(condition, frameState, DeoptType::DIVZERO);
|
||||
result = builder_.BinaryArithmetic(circuit_->Sdiv(), MachineType::I32, left, right, GateType::NJSValue());
|
||||
GateRef truncated = builder_.BinaryArithmetic(circuit_->Mul(), MachineType::I32, result, right);
|
||||
GateRef truncated = builder_.BinaryArithmetic(circuit_->Mul(),
|
||||
MachineType::I32, result, right, GateType::NJSValue());
|
||||
GateRef overCheck = builder_.Int32Equal(truncated, left);
|
||||
builder_.DeoptCheck(overCheck, frameState, DeoptType::NOTINT);
|
||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
|
||||
}
|
||||
|
||||
void LCRLowering::LowerStoreMemory(GateRef gate){
|
||||
void LCRLowering::LowerStoreMemory(GateRef gate)
|
||||
{
|
||||
Environment env(gate, circuit_, &builder_);
|
||||
GateRef receiver = acc_.GetValueIn(gate, 0);
|
||||
GateRef index = acc_.GetValueIn(gate, 1);
|
||||
|
@ -36,7 +36,6 @@ public:
|
||||
return enableLog_;
|
||||
}
|
||||
void Run();
|
||||
StateDepend LowerCheckAndConvert(StateDepend stateDepend, GateRef gate, GateRef frameState);
|
||||
StateDepend LowerConvert(StateDepend stateDepend, GateRef gate);
|
||||
private:
|
||||
const std::string& GetMethodName() const
|
||||
@ -52,6 +51,8 @@ private:
|
||||
void LowerLoadConstOffset(GateRef gate);
|
||||
void LowerStoreConstOffset(GateRef gate);
|
||||
void LowerConvertHoleAsUndefined(GateRef gate);
|
||||
void LowerCheckAndConvert(GateRef gate);
|
||||
void LowerCheckUInt32AndConvert(GateRef gate, GateRef frameState);
|
||||
void LowerCheckTaggedIntAndConvert(GateRef gate, GateRef frameState);
|
||||
void LowerCheckTaggedDoubleAndConvert(GateRef gate, GateRef frameState, Label *exit);
|
||||
void LowerCheckTaggedNumberAndConvert(GateRef gate, GateRef frameState, Label *exit);
|
||||
@ -64,8 +65,6 @@ private:
|
||||
void LowerInt32CheckRightIsZero(GateRef gate);
|
||||
void LowerFloat64CheckRightIsZero(GateRef gate);
|
||||
void LowerValueCheckNegOverflow(GateRef gate);
|
||||
void LowerNegativeIndexCheck(GateRef gate);
|
||||
void LowerLargeIndexCheck(GateRef gate);
|
||||
void LowerOverflowCheck(GateRef gate);
|
||||
void LowerInt32UnsignedUpperBoundCheck(GateRef gate);
|
||||
void LowerInt32DivWithCheck(GateRef gate);
|
||||
@ -74,7 +73,9 @@ private:
|
||||
|
||||
GateRef ConvertBoolToTaggedBoolean(GateRef gate);
|
||||
GateRef ConvertInt32ToFloat64(GateRef gate);
|
||||
GateRef ConvertUInt32ToFloat64(GateRef gate);
|
||||
GateRef ConvertInt32ToTaggedInt(GateRef gate);
|
||||
GateRef ConvertUInt32ToTaggedNumber(GateRef gate, Label *exit);
|
||||
GateRef ConvertFloat64ToBool(GateRef gate);
|
||||
GateRef ConvertFloat64ToInt32(GateRef gate, Label *exit);
|
||||
GateRef ConvertFloat64ToTaggedDouble(GateRef gate);
|
||||
|
@ -149,9 +149,13 @@ uint8_t *CodeInfo::AllocaCodeSection(uintptr_t size, const char *sectionName)
|
||||
{
|
||||
uint8_t *addr = nullptr;
|
||||
auto curSec = ElfSection(sectionName);
|
||||
if (curSec.isValidAOTSec() && !alreadyPageAlign_) {
|
||||
addr = AllocaInReqSecBuffer(size, AOTFileInfo::TEXT_SEC_ALIGN);
|
||||
alreadyPageAlign_ = true;
|
||||
if (curSec.isValidAOTSec()) {
|
||||
if (!alreadyPageAlign_) {
|
||||
addr = AllocaInReqSecBuffer(size, AOTFileInfo::PAGE_ALIGN);
|
||||
alreadyPageAlign_ = true;
|
||||
} else {
|
||||
addr = AllocaInReqSecBuffer(size, AOTFileInfo::TEXT_SEC_ALIGN);
|
||||
}
|
||||
} else {
|
||||
addr = AllocaInReqSecBuffer(size);
|
||||
}
|
||||
@ -170,8 +174,8 @@ uint8_t *CodeInfo::AllocaDataSection(uintptr_t size, const char *sectionName)
|
||||
if (curSec.InRodataSection()) {
|
||||
size = AlignUp(size, static_cast<size_t>(MemAlignment::MEM_ALIGN_REGION));
|
||||
if (!alreadyPageAlign_) {
|
||||
addr = curSec.isSequentialAOTSec() ? AllocaInReqSecBuffer(size, AOTFileInfo::TEXT_SEC_ALIGN)
|
||||
: AllocaInNotReqSecBuffer(size, AOTFileInfo::TEXT_SEC_ALIGN);
|
||||
addr = curSec.isSequentialAOTSec() ? AllocaInReqSecBuffer(size, AOTFileInfo::PAGE_ALIGN)
|
||||
: AllocaInNotReqSecBuffer(size, AOTFileInfo::PAGE_ALIGN);
|
||||
alreadyPageAlign_ = true;
|
||||
} else {
|
||||
addr = curSec.isSequentialAOTSec() ? AllocaInReqSecBuffer(size, AOTFileInfo::DATA_SEC_ALIGN)
|
||||
|
@ -63,6 +63,7 @@ LLVMIRBuilder::LLVMIRBuilder(const std::vector<std::vector<GateRef>> *schedule,
|
||||
function_(function), llvmModule_(module), callConv_(callConv), enableLog_(enableLog),
|
||||
isFastCallAot_(isFastCallAot)
|
||||
{
|
||||
ASSERT(compCfg_->Is64Bit());
|
||||
context_ = module->GetContext();
|
||||
builder_ = LLVMCreateBuilderInContext(context_);
|
||||
bbID2BB_.clear();
|
||||
@ -70,17 +71,8 @@ LLVMIRBuilder::LLVMIRBuilder(const std::vector<std::vector<GateRef>> *schedule,
|
||||
InitializeHandlers();
|
||||
|
||||
LLVMSetGC(function_, "statepoint-example");
|
||||
if (compCfg_->Is32Bit()) {
|
||||
slotSize_ = sizeof(uint32_t);
|
||||
slotType_ = LLVMInt32TypeInContext(context_);
|
||||
} else {
|
||||
slotSize_ = sizeof(uint64_t);
|
||||
slotType_ = LLVMInt64TypeInContext(context_);
|
||||
}
|
||||
if (compCfg_->Is32Bit()) {
|
||||
// hard float instruction
|
||||
LLVMAddTargetDependentFunctionAttr(function_, "target-features", "+armv8-a");
|
||||
}
|
||||
slotSize_ = sizeof(uint64_t);
|
||||
slotType_ = GetInt64T();
|
||||
|
||||
LLVMMetadataRef dFile = llvmModule_->GetDFileMD();
|
||||
LLVMMetadataRef funcTyMD = GetFunctionTypeMD(dFile);
|
||||
@ -115,11 +107,7 @@ void LLVMIRBuilder::SetFunctionCallConv()
|
||||
LLVMSetFunctionCallConv(function_, LLVMGHCCallConv);
|
||||
break;
|
||||
case CallSignature::CallConv::WebKitJSCallConv: {
|
||||
if (!compCfg_->Is32Bit()) {
|
||||
LLVMSetFunctionCallConv(function_, LLVMWebKitJSCallConv);
|
||||
} else {
|
||||
LLVMSetFunctionCallConv(function_, LLVMCCallConv);
|
||||
}
|
||||
LLVMSetFunctionCallConv(function_, LLVMWebKitJSCallConv);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
@ -214,6 +202,7 @@ void LLVMIRBuilder::InitializeHandlers()
|
||||
{OpCode::MUL_WITH_OVERFLOW, &LLVMIRBuilder::HandleMulWithOverflow},
|
||||
{OpCode::EXTRACT_VALUE, &LLVMIRBuilder::HandleExtractValue},
|
||||
{OpCode::SQRT, &LLVMIRBuilder::HandleSqrt},
|
||||
{OpCode::READSP, &LLVMIRBuilder::HandleReadSp},
|
||||
};
|
||||
illegalOpHandlers_ = {
|
||||
OpCode::NOP, OpCode::CIRCUIT_ROOT, OpCode::DEPEND_ENTRY,
|
||||
@ -352,9 +341,6 @@ BasicBlockImpl *LLVMIRBuilder::EnsureBBImpl(BasicBlock *bb) const
|
||||
|
||||
void LLVMIRBuilder::GenPrologue()
|
||||
{
|
||||
if (compCfg_->Is32Bit()) {
|
||||
return;
|
||||
}
|
||||
auto frameType = circuit_->GetFrameType();
|
||||
if (IsInterpreted()) {
|
||||
return;
|
||||
@ -411,14 +397,12 @@ LLVMValueRef LLVMIRBuilder::CallingFp(LLVMModuleRef &module, LLVMBuilderRef &bui
|
||||
return LLVMGetParam(function_, static_cast<unsigned>(InterpreterHandlerInputs::SP));
|
||||
}
|
||||
/* 0:calling 1:its caller */
|
||||
std::vector<LLVMValueRef> args = {LLVMConstInt(LLVMInt32TypeInContext(context_), 0, isCaller)};
|
||||
std::vector<LLVMValueRef> args = {LLVMConstInt(GetInt32T(), 0, isCaller)};
|
||||
auto fn = LLVMGetNamedFunction(module, "llvm.frameaddress.p0i8");
|
||||
if (!fn) {
|
||||
/* init instrinsic function declare */
|
||||
LLVMTypeRef paramTys1[] = {
|
||||
LLVMInt32TypeInContext(context_),
|
||||
};
|
||||
auto fnTy = LLVMFunctionType(LLVMPointerType(LLVMInt8TypeInContext(context_), 0), paramTys1, 1, 0);
|
||||
LLVMTypeRef paramTys1[] = { GetInt32T() };
|
||||
auto fnTy = LLVMFunctionType(GetRawPtrT(), paramTys1, 1, 0);
|
||||
fn = LLVMAddFunction(module, "llvm.frameaddress.p0i8", fnTy);
|
||||
}
|
||||
LLVMValueRef fAddrRet = LLVMBuildCall(builder, fn, args.data(), 1, "");
|
||||
@ -435,7 +419,7 @@ LLVMValueRef LLVMIRBuilder::ReadRegister(LLVMModuleRef &module, [[maybe_unused]]
|
||||
LLVMTypeRef paramTys1[] = {
|
||||
GetMachineRepType(MachineRep::K_META),
|
||||
};
|
||||
auto fnTy = LLVMFunctionType(LLVMInt64TypeInContext(context_), paramTys1, 1, 0);
|
||||
auto fnTy = LLVMFunctionType(GetInt64T(), paramTys1, 1, 0);
|
||||
fn = LLVMAddFunction(module, "llvm.read_register.i64", fnTy);
|
||||
}
|
||||
LLVMValueRef fAddrRet = LLVMBuildCall(builder_, fn, args.data(), 1, "");
|
||||
@ -462,30 +446,25 @@ LLVMTypeRef LLVMIRBuilder::GetMachineRepType(MachineRep rep) const
|
||||
LLVMTypeRef dstType;
|
||||
switch (rep) {
|
||||
case MachineRep::K_BIT:
|
||||
dstType = LLVMInt1TypeInContext(context_);
|
||||
dstType = GetInt1T();
|
||||
break;
|
||||
case MachineRep::K_WORD8:
|
||||
dstType = LLVMInt8TypeInContext(context_);
|
||||
dstType = GetInt8T();
|
||||
break;
|
||||
case MachineRep::K_WORD16:
|
||||
dstType = LLVMInt16TypeInContext(context_);
|
||||
dstType = GetInt16T();
|
||||
break;
|
||||
case MachineRep::K_WORD32:
|
||||
dstType = LLVMInt32TypeInContext(context_);
|
||||
dstType = GetInt32T();
|
||||
break;
|
||||
case MachineRep::K_FLOAT64:
|
||||
dstType = LLVMDoubleTypeInContext(context_);
|
||||
dstType = GetDoubleT();
|
||||
break;
|
||||
case MachineRep::K_WORD64:
|
||||
dstType = LLVMInt64TypeInContext(context_);
|
||||
dstType = GetInt64T();
|
||||
break;
|
||||
case MachineRep::K_PTR_1:
|
||||
if (compCfg_->Is32Bit()) {
|
||||
dstType =
|
||||
LLVMVectorType(LLVMPointerType(LLVMInt8TypeInContext(context_), 1), 2); // 2: packed vector type
|
||||
} else {
|
||||
dstType = LLVMPointerType(LLVMInt64TypeInContext(context_), 1);
|
||||
}
|
||||
dstType = GetTaggedHPtrT();
|
||||
break;
|
||||
case MachineRep::K_META:
|
||||
dstType = LLVMMetadataTypeInContext(context_);
|
||||
@ -498,6 +477,12 @@ LLVMTypeRef LLVMIRBuilder::GetMachineRepType(MachineRep rep) const
|
||||
return dstType;
|
||||
}
|
||||
|
||||
void LLVMIRBuilder::HandleReadSp(GateRef gate)
|
||||
{
|
||||
ASSERT(acc_.GetOpCode(gate) == OpCode::READSP);
|
||||
VisitReadSp(gate);
|
||||
}
|
||||
|
||||
void LLVMIRBuilder::HandleCall(GateRef gate)
|
||||
{
|
||||
std::vector<GateRef> ins;
|
||||
@ -581,14 +566,14 @@ void LLVMIRBuilder::VisitRuntimeCall(GateRef gate, const std::vector<GateRef> &i
|
||||
auto kind = GetCallExceptionKind(stubIndex, OpCode::RUNTIME_CALL);
|
||||
|
||||
size_t actualNumArgs = 0;
|
||||
LLVMValueRef pcOffset = LLVMConstInt(LLVMInt32TypeInContext(context_), 0, 0);
|
||||
LLVMValueRef pcOffset = LLVMConstInt(GetInt32T(), 0, 0);
|
||||
ComputeArgCountAndPCOffset(actualNumArgs, pcOffset, inList, kind);
|
||||
|
||||
std::vector<LLVMValueRef> params;
|
||||
params.push_back(glue); // glue
|
||||
const int index = static_cast<int>(acc_.GetConstantValue(inList[static_cast<int>(CallInputs::TARGET)]));
|
||||
params.push_back(LLVMConstInt(LLVMInt64TypeInContext(context_), index, 0)); // target
|
||||
params.push_back(LLVMConstInt(LLVMInt64TypeInContext(context_),
|
||||
params.push_back(LLVMConstInt(GetInt64T(), index, 0)); // target
|
||||
params.push_back(LLVMConstInt(GetInt64T(),
|
||||
actualNumArgs - static_cast<size_t>(CallInputs::FIRST_PARAMETER), 0)); // argc
|
||||
for (size_t paraIdx = static_cast<size_t>(CallInputs::FIRST_PARAMETER); paraIdx < actualNumArgs; ++paraIdx) {
|
||||
GateRef gateTmp = inList[paraIdx];
|
||||
@ -602,8 +587,7 @@ void LLVMIRBuilder::VisitRuntimeCall(GateRef gate, const std::vector<GateRef> &i
|
||||
LLVMValueRef runtimeCall = nullptr;
|
||||
if (kind == CallExceptionKind::HAS_PC_OFFSET) {
|
||||
std::vector<LLVMValueRef> values;
|
||||
auto pcIndex =
|
||||
LLVMConstInt(LLVMInt64TypeInContext(context_), static_cast<int>(SpecVregIndex::PC_OFFSET_INDEX), 1);
|
||||
auto pcIndex = LLVMConstInt(GetInt64T(), static_cast<int>(SpecVregIndex::PC_OFFSET_INDEX), 1);
|
||||
values.push_back(pcIndex);
|
||||
values.push_back(pcOffset);
|
||||
runtimeCall = LLVMBuildCall3(builder_, funcType, callee, params.data(), actualNumArgs,
|
||||
@ -611,10 +595,7 @@ void LLVMIRBuilder::VisitRuntimeCall(GateRef gate, const std::vector<GateRef> &i
|
||||
} else {
|
||||
runtimeCall = LLVMBuildCall2(builder_, funcType, callee, params.data(), actualNumArgs, "");
|
||||
}
|
||||
|
||||
if (!compCfg_->Is32Bit()) { // Arm32 not support webkit jscc calling convention
|
||||
LLVMSetInstructionCallConv(runtimeCall, LLVMWebKitJSCallConv);
|
||||
}
|
||||
LLVMSetInstructionCallConv(runtimeCall, LLVMWebKitJSCallConv);
|
||||
gate2LValue_[gate] = runtimeCall;
|
||||
|
||||
if (IsLogEnabled()) {
|
||||
@ -656,7 +637,7 @@ void LLVMIRBuilder::VisitRuntimeCallWithArgv(GateRef gate, const std::vector<Gat
|
||||
params.push_back(glue); // glue
|
||||
|
||||
uint64_t index = acc_.GetConstantValue(inList[static_cast<size_t>(CallInputs::TARGET)]);
|
||||
auto targetId = LLVMConstInt(LLVMInt64TypeInContext(context_), index, 0);
|
||||
auto targetId = LLVMConstInt(GetInt64T(), index, 0);
|
||||
params.push_back(targetId); // target
|
||||
for (size_t paraIdx = static_cast<size_t>(CallInputs::FIRST_PARAMETER); paraIdx < inList.size(); ++paraIdx) {
|
||||
GateRef gateTmp = inList[paraIdx];
|
||||
@ -690,7 +671,7 @@ LLVMValueRef LLVMIRBuilder::GetCurrentFrameType(LLVMValueRef currentSpFrameAddr)
|
||||
{
|
||||
LLVMValueRef tmp = LLVMBuildSub(builder_, currentSpFrameAddr, LLVMConstInt(slotType_, slotSize_, 1), "");
|
||||
LLVMValueRef frameTypeAddr =
|
||||
LLVMBuildIntToPtr(builder_, tmp, LLVMPointerType(LLVMInt64TypeInContext(context_), 0), "");
|
||||
LLVMBuildIntToPtr(builder_, tmp, LLVMPointerType(GetInt64T(), 0), "");
|
||||
LLVMValueRef frameType = LLVMBuildLoad(builder_, frameTypeAddr, "");
|
||||
return frameType;
|
||||
}
|
||||
@ -799,7 +780,7 @@ void LLVMIRBuilder::UpdateLeaveFrame(LLVMValueRef glue)
|
||||
LLVMTypeRef glueType = LLVMTypeOf(glue);
|
||||
LLVMValueRef leaveFrameAddr = LLVMBuildIntToPtr(builder_, leaveFrameValue, LLVMPointerType(glueType, 0), "");
|
||||
LLVMValueRef llvmFpAddr = CallingFp(module_, builder_, true);
|
||||
LLVMValueRef fp = LLVMBuildPtrToInt(builder_, llvmFpAddr, LLVMInt64TypeInContext(context_), "cast_int64_t");
|
||||
LLVMValueRef fp = LLVMBuildPtrToInt(builder_, llvmFpAddr, GetInt64T(), "cast_int64_t");
|
||||
LLVMBuildStore(builder_, fp, leaveFrameAddr);
|
||||
}
|
||||
|
||||
@ -818,6 +799,12 @@ LLVMValueRef LLVMIRBuilder::GetCallee(const std::vector<GateRef> &inList, const
|
||||
return callee;
|
||||
}
|
||||
|
||||
void LLVMIRBuilder::VisitReadSp(GateRef gate)
|
||||
{
|
||||
LLVMValueRef spValue = GetCurrentSP();
|
||||
gate2LValue_[gate] = spValue;
|
||||
}
|
||||
|
||||
void LLVMIRBuilder::VisitCall(GateRef gate, const std::vector<GateRef> &inList, OpCode op)
|
||||
{
|
||||
size_t targetIndex = static_cast<size_t>(CallInputs::TARGET);
|
||||
@ -888,7 +875,7 @@ void LLVMIRBuilder::VisitCall(GateRef gate, const std::vector<GateRef> &inList,
|
||||
|
||||
int extraParameterCnt = 0;
|
||||
size_t actualNumArgs = 0;
|
||||
LLVMValueRef pcOffset = LLVMConstInt(LLVMInt32TypeInContext(context_), 0, 0);
|
||||
LLVMValueRef pcOffset = LLVMConstInt(GetInt32T(), 0, 0);
|
||||
ComputeArgCountAndPCOffset(actualNumArgs, pcOffset, inList, kind);
|
||||
|
||||
// then push the actual parameter for js function call
|
||||
@ -900,8 +887,8 @@ void LLVMIRBuilder::VisitCall(GateRef gate, const std::vector<GateRef> &inList,
|
||||
// match parameter types and function signature types
|
||||
if (IsHeapPointerType(paramType) && !IsHeapPointerType(gateTmpType)) {
|
||||
params.push_back(LLVMBuildIntToPtr(builder_,
|
||||
LLVMBuildBitCast(builder_, gate2LValue_[gateTmp], LLVMInt64TypeInContext(context_), ""),
|
||||
paramType, ""));
|
||||
LLVMBuildBitCast(builder_, gate2LValue_[gateTmp], GetInt64T(), ""),
|
||||
paramType, ""));
|
||||
} else {
|
||||
params.push_back(LLVMBuildBitCast(builder_, gate2LValue_[gateTmp], paramType, ""));
|
||||
}
|
||||
@ -915,8 +902,7 @@ void LLVMIRBuilder::VisitCall(GateRef gate, const std::vector<GateRef> &inList,
|
||||
callee = LLVMBuildPointerCast(builder_, callee, LLVMPointerType(funcType, 0), "");
|
||||
if (kind == CallExceptionKind::HAS_PC_OFFSET) {
|
||||
std::vector<LLVMValueRef> values;
|
||||
auto pcIndex =
|
||||
LLVMConstInt(LLVMInt64TypeInContext(context_), static_cast<int>(SpecVregIndex::PC_OFFSET_INDEX), 1);
|
||||
auto pcIndex = LLVMConstInt(GetInt64T(), static_cast<int>(SpecVregIndex::PC_OFFSET_INDEX), 1);
|
||||
values.push_back(pcIndex);
|
||||
values.push_back(pcOffset);
|
||||
call = LLVMBuildCall3(builder_, funcType, callee, params.data(), actualNumArgs - firstArg + extraParameterCnt,
|
||||
@ -1114,7 +1100,7 @@ void LLVMIRBuilder::LinkToLLVMCfg(int bbId, const OperandsVector &predecessors)
|
||||
LLVMBasicBlockRef preLBB = EnsureLBB(pre);
|
||||
LLVMMoveBasicBlockBefore(preLBB, lBB);
|
||||
}
|
||||
if (isPrologue(bbId)) {
|
||||
if (IsPrologue(bbId)) {
|
||||
GenPrologue();
|
||||
}
|
||||
}
|
||||
@ -1168,26 +1154,16 @@ void LLVMIRBuilder::VisitConstant(GateRef gate, std::bitset<64> value) // 64: bi
|
||||
LLVMValueRef llvmValue = nullptr;
|
||||
auto machineType = acc_.GetMachineType(gate);
|
||||
if (machineType == MachineType::ARCH) {
|
||||
machineType = compCfg_->Is32Bit() ? MachineType::I32 : MachineType::I64;
|
||||
ASSERT(compCfg_->Is64Bit());
|
||||
machineType = MachineType::I64;
|
||||
}
|
||||
if (machineType == MachineType::I32) {
|
||||
llvmValue = LLVMConstInt(LLVMInt32TypeInContext(context_), value.to_ulong(), 0);
|
||||
llvmValue = LLVMConstInt(GetInt32T(), value.to_ulong(), 0);
|
||||
} else if (machineType == MachineType::I64) {
|
||||
llvmValue = LLVMConstInt(LLVMInt64TypeInContext(context_), value.to_ullong(), 0);
|
||||
llvmValue = LLVMConstInt(GetInt64T(), value.to_ullong(), 0);
|
||||
LLVMTypeRef type = ConvertLLVMTypeFromGate(gate);
|
||||
if (LLVMGetTypeKind(type) == LLVMPointerTypeKind) {
|
||||
llvmValue = LLVMBuildIntToPtr(builder_, llvmValue, type, "");
|
||||
} else if (LLVMGetTypeKind(type) == LLVMVectorTypeKind) {
|
||||
LLVMValueRef tmp1Value = LLVMBuildLShr(
|
||||
builder_, llvmValue, LLVMConstInt(LLVMInt64TypeInContext(context_), 32, 0), ""); // 32: offset
|
||||
LLVMValueRef tmp2Value = LLVMBuildIntCast(builder_, llvmValue, LLVMInt32TypeInContext(context_), ""); // low
|
||||
LLVMValueRef emptyValue = LLVMGetUndef(type);
|
||||
tmp1Value = LLVMBuildIntToPtr(builder_, tmp1Value, LLVMPointerType(LLVMInt8TypeInContext(context_), 1), "");
|
||||
tmp2Value = LLVMBuildIntToPtr(builder_, tmp2Value, LLVMPointerType(LLVMInt8TypeInContext(context_), 1), "");
|
||||
llvmValue = LLVMBuildInsertElement(
|
||||
builder_, emptyValue, tmp2Value, LLVMConstInt(LLVMInt32TypeInContext(context_), 0, 0), "");
|
||||
llvmValue = LLVMBuildInsertElement(
|
||||
builder_, llvmValue, tmp1Value, LLVMConstInt(LLVMInt32TypeInContext(context_), 1, 0), "");
|
||||
} else if (LLVMGetTypeKind(type) == LLVMIntegerTypeKind) {
|
||||
// do nothing
|
||||
} else {
|
||||
@ -1196,13 +1172,13 @@ void LLVMIRBuilder::VisitConstant(GateRef gate, std::bitset<64> value) // 64: bi
|
||||
}
|
||||
} else if (machineType == MachineType::F64) {
|
||||
auto doubleValue = base::bit_cast<double>(value.to_ullong()); // actual double value
|
||||
llvmValue = LLVMConstReal(LLVMDoubleTypeInContext(context_), doubleValue);
|
||||
llvmValue = LLVMConstReal(GetDoubleT(), doubleValue);
|
||||
} else if (machineType == MachineType::I8) {
|
||||
llvmValue = LLVMConstInt(LLVMInt8TypeInContext(context_), value.to_ulong(), 0);
|
||||
llvmValue = LLVMConstInt(GetInt8T(), value.to_ulong(), 0);
|
||||
} else if (machineType == MachineType::I16) {
|
||||
llvmValue = LLVMConstInt(LLVMInt16TypeInContext(context_), value.to_ulong(), 0);
|
||||
llvmValue = LLVMConstInt(GetInt16T(), value.to_ulong(), 0);
|
||||
} else if (machineType == MachineType::I1) {
|
||||
llvmValue = LLVMConstInt(LLVMInt1TypeInContext(context_), value.to_ulong(), 0);
|
||||
llvmValue = LLVMConstInt(GetInt1T(), value.to_ulong(), 0);
|
||||
} else {
|
||||
LOG_ECMA(FATAL) << "this branch is unreachable";
|
||||
UNREACHABLE();
|
||||
@ -1233,8 +1209,8 @@ void LLVMIRBuilder::HandleRelocatableData(GateRef gate)
|
||||
|
||||
void LLVMIRBuilder::VisitRelocatableData(GateRef gate, uint64_t value)
|
||||
{
|
||||
LLVMValueRef globalValue = LLVMAddGlobal(module_, LLVMInt64TypeInContext(context_), "G");
|
||||
LLVMSetInitializer(globalValue, LLVMConstInt(LLVMInt64TypeInContext(context_), value, 0));
|
||||
LLVMValueRef globalValue = LLVMAddGlobal(module_, GetInt64T(), "G");
|
||||
LLVMSetInitializer(globalValue, LLVMConstInt(GetInt64T(), value, 0));
|
||||
gate2LValue_[gate] = globalValue;
|
||||
}
|
||||
|
||||
@ -1377,44 +1353,40 @@ void LLVMIRBuilder::VisitSwitch(GateRef gate, GateRef input, const std::vector<G
|
||||
gate2LValue_[gate] = result;
|
||||
}
|
||||
|
||||
unsigned LLVMIRBuilder::GetPtrAddressSpace(LLVMValueRef v) const
|
||||
{
|
||||
return LLVMGetPointerAddressSpace(LLVMTypeOf(v));
|
||||
}
|
||||
|
||||
void LLVMIRBuilder::VisitLoad(GateRef gate, GateRef base)
|
||||
{
|
||||
LLVMValueRef baseAddr = gate2LValue_[base];
|
||||
LLVMTypeRef returnType;
|
||||
baseAddr = CanonicalizeToPtr(baseAddr);
|
||||
returnType = ConvertLLVMTypeFromGate(gate);
|
||||
baseAddr = LLVMBuildPointerCast(builder_, baseAddr,
|
||||
LLVMPointerType(returnType, LLVMGetPointerAddressSpace(LLVMTypeOf(baseAddr))), "");
|
||||
|
||||
LLVMTypeRef returnType = ConvertLLVMTypeFromGate(gate);
|
||||
LLVMTypeRef memType = LLVMPointerType(returnType, GetPtrAddressSpace(baseAddr));
|
||||
baseAddr = CanonicalizeToPtr(baseAddr, memType);
|
||||
|
||||
LLVMValueRef result = LLVMBuildLoad(builder_, baseAddr, "");
|
||||
gate2LValue_[gate] = result;
|
||||
}
|
||||
|
||||
void LLVMIRBuilder::VisitStore(GateRef gate, GateRef base, GateRef dataToStore)
|
||||
void LLVMIRBuilder::VisitStore(GateRef gate, GateRef base, GateRef value)
|
||||
{
|
||||
LLVMValueRef baseAddr = gate2LValue_[base];
|
||||
baseAddr = CanonicalizeToPtr(baseAddr);
|
||||
LLVMValueRef data = gate2LValue_[dataToStore];
|
||||
baseAddr = LLVMBuildPointerCast(builder_, baseAddr,
|
||||
LLVMPointerType(ConvertLLVMTypeFromGate(dataToStore), LLVMGetPointerAddressSpace(LLVMTypeOf(baseAddr))), "");
|
||||
LLVMValueRef value = LLVMBuildStore(builder_, data, baseAddr);
|
||||
gate2LValue_[gate] = value;
|
||||
LLVMValueRef data = gate2LValue_[value];
|
||||
|
||||
LLVMTypeRef returnType = ConvertLLVMTypeFromGate(value);
|
||||
LLVMTypeRef ptrType = LLVMPointerType(returnType, GetPtrAddressSpace(baseAddr));
|
||||
baseAddr = CanonicalizeToPtr(baseAddr, ptrType);
|
||||
|
||||
LLVMValueRef store = LLVMBuildStore(builder_, data, baseAddr);
|
||||
gate2LValue_[gate] = store;
|
||||
}
|
||||
|
||||
LLVMValueRef LLVMIRBuilder::CanonicalizeToInt(LLVMValueRef value)
|
||||
LLVMValueRef LLVMIRBuilder::CanonicalizeToInt(LLVMValueRef value) const
|
||||
{
|
||||
if (LLVMGetTypeKind(LLVMTypeOf(value)) == LLVMVectorTypeKind) {
|
||||
LLVMValueRef e1Value0 = LLVMBuildExtractElement(
|
||||
builder_, value, LLVMConstInt(LLVMInt32TypeInContext(context_), 0, 1), "");
|
||||
LLVMValueRef e1Value1 = LLVMBuildExtractElement(
|
||||
builder_, value, LLVMConstInt(LLVMInt32TypeInContext(context_), 1, 1), "");
|
||||
LLVMValueRef tmp1 = LLVMBuildPtrToInt(builder_, e1Value1, LLVMInt64TypeInContext(context_), "");
|
||||
LLVMValueRef constValue = LLVMConstInt(LLVMInt64TypeInContext(context_), 32, 0); // 32: offset
|
||||
LLVMValueRef tmp1Value = LLVMBuildShl(builder_, tmp1, constValue, "");
|
||||
LLVMValueRef tmp2Value = LLVMBuildPtrToInt(builder_, e1Value0, LLVMInt64TypeInContext(context_), "");
|
||||
LLVMValueRef resultValue = LLVMBuildAdd(builder_, tmp1Value, tmp2Value, "");
|
||||
return resultValue;
|
||||
} else if (LLVMGetTypeKind(LLVMTypeOf(value)) == LLVMPointerTypeKind) {
|
||||
return LLVMBuildPtrToInt(builder_, value, LLVMInt64TypeInContext(context_), "");
|
||||
if (LLVMGetTypeKind(LLVMTypeOf(value)) == LLVMPointerTypeKind) {
|
||||
return LLVMBuildPtrToInt(builder_, value, GetInt64T(), "");
|
||||
} else if (LLVMGetTypeKind(LLVMTypeOf(value)) == LLVMIntegerTypeKind) {
|
||||
return value;
|
||||
} else {
|
||||
@ -1423,18 +1395,32 @@ LLVMValueRef LLVMIRBuilder::CanonicalizeToInt(LLVMValueRef value)
|
||||
}
|
||||
}
|
||||
|
||||
LLVMValueRef LLVMIRBuilder::CanonicalizeToPtr(LLVMValueRef value)
|
||||
LLVMValueRef LLVMIRBuilder::CanonicalizeToPtr(LLVMValueRef value, LLVMTypeRef ptrType) const
|
||||
{
|
||||
if (LLVMGetTypeKind(LLVMTypeOf(value)) == LLVMVectorTypeKind) {
|
||||
LLVMValueRef tmp = LLVMBuildExtractElement(
|
||||
builder_, value, LLVMConstInt(LLVMInt32TypeInContext(context_), 0, 1), "");
|
||||
return LLVMBuildPointerCast(builder_, tmp, LLVMPointerType(LLVMInt8TypeInContext(context_), 1), "");
|
||||
} else if (LLVMGetTypeKind(LLVMTypeOf(value)) == LLVMPointerTypeKind) {
|
||||
return LLVMBuildPointerCast(builder_, value,
|
||||
LLVMPointerType(LLVMInt8TypeInContext(context_), LLVMGetPointerAddressSpace(LLVMTypeOf(value))), "");
|
||||
} else if (LLVMGetTypeKind(LLVMTypeOf(value)) == LLVMIntegerTypeKind) {
|
||||
LLVMValueRef tmp = LLVMBuildIntToPtr(builder_, value, LLVMPointerType(LLVMInt64TypeInContext(context_), 0), "");
|
||||
return LLVMBuildPointerCast(builder_, tmp, LLVMPointerType(LLVMInt8TypeInContext(context_), 0), "");
|
||||
LLVMTypeRef valueT = LLVMTypeOf(value);
|
||||
if (LLVMGetTypeKind(valueT) == LLVMPointerTypeKind) {
|
||||
if (valueT != ptrType) {
|
||||
return LLVMBuildPointerCast(builder_, value, ptrType, "");
|
||||
}
|
||||
} else if (LLVMGetTypeKind(valueT) == LLVMIntegerTypeKind) {
|
||||
LLVMValueRef result = LLVMBuildIntToPtr(builder_, value, ptrType, "");
|
||||
return result;
|
||||
} else {
|
||||
LOG_COMPILER(FATAL) << "can't Canonicalize to Ptr: ";
|
||||
UNREACHABLE();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
LLVMValueRef LLVMIRBuilder::CanonicalizeToPtr(LLVMValueRef value) const
|
||||
{
|
||||
LLVMTypeRef valueT = LLVMTypeOf(value);
|
||||
if (LLVMGetTypeKind(valueT) == LLVMPointerTypeKind) {
|
||||
auto ptrType = LLVMPointerType(GetInt8T(), GetPtrAddressSpace(value));
|
||||
return LLVMBuildPointerCast(builder_, value, ptrType, "");
|
||||
} else if (LLVMGetTypeKind(valueT) == LLVMIntegerTypeKind) {
|
||||
LLVMValueRef result = LLVMBuildIntToPtr(builder_, value, GetRawPtrT(), "");
|
||||
return result;
|
||||
} else {
|
||||
LOG_COMPILER(FATAL) << "can't Canonicalize to Ptr: ";
|
||||
UNREACHABLE();
|
||||
@ -1463,56 +1449,51 @@ void LLVMIRBuilder::VisitIntRev(GateRef gate, GateRef e1)
|
||||
gate2LValue_[gate] = result;
|
||||
}
|
||||
|
||||
LLVMValueRef LLVMIRBuilder::PointerAdd(LLVMValueRef baseAddr, LLVMValueRef offset, LLVMTypeRef rep)
|
||||
bool LLVMIRBuilder::IsLInteger(LLVMValueRef v) const
|
||||
{
|
||||
LLVMValueRef ptr = CanonicalizeToPtr(baseAddr);
|
||||
LLVMValueRef dstRef8 = LLVMBuildGEP(builder_, ptr, &offset, 1, "");
|
||||
LLVMValueRef result = LLVMBuildPointerCast(builder_, dstRef8, rep, "");
|
||||
return result;
|
||||
LLVMTypeRef r = LLVMTypeOf(v);
|
||||
return LLVMGetTypeKind(r) == LLVMIntegerTypeKind;
|
||||
}
|
||||
|
||||
LLVMValueRef LLVMIRBuilder::VectorAdd(LLVMValueRef baseAddr, LLVMValueRef offset, [[maybe_unused]] LLVMTypeRef rep)
|
||||
bool LLVMIRBuilder::IsLPointer(LLVMValueRef v) const
|
||||
{
|
||||
LLVMTypeRef r = LLVMTypeOf(v);
|
||||
return LLVMGetTypeKind(r) == LLVMPointerTypeKind;
|
||||
}
|
||||
|
||||
LLVMValueRef LLVMIRBuilder::PointerAdd(LLVMValueRef baseAddr, LLVMValueRef offsetInByte, LLVMTypeRef rep)
|
||||
{
|
||||
LLVMValueRef ptr = CanonicalizeToPtr(baseAddr);
|
||||
LLVMValueRef dstRef8 = LLVMBuildGEP(builder_, ptr, &offset, 1, "");
|
||||
LLVMValueRef result = LLVMBuildInsertElement(
|
||||
builder_, baseAddr, dstRef8, LLVMConstInt(LLVMInt32TypeInContext(context_), 0, 0), "");
|
||||
LLVMValueRef dstRef8 = LLVMBuildGEP(builder_, ptr, &offsetInByte, 1, "");
|
||||
LLVMValueRef result = LLVMBuildPointerCast(builder_, dstRef8, rep, "");
|
||||
return result;
|
||||
}
|
||||
|
||||
LLVMTypeRef LLVMIRBuilder::ConvertLLVMTypeFromGate(GateRef gate) const
|
||||
{
|
||||
if (acc_.IsGCRelated(gate)) {
|
||||
if (compCfg_->Is32Bit()) {
|
||||
return LLVMVectorType(LLVMPointerType(LLVMInt8TypeInContext(context_), 1), 2); // 2: packed vector type
|
||||
} else {
|
||||
return LLVMPointerType(LLVMInt64TypeInContext(context_), 1);
|
||||
}
|
||||
return GetTaggedHPtrT();
|
||||
}
|
||||
MachineType t = acc_.GetMachineType(gate);
|
||||
switch (t) {
|
||||
case MachineType::NOVALUE:
|
||||
return LLVMVoidTypeInContext(context_);
|
||||
return GetVoidT();
|
||||
case MachineType::I1:
|
||||
return LLVMInt1TypeInContext(context_);
|
||||
return GetInt1T();
|
||||
case MachineType::I8:
|
||||
return LLVMInt8TypeInContext(context_);
|
||||
return GetInt8T();
|
||||
case MachineType::I16:
|
||||
return LLVMInt16TypeInContext(context_);
|
||||
return GetInt16T();
|
||||
case MachineType::I32:
|
||||
return LLVMInt32TypeInContext(context_);
|
||||
return GetInt32T();
|
||||
case MachineType::I64:
|
||||
return LLVMInt64TypeInContext(context_);
|
||||
return GetInt64T();
|
||||
case MachineType::F32:
|
||||
return LLVMFloatTypeInContext(context_);
|
||||
return GetFloatT();
|
||||
case MachineType::F64:
|
||||
return LLVMDoubleTypeInContext(context_);
|
||||
return GetDoubleT();
|
||||
case MachineType::ARCH: {
|
||||
if (compCfg_->Is32Bit()) {
|
||||
return LLVMInt32TypeInContext(context_);
|
||||
} else {
|
||||
return LLVMInt64TypeInContext(context_);
|
||||
}
|
||||
return GetInt64T();
|
||||
}
|
||||
default:
|
||||
LOG_ECMA(FATAL) << "this branch is unreachable";
|
||||
@ -1597,19 +1578,12 @@ void LLVMIRBuilder::VisitAdd(GateRef gate, GateRef e1, GateRef e2)
|
||||
LLVMValueRef e1Value = gate2LValue_[e1];
|
||||
LLVMValueRef e2Value = gate2LValue_[e2];
|
||||
LLVMValueRef result = nullptr;
|
||||
/*
|
||||
* If the first operand is pointer, special treatment is needed
|
||||
* 1) add, pointer, int
|
||||
* 2) add, vector{i8* x 2}, int
|
||||
*/
|
||||
LLVMTypeRef returnType = ConvertLLVMTypeFromGate(gate);
|
||||
|
||||
LLVMTypeRef returnType = ConvertLLVMTypeFromGate(gate);
|
||||
auto machineType = acc_.GetMachineType(gate);
|
||||
if (IsAddIntergerType(machineType)) {
|
||||
auto e1Type = LLVMGetTypeKind(ConvertLLVMTypeFromGate(e1));
|
||||
if (e1Type == LLVMVectorTypeKind) {
|
||||
result = VectorAdd(e1Value, e2Value, returnType);
|
||||
} else if (e1Type == LLVMPointerTypeKind) {
|
||||
if (e1Type == LLVMPointerTypeKind) {
|
||||
result = PointerAdd(e1Value, e2Value, returnType);
|
||||
} else {
|
||||
LLVMValueRef tmp1Value = LLVMBuildIntCast2(builder_, e1Value, returnType, 0, "");
|
||||
@ -1762,14 +1736,8 @@ void LLVMIRBuilder::VisitAddWithOverflow(GateRef gate, GateRef e1, GateRef e2)
|
||||
auto fn = LLVMGetNamedFunction(module_, "llvm.sadd.with.overflow.i32");
|
||||
if (!fn) {
|
||||
/* init instrinsic function declare */
|
||||
LLVMTypeRef paramTys1[] = {
|
||||
LLVMInt32TypeInContext(context_),
|
||||
LLVMInt32TypeInContext(context_),
|
||||
};
|
||||
LLVMTypeRef structTys[] = {
|
||||
LLVMInt32TypeInContext(context_),
|
||||
LLVMInt1TypeInContext(context_),
|
||||
};
|
||||
LLVMTypeRef paramTys1[] = { GetInt32T(), GetInt32T() };
|
||||
LLVMTypeRef structTys[] = { GetInt32T(), GetInt1T() };
|
||||
LLVMTypeRef returnType = LLVMStructTypeInContext(context_, structTys, 2, 0);
|
||||
auto fnTy = LLVMFunctionType(returnType, paramTys1, 2, 0);
|
||||
fn = LLVMAddFunction(module_, "llvm.sadd.with.overflow.i32", fnTy);
|
||||
@ -1795,14 +1763,8 @@ void LLVMIRBuilder::VisitSubWithOverflow(GateRef gate, GateRef e1, GateRef e2)
|
||||
auto fn = LLVMGetNamedFunction(module_, "llvm.ssub.with.overflow.i32");
|
||||
if (!fn) {
|
||||
/* init instrinsic function declare */
|
||||
LLVMTypeRef paramTys1[] = {
|
||||
LLVMInt32TypeInContext(context_),
|
||||
LLVMInt32TypeInContext(context_),
|
||||
};
|
||||
LLVMTypeRef structTys[] = {
|
||||
LLVMInt32TypeInContext(context_),
|
||||
LLVMInt1TypeInContext(context_),
|
||||
};
|
||||
LLVMTypeRef paramTys1[] = { GetInt32T(), GetInt32T() };
|
||||
LLVMTypeRef structTys[] = { GetInt32T(), GetInt1T() };
|
||||
LLVMTypeRef returnType = LLVMStructTypeInContext(context_, structTys, 2, 0);
|
||||
auto fnTy = LLVMFunctionType(returnType, paramTys1, 2, 0);
|
||||
fn = LLVMAddFunction(module_, "llvm.ssub.with.overflow.i32", fnTy);
|
||||
@ -1828,14 +1790,8 @@ void LLVMIRBuilder::VisitMulWithOverflow(GateRef gate, GateRef e1, GateRef e2)
|
||||
auto fn = LLVMGetNamedFunction(module_, "llvm.smul.with.overflow.i32");
|
||||
if (!fn) {
|
||||
/* init instrinsic function declare */
|
||||
LLVMTypeRef paramTys1[] = {
|
||||
LLVMInt32TypeInContext(context_),
|
||||
LLVMInt32TypeInContext(context_),
|
||||
};
|
||||
LLVMTypeRef structTys[] = {
|
||||
LLVMInt32TypeInContext(context_),
|
||||
LLVMInt1TypeInContext(context_),
|
||||
};
|
||||
LLVMTypeRef paramTys1[] = { GetInt32T(), GetInt32T() };
|
||||
LLVMTypeRef structTys[] = { GetInt32T(), GetInt1T() };
|
||||
LLVMTypeRef returnType = LLVMStructTypeInContext(context_, structTys, 2, 0);
|
||||
auto fnTy = LLVMFunctionType(returnType, paramTys1, 2, 0);
|
||||
fn = LLVMAddFunction(module_, "llvm.smul.with.overflow.i32", fnTy);
|
||||
@ -1873,10 +1829,8 @@ void LLVMIRBuilder::VisitSqrt(GateRef gate, GateRef e1)
|
||||
auto fn = LLVMGetNamedFunction(module_, "llvm.sqrt.f64");
|
||||
if (!fn) {
|
||||
/* init instrinsic function declare */
|
||||
LLVMTypeRef paramTys1[] = {
|
||||
LLVMDoubleTypeInContext(context_),
|
||||
};
|
||||
auto fnTy = LLVMFunctionType(LLVMDoubleTypeInContext(context_), paramTys1, 1, 0);
|
||||
LLVMTypeRef paramTys1[] = { GetDoubleT() };
|
||||
auto fnTy = LLVMFunctionType(GetDoubleT(), paramTys1, 1, 0);
|
||||
fn = LLVMAddFunction(module_, "llvm.sqrt.f64", fnTy);
|
||||
}
|
||||
LLVMValueRef result = LLVMBuildCall(builder_, fn, args.data(), 1, "");
|
||||
@ -1943,9 +1897,7 @@ void LLVMIRBuilder::VisitCmp(GateRef gate, GateRef e1, GateRef e2)
|
||||
[[maybe_unused]] auto e1ValCode = acc_.GetMachineType(e1);
|
||||
[[maybe_unused]] auto e2ValCode = acc_.GetMachineType(e2);
|
||||
ASSERT((e1ValCode == e2ValCode) ||
|
||||
(compCfg_->Is32Bit() && (e1ValCode == MachineType::ARCH) && (e2ValCode == MachineType::I32)) ||
|
||||
(compCfg_->Is64Bit() && (e1ValCode == MachineType::ARCH) && (e2ValCode == MachineType::I64)) ||
|
||||
(compCfg_->Is32Bit() && (e2ValCode == MachineType::ARCH) && (e1ValCode == MachineType::I32)) ||
|
||||
(compCfg_->Is64Bit() && (e2ValCode == MachineType::ARCH) && (e1ValCode == MachineType::I64)));
|
||||
LLVMIntPredicate intOpcode = LLVMIntEQ;
|
||||
LLVMRealPredicate realOpcode = LLVMRealPredicateFalse;
|
||||
@ -2156,14 +2108,14 @@ void LLVMIRBuilder::VisitChangeInt32ToDouble(GateRef gate, GateRef e1)
|
||||
void LLVMIRBuilder::VisitChangeUInt32ToDouble(GateRef gate, GateRef e1)
|
||||
{
|
||||
LLVMValueRef e1Value = gate2LValue_[e1];
|
||||
LLVMValueRef result = LLVMBuildUIToFP(builder_, e1Value, LLVMDoubleTypeInContext(context_), "");
|
||||
LLVMValueRef result = LLVMBuildUIToFP(builder_, e1Value, GetDoubleT(), "");
|
||||
gate2LValue_[gate] = result;
|
||||
}
|
||||
|
||||
void LLVMIRBuilder::VisitChangeDoubleToInt32(GateRef gate, GateRef e1)
|
||||
{
|
||||
LLVMValueRef e1Value = gate2LValue_[e1];
|
||||
LLVMValueRef result = LLVMBuildFPToSI(builder_, e1Value, LLVMInt32TypeInContext(context_), "");
|
||||
LLVMValueRef result = LLVMBuildFPToSI(builder_, e1Value, GetInt32T(), "");
|
||||
gate2LValue_[gate] = result;
|
||||
}
|
||||
|
||||
@ -2178,23 +2130,7 @@ void LLVMIRBuilder::VisitChangeInt64ToTagged(GateRef gate, GateRef e1)
|
||||
{
|
||||
LLVMValueRef e1Value = gate2LValue_[e1];
|
||||
ASSERT(LLVMGetTypeKind(LLVMTypeOf(e1Value)) == LLVMIntegerTypeKind);
|
||||
LLVMValueRef result;
|
||||
if (compCfg_->Is32Bit()) {
|
||||
LLVMValueRef tmp1Value =
|
||||
LLVMBuildLShr(builder_, e1Value, LLVMConstInt(LLVMInt64TypeInContext(context_), 32, 0), ""); // 32: offset
|
||||
LLVMValueRef tmp2Value = LLVMBuildIntCast(builder_, e1Value, LLVMInt32TypeInContext(context_), ""); // low
|
||||
LLVMTypeRef vectorType = LLVMVectorType(
|
||||
LLVMPointerType(LLVMInt8TypeInContext(context_), 1), 2); // 2: packed vector type
|
||||
LLVMValueRef emptyValue = LLVMGetUndef(vectorType);
|
||||
tmp1Value = LLVMBuildIntToPtr(builder_, tmp1Value, LLVMPointerType(LLVMInt8TypeInContext(context_), 1), "");
|
||||
tmp2Value = LLVMBuildIntToPtr(builder_, tmp2Value, LLVMPointerType(LLVMInt8TypeInContext(context_), 1), "");
|
||||
result = LLVMBuildInsertElement(
|
||||
builder_, emptyValue, tmp2Value, LLVMConstInt(LLVMInt32TypeInContext(context_), 0, 0), "");
|
||||
result = LLVMBuildInsertElement(
|
||||
builder_, result, tmp1Value, LLVMConstInt(LLVMInt32TypeInContext(context_), 1, 0), "");
|
||||
} else {
|
||||
result = LLVMBuildIntToPtr(builder_, e1Value, LLVMPointerType(LLVMInt64TypeInContext(context_), 1), "");
|
||||
}
|
||||
LLVMValueRef result = LLVMBuildIntToPtr(builder_, e1Value, GetTaggedHPtrT(), "");
|
||||
gate2LValue_[gate] = result;
|
||||
}
|
||||
|
||||
@ -2244,7 +2180,7 @@ void LLVMIRBuilder::HandleDeoptCheck(GateRef gate)
|
||||
|
||||
LLVMTypeRef LLVMIRBuilder::GetExperimentalDeoptTy()
|
||||
{
|
||||
auto fnTy = LLVMFunctionType(LLVMPointerType(LLVMInt64TypeInContext(context_), 1), nullptr, 0, 1);
|
||||
auto fnTy = LLVMFunctionType(GetTaggedHPtrT(), nullptr, 0, 1);
|
||||
return fnTy;
|
||||
}
|
||||
|
||||
@ -2257,9 +2193,8 @@ LLVMValueRef LLVMModule::GetDeoptFunction()
|
||||
void LLVMIRBuilder::GenDeoptEntry(LLVMModuleRef &module)
|
||||
{
|
||||
// glue type depth
|
||||
std::vector<LLVMTypeRef> paramTys = {
|
||||
LLVMInt64TypeInContext(context_), LLVMInt64TypeInContext(context_), LLVMInt64TypeInContext(context_)};
|
||||
auto funcType = LLVMFunctionType(LLVMInt64TypeInContext(context_), paramTys.data(), paramTys.size(), 0);
|
||||
std::vector<LLVMTypeRef> paramTys = { GetInt64T(), GetInt64T(), GetInt64T() };
|
||||
auto funcType = LLVMFunctionType(GetInt64T(), paramTys.data(), paramTys.size(), 0);
|
||||
auto function = LLVMAddFunction(module, Deoptimizier::GetLLVMDeoptRelocateSymbol(), funcType);
|
||||
LLVMSetFunctionCallConv(function, LLVMCCallConv);
|
||||
llvmModule_->SetFunction(LLVMModule::kDeoptEntryOffset, function, false);
|
||||
@ -2279,8 +2214,7 @@ void LLVMIRBuilder::GenDeoptEntry(LLVMModuleRef &module)
|
||||
StubIdType stubId = RTSTUB_ID(DeoptHandlerAsm);
|
||||
int stubIndex = static_cast<int>(std::get<RuntimeStubCSigns::ID>(stubId));
|
||||
LLVMValueRef rtoffset = LLVMBuildAdd(builder, glue, GetRTStubOffset(glue, stubIndex), "");
|
||||
LLVMValueRef patchAddr = LLVMBuildIntToPtr(
|
||||
builder, rtoffset, LLVMPointerType(LLVMInt64TypeInContext(context_), 0), "");
|
||||
LLVMValueRef patchAddr = LLVMBuildIntToPtr(builder, rtoffset, GetTaggedPtrT(), "");
|
||||
LLVMValueRef llvmAddr = LLVMBuildLoad(builder, patchAddr, "");
|
||||
LLVMTypeRef rtfuncTypePtr = LLVMPointerType(funcType, 0);
|
||||
LLVMValueRef callee = LLVMBuildIntToPtr(builder, llvmAddr, rtfuncTypePtr, "");
|
||||
@ -2306,10 +2240,10 @@ LLVMValueRef LLVMIRBuilder::GetExperimentalDeopt(LLVMModuleRef &module)
|
||||
LLVMValueRef LLVMIRBuilder::ConvertBoolToTaggedBoolean(GateRef gate)
|
||||
{
|
||||
LLVMValueRef value = gate2LValue_[gate];
|
||||
LLVMValueRef e1Value = LLVMBuildZExt(builder_, value, LLVMInt64TypeInContext(context_), "");
|
||||
auto tagMask = LLVMConstInt(LLVMInt64TypeInContext(context_), JSTaggedValue::TAG_BOOLEAN_MASK, 0);
|
||||
LLVMValueRef e1Value = LLVMBuildZExt(builder_, value, GetInt64T(), "");
|
||||
auto tagMask = LLVMConstInt(GetInt64T(), JSTaggedValue::TAG_BOOLEAN_MASK, 0);
|
||||
LLVMValueRef result = LLVMBuildOr(builder_, e1Value, tagMask, "");
|
||||
return LLVMBuildIntToPtr(builder_, result, LLVMPointerType(LLVMInt64TypeInContext(context_), 1), "");
|
||||
return LLVMBuildIntToPtr(builder_, result, GetTaggedHPtrT(), "");
|
||||
}
|
||||
|
||||
LLVMValueRef LLVMIRBuilder::ConvertInt32ToTaggedInt(GateRef gate)
|
||||
@ -2320,19 +2254,19 @@ LLVMValueRef LLVMIRBuilder::ConvertInt32ToTaggedInt(GateRef gate)
|
||||
|
||||
LLVMValueRef LLVMIRBuilder::ConvertInt32ToTaggedInt(LLVMValueRef value)
|
||||
{
|
||||
LLVMValueRef e1Value = LLVMBuildSExt(builder_, value, LLVMInt64TypeInContext(context_), "");
|
||||
auto tagMask = LLVMConstInt(LLVMInt64TypeInContext(context_), JSTaggedValue::TAG_INT, 0);
|
||||
LLVMValueRef e1Value = LLVMBuildSExt(builder_, value, GetInt64T(), "");
|
||||
auto tagMask = LLVMConstInt(GetInt64T(), JSTaggedValue::TAG_INT, 0);
|
||||
LLVMValueRef result = LLVMBuildOr(builder_, e1Value, tagMask, "");
|
||||
return LLVMBuildIntToPtr(builder_, result, LLVMPointerType(LLVMInt64TypeInContext(context_), 1), "");
|
||||
return LLVMBuildIntToPtr(builder_, result, GetTaggedHPtrT(), "");
|
||||
}
|
||||
|
||||
LLVMValueRef LLVMIRBuilder::ConvertFloat64ToTaggedDouble(GateRef gate)
|
||||
{
|
||||
LLVMValueRef value = gate2LValue_[gate];
|
||||
LLVMValueRef e1Value = LLVMBuildBitCast(builder_, value, LLVMInt64TypeInContext(context_), "");
|
||||
auto offset = LLVMConstInt(LLVMInt64TypeInContext(context_), JSTaggedValue::DOUBLE_ENCODE_OFFSET, 0);
|
||||
LLVMValueRef e1Value = LLVMBuildBitCast(builder_, value, GetInt64T(), "");
|
||||
auto offset = LLVMConstInt(GetInt64T(), JSTaggedValue::DOUBLE_ENCODE_OFFSET, 0);
|
||||
LLVMValueRef result = LLVMBuildAdd(builder_, e1Value, offset, "");
|
||||
return LLVMBuildIntToPtr(builder_, result, LLVMPointerType(LLVMInt64TypeInContext(context_), 1), "");
|
||||
return LLVMBuildIntToPtr(builder_, result, GetTaggedHPtrT(), "");
|
||||
}
|
||||
|
||||
LLVMValueRef LLVMIRBuilder::ConvertToTagged(GateRef gate)
|
||||
@ -2359,17 +2293,16 @@ void LLVMIRBuilder::SaveDeoptVregInfo(std::vector<LLVMValueRef> &values, int32_t
|
||||
GateRef gate)
|
||||
{
|
||||
int32_t encodeIndex = Deoptimizier::EncodeDeoptVregIndex(index, curDepth, shift);
|
||||
values.emplace_back(LLVMConstInt(LLVMInt32TypeInContext(context_), encodeIndex, false));
|
||||
values.emplace_back(LLVMConstInt(GetInt32T(), encodeIndex, false));
|
||||
values.emplace_back(ConvertToTagged(gate));
|
||||
}
|
||||
|
||||
void LLVMIRBuilder::SaveDeoptVregInfoWithI64(std::vector<LLVMValueRef> &values, int32_t index, size_t curDepth,
|
||||
size_t shift, GateRef gate)
|
||||
{
|
||||
LLVMValueRef value = LLVMBuildIntCast2(builder_, gate2LValue_.at(gate),
|
||||
LLVMInt32TypeInContext(context_), 1, "");
|
||||
LLVMValueRef value = LLVMBuildIntCast2(builder_, gate2LValue_.at(gate), GetInt32T(), 1, "");
|
||||
int32_t encodeIndex = Deoptimizier::EncodeDeoptVregIndex(index, curDepth, shift);
|
||||
values.emplace_back(LLVMConstInt(LLVMInt32TypeInContext(context_), encodeIndex, false));
|
||||
values.emplace_back(LLVMConstInt(GetInt32T(), encodeIndex, false));
|
||||
values.emplace_back(ConvertInt32ToTaggedInt(value));
|
||||
}
|
||||
|
||||
@ -2382,8 +2315,7 @@ void LLVMIRBuilder::VisitDeoptCheck(GateRef gate)
|
||||
params.push_back(glue); // glue
|
||||
GateRef deoptType = acc_.GetValueIn(gate, 2); // 2: deopt type
|
||||
uint64_t v = acc_.GetConstantValue(deoptType);
|
||||
params.push_back(ConvertInt32ToTaggedInt(LLVMConstInt(LLVMInt32TypeInContext(context_),
|
||||
static_cast<uint32_t>(v), false))); // deoptType
|
||||
params.push_back(ConvertInt32ToTaggedInt(LLVMConstInt(GetInt32T(), static_cast<uint32_t>(v), false))); // deoptType
|
||||
LLVMValueRef callee = GetExperimentalDeopt(module_);
|
||||
LLVMTypeRef funcType = GetExperimentalDeoptTy();
|
||||
|
||||
@ -2394,12 +2326,11 @@ void LLVMIRBuilder::VisitDeoptCheck(GateRef gate)
|
||||
maxDepth++;
|
||||
frameState = acc_.GetFrameState(frameState);
|
||||
}
|
||||
params.push_back(ConvertInt32ToTaggedInt(LLVMConstInt(LLVMInt32TypeInContext(context_),
|
||||
static_cast<uint32_t>(maxDepth), false)));
|
||||
params.push_back(ConvertInt32ToTaggedInt(LLVMConstInt(GetInt32T(), static_cast<uint32_t>(maxDepth), false)));
|
||||
size_t shift = Deoptimizier::ComputeShift(maxDepth);
|
||||
frameState = deoptFrameState;
|
||||
ArgumentAccessor argAcc(const_cast<Circuit *>(circuit_));
|
||||
for (int32_t curDepth = maxDepth; curDepth >= 0; curDepth--) {
|
||||
for (int32_t curDepth = static_cast<int32_t>(maxDepth); curDepth >= 0; curDepth--) {
|
||||
ASSERT(acc_.GetOpCode(frameState) == OpCode::FRAME_STATE);
|
||||
GateRef frameValues = acc_.GetValueIn(frameState, 1); // 1: frame values
|
||||
const size_t numValueIn = acc_.GetNumValueIn(frameValues);
|
||||
@ -2433,8 +2364,8 @@ void LLVMIRBuilder::VisitDeoptCheck(GateRef gate)
|
||||
// pc offset
|
||||
int32_t specPcOffsetIndex = static_cast<int32_t>(SpecVregIndex::PC_OFFSET_INDEX);
|
||||
int32_t encodeIndex = Deoptimizier::EncodeDeoptVregIndex(specPcOffsetIndex, curDepth, shift);
|
||||
values.emplace_back(LLVMConstInt(LLVMInt32TypeInContext(context_), encodeIndex, false));
|
||||
values.emplace_back(LLVMConstInt(LLVMInt32TypeInContext(context_), pc, false));
|
||||
values.emplace_back(LLVMConstInt(GetInt32T(), encodeIndex, false));
|
||||
values.emplace_back(LLVMConstInt(GetInt32T(), pc, false));
|
||||
// func
|
||||
int32_t specCallTargetIndex = static_cast<int32_t>(SpecVregIndex::FUNC_INDEX);
|
||||
SaveDeoptVregInfo(values, specCallTargetIndex, curDepth, shift, jsFunc);
|
||||
@ -2468,6 +2399,18 @@ LLVMModule::LLVMModule(NativeAreaAllocator* allocator, const std::string &name,
|
||||
0, 0, NULL, 0, 0, NULL, 0, LLVMDWARFEmissionFull,
|
||||
0, 0, 0, "/", 1, "", 0);
|
||||
debugInfo_ = new DebugInfo(allocator, logDbg);
|
||||
|
||||
voidT_ = LLVMVoidTypeInContext(context_);
|
||||
int1T_ = LLVMInt1TypeInContext(context_);
|
||||
int8T_ = LLVMInt8TypeInContext(context_);
|
||||
int16T_ = LLVMInt16TypeInContext(context_);
|
||||
int32T_ = LLVMInt32TypeInContext(context_);
|
||||
int64T_ = LLVMInt64TypeInContext(context_);
|
||||
floatT_ = LLVMFloatTypeInContext(context_);
|
||||
doubleT_ = LLVMDoubleTypeInContext(context_);
|
||||
taggedHPtrT_ = LLVMPointerType(LLVMInt64TypeInContext(context_), 1);
|
||||
taggedPtrT_ = LLVMPointerType(LLVMInt64TypeInContext(context_), 0);
|
||||
rawPtrT_ = LLVMPointerType(LLVMInt8TypeInContext(context_), 0);
|
||||
}
|
||||
|
||||
LLVMModule::~LLVMModule()
|
||||
@ -2558,29 +2501,22 @@ LLVMTypeRef LLVMModule::GenerateFuncType(const std::vector<LLVMValueRef> ¶ms
|
||||
LLVMTypeRef LLVMModule::ConvertLLVMTypeFromVariableType(VariableType type)
|
||||
{
|
||||
std::map<VariableType, LLVMTypeRef> machineTypeMap = {
|
||||
{VariableType::VOID(), LLVMVoidTypeInContext(context_)},
|
||||
{VariableType::BOOL(), LLVMInt1TypeInContext(context_)},
|
||||
{VariableType::INT8(), LLVMInt8TypeInContext(context_)},
|
||||
{VariableType::INT16(), LLVMInt16TypeInContext(context_)},
|
||||
{VariableType::INT32(), LLVMInt32TypeInContext(context_)},
|
||||
{VariableType::INT64(), LLVMInt64TypeInContext(context_)},
|
||||
{VariableType::INT8(), LLVMInt8TypeInContext(context_)},
|
||||
{VariableType::INT16(), LLVMInt16TypeInContext(context_)},
|
||||
{VariableType::INT32(), LLVMInt32TypeInContext(context_)},
|
||||
{VariableType::INT64(), LLVMInt64TypeInContext(context_)},
|
||||
{VariableType::FLOAT32(), LLVMFloatTypeInContext(context_)},
|
||||
{VariableType::FLOAT64(), LLVMDoubleTypeInContext(context_)},
|
||||
{VariableType::NATIVE_POINTER(), LLVMInt64TypeInContext(context_)},
|
||||
{VariableType::JS_POINTER(), LLVMPointerType(LLVMInt64TypeInContext(context_), 1)},
|
||||
{VariableType::JS_ANY(), LLVMPointerType(LLVMInt64TypeInContext(context_), 1)},
|
||||
{VariableType::VOID(), GetVoidT() },
|
||||
{VariableType::BOOL(), GetInt1T() },
|
||||
{VariableType::INT8(), GetInt8T() },
|
||||
{VariableType::INT16(), GetInt16T() },
|
||||
{VariableType::INT32(), GetInt32T() },
|
||||
{VariableType::INT64(), GetInt64T() },
|
||||
{VariableType::INT8(), GetInt8T() },
|
||||
{VariableType::INT16(), GetInt16T() },
|
||||
{VariableType::INT32(), GetInt32T() },
|
||||
{VariableType::INT64(), GetInt64T() },
|
||||
{VariableType::FLOAT32(), GetFloatT() },
|
||||
{VariableType::FLOAT64(), GetDoubleT() },
|
||||
{VariableType::NATIVE_POINTER(), GetInt64T() },
|
||||
{VariableType::JS_POINTER(), GetTaggedHPtrT() },
|
||||
{VariableType::JS_ANY(), GetTaggedHPtrT()},
|
||||
};
|
||||
if (Is32Bit()) {
|
||||
machineTypeMap[VariableType::NATIVE_POINTER()] = LLVMInt32TypeInContext(context_);
|
||||
LLVMTypeRef vectorType = LLVMVectorType(
|
||||
LLVMPointerType(LLVMInt8TypeInContext(context_), 1), 2); // 2: packed vector type
|
||||
machineTypeMap[VariableType::JS_POINTER()] = vectorType;
|
||||
machineTypeMap[VariableType::JS_ANY()] = vectorType;
|
||||
}
|
||||
return machineTypeMap[type];
|
||||
}
|
||||
|
||||
|
@ -213,6 +213,60 @@ public:
|
||||
|
||||
static constexpr int kDeoptEntryOffset = 0;
|
||||
|
||||
LLVMTypeRef GetVoidT() const
|
||||
{
|
||||
return voidT_;
|
||||
}
|
||||
|
||||
LLVMTypeRef GetInt1T() const
|
||||
{
|
||||
return int1T_;
|
||||
}
|
||||
|
||||
LLVMTypeRef GetInt8T() const
|
||||
{
|
||||
return int8T_;
|
||||
}
|
||||
|
||||
LLVMTypeRef GetInt16T() const
|
||||
{
|
||||
return int16T_;
|
||||
}
|
||||
|
||||
LLVMTypeRef GetInt32T() const
|
||||
{
|
||||
return int32T_;
|
||||
}
|
||||
|
||||
LLVMTypeRef GetInt64T() const
|
||||
{
|
||||
return int64T_;
|
||||
}
|
||||
|
||||
LLVMTypeRef GetFloatT() const
|
||||
{
|
||||
return floatT_;
|
||||
}
|
||||
|
||||
LLVMTypeRef GetDoubleT() const
|
||||
{
|
||||
return doubleT_;
|
||||
}
|
||||
|
||||
LLVMTypeRef GetTaggedPtrT() const
|
||||
{
|
||||
return taggedPtrT_;
|
||||
}
|
||||
|
||||
LLVMTypeRef GetTaggedHPtrT() const
|
||||
{
|
||||
return taggedHPtrT_;
|
||||
}
|
||||
|
||||
LLVMTypeRef GetRawPtrT() const
|
||||
{
|
||||
return rawPtrT_;
|
||||
}
|
||||
private:
|
||||
LLVMValueRef AddAndGetFunc(const CallSignature *stubDescriptor);
|
||||
void InitialLLVMFuncTypeAndFuncByModuleCSigns();
|
||||
@ -229,6 +283,19 @@ private:
|
||||
LLVMMetadataRef dUnitMD_ {nullptr};
|
||||
LLVMDIBuilderRef dBuilder_ {nullptr};
|
||||
DebugInfo* debugInfo_ {nullptr};
|
||||
|
||||
LLVMTypeRef voidT_ {nullptr};
|
||||
LLVMTypeRef int1T_ {nullptr};
|
||||
LLVMTypeRef int8T_ {nullptr};
|
||||
LLVMTypeRef int16T_ {nullptr};
|
||||
LLVMTypeRef int32T_ {nullptr};
|
||||
LLVMTypeRef int64T_ {nullptr};
|
||||
LLVMTypeRef floatT_ {nullptr};
|
||||
LLVMTypeRef doubleT_ {nullptr};
|
||||
LLVMTypeRef taggedHPtrT_ {nullptr};
|
||||
LLVMTypeRef taggedPtrT_ {nullptr};
|
||||
LLVMTypeRef rawPtrT_ {nullptr};
|
||||
|
||||
std::string tripleStr_;
|
||||
bool is64Bit_ {false};
|
||||
Triple triple_;
|
||||
@ -289,7 +356,8 @@ private:
|
||||
V(SubWithOverflow, (GateRef gate, GateRef e1, GateRef e2)) \
|
||||
V(MulWithOverflow, (GateRef gate, GateRef e1, GateRef e2)) \
|
||||
V(ExtractValue, (GateRef gate, GateRef e1, GateRef e2)) \
|
||||
V(Sqrt, (GateRef gate, GateRef e1))
|
||||
V(Sqrt, (GateRef gate, GateRef e1)) \
|
||||
V(ReadSp, (GateRef gate))
|
||||
|
||||
// runtime/common stub ID, opcodeOffset for bc stub
|
||||
using StubIdType = std::variant<RuntimeStubCSigns::ID, CommonStubCSigns::ID, LLVMValueRef>;
|
||||
@ -310,7 +378,7 @@ private:
|
||||
OPCODES(DECLAREHANDLEOPCODE)
|
||||
#undef DECLAREHANDLEOPCODE
|
||||
|
||||
bool isPrologue(int bbId) const
|
||||
bool IsPrologue(int bbId) const
|
||||
{
|
||||
return bbId == 0;
|
||||
}
|
||||
@ -333,19 +401,12 @@ private:
|
||||
void InitializeHandlers();
|
||||
std::string LLVMValueToString(LLVMValueRef val) const;
|
||||
|
||||
LLVMTypeRef GetIntPtr() const
|
||||
{
|
||||
if (compCfg_->Is32Bit()) {
|
||||
return LLVMInt32TypeInContext(context_);
|
||||
}
|
||||
return LLVMInt64TypeInContext(context_);
|
||||
}
|
||||
LLVMTypeRef ConvertLLVMTypeFromGate(GateRef gate) const;
|
||||
int64_t GetBitWidthFromMachineType(MachineType machineType) const;
|
||||
LLVMValueRef PointerAdd(LLVMValueRef baseAddr, LLVMValueRef offset, LLVMTypeRef rep);
|
||||
LLVMValueRef VectorAdd(LLVMValueRef e1Value, LLVMValueRef e2Value, LLVMTypeRef rep);
|
||||
LLVMValueRef CanonicalizeToInt(LLVMValueRef value);
|
||||
LLVMValueRef CanonicalizeToPtr(LLVMValueRef value);
|
||||
LLVMValueRef PointerAdd(LLVMValueRef baseAddr, LLVMValueRef offsetInByte, LLVMTypeRef rep);
|
||||
LLVMValueRef CanonicalizeToInt(LLVMValueRef value) const;
|
||||
LLVMValueRef CanonicalizeToPtr(LLVMValueRef value) const;
|
||||
LLVMValueRef CanonicalizeToPtr(LLVMValueRef value, LLVMTypeRef ptrType) const;
|
||||
LLVMValueRef GetCurrentFrameType(LLVMValueRef currentSpFrameAddr);
|
||||
void SetFunctionCallConv();
|
||||
|
||||
@ -366,6 +427,61 @@ private:
|
||||
void SetCallConvAttr(const CallSignature *calleeDescriptor, LLVMValueRef call);
|
||||
bool IsHeapPointerType(LLVMTypeRef valueType);
|
||||
|
||||
LLVMTypeRef GetVoidT() const
|
||||
{
|
||||
return llvmModule_->GetVoidT();
|
||||
}
|
||||
|
||||
LLVMTypeRef GetInt1T() const
|
||||
{
|
||||
return llvmModule_->GetInt1T();
|
||||
}
|
||||
|
||||
LLVMTypeRef GetInt8T() const
|
||||
{
|
||||
return llvmModule_->GetInt8T();
|
||||
}
|
||||
|
||||
LLVMTypeRef GetInt16T() const
|
||||
{
|
||||
return llvmModule_->GetInt16T();
|
||||
}
|
||||
|
||||
LLVMTypeRef GetInt32T() const
|
||||
{
|
||||
return llvmModule_->GetInt32T();
|
||||
}
|
||||
|
||||
LLVMTypeRef GetInt64T() const
|
||||
{
|
||||
return llvmModule_->GetInt64T();
|
||||
}
|
||||
|
||||
LLVMTypeRef GetFloatT() const
|
||||
{
|
||||
return llvmModule_->GetFloatT();
|
||||
}
|
||||
|
||||
LLVMTypeRef GetDoubleT() const
|
||||
{
|
||||
return llvmModule_->GetDoubleT();
|
||||
}
|
||||
|
||||
LLVMTypeRef GetTaggedPtrT() const
|
||||
{
|
||||
return llvmModule_->GetTaggedPtrT();
|
||||
}
|
||||
|
||||
LLVMTypeRef GetTaggedHPtrT() const
|
||||
{
|
||||
return llvmModule_->GetTaggedHPtrT();
|
||||
}
|
||||
|
||||
LLVMTypeRef GetRawPtrT() const
|
||||
{
|
||||
return llvmModule_->GetRawPtrT();
|
||||
}
|
||||
|
||||
private:
|
||||
enum class CallInputs : size_t {
|
||||
DEPEND = 0,
|
||||
@ -383,6 +499,9 @@ private:
|
||||
return llvmModule_ == nullptr ? nullptr : llvmModule_->GetDIBuilder();
|
||||
}
|
||||
|
||||
unsigned GetPtrAddressSpace(LLVMValueRef v) const;
|
||||
bool IsLInteger(LLVMValueRef v) const;
|
||||
bool IsLPointer(LLVMValueRef v) const;
|
||||
LLVMRealPredicate ConvertLLVMPredicateFromFCMP(FCmpCondition cond);
|
||||
LLVMIntPredicate ConvertLLVMPredicateFromICMP(ICmpCondition cond);
|
||||
LLVMValueRef GetGlue(const std::vector<GateRef> &inList);
|
||||
|
@ -50,16 +50,16 @@ void NTypeHCRLowering::Lower(GateRef gate)
|
||||
switch (ecmaOpcode) {
|
||||
case EcmaOpcode::CREATEEMPTYARRAY_IMM8:
|
||||
case EcmaOpcode::CREATEEMPTYARRAY_IMM16:
|
||||
LowerTypedCreateEmptyArray(gate);
|
||||
LowerNTypedCreateEmptyArray(gate);
|
||||
break;
|
||||
case EcmaOpcode::STOWNBYINDEX_IMM8_V8_IMM16:
|
||||
case EcmaOpcode::STOWNBYINDEX_IMM16_V8_IMM16:
|
||||
case EcmaOpcode::WIDE_STOWNBYINDEX_PREF_V8_IMM32:
|
||||
LowerTypedStownByIndex(gate);
|
||||
LowerNTypedStownByIndex(gate);
|
||||
break;
|
||||
case EcmaOpcode::STOWNBYNAME_IMM8_ID16_V8:
|
||||
case EcmaOpcode::STOWNBYNAME_IMM16_ID16_V8:
|
||||
LowerTypedStOwnByName(gate);
|
||||
LowerNTypedStOwnByName(gate);
|
||||
break;
|
||||
case EcmaOpcode::THROW_UNDEFINEDIFHOLEWITHNAME_PREF_ID16:
|
||||
LowerThrowUndefinedIfHoleWithName(gate);
|
||||
@ -81,7 +81,6 @@ void NTypeHCRLowering::Lower(GateRef gate)
|
||||
|
||||
void NTypeHCRLowering::LowerThrowUndefinedIfHoleWithName(GateRef gate)
|
||||
{
|
||||
|
||||
GateRef value = acc_.GetValueIn(gate, 1); // 1: the second parameter
|
||||
builder_.LexVarIsHoleCheck(value);
|
||||
acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), Circuit::NullGate());
|
||||
@ -134,7 +133,7 @@ void NTypeHCRLowering::LowerStLexVar(GateRef gate)
|
||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
|
||||
}
|
||||
|
||||
void NTypeHCRLowering::LowerTypedCreateEmptyArray(GateRef gate)
|
||||
void NTypeHCRLowering::LowerNTypedCreateEmptyArray(GateRef gate)
|
||||
{
|
||||
// in the future, the type of the elements in the array will be obtained through pgo,
|
||||
// and the type will be used to determine whether to create a typed-array.
|
||||
@ -143,27 +142,65 @@ void NTypeHCRLowering::LowerTypedCreateEmptyArray(GateRef gate)
|
||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), array);
|
||||
}
|
||||
|
||||
void NTypeHCRLowering::LowerTypedStownByIndex(GateRef gate)
|
||||
void NTypeHCRLowering::LowerNTypedCreateArrayWithBuffer(GateRef gate)
|
||||
{
|
||||
// 1: number of value inputs
|
||||
ASSERT(acc_.GetNumValueIn(gate) == 1);
|
||||
GateRef index = acc_.GetValueIn(gate, 0);
|
||||
auto thread = tsManager_->GetEcmaVM()->GetJSThread();
|
||||
uint32_t cpIdx = static_cast<uint32_t>(acc_.GetConstantValue(index));
|
||||
JSHandle<ConstantPool> constpoolHandle(tsManager_->GetConstantPool());
|
||||
JSTaggedValue arr = ConstantPool::GetLiteralFromCache<ConstPoolType::ARRAY_LITERAL>(
|
||||
thread, constpoolHandle.GetTaggedValue(), cpIdx, recordName_);
|
||||
JSHandle<JSArray> arrayHandle(thread, arr);
|
||||
JSHandle<JSHClass> oldHClass(thread, arrayHandle->GetClass());
|
||||
JSHandle<JSHClass> hclass = JSHClass::Clone(thread, oldHClass);
|
||||
|
||||
GateType gateType = acc_.GetGateType(gate);
|
||||
panda_file::File::EntityId id = ConstantPool::GetIdFromCache(constpoolHandle.GetTaggedValue(), cpIdx);
|
||||
JSHandle<TaggedArray> elements(thread, arrayHandle->GetElements());
|
||||
tsManager_->AddArrayTSHClass(id, hclass);
|
||||
tsManager_->AddArrayTSElements(id, elements);
|
||||
gateType = tsManager_->TryNarrowUnionType(gateType);
|
||||
|
||||
int hclassIndex = -1;
|
||||
int elementIndex = -1;
|
||||
if (tsManager_->IsArrayTypeKind(gateType)) {
|
||||
hclassIndex = tsManager_->GetHClassIndexByArrayType(gateType, id);
|
||||
elementIndex = tsManager_->GetElementsIndexByArrayType(gateType, id);
|
||||
}
|
||||
if (hclassIndex == -1 || elementIndex == -1) { // slowpath
|
||||
return;
|
||||
}
|
||||
|
||||
AddProfiling(gate);
|
||||
GateRef elementIndexGate = builder_.IntPtr(elementIndex);
|
||||
GateRef array = builder_.CreateArrayWithBuffer(0, index, elementIndexGate);
|
||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), array);
|
||||
}
|
||||
|
||||
void NTypeHCRLowering::LowerNTypedStownByIndex(GateRef gate)
|
||||
{
|
||||
// 3: number of value inputs
|
||||
ASSERT(acc_.GetNumValueIn(gate) == 3);
|
||||
GateRef receiver = acc_.GetValueIn(gate, 0);
|
||||
GateRef index = acc_.GetValueIn(gate, 1);
|
||||
GateRef value = acc_.GetValueIn(gate, 2);
|
||||
if (acc_.GetOpCode(receiver) != OpCode::CREATE_ARRAY) {
|
||||
if (acc_.GetOpCode(receiver) != OpCode::CREATE_ARRAY &&
|
||||
acc_.GetOpCode(receiver) != OpCode::CREATE_ARRAY_WITH_BUFFER) {
|
||||
return;
|
||||
}
|
||||
|
||||
AddProfiling(gate);
|
||||
uint32_t arraySize = acc_.GetArraySize(receiver);
|
||||
uint32_t indexValue = static_cast<uint32_t>(acc_.GetConstantValue(index));
|
||||
uint32_t arraySize = acc_.GetArraySize(receiver);
|
||||
acc_.SetArraySize(receiver, std::max(arraySize, indexValue + 1));
|
||||
index = builder_.Int32(indexValue);
|
||||
builder_.StoreElement<TypedStoreOp::ARRAY_STORE_ELEMENT>(receiver, index, value);
|
||||
acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), Circuit::NullGate());
|
||||
}
|
||||
|
||||
void NTypeHCRLowering::LowerTypedStOwnByName(GateRef gate)
|
||||
void NTypeHCRLowering::LowerNTypedStOwnByName(GateRef gate)
|
||||
{
|
||||
// 3: number of value inputs
|
||||
ASSERT(acc_.GetNumValueIn(gate) == 3);
|
||||
@ -185,7 +222,7 @@ void NTypeHCRLowering::LowerTypedStOwnByName(GateRef gate)
|
||||
if (hclassIndex == -1) { // slowpath
|
||||
return;
|
||||
}
|
||||
JSHClass *hclass = JSHClass::Cast(tsManager_->GetHClassFromCache(hclassIndex).GetTaggedObject());
|
||||
JSHClass *hclass = JSHClass::Cast(tsManager_->GetValueFromCache(hclassIndex).GetTaggedObject());
|
||||
|
||||
PropertyLookupResult plr = JSHClass::LookupPropertyInAotHClass(thread, hclass, propKey);
|
||||
if (!plr.IsFound() || !plr.IsLocal() || plr.IsAccessor() || !plr.IsWritable()) { // slowpath
|
||||
|
@ -26,10 +26,11 @@ namespace panda::ecmascript::kungfu {
|
||||
class NTypeHCRLowering {
|
||||
public:
|
||||
NTypeHCRLowering(Circuit *circuit, PassContext *ctx, TSManager *tsManager,
|
||||
bool enableLog, const std::string& name)
|
||||
const CString &recordName, bool enableLog, const std::string& name)
|
||||
: circuit_(circuit),
|
||||
acc_(circuit),
|
||||
builder_(circuit, ctx->GetCompilerConfig()),
|
||||
recordName_(recordName),
|
||||
tsManager_(tsManager),
|
||||
enableLog_(enableLog),
|
||||
profiling_(ctx->GetCompilerConfig()->IsProfiling()),
|
||||
@ -42,9 +43,10 @@ public:
|
||||
void RunNTypeHCRLowering();
|
||||
private:
|
||||
void Lower(GateRef gate);
|
||||
void LowerTypedCreateEmptyArray(GateRef gate);
|
||||
void LowerTypedStownByIndex(GateRef gate);
|
||||
void LowerTypedStOwnByName(GateRef gate);
|
||||
void LowerNTypedCreateEmptyArray(GateRef gate);
|
||||
void LowerNTypedCreateArrayWithBuffer(GateRef gate);
|
||||
void LowerNTypedStownByIndex(GateRef gate);
|
||||
void LowerNTypedStOwnByName(GateRef gate);
|
||||
void LowerLdLexVar(GateRef gate);
|
||||
void LowerStLexVar(GateRef gate);
|
||||
void LowerThrowUndefinedIfHoleWithName(GateRef gate);
|
||||
@ -73,7 +75,8 @@ private:
|
||||
Circuit *circuit_ {nullptr};
|
||||
GateAccessor acc_;
|
||||
CircuitBuilder builder_;
|
||||
[[maybe_unused]] TSManager *tsManager_ {nullptr};
|
||||
const CString &recordName_;
|
||||
TSManager *tsManager_ {nullptr};
|
||||
bool enableLog_ {false};
|
||||
bool profiling_ {false};
|
||||
bool traceBc_ {false};
|
||||
|
@ -46,6 +46,9 @@ void NTypeMCRLowering::Lower(GateRef gate)
|
||||
case OpCode::CREATE_ARRAY:
|
||||
LowerCreateArray(gate, glue);
|
||||
break;
|
||||
case OpCode::CREATE_ARRAY_WITH_BUFFER:
|
||||
LowerCreateArrayWithBuffer(gate);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -63,33 +66,10 @@ void NTypeMCRLowering::LowerCreateArray(GateRef gate, GateRef glue)
|
||||
|
||||
void NTypeMCRLowering::LowerCreateEmptyArray(GateRef gate)
|
||||
{
|
||||
JSHandle<JSFunction> arrayFunc(tsManager_->GetEcmaVM()->GetGlobalEnv()->GetArrayFunction());
|
||||
JSTaggedValue protoOrHClass = arrayFunc->GetProtoOrHClass();
|
||||
JSHClass *arrayHC = JSHClass::Cast(protoOrHClass.GetTaggedObject());
|
||||
size_t arraySize = arrayHC->GetObjectSize();
|
||||
size_t lengthAccessorOffset = arrayHC->GetInlinedPropertiesOffset(JSArray::LENGTH_INLINE_PROPERTY_INDEX);
|
||||
GateRef length = builder_.Int32(0);
|
||||
GateRef elements = builder_.GetGlobalConstantValue(ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX);
|
||||
|
||||
GateRef obj = builder_.GetGlobalConstantValue(ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX);
|
||||
GateRef globalEnv = builder_.GetGlobalEnv();
|
||||
GateRef accessor = builder_.GetGlobalConstantValue(ConstantIndex::ARRAY_LENGTH_ACCESSOR);
|
||||
GateRef hclass = builder_.GetGlobalEnvObjHClass(globalEnv, GlobalEnv::ARRAY_FUNCTION_INDEX);
|
||||
GateRef size = builder_.IntPtr(arrayHC->GetObjectSize());
|
||||
|
||||
builder_.StartAllocate();
|
||||
GateRef array = builder_.HeapAlloc(size, GateType::TaggedValue(), RegionSpaceFlag::IN_YOUNG_SPACE);
|
||||
// initialization
|
||||
for (size_t offset = JSArray::SIZE; offset < arraySize; offset += JSTaggedValue::TaggedTypeSize()) {
|
||||
builder_.StoreConstOffset(VariableType::INT64(), array, offset, builder_.Undefined());
|
||||
}
|
||||
builder_.StoreConstOffset(VariableType::JS_POINTER(), array, 0, hclass);
|
||||
builder_.StoreConstOffset(VariableType::INT64(), array, ECMAObject::HASH_OFFSET,
|
||||
builder_.Int64(JSTaggedValue(0).GetRawData()));
|
||||
builder_.StoreConstOffset(VariableType::JS_POINTER(), array, JSObject::PROPERTIES_OFFSET, obj);
|
||||
builder_.StoreConstOffset(VariableType::JS_POINTER(), array, JSObject::ELEMENTS_OFFSET, obj);
|
||||
builder_.StoreConstOffset(VariableType::JS_ANY(), array, JSArray::LENGTH_OFFSET,
|
||||
builder_.Int32ToTaggedInt(builder_.Int32(0)));
|
||||
builder_.StoreConstOffset(VariableType::JS_POINTER(), array, lengthAccessorOffset, accessor);
|
||||
builder_.FinishAllocate();
|
||||
auto array = NewJSArrayLiteral(elements, length);
|
||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), array);
|
||||
}
|
||||
|
||||
@ -104,13 +84,53 @@ void NTypeMCRLowering::LowerCreateArrayWithOwn(GateRef gate, GateRef glue)
|
||||
elements = LowerCallRuntime(glue, gate, RTSTUB_ID(NewTaggedArray), { builder_.Int32ToTaggedInt(length) }, true);
|
||||
}
|
||||
|
||||
auto array = NewJSArrayLiteral(elements, length);
|
||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), array);
|
||||
}
|
||||
|
||||
void NTypeMCRLowering::LowerCreateArrayWithBuffer(GateRef gate)
|
||||
{
|
||||
Environment env(gate, circuit_, &builder_);
|
||||
// 2: number of value inputs
|
||||
ASSERT(acc_.GetNumValueIn(gate) == 2);
|
||||
GateRef index = acc_.GetValueIn(gate, 0);
|
||||
GateRef aotElmIndex = acc_.GetValueIn(gate, 1);
|
||||
auto elementIndex = acc_.GetConstantValue(aotElmIndex);
|
||||
uint32_t elementLength = static_cast<uint32_t>(acc_.GetArraySize(gate));
|
||||
uint32_t constPoolIndex = static_cast<uint32_t>(acc_.GetConstantValue(index));
|
||||
ArgumentAccessor argAcc(circuit_);
|
||||
GateRef frameState = GetFrameState(gate);
|
||||
GateRef jsFunc = argAcc.GetFrameArgsIn(frameState, FrameArgIdx::FUNC);
|
||||
GateRef elements = LoadFromConstPool(jsFunc, elementIndex);
|
||||
auto thread = tsManager_->GetEcmaVM()->GetJSThread();
|
||||
JSHandle<ConstantPool> constpoolHandle(tsManager_->GetConstantPool());
|
||||
JSTaggedValue arr = ConstantPool::GetLiteralFromCache<ConstPoolType::ARRAY_LITERAL>(
|
||||
thread, constpoolHandle.GetTaggedValue(), constPoolIndex, recordName_);
|
||||
JSHandle<JSArray> arrayHandle(thread, arr);
|
||||
TaggedArray *arrayLiteral = TaggedArray::Cast(arrayHandle->GetElements());
|
||||
uint32_t literialLength = arrayLiteral->GetLength();
|
||||
uint32_t arrayLength = std::max(literialLength, elementLength);
|
||||
GateRef length = builder_.IntPtr(arrayLength);
|
||||
|
||||
auto array = NewJSArrayLiteral(elements, length);
|
||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), array);
|
||||
}
|
||||
|
||||
GateRef NTypeMCRLowering::LoadFromConstPool(GateRef jsFunc, size_t index)
|
||||
{
|
||||
GateRef constPool = builder_.GetConstPool(jsFunc);
|
||||
return builder_.LoadFromTaggedArray(constPool, index);
|
||||
}
|
||||
|
||||
GateRef NTypeMCRLowering::NewJSArrayLiteral(GateRef elements, GateRef length)
|
||||
{
|
||||
JSHandle<JSFunction> arrayFunc(tsManager_->GetEcmaVM()->GetGlobalEnv()->GetArrayFunction());
|
||||
JSTaggedValue protoOrHClass = arrayFunc->GetProtoOrHClass();
|
||||
JSHClass *arrayHC = JSHClass::Cast(protoOrHClass.GetTaggedObject());
|
||||
size_t arraySize = arrayHC->GetObjectSize();
|
||||
size_t lengthAccessorOffset = arrayHC->GetInlinedPropertiesOffset(JSArray::LENGTH_INLINE_PROPERTY_INDEX);
|
||||
|
||||
GateRef obj = builder_.GetGlobalConstantValue(ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX);
|
||||
GateRef emptyArray = builder_.GetGlobalConstantValue(ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX);
|
||||
GateRef globalEnv = builder_.GetGlobalEnv();
|
||||
GateRef accessor = builder_.GetGlobalConstantValue(ConstantIndex::ARRAY_LENGTH_ACCESSOR);
|
||||
GateRef hclass = builder_.GetGlobalEnvObjHClass(globalEnv, GlobalEnv::ARRAY_FUNCTION_INDEX);
|
||||
@ -125,12 +145,12 @@ void NTypeMCRLowering::LowerCreateArrayWithOwn(GateRef gate, GateRef glue)
|
||||
builder_.StoreConstOffset(VariableType::JS_POINTER(), array, 0, hclass);
|
||||
builder_.StoreConstOffset(VariableType::INT64(), array, ECMAObject::HASH_OFFSET,
|
||||
builder_.Int64(JSTaggedValue(0).GetRawData()));
|
||||
builder_.StoreConstOffset(VariableType::JS_POINTER(), array, JSObject::PROPERTIES_OFFSET, obj);
|
||||
builder_.StoreConstOffset(VariableType::JS_POINTER(), array, JSObject::PROPERTIES_OFFSET, emptyArray);
|
||||
builder_.StoreConstOffset(VariableType::JS_POINTER(), array, JSObject::ELEMENTS_OFFSET, elements);
|
||||
builder_.StoreConstOffset(VariableType::JS_ANY(), array, JSArray::LENGTH_OFFSET, builder_.Int32ToTaggedInt(length));
|
||||
builder_.StoreConstOffset(VariableType::JS_POINTER(), array, lengthAccessorOffset, accessor);
|
||||
builder_.FinishAllocate();
|
||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), array);
|
||||
return array;
|
||||
}
|
||||
|
||||
GateRef NTypeMCRLowering::NewTaggedArray(size_t length)
|
||||
|
@ -24,13 +24,14 @@
|
||||
namespace panda::ecmascript::kungfu {
|
||||
class NTypeMCRLowering {
|
||||
public:
|
||||
NTypeMCRLowering(Circuit *circuit, PassContext *ctx, TSManager *tsManager,
|
||||
NTypeMCRLowering(Circuit *circuit, PassContext *ctx, const CString &recordName,
|
||||
bool enableLog, const std::string& name)
|
||||
: circuit_(circuit),
|
||||
acc_(circuit),
|
||||
builder_(circuit, ctx->GetCompilerConfig()),
|
||||
dependEntry_(circuit->GetDependRoot()),
|
||||
tsManager_(tsManager),
|
||||
tsManager_(ctx->GetTSManager()),
|
||||
recordName_(recordName),
|
||||
enableLog_(enableLog),
|
||||
profiling_(ctx->GetCompilerConfig()->IsProfiling()),
|
||||
traceBc_(ctx->GetCompilerConfig()->IsTraceBC()),
|
||||
@ -44,15 +45,23 @@ private:
|
||||
static constexpr int MAX_TAGGED_ARRAY_LENGTH = 50;
|
||||
void Lower(GateRef gate);
|
||||
void LowerCreateArray(GateRef gate, GateRef glue);
|
||||
void LowerCreateArrayWithBuffer(GateRef gate);
|
||||
void LowerCreateEmptyArray(GateRef gate);
|
||||
void LowerCreateArrayWithOwn(GateRef gate, GateRef glue);
|
||||
void LowerStLexVar(GateRef gate);
|
||||
void LowerLdLexVar(GateRef gate);
|
||||
|
||||
GateRef LoadFromConstPool(GateRef jsFunc, size_t index);
|
||||
GateRef NewJSArrayLiteral(GateRef elements, GateRef length);
|
||||
GateRef NewTaggedArray(size_t length);
|
||||
GateRef LowerCallRuntime(GateRef glue, GateRef hirGate, int index, const std::vector<GateRef> &args,
|
||||
bool useLabel = false);
|
||||
|
||||
GateRef GetFrameState(GateRef gate) const
|
||||
{
|
||||
return acc_.GetFrameState(gate);
|
||||
}
|
||||
|
||||
bool IsLogEnabled() const
|
||||
{
|
||||
return enableLog_;
|
||||
@ -68,6 +77,8 @@ private:
|
||||
CircuitBuilder builder_;
|
||||
GateRef dependEntry_;
|
||||
TSManager *tsManager_ {nullptr};
|
||||
const CString &recordName_;
|
||||
panda_file::File::EntityId methodId_ {0};
|
||||
bool enableLog_ {false};
|
||||
bool profiling_ {false};
|
||||
bool traceBc_ {false};
|
||||
|
@ -25,6 +25,7 @@ enum class TypeInfo {
|
||||
NONE,
|
||||
INT1,
|
||||
INT32,
|
||||
UINT32,
|
||||
FLOAT64,
|
||||
TAGGED,
|
||||
};
|
||||
@ -99,18 +100,18 @@ public:
|
||||
max_ = *std::lower_bound(rangeBounds_.begin(), rangeBounds_.end(), max);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static constexpr int32_t UINT30_MAX = 0x3fffffff;
|
||||
static constexpr int32_t TYPED_ARRAY_ONHEAP_MAX = JSTypedArray::MAX_ONHEAP_LENGTH;
|
||||
static const inline std::vector<int32_t> rangeBounds_ = { INT32_MIN, INT32_MIN + 1,
|
||||
-1, 0, 1, TYPED_ARRAY_ONHEAP_MAX - 1, TYPED_ARRAY_ONHEAP_MAX, TYPED_ARRAY_ONHEAP_MAX + 1, TYPED_ARRAY_ONHEAP_MAX * 3, UINT30_MAX, UINT30_MAX + 1,
|
||||
INT32_MAX - 1, INT32_MAX };
|
||||
-1, 0, 1, TYPED_ARRAY_ONHEAP_MAX - 1, TYPED_ARRAY_ONHEAP_MAX, TYPED_ARRAY_ONHEAP_MAX + 1,
|
||||
TYPED_ARRAY_ONHEAP_MAX * 3, UINT30_MAX, UINT30_MAX + 1, INT32_MAX - 1, INT32_MAX };
|
||||
|
||||
static RangeInfo NONE()
|
||||
{
|
||||
return RangeInfo(INT32_MAX, INT32_MIN);
|
||||
}
|
||||
|
||||
|
||||
static RangeInfo ANY()
|
||||
{
|
||||
return RangeInfo(INT32_MIN, INT32_MAX);
|
||||
@ -225,7 +226,7 @@ public:
|
||||
{
|
||||
return (min_ == INT32_MAX) && (max_ == INT32_MIN);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
int32_t min_ {INT32_MIN};
|
||||
int32_t max_ {INT32_MAX};
|
||||
|
@ -34,10 +34,6 @@ void NumberSpeculativeLowering::Run()
|
||||
for (auto gate : gateList) {
|
||||
auto op = acc_.GetOpCode(gate);
|
||||
switch (op) {
|
||||
case OpCode::INDEX_CHECK: {
|
||||
checkedGates_.push_back(gate);
|
||||
break;
|
||||
}
|
||||
case OpCode::RANGE_GUARD: {
|
||||
rangeGuardGates_.push_back(gate);
|
||||
break;
|
||||
@ -47,9 +43,6 @@ void NumberSpeculativeLowering::Run()
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto check : checkedGates_) {
|
||||
VisitIndexCheck(check);
|
||||
}
|
||||
for (auto rangeGuard : rangeGuardGates_) {
|
||||
VisitRangeGuard(rangeGuard);
|
||||
}
|
||||
@ -338,7 +331,8 @@ void NumberSpeculativeLowering::VisitNumberDiv(GateRef gate)
|
||||
result = builder_.Int32DivWithCheck(left, right);
|
||||
acc_.SetMachineType(gate, MachineType::I32);
|
||||
} else {
|
||||
result = builder_.BinaryArithmetic(circuit_->Fdiv(), MachineType::F64, left, right);
|
||||
result = builder_.BinaryArithmetic(circuit_->Fdiv(),
|
||||
MachineType::F64, left, right, GateType::NJSValue());
|
||||
acc_.SetMachineType(gate, MachineType::F64);
|
||||
}
|
||||
acc_.SetGateType(gate, GateType::NJSValue());
|
||||
@ -553,31 +547,6 @@ void NumberSpeculativeLowering::VisitLoadProperty(GateRef gate)
|
||||
}
|
||||
}
|
||||
|
||||
void NumberSpeculativeLowering::VisitIndexCheck(GateRef gate)
|
||||
{
|
||||
auto type = acc_.GetParamGateType(gate);
|
||||
if (!tsManager_->IsArrayTypeKind(type)) {
|
||||
// return checked index value
|
||||
acc_.SetGateType(gate, GateType::NJSValue());
|
||||
acc_.SetMachineType(gate, MachineType::I32);
|
||||
return;
|
||||
}
|
||||
Environment env(gate, circuit_, &builder_);
|
||||
GateRef index = acc_.GetValueIn(gate, 1);
|
||||
if (!noCheck_) {
|
||||
GateRef length = acc_.GetValueIn(gate, 0);
|
||||
RangeInfo indexRange = GetRange(index);
|
||||
if (indexRange.GetMin() < 0) {
|
||||
builder_.NegativeIndexCheck(index);
|
||||
}
|
||||
builder_.LargeIndexCheck(index, length);
|
||||
// return checked index value
|
||||
acc_.SetGateType(gate, GateType::NJSValue());
|
||||
acc_.SetMachineType(gate, MachineType::I32);
|
||||
}
|
||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), index);
|
||||
}
|
||||
|
||||
void NumberSpeculativeLowering::VisitRangeGuard(GateRef gate)
|
||||
{
|
||||
Environment env(gate, circuit_, &builder_);
|
||||
@ -610,7 +579,8 @@ GateRef NumberSpeculativeLowering::CalculateInts(GateRef left, GateRef right)
|
||||
res = builder_.MulWithOverflow(left, right);
|
||||
break;
|
||||
case TypedBinOp::TYPED_MOD: {
|
||||
return builder_.BinaryArithmetic(circuit_->Smod(), MachineType::I32, left, right);
|
||||
return builder_.BinaryArithmetic(circuit_->Smod(),
|
||||
MachineType::I32, left, right, GateType::NJSValue());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -808,7 +778,9 @@ GateRef NumberSpeculativeLowering::MonocularDouble(GateRef value)
|
||||
void NumberSpeculativeLowering::UpdateRange(GateRef gate, const RangeInfo& range)
|
||||
{
|
||||
auto id = acc_.GetId(gate);
|
||||
rangeInfos_.resize(id + 1, RangeInfo::ANY());
|
||||
if (id >= rangeInfos_.size()) {
|
||||
rangeInfos_.resize(id + 1, RangeInfo::ANY());
|
||||
}
|
||||
rangeInfos_[id] = range;
|
||||
}
|
||||
|
||||
|
@ -27,10 +27,10 @@
|
||||
namespace panda::ecmascript::kungfu {
|
||||
class NumberSpeculativeLowering {
|
||||
public:
|
||||
NumberSpeculativeLowering(Circuit* circuit, Chunk* chunk, TSManager* tsManager,
|
||||
ChunkVector<TypeInfo>& typeInfos, ChunkVector<RangeInfo>& rangeInfos, bool noCheck)
|
||||
: circuit_(circuit), acc_(circuit), builder_(circuit), tsManager_(tsManager),
|
||||
typeInfos_(typeInfos), rangeInfos_(rangeInfos), checkedGates_(chunk), rangeGuardGates_(chunk), noCheck_(noCheck) {}
|
||||
NumberSpeculativeLowering(Circuit* circuit, Chunk* chunk, ChunkVector<TypeInfo>& typeInfos,
|
||||
ChunkVector<RangeInfo>& rangeInfos)
|
||||
: circuit_(circuit), acc_(circuit), builder_(circuit), typeInfos_(typeInfos),
|
||||
rangeInfos_(rangeInfos), rangeGuardGates_(chunk) {}
|
||||
void Run();
|
||||
|
||||
private:
|
||||
@ -44,7 +44,6 @@ private:
|
||||
void VisitPhi(GateRef gate);
|
||||
void VisitUndefinedStrictEq(GateRef gate);
|
||||
void VisitCallBuiltins(GateRef gate);
|
||||
void VisitIndexCheck(GateRef gate);
|
||||
void VisitRangeGuard(GateRef gate);
|
||||
void VisitLoadArrayLength(GateRef gate);
|
||||
void VisitLoadElement(GateRef gate);
|
||||
@ -97,12 +96,9 @@ private:
|
||||
Circuit* circuit_;
|
||||
GateAccessor acc_;
|
||||
CircuitBuilder builder_;
|
||||
TSManager* tsManager_ {nullptr};
|
||||
ChunkVector<TypeInfo>& typeInfos_;
|
||||
ChunkVector<RangeInfo>& rangeInfos_;
|
||||
ChunkVector<GateRef> checkedGates_;
|
||||
ChunkVector<GateRef> rangeGuardGates_;
|
||||
bool noCheck_;
|
||||
};
|
||||
} // panda::ecmascript::kungfu
|
||||
#endif // ECMASCRIPT_COMPILER_NUMBER_SPECULATIVE_LOWERING_H
|
||||
|
@ -66,6 +66,13 @@ GateRef NumberSpeculativeRetype::SetOutputType(GateRef gate, Representation rep)
|
||||
return old == type ? Circuit::NullGate() : gate;
|
||||
}
|
||||
|
||||
GateRef NumberSpeculativeRetype::SetOutputType(GateRef gate, TypeInfo type)
|
||||
{
|
||||
TypeInfo old = GetOutputTypeInfo(gate);
|
||||
SetOutputTypeInfo(gate, type);
|
||||
return old == type ? Circuit::NullGate() : gate;
|
||||
}
|
||||
|
||||
GateRef NumberSpeculativeRetype::VisitGate(GateRef gate)
|
||||
{
|
||||
OpCode op = acc_.GetOpCode(gate);
|
||||
@ -78,7 +85,6 @@ GateRef NumberSpeculativeRetype::VisitGate(GateRef gate)
|
||||
return VisitTypedConditionJump(gate);
|
||||
case OpCode::INDEX_CHECK:
|
||||
return VisitIndexCheck(gate);
|
||||
case OpCode::RANGE_GUARD:
|
||||
case OpCode::LOAD_ARRAY_LENGTH:
|
||||
case OpCode::LOAD_TYPED_ARRAY_LENGTH:
|
||||
return VisitLoadArrayLength(gate);
|
||||
@ -108,7 +114,8 @@ GateRef NumberSpeculativeRetype::VisitGate(GateRef gate)
|
||||
case OpCode::OBJECT_TYPE_CHECK:
|
||||
return VisitWithConstantValue(gate, PROPERTY_LOOKUP_RESULT_INDEX);
|
||||
case OpCode::LOOP_EXIT_VALUE:
|
||||
return VisitLoopExitValue(gate);
|
||||
case OpCode::RANGE_GUARD:
|
||||
return VisitIntermediateValue(gate);
|
||||
case OpCode::JS_BYTECODE:
|
||||
case OpCode::PRIMITIVE_TYPE_CHECK:
|
||||
case OpCode::STABLE_ARRAY_CHECK:
|
||||
@ -186,7 +193,7 @@ GateRef NumberSpeculativeRetype::VisitConstant(GateRef gate)
|
||||
return Circuit::NullGate();
|
||||
}
|
||||
|
||||
GateRef NumberSpeculativeRetype::VisitLoopExitValue(GateRef gate)
|
||||
GateRef NumberSpeculativeRetype::VisitIntermediateValue(GateRef gate)
|
||||
{
|
||||
GateRef value = acc_.GetValueIn(gate, 0);
|
||||
TypeInfo valueInfo = GetOutputTypeInfo(value);
|
||||
@ -209,12 +216,12 @@ TypeInfo NumberSpeculativeRetype::GetOuputForPhi(GateRef gate, bool ignoreConsta
|
||||
if (inputInfo == TypeInfo::NONE) {
|
||||
continue;
|
||||
}
|
||||
if (ignoreConstant && acc_.GetOpCode(input) == OpCode::CONSTANT) {
|
||||
if (ignoreConstant && acc_.IsConstantNumber(input)) {
|
||||
hasConstantInput = true;
|
||||
continue;
|
||||
}
|
||||
// use less general input as phi output
|
||||
if (tempType == TypeInfo::NONE || tempType == TypeInfo::TAGGED) {
|
||||
if (tempType == TypeInfo::NONE) {
|
||||
tempType = inputInfo;
|
||||
} else if (tempType != inputInfo) {
|
||||
tempType = TypeInfo::TAGGED;
|
||||
@ -241,17 +248,20 @@ GateRef NumberSpeculativeRetype::VisitPhi(GateRef gate)
|
||||
}
|
||||
ASSERT(IsConvert());
|
||||
size_t valueNum = acc_.GetNumValueIn(gate);
|
||||
auto state = acc_.GetState(gate);
|
||||
auto dependSelector = acc_.GetDependSelectorFromMerge(state);
|
||||
auto merge = acc_.GetState(gate);
|
||||
auto dependSelector = acc_.GetDependSelectorFromMerge(merge);
|
||||
TypeInfo output = GetOutputTypeInfo(gate);
|
||||
for (size_t i = 0; i < valueNum; ++i) {
|
||||
GateRef input = acc_.GetValueIn(gate, i);
|
||||
if (output == TypeInfo::TAGGED || output == TypeInfo::NONE) {
|
||||
input = ConvertToTagged(input);
|
||||
} else {
|
||||
auto state = acc_.GetState(merge, i);
|
||||
auto depend = acc_.GetDep(dependSelector, i);
|
||||
Environment env(state, depend, {}, circuit_, &builder_);
|
||||
input = ConvertTaggedToNJSValue(input, output);
|
||||
acc_.ReplaceStateIn(merge, builder_.GetState(), i);
|
||||
acc_.ReplaceDependIn(dependSelector, builder_.GetDepend(), i);
|
||||
}
|
||||
acc_.ReplaceValueIn(gate, input, i);
|
||||
}
|
||||
@ -325,7 +335,6 @@ GateRef NumberSpeculativeRetype::VisitTypedUnaryOp(GateRef gate)
|
||||
case TypedUnOp::TYPED_NOT:
|
||||
return VisitNumberNot(gate);
|
||||
case TypedUnOp::TYPED_ISFALSE:
|
||||
return VisitIsTrueOrFalse(gate);
|
||||
case TypedUnOp::TYPED_ISTRUE:
|
||||
return VisitIsTrueOrFalse(gate);
|
||||
default:
|
||||
@ -395,7 +404,7 @@ GateRef NumberSpeculativeRetype::VisitNumberShiftAndLogical(GateRef gate)
|
||||
rightType = GateType::NumberType();
|
||||
}
|
||||
}
|
||||
ConvertForIntOperator(gate, leftType, rightType);
|
||||
ConvertForShiftAndLogicalOperator(gate, leftType, rightType);
|
||||
}
|
||||
return Circuit::NullGate();
|
||||
}
|
||||
@ -421,6 +430,8 @@ GateRef NumberSpeculativeRetype::VisitIntMonocular(GateRef gate)
|
||||
if (IsConvert()) {
|
||||
GateRef value = acc_.GetValueIn(gate, 0);
|
||||
acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(value, GateType::IntType()), 0);
|
||||
acc_.ReplaceStateIn(gate, builder_.GetState());
|
||||
acc_.ReplaceDependIn(gate, builder_.GetDepend());
|
||||
}
|
||||
return Circuit::NullGate();
|
||||
}
|
||||
@ -435,6 +446,8 @@ GateRef NumberSpeculativeRetype::VisitDoubleMonocular(GateRef gate)
|
||||
TypedUnaryAccessor accessor(acc_.TryGetValue(gate));
|
||||
GateRef value = acc_.GetValueIn(gate, 0);
|
||||
acc_.ReplaceValueIn(gate, CheckAndConvertToFloat64(value, accessor.GetTypeValue()), 0);
|
||||
acc_.ReplaceStateIn(gate, builder_.GetState());
|
||||
acc_.ReplaceDependIn(gate, builder_.GetDepend());
|
||||
}
|
||||
return Circuit::NullGate();
|
||||
}
|
||||
@ -453,6 +466,8 @@ GateRef NumberSpeculativeRetype::VisitIsTrueOrFalse(GateRef gate)
|
||||
auto input = CheckAndConvertToBool(value, valueType);
|
||||
ResizeAndSetTypeInfo(input, TypeInfo::INT1);
|
||||
acc_.ReplaceValueIn(gate, input, 0);
|
||||
acc_.ReplaceStateIn(gate, builder_.GetState());
|
||||
acc_.ReplaceDependIn(gate, builder_.GetDepend());
|
||||
}
|
||||
return Circuit::NullGate();
|
||||
}
|
||||
@ -469,6 +484,8 @@ GateRef NumberSpeculativeRetype::VisitNumberNot(GateRef gate)
|
||||
Environment env(gate, circuit_, &builder_);
|
||||
GateRef value = acc_.GetValueIn(gate, 0);
|
||||
acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(value, valueType), 0);
|
||||
acc_.ReplaceStateIn(gate, builder_.GetState());
|
||||
acc_.ReplaceDependIn(gate, builder_.GetDepend());
|
||||
}
|
||||
return Circuit::NullGate();
|
||||
}
|
||||
@ -490,6 +507,8 @@ GateRef NumberSpeculativeRetype::VisitBooleanJump(GateRef gate)
|
||||
}
|
||||
ResizeAndSetTypeInfo(input, TypeInfo::INT1);
|
||||
acc_.ReplaceValueIn(gate, input, 0);
|
||||
acc_.ReplaceStateIn(gate, builder_.GetState());
|
||||
acc_.ReplaceDependIn(gate, builder_.GetDepend());
|
||||
}
|
||||
return Circuit::NullGate();
|
||||
}
|
||||
@ -535,6 +554,8 @@ GateRef NumberSpeculativeRetype::VisitCallBuiltins(GateRef gate)
|
||||
GateRef input = acc_.GetValueIn(gate, i);
|
||||
acc_.ReplaceValueIn(gate, CheckAndConvertToFloat64(input, GateType::NumberType()), i);
|
||||
}
|
||||
acc_.ReplaceStateIn(gate, builder_.GetState());
|
||||
acc_.ReplaceDependIn(gate, builder_.GetDepend());
|
||||
}
|
||||
return Circuit::NullGate();
|
||||
}
|
||||
@ -588,6 +609,8 @@ GateRef NumberSpeculativeRetype::CheckAndConvertToBool(GateRef gate, GateType ga
|
||||
return gate;
|
||||
case TypeInfo::INT32:
|
||||
return builder_.ConvertInt32ToBool(gate);
|
||||
case TypeInfo::UINT32:
|
||||
return builder_.ConvertUInt32ToBool(gate);
|
||||
case TypeInfo::FLOAT64:
|
||||
return builder_.ConvertFloat64ToBool(gate);
|
||||
case TypeInfo::TAGGED: {
|
||||
@ -668,6 +691,23 @@ void NumberSpeculativeRetype::ConvertForIntOperator(GateRef gate, GateType leftT
|
||||
|
||||
acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(left, leftType), 0);
|
||||
acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(right, rightType), 1);
|
||||
|
||||
acc_.ReplaceStateIn(gate, builder_.GetState());
|
||||
acc_.ReplaceDependIn(gate, builder_.GetDepend());
|
||||
}
|
||||
|
||||
void NumberSpeculativeRetype::ConvertForShiftAndLogicalOperator(GateRef gate, GateType leftType, GateType rightType)
|
||||
{
|
||||
GateRef left = acc_.GetValueIn(gate, 0);
|
||||
GateRef right = acc_.GetValueIn(gate, 1);
|
||||
GateRef cLeft = CheckAndConvertToInt32(left, leftType, ConvertSupport::ENABLE, OpType::SHIFT_AND_LOGICAL);
|
||||
GateRef cRight = CheckAndConvertToInt32(right, rightType, ConvertSupport::ENABLE, OpType::SHIFT_AND_LOGICAL);
|
||||
|
||||
acc_.ReplaceValueIn(gate, cLeft, 0);
|
||||
acc_.ReplaceValueIn(gate, cRight, 1);
|
||||
|
||||
acc_.ReplaceStateIn(gate, builder_.GetState());
|
||||
acc_.ReplaceDependIn(gate, builder_.GetDepend());
|
||||
}
|
||||
|
||||
void NumberSpeculativeRetype::ConvertForDoubleOperator(GateRef gate, GateType leftType, GateType rightType)
|
||||
@ -677,6 +717,9 @@ void NumberSpeculativeRetype::ConvertForDoubleOperator(GateRef gate, GateType le
|
||||
|
||||
acc_.ReplaceValueIn(gate, CheckAndConvertToFloat64(left, leftType), 0);
|
||||
acc_.ReplaceValueIn(gate, CheckAndConvertToFloat64(right, rightType), 1);
|
||||
|
||||
acc_.ReplaceStateIn(gate, builder_.GetState());
|
||||
acc_.ReplaceDependIn(gate, builder_.GetDepend());
|
||||
}
|
||||
|
||||
GateRef NumberSpeculativeRetype::TryConvertConstant(GateRef gate, bool needInt32)
|
||||
@ -698,7 +741,7 @@ GateRef NumberSpeculativeRetype::TryConvertConstant(GateRef gate, bool needInt32
|
||||
return Circuit::NullGate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
JSTaggedValue value(acc_.GetConstantValue(gate));
|
||||
if(value.IsInt()) {
|
||||
int32_t rawValue = value.GetInt();
|
||||
@ -711,7 +754,8 @@ GateRef NumberSpeculativeRetype::TryConvertConstant(GateRef gate, bool needInt32
|
||||
return Circuit::NullGate();
|
||||
}
|
||||
|
||||
GateRef NumberSpeculativeRetype::CheckAndConvertToInt32(GateRef gate, GateType gateType, ConvertSupport support)
|
||||
GateRef NumberSpeculativeRetype::CheckAndConvertToInt32(GateRef gate, GateType gateType, ConvertSupport support,
|
||||
OpType type)
|
||||
{
|
||||
auto result = TryConvertConstant(gate, true);
|
||||
if (result != Circuit::NullGate()) {
|
||||
@ -726,6 +770,14 @@ GateRef NumberSpeculativeRetype::CheckAndConvertToInt32(GateRef gate, GateType g
|
||||
break;
|
||||
case TypeInfo::INT32:
|
||||
return gate;
|
||||
case TypeInfo::UINT32: {
|
||||
if (type != OpType::SHIFT_AND_LOGICAL) {
|
||||
result = builder_.CheckUInt32AndConvertToInt32(gate);
|
||||
} else {
|
||||
result = gate;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TypeInfo::FLOAT64:
|
||||
result = builder_.ConvertFloat64ToInt32(gate);
|
||||
break;
|
||||
@ -765,6 +817,9 @@ GateRef NumberSpeculativeRetype::CheckAndConvertToFloat64(GateRef gate, GateType
|
||||
case TypeInfo::INT32:
|
||||
result = builder_.ConvertInt32ToFloat64(gate);
|
||||
break;
|
||||
case TypeInfo::UINT32:
|
||||
result = builder_.ConvertUInt32ToFloat64(gate);
|
||||
break;
|
||||
case TypeInfo::FLOAT64:
|
||||
return gate;
|
||||
case TypeInfo::TAGGED: {
|
||||
@ -795,6 +850,8 @@ GateRef NumberSpeculativeRetype::CheckAndConvertToTagged(GateRef gate, GateType
|
||||
return builder_.ConvertBoolToTaggedBoolean(gate);
|
||||
case TypeInfo::INT32:
|
||||
return builder_.ConvertInt32ToTaggedInt(gate);
|
||||
case TypeInfo::UINT32:
|
||||
return builder_.ConvertUInt32ToTaggedNumber(gate);
|
||||
case TypeInfo::FLOAT64:
|
||||
return builder_.ConvertFloat64ToTaggedDouble(gate);
|
||||
case TypeInfo::TAGGED: {
|
||||
@ -817,6 +874,8 @@ GateRef NumberSpeculativeRetype::ConvertToTagged(GateRef gate)
|
||||
return builder_.ConvertBoolToTaggedBoolean(gate);
|
||||
case TypeInfo::INT32:
|
||||
return builder_.ConvertInt32ToTaggedInt(gate);
|
||||
case TypeInfo::UINT32:
|
||||
return builder_.ConvertUInt32ToTaggedNumber(gate);
|
||||
case TypeInfo::FLOAT64:
|
||||
return builder_.ConvertFloat64ToTaggedDouble(gate);
|
||||
case TypeInfo::NONE:
|
||||
@ -840,15 +899,13 @@ GateRef NumberSpeculativeRetype::VisitIndexCheck(GateRef gate)
|
||||
Environment env(gate, circuit_, &builder_);
|
||||
GateRef receiver = acc_.GetValueIn(gate, 0);
|
||||
GateRef index = acc_.GetValueIn(gate, 1);
|
||||
GateType gateType = acc_.GetParamGateType(gate);
|
||||
GateType receiverType = acc_.GetGateType(receiver);
|
||||
GateType indexType = acc_.GetGateType(index);
|
||||
if (tsManager_->IsArrayTypeKind(gateType)) {
|
||||
// IndexCheck receive length at first value input.
|
||||
ASSERT(receiverType.IsNumberType());
|
||||
acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(receiver, receiverType), 0);
|
||||
}
|
||||
acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(receiver, receiverType), 0);
|
||||
acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(index, indexType), 1);
|
||||
|
||||
acc_.ReplaceStateIn(gate, builder_.GetState());
|
||||
acc_.ReplaceDependIn(gate, builder_.GetDepend());
|
||||
}
|
||||
|
||||
return Circuit::NullGate();
|
||||
@ -875,6 +932,8 @@ GateRef NumberSpeculativeRetype::VisitLoadElement(GateRef gate)
|
||||
case TypedLoadOp::UINT16ARRAY_LOAD_ELEMENT:
|
||||
case TypedLoadOp::INT32ARRAY_LOAD_ELEMENT:
|
||||
return SetOutputType(gate, GateType::IntType());
|
||||
case TypedLoadOp::UINT32ARRAY_LOAD_ELEMENT:
|
||||
return SetOutputType(gate, TypeInfo::UINT32);
|
||||
case TypedLoadOp::FLOAT32ARRAY_LOAD_ELEMENT:
|
||||
case TypedLoadOp::FLOAT64ARRAY_LOAD_ELEMENT:
|
||||
return SetOutputType(gate, GateType::DoubleType());
|
||||
@ -888,6 +947,8 @@ GateRef NumberSpeculativeRetype::VisitLoadElement(GateRef gate)
|
||||
GateRef index = acc_.GetValueIn(gate, 1);
|
||||
GateType indexType = acc_.GetGateType(index);
|
||||
acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(index, indexType), 1);
|
||||
acc_.ReplaceStateIn(gate, builder_.GetState());
|
||||
acc_.ReplaceDependIn(gate, builder_.GetDepend());
|
||||
}
|
||||
|
||||
return Circuit::NullGate();
|
||||
@ -913,6 +974,7 @@ GateRef NumberSpeculativeRetype::VisitStoreElement(GateRef gate)
|
||||
case TypedStoreOp::INT16ARRAY_STORE_ELEMENT:
|
||||
case TypedStoreOp::UINT16ARRAY_STORE_ELEMENT:
|
||||
case TypedStoreOp::INT32ARRAY_STORE_ELEMENT:
|
||||
case TypedStoreOp::UINT32ARRAY_STORE_ELEMENT:
|
||||
acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(value, GateType::NumberType()), 2); // 2: value idx
|
||||
break;
|
||||
case TypedStoreOp::FLOAT32ARRAY_STORE_ELEMENT:
|
||||
@ -923,6 +985,8 @@ GateRef NumberSpeculativeRetype::VisitStoreElement(GateRef gate)
|
||||
acc_.ReplaceValueIn(gate, ConvertToTagged(value), 2); // 2: value idx
|
||||
break;
|
||||
}
|
||||
acc_.ReplaceStateIn(gate, builder_.GetState());
|
||||
acc_.ReplaceDependIn(gate, builder_.GetDepend());
|
||||
}
|
||||
|
||||
return Circuit::NullGate();
|
||||
@ -957,6 +1021,8 @@ GateRef NumberSpeculativeRetype::VisitStoreProperty(GateRef gate)
|
||||
|
||||
GateRef receiver = acc_.GetValueIn(gate, 0); // receiver
|
||||
acc_.ReplaceValueIn(gate, ConvertToTagged(receiver), 0);
|
||||
acc_.ReplaceStateIn(gate, builder_.GetState());
|
||||
acc_.ReplaceDependIn(gate, builder_.GetDepend());
|
||||
return Circuit::NullGate();
|
||||
}
|
||||
|
||||
|
@ -28,9 +28,9 @@
|
||||
namespace panda::ecmascript::kungfu {
|
||||
class NumberSpeculativeRetype : public GraphVisitor {
|
||||
public:
|
||||
NumberSpeculativeRetype(Circuit *circuit, Chunk* chunk, TSManager* tsManager, ChunkVector<TypeInfo>& typeInfos)
|
||||
NumberSpeculativeRetype(Circuit *circuit, Chunk* chunk, ChunkVector<TypeInfo>& typeInfos)
|
||||
: GraphVisitor(circuit, chunk), acc_(circuit), builder_(circuit),
|
||||
tsManager_(tsManager), typeInfos_(typeInfos) {}
|
||||
typeInfos_(typeInfos) {}
|
||||
void Run();
|
||||
GateRef VisitGate(GateRef gate);
|
||||
|
||||
@ -40,6 +40,11 @@ private:
|
||||
Convert,
|
||||
};
|
||||
|
||||
enum class OpType {
|
||||
NORMAL,
|
||||
SHIFT_AND_LOGICAL,
|
||||
};
|
||||
|
||||
bool IsRetype() const
|
||||
{
|
||||
return state_ == State::Retype;
|
||||
@ -53,6 +58,7 @@ private:
|
||||
GateRef SetOutputType(GateRef gate, PGOSampleType type);
|
||||
GateRef SetOutputType(GateRef gate, GateType type);
|
||||
GateRef SetOutputType(GateRef gate, Representation rep);
|
||||
GateRef SetOutputType(GateRef gate, TypeInfo type);
|
||||
GateRef VisitPhi(GateRef gate);
|
||||
GateRef VisitConstant(GateRef gate);
|
||||
GateRef VisitTypedBinaryOp(GateRef gate);
|
||||
@ -85,14 +91,16 @@ private:
|
||||
GateRef VisitFrameState(GateRef gate);
|
||||
GateRef VisitIsTrueOrFalse(GateRef gate);
|
||||
GateRef VisitWithConstantValue(GateRef gate, size_t ignoreIndex);
|
||||
GateRef VisitLoopExitValue(GateRef gate);
|
||||
GateRef VisitIntermediateValue(GateRef gate);
|
||||
|
||||
void ConvertForBinaryOp(GateRef gate);
|
||||
void ConvertForCompareOp(GateRef gate);
|
||||
void ConvertForIntOperator(GateRef gate, GateType leftType, GateType rightType);
|
||||
void ConvertForShiftAndLogicalOperator(GateRef gate, GateType leftType, GateType rightType);
|
||||
void ConvertForDoubleOperator(GateRef gate, GateType leftType, GateType rightType);
|
||||
|
||||
GateRef CheckAndConvertToInt32(GateRef gate, GateType gateType, ConvertSupport support = ConvertSupport::ENABLE);
|
||||
GateRef CheckAndConvertToInt32(GateRef gate, GateType gateType, ConvertSupport support = ConvertSupport::ENABLE,
|
||||
OpType type = OpType::NORMAL);
|
||||
GateRef CheckAndConvertToFloat64(GateRef gate, GateType gateType, ConvertSupport support = ConvertSupport::ENABLE);
|
||||
GateRef CheckAndConvertToTagged(GateRef gate, GateType gateType);
|
||||
GateRef CheckAndConvertToBool(GateRef gate, GateType gateType);
|
||||
@ -128,7 +136,6 @@ private:
|
||||
static constexpr size_t PROPERTY_LOOKUP_RESULT_INDEX = 1;
|
||||
GateAccessor acc_;
|
||||
CircuitBuilder builder_;
|
||||
TSManager* tsManager_ {nullptr};
|
||||
ChunkVector<TypeInfo>& typeInfos_;
|
||||
State state_ {0};
|
||||
};
|
||||
|
@ -21,9 +21,24 @@
|
||||
namespace panda::ecmascript::kungfu {
|
||||
void NumberSpeculativeRunner::Run()
|
||||
{
|
||||
RangeGuard rangeGuard(circuit_, chunk_);
|
||||
rangeGuard.Run();
|
||||
|
||||
if (IsLogEnabled()) {
|
||||
LOG_COMPILER(INFO) << "";
|
||||
LOG_COMPILER(INFO) << "\033[34m"
|
||||
<< "===================="
|
||||
<< " After range guard "
|
||||
<< "[" << GetMethodName() << "]"
|
||||
<< "===================="
|
||||
<< "\033[0m";
|
||||
circuit_->PrintAllGatesWithBytecode();
|
||||
LOG_COMPILER(INFO) << "\033[34m" << "========================= End ==========================" << "\033[0m";
|
||||
}
|
||||
|
||||
auto maxId = circuit_->GetMaxGateId();
|
||||
typeInfos_.resize(maxId + 1, TypeInfo::NONE);
|
||||
NumberSpeculativeRetype retype(circuit_, chunk_, tsManager_, typeInfos_);
|
||||
NumberSpeculativeRetype retype(circuit_, chunk_, typeInfos_);
|
||||
retype.Run();
|
||||
|
||||
if (IsLogEnabled()) {
|
||||
@ -54,7 +69,7 @@ void NumberSpeculativeRunner::Run()
|
||||
LOG_COMPILER(INFO) << "\033[34m" << "========================= End ==========================" << "\033[0m";
|
||||
}
|
||||
|
||||
NumberSpeculativeLowering lowering(circuit_, chunk_, tsManager_, typeInfos_, rangeInfos_, noCheck_);
|
||||
NumberSpeculativeLowering lowering(circuit_, chunk_, typeInfos_, rangeInfos_);
|
||||
lowering.Run();
|
||||
if (IsLogEnabled()) {
|
||||
LOG_COMPILER(INFO) << "";
|
||||
|
@ -19,16 +19,15 @@
|
||||
#include "ecmascript/compiler/number_speculative_lowering.h"
|
||||
#include "ecmascript/compiler/pass_manager.h"
|
||||
#include "ecmascript/compiler/number_speculative_retype.h"
|
||||
#include "ecmascript/compiler/range_guard.h"
|
||||
#include "ecmascript/ts_types/ts_manager.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
class NumberSpeculativeRunner {
|
||||
public:
|
||||
NumberSpeculativeRunner(Circuit *circuit, TSManager* tsManager,
|
||||
bool enableLog, const std::string& name, Chunk* chunk, PassContext *ctx)
|
||||
: circuit_(circuit), acc_(circuit), tsManager_(tsManager), enableLog_(enableLog),
|
||||
methodName_(name), chunk_(chunk), typeInfos_(chunk), rangeInfos_(chunk),
|
||||
noCheck_(ctx->GetEcmaVM()->GetJSOptions().IsCompilerNoCheck()) {}
|
||||
NumberSpeculativeRunner(Circuit *circuit, bool enableLog, const std::string& name, Chunk* chunk)
|
||||
: circuit_(circuit), acc_(circuit), enableLog_(enableLog), methodName_(name),
|
||||
chunk_(chunk), typeInfos_(chunk), rangeInfos_(chunk) {}
|
||||
|
||||
~NumberSpeculativeRunner() = default;
|
||||
void Run();
|
||||
@ -45,13 +44,11 @@ private:
|
||||
|
||||
Circuit *circuit_ {nullptr};
|
||||
GateAccessor acc_;
|
||||
TSManager* tsManager_ {nullptr};
|
||||
bool enableLog_ {false};
|
||||
std::string methodName_;
|
||||
Chunk *chunk_ {nullptr};
|
||||
ChunkVector<TypeInfo> typeInfos_;
|
||||
ChunkVector<RangeInfo> rangeInfos_;
|
||||
bool noCheck_ {false};
|
||||
};
|
||||
} // panda::ecmascript::kungfu
|
||||
#endif // ECMASCRIPT_COMPILER_NUMBER_SPECULATIVE_RUNNER_H
|
||||
|
125
ecmascript/compiler/object_access_helper.cpp
Normal file
125
ecmascript/compiler/object_access_helper.cpp
Normal file
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (c) 2023 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/object_access_helper.h"
|
||||
#include "ecmascript/ts_types/ts_type.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
bool ObjectAccessHelper::Compute(ChunkVector<ObjectAccessInfo> &infos)
|
||||
{
|
||||
ASSERT(infos.empty());
|
||||
bool result = false;
|
||||
ObjectAccessInfo info(type_);
|
||||
TSTypeKind kind = tsManager_->GetTypeKind(type_.GetGTRef());
|
||||
switch (kind) {
|
||||
case TSTypeKind::CLASS_INSTANCE:
|
||||
result = ComputeForClassInstance(info);
|
||||
break;
|
||||
case TSTypeKind::CLASS:
|
||||
case TSTypeKind::OBJECT:
|
||||
result = ComputeForClassOrObject(info);
|
||||
break;
|
||||
case TSTypeKind::UNION:
|
||||
return ComputePolymorphism(infos);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
infos.emplace_back(info);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool ObjectAccessHelper::ComputeForClassInstance(ObjectAccessInfo &info)
|
||||
{
|
||||
int hclassIndex = tsManager_->GetHClassIndexByInstanceGateType(info.Type());
|
||||
if (hclassIndex == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JSHClass *hclass = JSHClass::Cast(tsManager_->GetValueFromCache(hclassIndex).GetTaggedObject());
|
||||
if (!hclass->HasTSSubtyping()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PropertyLookupResult plr = JSHClass::LookupPropertyInAotHClass(thread_, hclass, key_);
|
||||
info.Set(hclassIndex, plr);
|
||||
|
||||
if (IsLoading()) {
|
||||
return plr.IsFound();
|
||||
}
|
||||
|
||||
return (plr.IsFound() && !plr.IsFunction());
|
||||
}
|
||||
|
||||
bool ObjectAccessHelper::ComputeForClassOrObject(ObjectAccessInfo &info)
|
||||
{
|
||||
GateType type = info.Type();
|
||||
int hclassIndex = -1;
|
||||
if (tsManager_->IsClassTypeKind(type)) {
|
||||
hclassIndex = tsManager_->GetConstructorHClassIndexByClassGateType(type);
|
||||
} else if (tsManager_->IsObjectTypeKind(type)) {
|
||||
hclassIndex = tsManager_->GetHClassIndexByObjectType(type);
|
||||
}
|
||||
|
||||
if (hclassIndex == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JSHClass *hclass = JSHClass::Cast(tsManager_->GetValueFromCache(hclassIndex).GetTaggedObject());
|
||||
PropertyLookupResult plr = JSHClass::LookupPropertyInAotHClass(thread_, hclass, key_);
|
||||
info.Set(hclassIndex, plr);
|
||||
|
||||
if (IsLoading()) {
|
||||
return (plr.IsFound() && plr.IsLocal() && !plr.IsAccessor());
|
||||
}
|
||||
|
||||
return (plr.IsFound() && plr.IsLocal() && !plr.IsAccessor() && plr.IsWritable());
|
||||
}
|
||||
|
||||
bool ObjectAccessHelper::ComputePolymorphism(ChunkVector<ObjectAccessInfo> &infos)
|
||||
{
|
||||
DISALLOW_GARBAGE_COLLECTION;
|
||||
ASSERT(tsManager_->IsUnionTypeKind(type_));
|
||||
JSHandle<TSUnionType> unionType(tsManager_->GetTSType(type_.GetGTRef()));
|
||||
TaggedArray *components = TaggedArray::Cast(unionType->GetComponents().GetTaggedObject());
|
||||
uint32_t length = components->GetLength();
|
||||
for (uint32_t i = 0; i < length; ++i) {
|
||||
GlobalTSTypeRef gt(components->Get(i).GetInt());
|
||||
GateType type = GateType(gt);
|
||||
ObjectAccessInfo info(type);
|
||||
TSTypeKind kind = tsManager_->GetTypeKind(gt);
|
||||
switch (kind) {
|
||||
case TSTypeKind::CLASS_INSTANCE: {
|
||||
if (!ComputeForClassInstance(info)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TSTypeKind::CLASS:
|
||||
case TSTypeKind::OBJECT: {
|
||||
if (!ComputeForClassOrObject(info)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
infos.emplace_back(info);
|
||||
}
|
||||
|
||||
return infos.size() <= POLYMORPHIC_MAX_SIZE;
|
||||
}
|
||||
} // namespace panda::ecmascript::kungfu
|
114
ecmascript/compiler/object_access_helper.h
Normal file
114
ecmascript/compiler/object_access_helper.h
Normal file
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 2023 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_OBJECT_ACCESS_HELPER_H
|
||||
#define ECMASCRIPT_COMPILER_OBJECT_ACCESS_HELPER_H
|
||||
|
||||
#include "ecmascript/ts_types/ts_manager.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
class ObjectAccessInfo final {
|
||||
public:
|
||||
explicit ObjectAccessInfo(GateType type, int hclassIndex = -1, PropertyLookupResult plr = PropertyLookupResult())
|
||||
: type_(type), hclassIndex_(hclassIndex), plr_(plr) {}
|
||||
~ObjectAccessInfo() = default;
|
||||
|
||||
void Set(int hclassIndex, PropertyLookupResult plr)
|
||||
{
|
||||
hclassIndex_ = hclassIndex;
|
||||
plr_ = plr;
|
||||
}
|
||||
|
||||
GateType Type() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
||||
int HClassIndex() const
|
||||
{
|
||||
return hclassIndex_;
|
||||
}
|
||||
|
||||
PropertyLookupResult Plr() const
|
||||
{
|
||||
return plr_;
|
||||
}
|
||||
|
||||
private:
|
||||
GateType type_ {GateType::AnyType()};
|
||||
int hclassIndex_ {-1};
|
||||
PropertyLookupResult plr_ {};
|
||||
};
|
||||
|
||||
// An auxiliary class serving TSHCRLowering, used for named object property access,
|
||||
// invoking TSManager and HClass.
|
||||
class ObjectAccessHelper final {
|
||||
public:
|
||||
static constexpr size_t POLYMORPHIC_MAX_SIZE = 4;
|
||||
|
||||
enum AccessMode : uint8_t {
|
||||
LOAD = 0,
|
||||
STORE
|
||||
};
|
||||
|
||||
explicit ObjectAccessHelper(TSManager *tsManager, AccessMode mode, GateRef receiver, GateType type,
|
||||
JSTaggedValue key, GateRef value)
|
||||
: tsManager_(tsManager),
|
||||
thread_(tsManager_->GetThread()),
|
||||
mode_(mode),
|
||||
receiver_(receiver),
|
||||
type_(type),
|
||||
key_(key),
|
||||
value_(value) {}
|
||||
|
||||
~ObjectAccessHelper() = default;
|
||||
|
||||
bool Compute(ChunkVector<ObjectAccessInfo> &infos);
|
||||
|
||||
AccessMode GetAccessMode() const
|
||||
{
|
||||
return mode_;
|
||||
}
|
||||
|
||||
bool IsLoading() const
|
||||
{
|
||||
return mode_ == AccessMode::LOAD;
|
||||
}
|
||||
|
||||
GateRef GetReceiver() const
|
||||
{
|
||||
return receiver_;
|
||||
}
|
||||
|
||||
GateRef GetValue() const
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
|
||||
private:
|
||||
bool ComputeForClassInstance(ObjectAccessInfo &info);
|
||||
bool ComputeForClassOrObject(ObjectAccessInfo &info);
|
||||
bool ComputePolymorphism(ChunkVector<ObjectAccessInfo> &infos);
|
||||
|
||||
TSManager *tsManager_ {nullptr};
|
||||
const JSThread *thread_ {nullptr};
|
||||
AccessMode mode_ {};
|
||||
GateRef receiver_ {Circuit::NullGate()};
|
||||
GateType type_ {GateType::AnyType()};
|
||||
JSTaggedValue key_ {JSTaggedValue::Hole()};
|
||||
GateRef value_ {Circuit::NullGate()};
|
||||
};
|
||||
} // panda::ecmascript::kungfu
|
||||
#endif // ECMASCRIPT_COMPILER_OBJECT_ACCESS_HELPER_H
|
@ -30,7 +30,6 @@
|
||||
#include "ecmascript/compiler/ntype_hcr_lowering.h"
|
||||
#include "ecmascript/compiler/ntype_mcr_lowering.h"
|
||||
#include "ecmascript/compiler/number_speculative_runner.h"
|
||||
#include "ecmascript/compiler/range_guard.h"
|
||||
#include "ecmascript/compiler/scheduler.h"
|
||||
#include "ecmascript/compiler/slowpath_lowering.h"
|
||||
#include "ecmascript/compiler/state_split_linearizer.h"
|
||||
@ -292,7 +291,7 @@ public:
|
||||
bool enableLog = data->GetLog()->EnableMethodCIRLog();
|
||||
bool enableTypeLog = data->GetLog()->GetEnableMethodLog() && data->GetLog()->OutputType();
|
||||
TSHCRLowering lowering(data->GetCircuit(), data->GetPassContext(),
|
||||
enableLog, enableTypeLog, passOptions->EnableOptStaticMethod(), data->GetMethodName());
|
||||
enableLog, enableTypeLog, data->GetMethodName());
|
||||
bool success = lowering.RunTSHCRLowering();
|
||||
if (!success) {
|
||||
data->MarkAsTypeAbort();
|
||||
@ -312,7 +311,7 @@ public:
|
||||
TimeScope timescope("NTypeHCRLoweringPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
|
||||
bool enableLog = data->GetLog()->EnableMethodCIRLog();
|
||||
NTypeHCRLowering lowering(data->GetCircuit(), data->GetPassContext(),
|
||||
data->GetTSManager(), enableLog, data->GetMethodName());
|
||||
data->GetTSManager(), data->GetRecordName(), enableLog, data->GetMethodName());
|
||||
lowering.RunNTypeHCRLowering();
|
||||
return true;
|
||||
}
|
||||
@ -345,8 +344,8 @@ public:
|
||||
}
|
||||
TimeScope timescope("NTypeMCRLoweringPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
|
||||
bool enableLog = data->GetLog()->EnableMethodCIRLog();
|
||||
NTypeMCRLowering lowering(data->GetCircuit(), data->GetPassContext(), data->GetTSManager(),
|
||||
enableLog, data->GetMethodName());
|
||||
NTypeMCRLowering lowering(data->GetCircuit(), data->GetPassContext(),
|
||||
data->GetRecordName(), enableLog, data->GetMethodName());
|
||||
lowering.RunNTypeMCRLowering();
|
||||
return true;
|
||||
}
|
||||
@ -379,7 +378,7 @@ public:
|
||||
TimeScope timescope("TSInlineLoweringPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
|
||||
bool enableLog = data->GetLog()->EnableMethodCIRLog();
|
||||
TSInlineLowering inlining(data->GetCircuit(), data->GetPassContext(), enableLog, data->GetMethodName(),
|
||||
data->GetNativeAreaAllocator(), passOptions);
|
||||
data->GetNativeAreaAllocator(), passOptions, data->GetMethodOffset());
|
||||
inlining.RunTSInlineLowering();
|
||||
return true;
|
||||
}
|
||||
@ -389,12 +388,10 @@ class SlowPathLoweringPass {
|
||||
public:
|
||||
bool Run(PassData* data)
|
||||
{
|
||||
PassOptions *passOptions = data->GetPassOptions();
|
||||
TimeScope timescope("SlowPathLoweringPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
|
||||
bool enableLog = data->GetLog()->EnableMethodCIRLog();
|
||||
SlowPathLowering lowering(data->GetCircuit(), data->GetCompilerConfig(), data->GetTSManager(),
|
||||
data->GetMethodLiteral(), enableLog,
|
||||
passOptions->EnableOptStaticMethod(), data->GetMethodName());
|
||||
data->GetMethodLiteral(), enableLog, data->GetMethodName());
|
||||
lowering.CallRuntimeLowering();
|
||||
return true;
|
||||
}
|
||||
@ -426,8 +423,7 @@ public:
|
||||
TimeScope timescope("NumberSpeculativePass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
|
||||
Chunk chunk(data->GetNativeAreaAllocator());
|
||||
bool enableLog = data->GetLog()->EnableMethodCIRLog();
|
||||
NumberSpeculativeRunner(data->GetCircuit(), data->GetTSManager(),
|
||||
enableLog, data->GetMethodName(), &chunk, data->GetPassContext()).Run();
|
||||
NumberSpeculativeRunner(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk).Run();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@ -490,22 +486,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class RangeGuardPass {
|
||||
public:
|
||||
bool Run(PassData* data)
|
||||
{
|
||||
PassOptions *passOptions = data->GetPassOptions();
|
||||
if (!passOptions->EnableTypeLowering() || !passOptions->EnableRangeGuard()) {
|
||||
return false;
|
||||
}
|
||||
TimeScope timescope("RangeGuardPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
|
||||
Chunk chunk(data->GetNativeAreaAllocator());
|
||||
bool enableLog = data->GetLog()->EnableMethodCIRLog();
|
||||
RangeGuard(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk, data->GetPassContext()).Run();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class ValueNumberingPass {
|
||||
public:
|
||||
bool Run(PassData* data)
|
||||
|
@ -133,15 +133,14 @@ bool PassManager::Compile(JSPandaFile *jsPandaFile, const std::string &fileName,
|
||||
return;
|
||||
}
|
||||
pipeline.RunPass<EarlyEliminationPass>();
|
||||
pipeline.RunPass<RangeGuardPass>();
|
||||
pipeline.RunPass<NumberSpeculativePass>();
|
||||
pipeline.RunPass<LaterEliminationPass>();
|
||||
pipeline.RunPass<ValueNumberingPass>();
|
||||
pipeline.RunPass<StateSplitLinearizerPass>();
|
||||
pipeline.RunPass<NTypeMCRLoweringPass>();
|
||||
pipeline.RunPass<TypeMCRLoweringPass>();
|
||||
pipeline.RunPass<EarlyEliminationPass>();
|
||||
pipeline.RunPass<LaterEliminationPass>();
|
||||
pipeline.RunPass<EarlyEliminationPass>();
|
||||
pipeline.RunPass<LCRLoweringPass>();
|
||||
pipeline.RunPass<SlowPathLoweringPass>();
|
||||
pipeline.RunPass<VerifierPass>();
|
||||
@ -182,9 +181,8 @@ void PassManager::ResolveModule(const JSPandaFile *jsPandaFile, const std::strin
|
||||
ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager();
|
||||
[[maybe_unused]] EcmaHandleScope scope(thread);
|
||||
for (auto info: recordInfo) {
|
||||
auto recordName = info.first;
|
||||
if (jsPandaFile->IsModule(thread, recordName)) {
|
||||
ASSERT(!thread->HasPendingException());
|
||||
if (jsPandaFile->IsModule(info.second)) {
|
||||
auto recordName = info.first;
|
||||
JSHandle<JSTaggedValue> moduleRecord = moduleManager->HostResolveImportedModuleWithMerge(fileName.c_str(),
|
||||
recordName);
|
||||
SourceTextModule::Instantiate(thread, moduleRecord);
|
||||
|
@ -126,17 +126,15 @@ private:
|
||||
|
||||
class PassOptions {
|
||||
public:
|
||||
PassOptions(bool enableTypeLowering, bool enableEarlyElimination, bool enableRangeGuard, bool enableLaterElimination,
|
||||
PassOptions(bool enableTypeLowering, bool enableEarlyElimination, bool enableLaterElimination,
|
||||
bool enableValueNumbering, bool enableTypeInfer, bool enableOptInlining,
|
||||
bool enableOptStaticMethod, bool enableOptPGOType, bool enableOptTrackField, bool enableOptLoopPeeling)
|
||||
bool enableOptPGOType, bool enableOptTrackField, bool enableOptLoopPeeling)
|
||||
: enableTypeLowering_(enableTypeLowering),
|
||||
enableEarlyElimination_(enableEarlyElimination),
|
||||
enableRangeGuard_(enableRangeGuard),
|
||||
enableLaterElimination_(enableLaterElimination),
|
||||
enableValueNumbering_(enableValueNumbering),
|
||||
enableTypeInfer_(enableTypeInfer),
|
||||
enableOptInlining_(enableOptInlining),
|
||||
enableOptStaticMethod_(enableOptStaticMethod),
|
||||
enableOptPGOType_(enableOptPGOType),
|
||||
enableOptTrackField_(enableOptTrackField),
|
||||
enableOptLoopPeeling_(enableOptLoopPeeling)
|
||||
@ -146,12 +144,10 @@ public:
|
||||
#define OPTION_LIST(V) \
|
||||
V(TypeLowering, true) \
|
||||
V(EarlyElimination, true) \
|
||||
V(RangeGuard, true) \
|
||||
V(LaterElimination, true) \
|
||||
V(ValueNumbering, false) \
|
||||
V(TypeInfer, false) \
|
||||
V(OptInlining, false) \
|
||||
V(OptStaticMethod, false) \
|
||||
V(OptNoGCCall, false) \
|
||||
V(OptPGOType, false) \
|
||||
V(NoCheck, false) \
|
||||
|
@ -20,9 +20,10 @@ void PGOBCInfo::Info::Record(const InfoDetail &detail)
|
||||
{
|
||||
auto it = methodOffsetToValVec_.find(detail.methodOffset);
|
||||
if (it == methodOffsetToValVec_.end()) {
|
||||
methodOffsetToValVec_[detail.methodOffset] = ValVec { Val { detail.bcIndex, detail.cpIndex} };
|
||||
methodOffsetToValVec_[detail.methodOffset] =
|
||||
ValVec { Val { detail.bcIndex, detail.bcOffset, detail.cpIndex} };
|
||||
} else {
|
||||
it->second.emplace_back(Val{ detail.bcIndex, detail.cpIndex });
|
||||
it->second.emplace_back(Val{ detail.bcIndex, detail.bcOffset, detail.cpIndex });
|
||||
}
|
||||
recordNameToValCount_[detail.recordName]++;
|
||||
}
|
||||
@ -59,19 +60,19 @@ void PGOBCInfo::Record(const InfoDetail &detail, Type type)
|
||||
}
|
||||
|
||||
void PGOBCInfo::Record(const BytecodeInstruction &bcIns, int32_t bcIndex,
|
||||
const CString &recordName, const MethodLiteral *method)
|
||||
const CString &recordName, const MethodLiteral *method)
|
||||
{
|
||||
BytecodeInstruction::Opcode opcode = static_cast<BytecodeInstruction::Opcode>(bcIns.GetOpcode());
|
||||
uint32_t methodOffset = method->GetMethodId().GetOffset();
|
||||
switch (opcode) {
|
||||
case BytecodeInstruction::Opcode::CREATEOBJECTWITHBUFFER_IMM8_ID16:
|
||||
case BytecodeInstruction::Opcode::CREATEOBJECTWITHBUFFER_IMM16_ID16: {
|
||||
auto cpIndex = bcIns.GetId().AsRawValue();
|
||||
Record(InfoDetail {recordName, methodOffset, bcIndex, cpIndex}, Type::OBJ_LITERAL);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
uint32_t bcOffset = bcIns.GetAddress() - method->GetBytecodeArray();
|
||||
if (Bytecodes::IsCreateObjectWithBufferOp(opcode)) {
|
||||
auto cpIndex = bcIns.GetId().AsRawValue();
|
||||
Record(InfoDetail {recordName, methodOffset, bcIndex, bcOffset, cpIndex}, Type::OBJ_LITERAL);
|
||||
} else if (Bytecodes::IsCreateArrayWithBufferOp(opcode)) {
|
||||
auto cpIndex = bcIns.GetId().AsRawValue();
|
||||
Record(InfoDetail {recordName, methodOffset, bcIndex, bcOffset, cpIndex}, Type::ARRAY_LITERAL);
|
||||
} else if (Bytecodes::IsCallOp(opcode)) {
|
||||
Record(InfoDetail {recordName, methodOffset, bcIndex, bcOffset, 0}, Type::CALL_TARGET);
|
||||
}
|
||||
}
|
||||
} // namespace panda::ecmascript
|
||||
|
@ -24,16 +24,18 @@ class PGOBCInfo {
|
||||
public:
|
||||
enum Type {
|
||||
OBJ_LITERAL = 0,
|
||||
|
||||
ARRAY_LITERAL,
|
||||
CALL_TARGET,
|
||||
TYPE_NUM,
|
||||
TYPE_FIRST = OBJ_LITERAL,
|
||||
TYPE_LAST = OBJ_LITERAL,
|
||||
TYPE_LAST = CALL_TARGET,
|
||||
};
|
||||
|
||||
struct InfoDetail {
|
||||
const CString &recordName;
|
||||
uint32_t methodOffset;
|
||||
uint32_t bcIndex;
|
||||
uint32_t bcOffset;
|
||||
uint32_t cpIndex;
|
||||
};
|
||||
|
||||
@ -49,13 +51,14 @@ public:
|
||||
if (methodOffsetToValVec_.find(methodOffset) != methodOffsetToValVec_.end()) {
|
||||
const ValVec &valVec = methodOffsetToValVec_.at(methodOffset);
|
||||
for (auto val : valVec) {
|
||||
cb(type, val.bcIndex, val.cpIndex);
|
||||
cb(type, val.bcIndex, val.bcOffset, val.cpIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
private:
|
||||
struct Val {
|
||||
uint32_t bcIndex;
|
||||
uint32_t bcOffset;
|
||||
uint32_t cpIndex;
|
||||
};
|
||||
using ValVec = CVector<Val>;
|
||||
|
@ -24,7 +24,6 @@
|
||||
namespace panda::ecmascript::kungfu {
|
||||
enum class OperationType : uint8_t {
|
||||
CALL,
|
||||
CALL_WIDE,
|
||||
OPERATION_TYPE,
|
||||
DEFINE_CLASS,
|
||||
CREATE_OBJECT,
|
||||
@ -47,11 +46,10 @@ public:
|
||||
return callback_ == nullptr;
|
||||
}
|
||||
|
||||
inline void ProfileCall(GateRef func, BytecodeInstruction::Format format) const
|
||||
inline void ProfileCall(GateRef func) const
|
||||
{
|
||||
if (callback_) {
|
||||
callback_({ func },
|
||||
format == BytecodeInstruction::Format::IMM16 ? OperationType::CALL_WIDE : OperationType::CALL);
|
||||
callback_({ func }, OperationType::CALL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,8 +25,7 @@ void ProfilerStubBuilder::PGOProfiler(GateRef glue, GateRef pc, GateRef func, Ga
|
||||
{
|
||||
switch (type) {
|
||||
case OperationType::CALL:
|
||||
case OperationType::CALL_WIDE:
|
||||
ProfileCall(glue, pc, profileTypeInfo, values[0], type);
|
||||
ProfileCall(glue, pc, func, values[0]);
|
||||
break;
|
||||
case OperationType::OPERATION_TYPE:
|
||||
ProfileOpType(glue, pc, func, profileTypeInfo, values[0]);
|
||||
@ -69,22 +68,32 @@ void ProfilerStubBuilder::ProfileOpType(GateRef glue, GateRef pc, GateRef func,
|
||||
}
|
||||
Bind(&profiler);
|
||||
{
|
||||
Label pushLabel(env);
|
||||
Label uninitialize(env);
|
||||
Label compareLabel(env);
|
||||
Label updateSlot(env);
|
||||
Label updateProfile(env);
|
||||
|
||||
GateRef slotId = ZExtInt8ToInt32(Load(VariableType::INT8(), pc, IntPtr(1)));
|
||||
GateRef slotValue = GetValueFromTaggedArray(profileTypeInfo, slotId);
|
||||
DEFVARIABLE(curType, VariableType::INT32(), type);
|
||||
Branch(TaggedIsInt(slotValue), &compareLabel, &pushLabel);
|
||||
Branch(TaggedIsInt(slotValue), &compareLabel, &uninitialize);
|
||||
Bind(&compareLabel);
|
||||
{
|
||||
GateRef oldSlotValue = TaggedGetInt(slotValue);
|
||||
curType = Int32Or(oldSlotValue, type);
|
||||
Branch(Int32Equal(oldSlotValue, *curType), &exit, &pushLabel);
|
||||
Branch(Int32Equal(oldSlotValue, *curType), &exit, &updateSlot);
|
||||
}
|
||||
Bind(&pushLabel);
|
||||
Bind(&uninitialize);
|
||||
{
|
||||
Branch(TaggedIsUndefined(slotValue), &updateSlot, &updateProfile);
|
||||
}
|
||||
Bind(&updateSlot);
|
||||
{
|
||||
SetValueToTaggedArray(VariableType::JS_ANY(), glue, profileTypeInfo, slotId, IntToTaggedInt(*curType));
|
||||
Jump(&updateProfile);
|
||||
}
|
||||
Bind(&updateProfile);
|
||||
{
|
||||
GateRef method = Load(VariableType::JS_ANY(), func, IntPtr(JSFunctionBase::METHOD_OFFSET));
|
||||
GateRef firstPC =
|
||||
Load(VariableType::NATIVE_POINTER(), method, IntPtr(Method::NATIVE_POINTER_OR_BYTECODE_ARRAY_OFFSET));
|
||||
@ -148,59 +157,32 @@ void ProfilerStubBuilder::ProfileObjLayout(GateRef glue, GateRef pc, GateRef fun
|
||||
env->SubCfgExit();
|
||||
}
|
||||
|
||||
void ProfilerStubBuilder::ProfileCall(
|
||||
GateRef glue, GateRef pc, GateRef profileTypeInfo, GateRef target, OperationType type)
|
||||
void ProfilerStubBuilder::ProfileCall(GateRef glue, GateRef pc, GateRef func, GateRef target)
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
Label subEntry(env);
|
||||
env->SubCfgEntry(&subEntry);
|
||||
|
||||
Label exit(env);
|
||||
Label fastpath(env);
|
||||
Label slowpath(env);
|
||||
Label fastpath(env);
|
||||
|
||||
DEFVARIABLE(inc, VariableType::INT32(), Int32(1));
|
||||
Branch(TaggedIsUndefined(profileTypeInfo), &slowpath, &fastpath);
|
||||
Bind(&fastpath);
|
||||
Label targetIsFunction(env);
|
||||
Branch(IsJSFunction(target), &targetIsFunction, &exit);
|
||||
Bind(&targetIsFunction);
|
||||
{
|
||||
Label initialLabel(env);
|
||||
Label uninitialLabel(env);
|
||||
GateRef slotId = Int32(panda::ecmascript::ProfileTypeInfo::INVALID_SLOT_INDEX);
|
||||
if (type == OperationType::CALL_WIDE) {
|
||||
GateRef currentInstHigh = ZExtInt8ToInt16(Load(VariableType::INT8(), pc, IntPtr(HIGH_WORD_OFFSET)));
|
||||
GateRef currentInstHighLsl = Int16LSL(currentInstHigh, Int16(BITS_OF_WORD));
|
||||
GateRef currentInstLow = ZExtInt8ToInt16(Load(VariableType::INT8(), pc, IntPtr(LOW_WORD_OFFSET)));
|
||||
slotId = ZExtInt16ToInt32(Int16Add(currentInstHighLsl, currentInstLow));
|
||||
} else {
|
||||
slotId = ZExtInt8ToInt32(Load(VariableType::INT8(), pc, IntPtr(1)));
|
||||
}
|
||||
GateRef slotValue = GetValueFromTaggedArray(profileTypeInfo, slotId);
|
||||
Branch(TaggedIsInt(slotValue), &initialLabel, &uninitialLabel);
|
||||
Bind(&initialLabel);
|
||||
GateRef targetProfileInfo = GetProfileTypeInfo(target);
|
||||
Label nonHotness(env);
|
||||
Branch(TaggedIsUndefined(targetProfileInfo), &nonHotness, &exit);
|
||||
Bind(&nonHotness);
|
||||
{
|
||||
Label fastLabel(env);
|
||||
GateRef oldInc = TaggedGetInt(slotValue);
|
||||
Branch(Int32GreaterThan(oldInc, Int32(MAX_PROFILE_CALL_COUNT)), &exit, &fastLabel);
|
||||
Bind(&fastLabel);
|
||||
GateRef count = Int32Add(oldInc, *inc);
|
||||
SetValueToTaggedArray(VariableType::JS_ANY(), glue, profileTypeInfo, slotId, IntToTaggedInt(count));
|
||||
inc = Int32(MIN_PROFILE_CALL_INTERVAL);
|
||||
GateRef mod = Int32Mod(oldInc, *inc);
|
||||
Branch(Int32Equal(mod, Int32(0)), &slowpath, &exit);
|
||||
GateRef method = Load(VariableType::JS_ANY(), func, IntPtr(JSFunctionBase::METHOD_OFFSET));
|
||||
GateRef firstPC =
|
||||
Load(VariableType::NATIVE_POINTER(), method, IntPtr(Method::NATIVE_POINTER_OR_BYTECODE_ARRAY_OFFSET));
|
||||
GateRef offset = TruncPtrToInt32(PtrSub(pc, firstPC));
|
||||
CallNGCRuntime(glue, RTSTUB_ID(ProfileCall), { glue, func, target, offset, Int32(1)});
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(&uninitialLabel);
|
||||
{
|
||||
Label fastLabel(env);
|
||||
Branch(TaggedIsUndefined(slotValue), &fastLabel, &slowpath);
|
||||
Bind(&fastLabel);
|
||||
SetValueToTaggedArray(VariableType::JS_ANY(), glue, profileTypeInfo, slotId, IntToTaggedInt(*inc));
|
||||
Jump(&slowpath);
|
||||
}
|
||||
}
|
||||
Bind(&slowpath);
|
||||
{
|
||||
CallNGCRuntime(glue, RTSTUB_ID(ProfileCall), { glue, target, *inc});
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(&exit);
|
||||
env->SubCfgExit();
|
||||
|
@ -31,7 +31,7 @@ public:
|
||||
|
||||
void PGOProfiler(GateRef glue, GateRef pc, GateRef func, GateRef profileTypeInfo,
|
||||
const std::vector<GateRef> &values, OperationType type);
|
||||
void ProfileCall(GateRef glue, GateRef pc, GateRef profileTypeInfo, GateRef target, OperationType type);
|
||||
void ProfileCall(GateRef glue, GateRef pc, GateRef func, GateRef target);
|
||||
void ProfileOpType(GateRef glue, GateRef pc, GateRef func, GateRef profileTypeInfo, GateRef type);
|
||||
void ProfileDefineClass(GateRef glue, GateRef pc, GateRef func, GateRef constructor);
|
||||
void ProfileCreateObject(GateRef glue, GateRef pc, GateRef func, GateRef originObj, GateRef newObj);
|
||||
|
@ -172,8 +172,10 @@ GateRef RangeAnalysis::VisitLoadTypedArrayLength(GateRef gate)
|
||||
}
|
||||
|
||||
GateRef RangeAnalysis::VisitRangeGuard(GateRef gate)
|
||||
{
|
||||
return UpdateRange(gate, RangeInfo(1, RangeInfo::TYPED_ARRAY_ONHEAP_MAX));
|
||||
{
|
||||
auto left = acc_.GetFirstValue(gate);
|
||||
auto right = acc_.GetSecondValue(gate);
|
||||
return UpdateRange(gate, RangeInfo(left, right));
|
||||
}
|
||||
|
||||
template<TypedBinOp Op>
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user