Merge branch 'master' of gitee.com:openharmony/arkcompiler_ets_runtime into master

Signed-off-by: 查维 <zhawei@kaihong.com>
This commit is contained in:
查维 2023-08-09 02:21:22 +00:00 committed by Gitee
commit ca768d783d
380 changed files with 14381 additions and 2821 deletions

View File

@ -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",
]

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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_);

View File

@ -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;

View File

@ -68,8 +68,8 @@ public:
}
/*
* Before: @xxx:****
* After: ****
* Before: @***:xxxx
* After: xxxx
*/
inline static CString GetStrippedModuleName(const CString &moduleRequestName)
{

View File

@ -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).

View File

@ -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);
}
}

View File

@ -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();
}

View File

@ -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 views [[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 views [[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

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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).

View File

@ -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);

View File

@ -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);

View File

@ -205,7 +205,7 @@ JSTaggedValue BuiltinsSet::ForEach(EcmaRuntimeCallInfo *argv)
// 6.Let entries be the List that is the value of Ss [[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();

View File

@ -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);

View File

@ -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 Os [[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(),

View File

@ -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);

View File

@ -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);

View File

@ -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()));

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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",

View File

@ -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, &notHole);
Bind(&notHole);
@ -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(&notFoundInRecord);
{
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(&notFoundInRecord);
{
GateRef globalObject = GetGlobalObject(glue);
result = GetGlobalOwnProperty(glue, globalObject, propKey);
result = GetGlobalOwnProperty(glue, globalObject, propKey, callback);
Label isFoundInGlobal(env);
Label notFoundInGlobal(env);
Branch(TaggedIsHole(*result), &notFoundInGlobal, &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);

View File

@ -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:

View File

@ -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);

View File

@ -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();
}

View File

@ -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 {

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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_ {};

View File

@ -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);

View File

@ -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

View File

@ -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

View 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

View 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

View File

@ -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) \

View File

@ -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

View File

@ -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);
}
}

View File

@ -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_;

View File

@ -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

View File

@ -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);

View File

@ -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:

View File

@ -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)
{

View File

@ -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());

View File

@ -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();

View File

@ -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 {

View File

@ -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()));
}
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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};

View File

@ -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();

View File

@ -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);

View File

@ -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)

View File

@ -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;

View File

@ -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;

View File

@ -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) \

View File

@ -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

View File

@ -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

View File

@ -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_);
}

View File

@ -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);

View File

@ -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, &notHole);
Bind(&notHole);
@ -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, &notHole);
Bind(&notHole);
@ -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, &notHole);
Bind(&notHole);
@ -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, &notHole);
Bind(&notHole);
@ -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)

View File

@ -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

View File

@ -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

View File

@ -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), &notOverFlow, &isOverFlow);
builder_.Bind(&notOverFlow);
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);

View File

@ -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);

View File

@ -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)

View File

@ -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> &params
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];
}

View File

@ -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);

View File

@ -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

View File

@ -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};

View File

@ -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)

View File

@ -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};

View File

@ -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};

View File

@ -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;
}

View File

@ -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

View File

@ -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();
}

View File

@ -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};
};

View File

@ -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) << "";

View File

@ -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

View 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

View 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

View File

@ -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)

View File

@ -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);

View File

@ -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) \

View File

@ -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

View File

@ -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>;

View File

@ -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);
}
}

View File

@ -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();

View File

@ -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);

View File

@ -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