Add fastpath for elementkind

issue:#I9O499

Signed-off-by: dov1s <maojunwei1@huawei.com>
Change-Id: Icad8c5624d50fa492c56fed8eec568d63a5d682c
This commit is contained in:
dov1s 2024-05-10 12:55:33 +08:00
parent 873b85e648
commit 555f00b5e3
9 changed files with 172 additions and 16 deletions

View File

@ -1812,6 +1812,49 @@ void BuiltinsArrayStubBuilder::Reverse(GateRef glue, GateRef thisValue, [[maybe_
DEFVARIABLE(i, VariableType::INT64(), Int64(0));
DEFVARIABLE(j, VariableType::INT64(), Int64Sub(thisArrLen, Int64(1)));
GateRef hclass = LoadHClass(thisValue);
GateRef kind = GetElementsKindFromHClass(hclass);
Label isInt(env);
Label isNotInt(env);
Label notFastKind(env);
GateRef elementsKindIntLB = Int32GreaterThanOrEqual(kind,
Int32(static_cast<int32_t>(ElementsKind::INT)));
GateRef elementsKindIntUB = Int32LessThanOrEqual(kind,
Int32(static_cast<int32_t>(ElementsKind::HOLE_INT)));
GateRef checkIntKind = BoolAnd(elementsKindIntLB, elementsKindIntUB);
BRANCH(checkIntKind, &isInt, &isNotInt);
Bind(&isInt);
{
FastReverse(glue, thisValue, thisArrLen, ElementsKind::INT, result, exit);
}
Bind(&isNotInt);
{
Label isNumber(env);
Label isNotNumber(env);
GateRef elementsKindNumberLB = Int32GreaterThanOrEqual(kind,
Int32(static_cast<int32_t>(ElementsKind::NUMBER)));
GateRef elementsKindNumberUB = Int32LessThanOrEqual(kind,
Int32(static_cast<int32_t>(ElementsKind::HOLE_NUMBER)));
GateRef checkNumberKind = BoolAnd(elementsKindNumberLB, elementsKindNumberUB);
BRANCH(checkNumberKind, &isNumber, &isNotNumber);
Bind(&isNumber);
{
FastReverse(glue, thisValue, thisArrLen, ElementsKind::NUMBER, result, exit);
}
Bind(&isNotNumber);
{
FastReverse(glue, thisValue, thisArrLen, ElementsKind::TAGGED, result, exit);
}
}
}
void BuiltinsArrayStubBuilder::FastReverse(GateRef glue, GateRef thisValue, GateRef len,
ElementsKind kind, Variable *result, Label *exit)
{
auto env = GetEnvironment();
DEFVARIABLE(i, VariableType::INT64(), Int64(0));
DEFVARIABLE(j, VariableType::INT64(), Int64Sub(len, Int64(1)));
GateRef elements = GetElementsArray(thisValue);
Label loopHead(env);
Label loopEnd(env);
Label next(env);
@ -1824,12 +1867,10 @@ void BuiltinsArrayStubBuilder::Reverse(GateRef glue, GateRef thisValue, [[maybe_
BRANCH(Int64LessThan(*i, *j), &next, &loopExit);
Bind(&next);
{
GateRef lower = GetTaggedValueWithElementsKind(thisValue, *i);
GateRef upper = GetTaggedValueWithElementsKind(thisValue, *j);
SetValueWithElementsKind(glue, thisValue, upper, *i, Boolean(false),
Int32(static_cast<uint32_t>(ElementsKind::NONE)));
SetValueWithElementsKind(glue, thisValue, lower, *j, Boolean(false),
Int32(static_cast<uint32_t>(ElementsKind::NONE)));
GateRef lower = FastGetValueWithElementsKind(elements, *i, kind);
GateRef upper = FastGetValueWithElementsKind(elements, *j, kind);
FastSetValueWithElementsKind(glue, elements, upper, *i, kind);
FastSetValueWithElementsKind(glue, elements, lower, *j, kind);
Jump(&loopEnd);
}
}

View File

@ -51,6 +51,9 @@ BUILTINS_WITH_ARRAY_STUB_BUILDER(DECLARE_BUILTINS_ARRAY_STUB_BUILDER)
GateRef DoSort(GateRef glue, GateRef receiver, GateRef receiverState,
Variable *result, Label *exit, Label *slowPath);
void FastReverse(GateRef glue, GateRef thisValue, GateRef len,
ElementsKind kind, Variable *result, Label *exit);
private:
static constexpr uint32_t MAX_LENGTH_ZERO = 0;
static constexpr uint32_t MAX_LENGTH_ONE = 1;

View File

@ -9834,6 +9834,55 @@ GateRef StubBuilder::SetValueWithElementsKind(GateRef glue, GateRef receiver, Ga
return ret;
}
GateRef StubBuilder::FastGetValueWithElementsKind(GateRef elements, GateRef index, ElementsKind kind)
{
auto env = GetEnvironment();
Label entryPass(env);
env->SubCfgEntry(&entryPass);
DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
Label exit(env);
if (kind == ElementsKind::INT || kind == ElementsKind::NUMBER) {
result = GetValueFromTaggedArray(elements, index);
Jump(&exit);
} else {
result = GetValueFromTaggedArray(elements, index);
Jump(&exit);
}
Bind(&exit);
auto ret = *result;
env->SubCfgExit();
return ret;
}
void StubBuilder::FastSetValueWithElementsKind(GateRef glue, GateRef elements, GateRef rawValue,
GateRef index, ElementsKind kind)
{
auto env = GetEnvironment();
Label entryPass(env);
env->SubCfgEntry(&entryPass);
Label exit(env);
if (kind == ElementsKind::INT || kind == ElementsKind::NUMBER) {
SetValueToTaggedArray(VariableType::INT64(), glue, elements, index, rawValue);
Jump(&exit);
} else {
Label storeToNormalArray(env);
Label storeToMutantArray(env);
BRANCH(TaggedIsHeapObject(rawValue), &storeToNormalArray, &storeToMutantArray);
Bind(&storeToNormalArray);
{
SetValueToTaggedArray(VariableType::JS_ANY(), glue, elements, index, rawValue);
Jump(&exit);
}
Bind(&storeToMutantArray);
{
SetValueToTaggedArray(VariableType::INT64(), glue, elements, index, rawValue);
Jump(&exit);
}
}
Bind(&exit);
env->SubCfgExit();
}
GateRef StubBuilder::CopyJSArrayToTaggedArrayArgs(GateRef glue, GateRef srcObj)
{
auto env = GetEnvironment();

View File

@ -516,6 +516,9 @@ public:
GateRef GetFieldTypeFromHandler(GateRef attr);
GateRef ClearSharedStoreKind(GateRef handlerInfo);
GateRef GetTaggedValueWithElementsKind(GateRef receiver, GateRef index);
GateRef FastGetValueWithElementsKind(GateRef elements, GateRef index, ElementsKind kind);
void FastSetValueWithElementsKind(GateRef glue, GateRef elements, GateRef rawValue,
GateRef index, ElementsKind kind);
GateRef SetValueWithElementsKind(GateRef glue, GateRef receiver, GateRef rawValue, GateRef index,
GateRef needTransition, GateRef extraKind);
GateRef CopyJSArrayToTaggedArrayArgs(GateRef glue, GateRef srcObj);

View File

@ -55,5 +55,41 @@ inline void ElementAccessor::Set(const JSThread *thread, JSHandle<JSObject> rece
Barriers::SetPrimitive<JSTaggedType>(elements->GetData(), offset, convertedValue);
}
}
template<typename T>
void ElementAccessor::FastSet(const JSThread *thread, JSHandle<TaggedArray> elements, uint32_t idx,
const JSHandle<T> &value, ElementsKind kind)
{
ASSERT(idx < elements->GetLength());
size_t offset = JSTaggedValue::TaggedTypeSize() * idx;
JSTaggedValue rawValue = value.GetTaggedValue();
switch (kind) {
case ElementsKind::INT:
Barriers::SetPrimitive<JSTaggedType>(elements->GetData(), offset,
static_cast<JSTaggedType>(rawValue.GetInt()));
break;
case ElementsKind::NUMBER:
if (rawValue.IsInt()) {
int intValue = rawValue.GetInt();
Barriers::SetPrimitive<JSTaggedType>(elements->GetData(), offset,
base::bit_cast<JSTaggedType>(static_cast<double>(intValue)));
} else {
Barriers::SetPrimitive<JSTaggedType>(elements->GetData(), offset,
base::bit_cast<JSTaggedType>(rawValue.GetDouble()));
}
break;
case ElementsKind::TAGGED:
if (value.GetTaggedValue().IsHeapObject()) {
Barriers::SetObject<true>(thread, elements->GetData(), offset, rawValue.GetRawData());
} else { // NOLINTNEXTLINE(readability-misleading-indentation)
Barriers::SetPrimitive<JSTaggedType>(elements->GetData(), offset, rawValue.GetRawData());
}
break;
default:
LOG_ECMA(FATAL) << "Trying to Convert TaggedValue With Unknown ElementsKind";
UNREACHABLE();
break;
}
}
} // namespace panda::ecmascript
#endif // ECMASCRIPT_ELEMENT_ACCESSOR_INL_H

View File

@ -56,6 +56,15 @@ JSTaggedValue ElementAccessor::Get(JSObject *receiver, uint32_t idx)
return GetTaggedValueWithElementsKind(rawValue, kind);
}
JSTaggedValue ElementAccessor::FastGet(JSHandle<TaggedArray> elements, uint32_t idx, ElementsKind kind)
{
ASSERT(idx < elements->GetLength());
size_t offset = JSTaggedValue::TaggedTypeSize() * idx;
// NOLINTNEXTLINE(readability-braces-around-statements, bugprone-suspicious-semicolon)
JSTaggedType rawValue = Barriers::GetValue<JSTaggedType>(elements->GetData(), offset);
return GetTaggedValueWithElementsKind(rawValue, kind);
}
bool ElementAccessor::IsDictionaryMode(JSHandle<JSObject> receiver)
{
TaggedArray *elements = TaggedArray::Cast(receiver->GetElements());

View File

@ -27,11 +27,15 @@ class ElementAccessor {
public:
static JSTaggedValue PUBLIC_API Get(JSHandle<JSObject> receiver, uint32_t idx);
static JSTaggedValue Get(JSObject *receiver, uint32_t idx);
static JSTaggedValue PUBLIC_API FastGet(JSHandle<TaggedArray> elements, uint32_t idx, ElementsKind kind);
template<typename T>
static void Set(const JSThread *thread, JSHandle<JSObject> receiver, uint32_t idx, const JSHandle<T> &value,
bool needTransition, ElementsKind extraKind = ElementsKind::NONE);
template<typename T>
static void FastSet(const JSThread *thread, JSHandle<TaggedArray> elements, uint32_t idx,
const JSHandle<T> &value, ElementsKind kind);
static bool IsDictionaryMode(JSHandle<JSObject> receiver);
static bool IsDictionaryMode(JSObject *receiver);

View File

@ -1048,23 +1048,32 @@ JSTaggedValue JSStableArray::Reverse(JSThread *thread, JSHandle<JSObject> thisOb
if (thisObjHandle->IsJSArray()) {
JSArray::CheckAndCopyArray(thread, JSHandle<JSArray>::Cast(thisObjHandle));
}
JSMutableHandle<JSTaggedValue> lowerP(thread, JSTaggedValue::Undefined());
JSMutableHandle<JSTaggedValue> upperP(thread, JSTaggedValue::Undefined());
ElementsKind kind = thisObjHandle->GetClass()->GetElementsKind();
JSHandle<TaggedArray> elements(thread, thisObjHandle->GetElements());
if (kind == ElementsKind::INT || kind == ElementsKind::HOLE_INT) {
return FastReverse(thread, elements, lower, len, ElementsKind::INT);
} else if (kind == ElementsKind::NUMBER || kind == ElementsKind::HOLE_NUMBER) {
return FastReverse(thread, elements, lower, len, ElementsKind::NUMBER);
} else {
return FastReverse(thread, elements, lower, len, ElementsKind::TAGGED);
}
}
JSTaggedValue JSStableArray::FastReverse(JSThread *thread, JSHandle<TaggedArray> elements,
int64_t &lower, uint32_t len, ElementsKind kind)
{
JSMutableHandle<JSTaggedValue> lowerValueHandle(thread, JSTaggedValue::Undefined());
JSMutableHandle<JSTaggedValue> upperValueHandle(thread, JSTaggedValue::Undefined());
int64_t middle = std::floor(len / 2);
bool needTransition = true;
while (lower != middle) {
if (ElementAccessor::GetElementsLength(thisObjHandle) != len) {
if (elements->GetLength() != len) {
break;
}
int64_t upper = static_cast<int64_t>(len) - lower - 1;
lowerP.Update(JSTaggedValue(lower));
upperP.Update(JSTaggedValue(upper));
lowerValueHandle.Update(ElementAccessor::Get(thisObjHandle, lower));
upperValueHandle.Update(ElementAccessor::Get(thisObjHandle, upper));
ElementAccessor::Set(thread, thisObjHandle, lower, upperValueHandle, needTransition);
ElementAccessor::Set(thread, thisObjHandle, upper, lowerValueHandle, needTransition);
lowerValueHandle.Update(ElementAccessor::FastGet(elements, lower, kind));
upperValueHandle.Update(ElementAccessor::FastGet(elements, upper, kind));
ElementAccessor::FastSet(thread, elements, lower, upperValueHandle, kind);
ElementAccessor::FastSet(thread, elements, upper, lowerValueHandle, kind);
lower++;
}
return base::BuiltinsBase::GetTaggedDouble(true);

View File

@ -63,6 +63,8 @@ public:
EcmaRuntimeCallInfo *argv, uint32_t &k, uint32_t len);
static JSTaggedValue Reverse(JSThread *thread, JSHandle<JSObject> thisObjHandle,
int64_t &lower, uint32_t len);
static JSTaggedValue FastReverse(JSThread *thread, JSHandle<TaggedArray> elements,
int64_t &lower, uint32_t len, ElementsKind kind);
static JSTaggedValue Concat(JSThread *thread, JSHandle<JSObject> newArrayHandle,
JSHandle<JSObject> thisObjHandle, int64_t &k, int64_t &n);
template<base::TypedArrayKind typedArrayKind = base::TypedArrayKind::NON_SHARED>