Reason:optimize HasOwnProperty

Issue:https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I8EN7A?from=project-issue

Signed-off-by: wupengyong <wupengyong@huawei.com>
Change-Id: Ia4fa9925dd89605d69085afa476b8b34f16c5aac
This commit is contained in:
wupengyong 2023-11-13 14:31:55 +08:00
parent 35346c6782
commit bb41d2733f
9 changed files with 68 additions and 21 deletions

View File

@ -720,10 +720,12 @@ JSTaggedValue BuiltinsObject::HasOwnProperty(EcmaRuntimeCallInfo *argv)
JSHandle<JSTaggedValue> thisValue = GetThis(argv);
JSHandle<JSTaggedValue> prop = GetCallArg(argv, 0);
JSTaggedValue result = ObjectFastOperator::HasOwnProperty(thread, thisValue.GetTaggedValue(),
std::pair<JSTaggedValue, bool> result = ObjectFastOperator::HasOwnProperty(thread, thisValue.GetTaggedValue(),
prop.GetTaggedValue());
if (!result.IsHole()) {
if (!result.first.IsHole()) {
return GetTaggedBoolean(true);
} else if (result.second) {
return GetTaggedBoolean(false);
}
JSHandle<JSTaggedValue> property = JSTaggedValue::ToPropertyKey(thread, prop);

View File

@ -143,9 +143,9 @@ private:
return (GetMixLength() & STRING_COMPRESSED_BIT) == STRING_UNCOMPRESSED;
}
inline bool IsInteger() const
inline bool IsInteger()
{
return (GetMixHashcode() & IS_INTEGER_MASK) == IS_INTEGER_MASK;
return (GetHashcode() & IS_INTEGER_MASK) == IS_INTEGER_MASK;
}
// require is LineString

View File

@ -185,6 +185,11 @@ EcmaString *EcmaStringTable::GetOrInternString(EcmaString *string)
return strFlat;
}
EcmaString *EcmaStringTable::TryGetInternString(EcmaString *string)
{
return GetString(string);
}
EcmaString *EcmaStringTable::GetOrInternStringWithSpaceType(const uint8_t *utf8Data, uint32_t utf8Len,
bool canBeCompress, MemSpaceType type,
bool isConstantString, uint32_t idOffset)

View File

@ -43,6 +43,7 @@ public:
MemSpaceType type, bool isConstantString, uint32_t idOffset);
EcmaString *GetOrInternStringWithSpaceType(const uint16_t *utf16Data, uint32_t utf16Len, bool canBeCompress,
MemSpaceType type);
EcmaString *TryGetInternString(EcmaString *string);
void SweepWeakReference(const WeakRootVisitor &visitor);
bool CheckStringTableValidity();

View File

@ -948,6 +948,11 @@ public:
return GetObjectType() >= JSType::JS_API_ARRAY_LIST && GetObjectType() <= JSType::JS_API_QUEUE;
}
inline bool IsRegularObject() const
{
return GetObjectType() < JSType::JS_API_ARRAY_LIST;
}
inline bool IsJSAPIArrayList() const
{
return GetObjectType() == JSType::JS_API_ARRAY_LIST;

View File

@ -1311,6 +1311,11 @@ inline bool JSTaggedValue::IsSlowKeysObject() const
return IsJSGlobalObject() || IsJSProxy() || IsSpecialKeysObject();
}
inline bool JSTaggedValue::IsRegularObject() const
{
return IsHeapObject() && GetTaggedObject()->GetClass()->IsRegularObject();
}
inline bool JSTaggedValue::IsMachineCodeObject() const
{
return IsHeapObject() && GetTaggedObject()->GetClass()->IsMachineCodeObject();

View File

@ -680,6 +680,7 @@ public:
bool IsTrackInfoObject() const;
bool IsSpecialKeysObject() const;
bool IsSlowKeysObject() const;
bool IsRegularObject() const;
bool IsMachineCodeObject() const;
bool IsClassInfoExtractor() const;
bool IsTSType() const;

View File

@ -18,6 +18,7 @@
#include "ecmascript/object_fast_operator.h"
#include "ecmascript/ecma_string_table.h"
#include "ecmascript/js_api/js_api_arraylist.h"
#include "ecmascript/js_api/js_api_deque.h"
#include "ecmascript/js_api/js_api_linked_list.h"
@ -42,28 +43,56 @@ namespace panda::ecmascript {
return JSTaggedValue::Hole(); \
}
JSTaggedValue ObjectFastOperator::HasOwnProperty(JSThread *thread, JSTaggedValue receiver, JSTaggedValue key)
std::pair<JSTaggedValue, bool> ObjectFastOperator::HasOwnProperty(JSThread *thread, JSTaggedValue receiver, JSTaggedValue key)
{
[[maybe_unused]] DisallowGarbageCollection noGc;
if (!receiver.IsHeapObject() ||
!(receiver.GetTaggedObject()->GetClass()->GetObjectType() == JSType::JS_OBJECT)) {
return JSTaggedValue::Hole();
if (!receiver.IsHeapObject() || !(receiver.IsRegularObject())) {
return std::make_pair(JSTaggedValue::Hole(), false);
}
if (!key.IsString() || !EcmaStringAccessor(key).IsInternString()) {
return JSTaggedValue::Hole();
if (!key.IsString())
{
return std::make_pair(JSTaggedValue::Hole(), false);
}
uint32_t index = 0;
if (JSTaggedValue::ToElementIndex(key, &index)) {
ASSERT(index < JSObject::MAX_ELEMENT_INDEX);
TaggedArray *elements = TaggedArray::Cast(JSObject::Cast(receiver)->GetElements().GetTaggedObject());
if (elements->GetLength() == 0) {
return std::make_pair(JSTaggedValue::Hole(), true); // Empty Array
}
if (!elements->IsDictionaryMode()) {
if (elements->GetLength() <= index) {
return std::make_pair(JSTaggedValue::Hole(), true);
}
JSTaggedValue value = elements->Get(index);
return std::make_pair(value, true);
} else {
NumberDictionary *dictionary =
NumberDictionary::Cast(JSObject::Cast(receiver)->GetElements().GetTaggedObject());
int entry = dictionary->FindEntry(JSTaggedValue(static_cast<int>(index)));
if (entry == -1) {
return std::make_pair(JSTaggedValue::Hole(), true);
}
return std::make_pair(JSTaggedValue::Undefined(), true);
}
}
if (!EcmaStringAccessor(key).IsInternString()) {
EcmaString *str =
thread->GetEcmaVM()->GetEcmaStringTable()->TryGetInternString(EcmaString::Cast(key.GetTaggedObject()));
if (str == nullptr) {
return std::make_pair(JSTaggedValue::Hole(), true);
}
key = JSTaggedValue(str);
}
auto *hclass = receiver.GetTaggedObject()->GetClass();
if (LIKELY(!hclass->IsDictionaryMode())) {
ASSERT(!TaggedArray::Cast(JSObject::Cast(receiver)->GetProperties().GetTaggedObject())->IsDictionaryMode());
int entry = JSHClass::FindPropertyEntry(thread, hclass, key);
if (entry != -1) {
LayoutInfo *layoutInfo = LayoutInfo::Cast(hclass->GetLayout().GetTaggedObject());
PropertyAttributes attr(layoutInfo->GetAttr(entry));
ASSERT(static_cast<int>(attr.GetOffset()) == entry);
auto value = JSObject::Cast(receiver)->GetProperty(hclass, attr);
return value;
return std::make_pair(JSTaggedValue::Undefined(), true);
}
} else {
TaggedArray *array = TaggedArray::Cast(JSObject::Cast(receiver)->GetProperties().GetTaggedObject());
@ -71,12 +100,10 @@ JSTaggedValue ObjectFastOperator::HasOwnProperty(JSThread *thread, JSTaggedValue
NameDictionary *dict = NameDictionary::Cast(array);
int entry = dict->FindEntry(key);
if (entry != -1) {
auto value = dict->GetValue(entry);
return value;
return std::make_pair(JSTaggedValue::Undefined(), true);
}
}
// not found
return JSTaggedValue::Hole();
return std::make_pair(JSTaggedValue::Hole(), true);
}
template<bool UseOwn>

View File

@ -23,7 +23,8 @@
namespace panda::ecmascript {
class ObjectFastOperator final {
public:
static inline JSTaggedValue HasOwnProperty(JSThread *thread, JSTaggedValue receiver, JSTaggedValue key);
static inline std::pair<JSTaggedValue, bool> HasOwnProperty(JSThread *thread,
JSTaggedValue receiver, JSTaggedValue key);
template<bool UseOwn = false>
static inline JSTaggedValue GetPropertyByName(JSThread *thread, JSTaggedValue receiver, JSTaggedValue key);