mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-11-23 10:09:54 +00:00
ElementsKind Support JSArray as Proto
Issue: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/IAE3RU Signed-off-by: yaoyuan <yuanyao14@huawei.com> Change-Id: I4501de04972faa211d6f5822c951da8592b909d0
This commit is contained in:
parent
be50acd63d
commit
72a3e62801
@ -484,8 +484,8 @@ JSTaggedValue BuiltinsArkTools::GetElementsKind(EcmaRuntimeCallInfo *info)
|
|||||||
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
||||||
|
|
||||||
JSHandle<JSTaggedValue> obj = GetCallArg(info, 0);
|
JSHandle<JSTaggedValue> obj = GetCallArg(info, 0);
|
||||||
JSHandle<JSObject> receiver(thread, obj.GetTaggedValue());
|
JSHClass *hclass = obj->GetTaggedObject()->GetClass();
|
||||||
ElementsKind kind = receiver->GetClass()->GetElementsKind();
|
ElementsKind kind = hclass->GetElementsKind();
|
||||||
return JSTaggedValue(static_cast<uint32_t>(kind));
|
return JSTaggedValue(static_cast<uint32_t>(kind));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ JSHandle<GlobalEnv> AOTCompilationEnv::GetGlobalEnv() const
|
|||||||
return vm_->GetGlobalEnv();
|
return vm_->GetGlobalEnv();
|
||||||
}
|
}
|
||||||
|
|
||||||
const CMap<ElementsKind, ConstantIndex> &AOTCompilationEnv::GetArrayHClassIndexMap() const
|
const CMap<ElementsKind, std::pair<ConstantIndex, ConstantIndex>> &AOTCompilationEnv::GetArrayHClassIndexMap() const
|
||||||
{
|
{
|
||||||
return thread_->GetArrayHClassIndexMap();
|
return thread_->GetArrayHClassIndexMap();
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ public:
|
|||||||
JSRuntimeOptions &GetJSOptions() override;
|
JSRuntimeOptions &GetJSOptions() override;
|
||||||
|
|
||||||
// thread
|
// thread
|
||||||
const CMap<ElementsKind, ConstantIndex> &GetArrayHClassIndexMap() const override;
|
const CMap<ElementsKind, std::pair<ConstantIndex, ConstantIndex>> &GetArrayHClassIndexMap() const override;
|
||||||
const BuiltinHClassEntries &GetBuiltinHClassEntries() const override;
|
const BuiltinHClassEntries &GetBuiltinHClassEntries() const override;
|
||||||
JSHClass *GetBuiltinPrototypeHClass(BuiltinTypeId type) const override;
|
JSHClass *GetBuiltinPrototypeHClass(BuiltinTypeId type) const override;
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ public:
|
|||||||
virtual std::shared_ptr<pgo::PGOProfiler> GetPGOProfiler() const;
|
virtual std::shared_ptr<pgo::PGOProfiler> GetPGOProfiler() const;
|
||||||
|
|
||||||
// thread
|
// thread
|
||||||
virtual const CMap<ElementsKind, ConstantIndex> &GetArrayHClassIndexMap() const = 0;
|
virtual const CMap<ElementsKind, std::pair<ConstantIndex, ConstantIndex>> &GetArrayHClassIndexMap() const = 0;
|
||||||
virtual const BuiltinHClassEntries &GetBuiltinHClassEntries() const = 0;
|
virtual const BuiltinHClassEntries &GetBuiltinHClassEntries() const = 0;
|
||||||
virtual JSHClass *GetBuiltinPrototypeHClass(BuiltinTypeId type) const = 0;
|
virtual JSHClass *GetBuiltinPrototypeHClass(BuiltinTypeId type) const = 0;
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ JSRuntimeOptions &JitCompilationEnv::GetJSOptions()
|
|||||||
return hostThread_->GetEcmaVM()->GetJSOptions();
|
return hostThread_->GetEcmaVM()->GetJSOptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
const CMap<ElementsKind, ConstantIndex> &JitCompilationEnv::GetArrayHClassIndexMap() const
|
const CMap<ElementsKind, std::pair<ConstantIndex, ConstantIndex>> &JitCompilationEnv::GetArrayHClassIndexMap() const
|
||||||
{
|
{
|
||||||
return hostThread_->GetArrayHClassIndexMap();
|
return hostThread_->GetArrayHClassIndexMap();
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ public:
|
|||||||
}
|
}
|
||||||
JSRuntimeOptions &GetJSOptions() override;
|
JSRuntimeOptions &GetJSOptions() override;
|
||||||
// thread
|
// thread
|
||||||
const CMap<ElementsKind, ConstantIndex> &GetArrayHClassIndexMap() const override;
|
const CMap<ElementsKind, std::pair<ConstantIndex, ConstantIndex>> &GetArrayHClassIndexMap() const override;
|
||||||
const BuiltinHClassEntries &GetBuiltinHClassEntries() const override;
|
const BuiltinHClassEntries &GetBuiltinHClassEntries() const override;
|
||||||
JSHClass *GetBuiltinPrototypeHClass(BuiltinTypeId type) const override;
|
JSHClass *GetBuiltinPrototypeHClass(BuiltinTypeId type) const override;
|
||||||
void SetTsManagerCompilationEnv();
|
void SetTsManagerCompilationEnv();
|
||||||
|
@ -206,7 +206,8 @@ GateRef NTypeHCRLowering::NewJSArrayLiteral(GateRef glue, GateRef gate, GateRef
|
|||||||
ElementsKind kind = acc_.GetArrayMetaDataAccessor(gate).GetElementsKind();
|
ElementsKind kind = acc_.GetArrayMetaDataAccessor(gate).GetElementsKind();
|
||||||
GateRef hclass = Circuit::NullGate();
|
GateRef hclass = Circuit::NullGate();
|
||||||
if (!Elements::IsGeneric(kind)) {
|
if (!Elements::IsGeneric(kind)) {
|
||||||
auto hclassIndex = compilationEnv_->GetArrayHClassIndexMap().at(kind);
|
// At define point, we use initial array class without IsPrototype set.
|
||||||
|
auto hclassIndex = compilationEnv_->GetArrayHClassIndexMap().at(kind).first;
|
||||||
hclass = builder_.GetGlobalConstantValue(hclassIndex);
|
hclass = builder_.GetGlobalConstantValue(hclassIndex);
|
||||||
} else {
|
} else {
|
||||||
GateRef globalEnv = builder_.GetGlobalEnv();
|
GateRef globalEnv = builder_.GetGlobalEnv();
|
||||||
|
@ -109,7 +109,9 @@ bool ArrayParser::RecordTypeInfo(const PGODefineOpType &defType, const PGOTypeLo
|
|||||||
ptManager_->RecordLocationToElementsKind(loc, kind);
|
ptManager_->RecordLocationToElementsKind(loc, kind);
|
||||||
|
|
||||||
auto traceId = rootType.GetId();
|
auto traceId = rootType.GetId();
|
||||||
auto hclassIdx = ptManager_->GetJSThread()->GetArrayHClassIndexMap().at(kind);
|
// For PGO, we do not care whether an array isPrototype or not.
|
||||||
|
// This type is used at define point, we can use initial array hclass without IsPrototype bit set.
|
||||||
|
auto hclassIdx = ptManager_->GetJSThread()->GetArrayHClassIndexMap().at(kind).first;
|
||||||
ptManager_->RecordConstantIndex(traceId, static_cast<uint32_t>(hclassIdx));
|
ptManager_->RecordConstantIndex(traceId, static_cast<uint32_t>(hclassIdx));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1567,7 +1567,7 @@ void SlowPathLowering::LowerFastStrictEqual(GateRef gate)
|
|||||||
void SlowPathLowering::LowerCreateEmptyArray(GateRef gate)
|
void SlowPathLowering::LowerCreateEmptyArray(GateRef gate)
|
||||||
{
|
{
|
||||||
GateRef result = builder_.CallStub(glue_, gate, CommonStubCSigns::CreateEmptyArray, { glue_ });
|
GateRef result = builder_.CallStub(glue_, gate, CommonStubCSigns::CreateEmptyArray, { glue_ });
|
||||||
GateRef newRes = LowerUpdateArrayHClass(gate, result);
|
GateRef newRes = LowerUpdateArrayHClassAtDefine(gate, result);
|
||||||
ReplaceHirWithValue(gate, newRes, true);
|
ReplaceHirWithValue(gate, newRes, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1583,15 +1583,15 @@ void SlowPathLowering::LowerCreateArrayWithBuffer(GateRef gate)
|
|||||||
GateRef index = builder_.TruncInt64ToInt32(acc_.GetValueIn(gate, 0));
|
GateRef index = builder_.TruncInt64ToInt32(acc_.GetValueIn(gate, 0));
|
||||||
GateRef result = builder_.CallStub(glue_, gate, CommonStubCSigns::CreateArrayWithBuffer, { glue_, index, jsFunc });
|
GateRef result = builder_.CallStub(glue_, gate, CommonStubCSigns::CreateArrayWithBuffer, { glue_, index, jsFunc });
|
||||||
// when elementsKind switch on, we should not update arrayHClass here.
|
// when elementsKind switch on, we should not update arrayHClass here.
|
||||||
GateRef newRes = LowerUpdateArrayHClass(gate, result);
|
GateRef newRes = LowerUpdateArrayHClassAtDefine(gate, result);
|
||||||
ReplaceHirWithValue(gate, newRes, true);
|
ReplaceHirWithValue(gate, newRes, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
GateRef SlowPathLowering::LowerUpdateArrayHClass(GateRef gate, GateRef array)
|
GateRef SlowPathLowering::LowerUpdateArrayHClassAtDefine(GateRef gate, GateRef array)
|
||||||
{
|
{
|
||||||
ElementsKind kind = acc_.TryGetElementsKind(gate);
|
ElementsKind kind = acc_.TryGetElementsKind(gate);
|
||||||
if (!Elements::IsGeneric(kind)) {
|
if (!Elements::IsGeneric(kind)) {
|
||||||
size_t hclassIndex = static_cast<size_t>(compilationEnv_->GetArrayHClassIndexMap().at(kind));
|
size_t hclassIndex = static_cast<size_t>(compilationEnv_->GetArrayHClassIndexMap().at(kind).first);
|
||||||
GateRef gConstAddr = builder_.Load(VariableType::JS_POINTER(), glue_,
|
GateRef gConstAddr = builder_.Load(VariableType::JS_POINTER(), glue_,
|
||||||
builder_.IntPtr(JSThread::GlueData::GetGlobalConstOffset(false)));
|
builder_.IntPtr(JSThread::GlueData::GetGlobalConstOffset(false)));
|
||||||
GateRef constantIndex = builder_.IntPtr(JSTaggedValue::TaggedTypeSize() * hclassIndex);
|
GateRef constantIndex = builder_.IntPtr(JSTaggedValue::TaggedTypeSize() * hclassIndex);
|
||||||
|
@ -303,7 +303,7 @@ private:
|
|||||||
void LowerSetGeneratorState(GateRef gate);
|
void LowerSetGeneratorState(GateRef gate);
|
||||||
GateRef GetValueFromTaggedArray(GateRef arrayGate, GateRef indexOffset);
|
GateRef GetValueFromTaggedArray(GateRef arrayGate, GateRef indexOffset);
|
||||||
GateRef GetTaggedArrayFromValueIn(Environment *env, GateRef gate, size_t length);
|
GateRef GetTaggedArrayFromValueIn(Environment *env, GateRef gate, size_t length);
|
||||||
GateRef LowerUpdateArrayHClass(GateRef gate, GateRef array);
|
GateRef LowerUpdateArrayHClassAtDefine(GateRef gate, GateRef array);
|
||||||
void AddProfiling(GateRef gate, bool skipGenerator = true);
|
void AddProfiling(GateRef gate, bool skipGenerator = true);
|
||||||
GateRef FastStrictEqual(GateRef left, GateRef right);
|
GateRef FastStrictEqual(GateRef left, GateRef right);
|
||||||
void LowerWideLdPatchVar(GateRef gate);
|
void LowerWideLdPatchVar(GateRef gate);
|
||||||
|
@ -599,9 +599,12 @@ void TypedHCRLowering::BuiltinInstanceHClassCheck(Environment *env, GateRef gate
|
|||||||
auto arrayHClassIndexMap = compilationEnv_->GetArrayHClassIndexMap();
|
auto arrayHClassIndexMap = compilationEnv_->GetArrayHClassIndexMap();
|
||||||
auto iter = arrayHClassIndexMap.find(kind);
|
auto iter = arrayHClassIndexMap.find(kind);
|
||||||
ASSERT(iter != arrayHClassIndexMap.end());
|
ASSERT(iter != arrayHClassIndexMap.end());
|
||||||
GateRef initialIhcAddress = builder_.GetGlobalConstantValue(iter->second);
|
GateRef initialIhcAddress = builder_.GetGlobalConstantValue(iter->second.first);
|
||||||
|
GateRef initialIhcWithProtoAddress = builder_.GetGlobalConstantValue(iter->second.second);
|
||||||
GateRef receiverHClass = builder_.LoadHClassByConstOffset(receiver);
|
GateRef receiverHClass = builder_.LoadHClassByConstOffset(receiver);
|
||||||
ihcMatches = builder_.Equal(receiverHClass, initialIhcAddress);
|
GateRef tryIhcMatches = builder_.Equal(receiverHClass, initialIhcAddress);
|
||||||
|
GateRef tryIhcWithProtoMatches = builder_.Equal(receiverHClass, initialIhcWithProtoAddress);
|
||||||
|
ihcMatches = builder_.BoolOr(tryIhcMatches, tryIhcWithProtoMatches);
|
||||||
} else {
|
} else {
|
||||||
GateRef receiverHClass = builder_.LoadHClassByConstOffset(receiver);
|
GateRef receiverHClass = builder_.LoadHClassByConstOffset(receiver);
|
||||||
GateRef elementsKind = builder_.GetElementsKindByHClass(receiverHClass);
|
GateRef elementsKind = builder_.GetElementsKindByHClass(receiverHClass);
|
||||||
|
@ -20,21 +20,14 @@
|
|||||||
#include "ecmascript/tagged_array-inl.h"
|
#include "ecmascript/tagged_array-inl.h"
|
||||||
|
|
||||||
namespace panda::ecmascript {
|
namespace panda::ecmascript {
|
||||||
CMap<ElementsKind, ConstantIndex> Elements::InitializeHClassMap()
|
CMap<ElementsKind, std::pair<ConstantIndex, ConstantIndex>> Elements::InitializeHClassMap()
|
||||||
{
|
{
|
||||||
CMap<ElementsKind, ConstantIndex> result;
|
CMap<ElementsKind, std::pair<ConstantIndex, ConstantIndex>> result;
|
||||||
result.emplace(ElementsKind::NONE, ConstantIndex::ELEMENT_NONE_HCLASS_INDEX);
|
#define INIT_ARRAY_HCLASS_INDEX_MAPS(name) \
|
||||||
result.emplace(ElementsKind::HOLE, ConstantIndex::ELEMENT_HOLE_HCLASS_INDEX);
|
result.emplace(ElementsKind::name, std::make_pair(ConstantIndex::ELEMENT_##name##_HCLASS_INDEX, \
|
||||||
result.emplace(ElementsKind::INT, ConstantIndex::ELEMENT_INT_HCLASS_INDEX);
|
ConstantIndex::ELEMENT_##name##_PROTO_HCLASS_INDEX));
|
||||||
result.emplace(ElementsKind::NUMBER, ConstantIndex::ELEMENT_NUMBER_HCLASS_INDEX);
|
ELEMENTS_KIND_INIT_HCLASS_LIST(INIT_ARRAY_HCLASS_INDEX_MAPS)
|
||||||
result.emplace(ElementsKind::STRING, ConstantIndex::ELEMENT_STRING_HCLASS_INDEX);
|
#undef INIT_ARRAY_HCLASS_INDEX_MAPS
|
||||||
result.emplace(ElementsKind::OBJECT, ConstantIndex::ELEMENT_OBJECT_HCLASS_INDEX);
|
|
||||||
result.emplace(ElementsKind::TAGGED, ConstantIndex::ELEMENT_TAGGED_HCLASS_INDEX);
|
|
||||||
result.emplace(ElementsKind::HOLE_INT, ConstantIndex::ELEMENT_HOLE_INT_HCLASS_INDEX);
|
|
||||||
result.emplace(ElementsKind::HOLE_NUMBER, ConstantIndex::ELEMENT_HOLE_NUMBER_HCLASS_INDEX);
|
|
||||||
result.emplace(ElementsKind::HOLE_STRING, ConstantIndex::ELEMENT_HOLE_STRING_HCLASS_INDEX);
|
|
||||||
result.emplace(ElementsKind::HOLE_OBJECT, ConstantIndex::ELEMENT_HOLE_OBJECT_HCLASS_INDEX);
|
|
||||||
result.emplace(ElementsKind::HOLE_TAGGED, ConstantIndex::ELEMENT_HOLE_TAGGED_HCLASS_INDEX);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +21,21 @@
|
|||||||
#include "ecmascript/mem/c_containers.h"
|
#include "ecmascript/mem/c_containers.h"
|
||||||
|
|
||||||
namespace panda::ecmascript {
|
namespace panda::ecmascript {
|
||||||
|
|
||||||
|
#define ELEMENTS_KIND_INIT_HCLASS_LIST(V) \
|
||||||
|
V(NONE) \
|
||||||
|
V(HOLE) \
|
||||||
|
V(INT) \
|
||||||
|
V(NUMBER) \
|
||||||
|
V(STRING) \
|
||||||
|
V(OBJECT) \
|
||||||
|
V(TAGGED) \
|
||||||
|
V(HOLE_INT) \
|
||||||
|
V(HOLE_NUMBER) \
|
||||||
|
V(HOLE_STRING) \
|
||||||
|
V(HOLE_OBJECT) \
|
||||||
|
V(HOLE_TAGGED)
|
||||||
|
|
||||||
enum class ElementsKind : uint8_t {
|
enum class ElementsKind : uint8_t {
|
||||||
NONE = 0x00UL,
|
NONE = 0x00UL,
|
||||||
HOLE = 0x01UL,
|
HOLE = 0x01UL,
|
||||||
@ -40,7 +55,7 @@ enum class ElementsKind : uint8_t {
|
|||||||
|
|
||||||
class PUBLIC_API Elements {
|
class PUBLIC_API Elements {
|
||||||
public:
|
public:
|
||||||
static CMap<ElementsKind, ConstantIndex> InitializeHClassMap();
|
static CMap<ElementsKind, std::pair<ConstantIndex, ConstantIndex>> InitializeHClassMap();
|
||||||
|
|
||||||
static std::string GetString(ElementsKind kind);
|
static std::string GetString(ElementsKind kind);
|
||||||
static bool IsInt(ElementsKind kind);
|
static bool IsInt(ElementsKind kind);
|
||||||
|
@ -419,12 +419,14 @@ void GlobalEnvConstants::InitElementKindHClass(const JSThread *thread, JSHandle<
|
|||||||
{
|
{
|
||||||
auto map = thread->GetArrayHClassIndexMap();
|
auto map = thread->GetArrayHClassIndexMap();
|
||||||
for (auto iter : map) {
|
for (auto iter : map) {
|
||||||
JSHandle<JSHClass> hclass = originHClass;
|
JSHandle<JSHClass> hclassWithProto = JSHClass::CloneWithElementsKind(thread, originHClass, iter.first, true);
|
||||||
if (iter.first != ElementsKind::GENERIC) {
|
if (iter.first != ElementsKind::GENERIC) {
|
||||||
hclass = JSHClass::Clone(thread, originHClass);
|
JSHandle<JSHClass> hclass = JSHClass::CloneWithElementsKind(thread, originHClass, iter.first, false);
|
||||||
hclass->SetElementsKind(iter.first);
|
SetConstant(iter.second.first, hclass);
|
||||||
|
} else {
|
||||||
|
SetConstant(iter.second.first, originHClass);
|
||||||
}
|
}
|
||||||
SetConstant(iter.second, hclass);
|
SetConstant(iter.second.second, hclassWithProto);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // namespace panda::ecmascript
|
} // namespace panda::ecmascript
|
||||||
|
@ -134,6 +134,18 @@ class ObjectFactory;
|
|||||||
V(JSTaggedValue, IteratorResultClass, ITERATOR_RESULT_CLASS, ecma_roots_class) \
|
V(JSTaggedValue, IteratorResultClass, ITERATOR_RESULT_CLASS, ecma_roots_class) \
|
||||||
V(JSTaggedValue, ClassPrototypeClass, CLASS_PROTOTYPE_HCLASS_INDEX, ecma_roots_class) \
|
V(JSTaggedValue, ClassPrototypeClass, CLASS_PROTOTYPE_HCLASS_INDEX, ecma_roots_class) \
|
||||||
V(JSTaggedValue, ClassConstructorClass, CLASS_CONSTRUCTOR_HCLASS_INDEX, ecma_roots_class) \
|
V(JSTaggedValue, ClassConstructorClass, CLASS_CONSTRUCTOR_HCLASS_INDEX, ecma_roots_class) \
|
||||||
|
V(JSTaggedValue, ElementNoneProtoClass, ELEMENT_NONE_PROTO_HCLASS_INDEX, ecma_roots_class) \
|
||||||
|
V(JSTaggedValue, ElementHoleProtoClass, ELEMENT_HOLE_PROTO_HCLASS_INDEX, ecma_roots_class) \
|
||||||
|
V(JSTaggedValue, ElementIntProtoClass, ELEMENT_INT_PROTO_HCLASS_INDEX, ecma_roots_class) \
|
||||||
|
V(JSTaggedValue, ElementNumberProtoClass, ELEMENT_NUMBER_PROTO_HCLASS_INDEX, ecma_roots_class) \
|
||||||
|
V(JSTaggedValue, ElementStringProtoClass, ELEMENT_STRING_PROTO_HCLASS_INDEX, ecma_roots_class) \
|
||||||
|
V(JSTaggedValue, ElementObjectProtoClass, ELEMENT_OBJECT_PROTO_HCLASS_INDEX, ecma_roots_class) \
|
||||||
|
V(JSTaggedValue, ElementTaggedProtoClass, ELEMENT_TAGGED_PROTO_HCLASS_INDEX, ecma_roots_class) \
|
||||||
|
V(JSTaggedValue, ElementHoleIntProtoClass, ELEMENT_HOLE_INT_PROTO_HCLASS_INDEX, ecma_roots_class) \
|
||||||
|
V(JSTaggedValue, ElementHoleNumberProtoClass, ELEMENT_HOLE_NUMBER_PROTO_HCLASS_INDEX, ecma_roots_class) \
|
||||||
|
V(JSTaggedValue, ElementHoleStringProtoClass, ELEMENT_HOLE_STRING_PROTO_HCLASS_INDEX, ecma_roots_class) \
|
||||||
|
V(JSTaggedValue, ElementHoleObjectProtoClass, ELEMENT_HOLE_OBJECT_PROTO_HCLASS_INDEX, ecma_roots_class) \
|
||||||
|
V(JSTaggedValue, ElementHoleTaggedProtoClass, ELEMENT_HOLE_TAGGED_PROTO_HCLASS_INDEX, ecma_roots_class) \
|
||||||
V(JSTaggedValue, ElementNoneClass, ELEMENT_NONE_HCLASS_INDEX, ecma_roots_class) \
|
V(JSTaggedValue, ElementNoneClass, ELEMENT_NONE_HCLASS_INDEX, ecma_roots_class) \
|
||||||
V(JSTaggedValue, ElementHoleClass, ELEMENT_HOLE_HCLASS_INDEX, ecma_roots_class) \
|
V(JSTaggedValue, ElementHoleClass, ELEMENT_HOLE_HCLASS_INDEX, ecma_roots_class) \
|
||||||
V(JSTaggedValue, ElementIntClass, ELEMENT_INT_HCLASS_INDEX, ecma_roots_class) \
|
V(JSTaggedValue, ElementIntClass, ELEMENT_INT_HCLASS_INDEX, ecma_roots_class) \
|
||||||
|
@ -985,7 +985,8 @@ bool JITProfiler::AddBuiltinsInfoByNameInInstance(ApEntityId abcId, int32_t bcOf
|
|||||||
}
|
}
|
||||||
JSHClass *exceptRecvHClass = nullptr;
|
JSHClass *exceptRecvHClass = nullptr;
|
||||||
if (builtinsId == BuiltinTypeId::ARRAY) {
|
if (builtinsId == BuiltinTypeId::ARRAY) {
|
||||||
exceptRecvHClass = thread->GetArrayInstanceHClass(receiver->GetElementsKind());
|
bool receiverIsPrototype = receiver->IsPrototype();
|
||||||
|
exceptRecvHClass = thread->GetArrayInstanceHClass(receiver->GetElementsKind(), receiverIsPrototype);
|
||||||
} else if (builtinsId == BuiltinTypeId::STRING) {
|
} else if (builtinsId == BuiltinTypeId::STRING) {
|
||||||
exceptRecvHClass = receiver;
|
exceptRecvHClass = receiver;
|
||||||
} else {
|
} else {
|
||||||
@ -1021,7 +1022,8 @@ bool JITProfiler::AddBuiltinsInfoByNameInProt(ApEntityId abcId, int32_t bcOffset
|
|||||||
auto thread = vm_->GetJSThread();
|
auto thread = vm_->GetJSThread();
|
||||||
JSHClass *exceptRecvHClass = nullptr;
|
JSHClass *exceptRecvHClass = nullptr;
|
||||||
if (builtinsId == BuiltinTypeId::ARRAY) {
|
if (builtinsId == BuiltinTypeId::ARRAY) {
|
||||||
exceptRecvHClass = thread->GetArrayInstanceHClass(receiver->GetElementsKind());
|
bool receiverIsPrototype = receiver->IsPrototype();
|
||||||
|
exceptRecvHClass = thread->GetArrayInstanceHClass(receiver->GetElementsKind(), receiverIsPrototype);
|
||||||
} else if (builtinsId == BuiltinTypeId::STRING) {
|
} else if (builtinsId == BuiltinTypeId::STRING) {
|
||||||
exceptRecvHClass = receiver;
|
exceptRecvHClass = receiver;
|
||||||
} else {
|
} else {
|
||||||
|
@ -30,6 +30,22 @@ inline JSHClass *JSHClass::Cast(const TaggedObject *object)
|
|||||||
return static_cast<JSHClass *>(const_cast<TaggedObject *>(object));
|
return static_cast<JSHClass *>(const_cast<TaggedObject *>(object));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool JSHClass::ProtoIsFastJSArray(const JSThread *thread, const JSHandle<JSTaggedValue> proto,
|
||||||
|
const JSHandle<JSHClass> hclass)
|
||||||
|
{
|
||||||
|
// Since we currently only support ElementsKind for JSArray initial hclass,
|
||||||
|
// if an object's hclass has a non-generic ElementsKind, it must be one of the JSArray initial hclass.
|
||||||
|
// if an object's hclass has a Generic ElementsKind, it might be the JSArray initial generic elementskind hclass,
|
||||||
|
// which therefore needs further hclass comparison.
|
||||||
|
if (proto->IsJSArray()) {
|
||||||
|
JSTaggedValue genericArrayHClass = thread->GlobalConstants()->GetElementHoleTaggedClass();
|
||||||
|
if (!Elements::IsGeneric(hclass->GetElementsKind()) || hclass.GetTaggedValue() == genericArrayHClass) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void JSHClass::AddTransitions(const JSThread *thread, const JSHandle<JSHClass> &parent, const JSHandle<JSHClass> &child,
|
void JSHClass::AddTransitions(const JSThread *thread, const JSHandle<JSHClass> &parent, const JSHandle<JSHClass> &child,
|
||||||
const JSHandle<JSTaggedValue> &key, PropertyAttributes attributes)
|
const JSHandle<JSTaggedValue> &key, PropertyAttributes attributes)
|
||||||
{
|
{
|
||||||
|
@ -267,6 +267,15 @@ JSHandle<JSHClass> JSHClass::Clone(const JSThread *thread, const JSHandle<JSHCla
|
|||||||
return newJsHClass;
|
return newJsHClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JSHandle<JSHClass> JSHClass::CloneWithElementsKind(const JSThread *thread, const JSHandle<JSHClass> &jshclass,
|
||||||
|
const ElementsKind kind, bool isPrototype)
|
||||||
|
{
|
||||||
|
JSHandle<JSHClass> newHClass = Clone(thread, jshclass);
|
||||||
|
newHClass->SetIsPrototype(isPrototype);
|
||||||
|
newHClass->SetElementsKind(kind);
|
||||||
|
return newHClass;
|
||||||
|
}
|
||||||
|
|
||||||
// use for transition to dictionary
|
// use for transition to dictionary
|
||||||
JSHandle<JSHClass> JSHClass::CloneWithoutInlinedProperties(const JSThread *thread, const JSHandle<JSHClass> &jshclass)
|
JSHandle<JSHClass> JSHClass::CloneWithoutInlinedProperties(const JSThread *thread, const JSHandle<JSHClass> &jshclass)
|
||||||
{
|
{
|
||||||
@ -530,7 +539,16 @@ void JSHClass::OptimizePrototypeForIC(const JSThread *thread, const JSHandle<JST
|
|||||||
// o1 becomes a prototype object of object o2 and an on-proto IC loading x from o2 will rely on the
|
// o1 becomes a prototype object of object o2 and an on-proto IC loading x from o2 will rely on the
|
||||||
// stability of the prototype-chain o2 -> o1. If directly marking the o1.hclass1 as a prototype hclass,
|
// stability of the prototype-chain o2 -> o1. If directly marking the o1.hclass1 as a prototype hclass,
|
||||||
// the previous IC of adding property x won't trigger IC-miss and fails to notify the IC on o2.
|
// the previous IC of adding property x won't trigger IC-miss and fails to notify the IC on o2.
|
||||||
JSHandle<JSHClass> newProtoClass = JSHClass::Clone(thread, hclass);
|
|
||||||
|
// At here, When a JSArray with initial hclass is set as a proto,
|
||||||
|
// we substitute its hclass with preserved proto hclass.
|
||||||
|
JSHandle<JSHClass> newProtoClass;
|
||||||
|
if (ProtoIsFastJSArray(thread, proto, hclass)) {
|
||||||
|
newProtoClass = JSHandle<JSHClass>(thread, thread->GetArrayInstanceHClass(hclass->GetElementsKind(),
|
||||||
|
true));
|
||||||
|
} else {
|
||||||
|
newProtoClass = JSHClass::Clone(thread, hclass);
|
||||||
|
}
|
||||||
JSTaggedValue layout = newProtoClass->GetLayout();
|
JSTaggedValue layout = newProtoClass->GetLayout();
|
||||||
// If the type of object is JSObject, the layout info value is initialized to the default value,
|
// If the type of object is JSObject, the layout info value is initialized to the default value,
|
||||||
// if the value is not JSObject, the layout info value is initialized to null.
|
// if the value is not JSObject, the layout info value is initialized to null.
|
||||||
@ -551,9 +569,6 @@ void JSHClass::OptimizePrototypeForIC(const JSThread *thread, const JSHandle<JST
|
|||||||
if (!isChangeProto) {
|
if (!isChangeProto) {
|
||||||
thread->GetEcmaVM()->GetPGOProfiler()->UpdateRootProfileTypeSafe(*hclass, *newProtoClass);
|
thread->GetEcmaVM()->GetPGOProfiler()->UpdateRootProfileTypeSafe(*hclass, *newProtoClass);
|
||||||
}
|
}
|
||||||
if (proto->IsJSObject()) {
|
|
||||||
TryRestoreElementsKind(thread, newProtoClass, JSHandle<JSObject>::Cast(proto));
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// There is no sharing in AOT hclass. Therefore, it is not necessary or possible to clone here.
|
// There is no sharing in AOT hclass. Therefore, it is not necessary or possible to clone here.
|
||||||
hclass->SetIsPrototype(true);
|
hclass->SetIsPrototype(true);
|
||||||
@ -659,17 +674,21 @@ void JSHClass::TransitionForRepChange(const JSThread *thread, const JSHandle<JSO
|
|||||||
// 4. Maybe Transition And Maintain subtypeing check
|
// 4. Maybe Transition And Maintain subtypeing check
|
||||||
}
|
}
|
||||||
|
|
||||||
JSHClass* JSHClass::GetInitialArrayHClassWithElementsKind(const JSThread *thread, const ElementsKind kind)
|
bool JSHClass::IsInitialArrayHClassWithElementsKind(const JSThread *thread, const JSHClass *targetHClass,
|
||||||
|
const ElementsKind targetKind)
|
||||||
{
|
{
|
||||||
const auto &arrayHClassIndexMap = thread->GetArrayHClassIndexMap();
|
const auto &arrayHClassIndexMap = thread->GetArrayHClassIndexMap();
|
||||||
auto newKindIter = arrayHClassIndexMap.find(kind);
|
auto newKindIter = arrayHClassIndexMap.find(targetKind);
|
||||||
if (newKindIter != arrayHClassIndexMap.end()) {
|
if (newKindIter != arrayHClassIndexMap.end()) {
|
||||||
auto index = static_cast<size_t>(newKindIter->second);
|
auto indexPair = newKindIter->second;
|
||||||
auto hclassVal = thread->GlobalConstants()->GetGlobalConstantObject(index);
|
auto hclassVal = thread->GlobalConstants()->GetGlobalConstantObject(static_cast<size_t>(indexPair.first));
|
||||||
|
auto hclassWithProtoVal = thread->GlobalConstants()->
|
||||||
|
GetGlobalConstantObject(static_cast<size_t>(indexPair.second));
|
||||||
JSHClass *hclass = JSHClass::Cast(hclassVal.GetTaggedObject());
|
JSHClass *hclass = JSHClass::Cast(hclassVal.GetTaggedObject());
|
||||||
return hclass;
|
JSHClass *hclassWithProto = JSHClass::Cast(hclassWithProtoVal.GetTaggedObject());
|
||||||
|
return (targetHClass == hclass || targetHClass == hclassWithProto);
|
||||||
}
|
}
|
||||||
return nullptr;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool JSHClass::TransitToElementsKindUncheck(const JSThread *thread, const JSHandle<JSObject> &obj,
|
bool JSHClass::TransitToElementsKindUncheck(const JSThread *thread, const JSHandle<JSObject> &obj,
|
||||||
@ -677,16 +696,21 @@ bool JSHClass::TransitToElementsKindUncheck(const JSThread *thread, const JSHand
|
|||||||
{
|
{
|
||||||
ElementsKind current = obj->GetJSHClass()->GetElementsKind();
|
ElementsKind current = obj->GetJSHClass()->GetElementsKind();
|
||||||
// currently we only support initial array hclass
|
// currently we only support initial array hclass
|
||||||
if (obj->GetClass() == GetInitialArrayHClassWithElementsKind(thread, current)) {
|
JSHClass *objHclass = obj->GetClass();
|
||||||
|
if (IsInitialArrayHClassWithElementsKind(thread, objHclass, current)) {
|
||||||
const auto &arrayHClassIndexMap = thread->GetArrayHClassIndexMap();
|
const auto &arrayHClassIndexMap = thread->GetArrayHClassIndexMap();
|
||||||
auto newKindIter = arrayHClassIndexMap.find(newKind);
|
auto newKindIter = arrayHClassIndexMap.find(newKind);
|
||||||
|
bool objHclassIsPrototype = objHclass->IsPrototype();
|
||||||
if (newKindIter != arrayHClassIndexMap.end()) {
|
if (newKindIter != arrayHClassIndexMap.end()) {
|
||||||
auto index = static_cast<size_t>(newKindIter->second);
|
auto indexPair = newKindIter->second;
|
||||||
|
auto index = objHclassIsPrototype ? static_cast<size_t>(indexPair.second) :
|
||||||
|
static_cast<size_t>(indexPair.first);
|
||||||
auto hclassVal = thread->GlobalConstants()->GetGlobalConstantObject(index);
|
auto hclassVal = thread->GlobalConstants()->GetGlobalConstantObject(index);
|
||||||
JSHClass *hclass = JSHClass::Cast(hclassVal.GetTaggedObject());
|
JSHClass *hclass = JSHClass::Cast(hclassVal.GetTaggedObject());
|
||||||
obj->SynchronizedSetClass(thread, hclass);
|
obj->SynchronizedSetClass(thread, hclass);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
LOG_ECMA(FATAL) << "Unknown newKind: " << static_cast<int32_t>(newKind);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -703,16 +727,9 @@ void JSHClass::TransitToElementsKind(const JSThread *thread, const JSHandle<JSAr
|
|||||||
if (newKind == current) {
|
if (newKind == current) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Currently, we only support fast array elementsKind
|
|
||||||
ASSERT(array->GetClass() == GetInitialArrayHClassWithElementsKind(thread, current));
|
ASSERT(IsInitialArrayHClassWithElementsKind(thread, array->GetJSHClass(), current));
|
||||||
const auto &arrayHClassIndexMap = thread->GetArrayHClassIndexMap();
|
TransitToElementsKindUncheck(thread, JSHandle<JSObject>(array), newKind);
|
||||||
auto newKindIter = arrayHClassIndexMap.find(newKind);
|
|
||||||
if (newKindIter != arrayHClassIndexMap.end()) {
|
|
||||||
auto index = static_cast<size_t>(newKindIter->second);
|
|
||||||
auto hclassVal = thread->GlobalConstants()->GetGlobalConstantObject(index);
|
|
||||||
JSHClass *hclass = JSHClass::Cast(hclassVal.GetTaggedObject());
|
|
||||||
array->SynchronizedSetClass(thread, hclass);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool JSHClass::TransitToElementsKind(const JSThread *thread, const JSHandle<JSObject> &object,
|
bool JSHClass::TransitToElementsKind(const JSThread *thread, const JSHandle<JSObject> &object,
|
||||||
@ -732,27 +749,21 @@ bool JSHClass::TransitToElementsKind(const JSThread *thread, const JSHandle<JSOb
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Currently, we only support fast array elementsKind
|
// Currently, we only support fast array elementsKind
|
||||||
ASSERT(object->GetClass() == GetInitialArrayHClassWithElementsKind(thread, current));
|
ASSERT(IsInitialArrayHClassWithElementsKind(thread, object->GetJSHClass(), current));
|
||||||
const auto &arrayHClassIndexMap = thread->GetArrayHClassIndexMap();
|
if (!TransitToElementsKindUncheck(thread, object, newKind)) {
|
||||||
auto newKindIter = arrayHClassIndexMap.find(newKind);
|
return false;
|
||||||
if (newKindIter != arrayHClassIndexMap.end()) {
|
}
|
||||||
auto index = static_cast<size_t>(newKindIter->second);
|
|
||||||
auto hclassVal = thread->GlobalConstants()->GetGlobalConstantObject(index);
|
|
||||||
JSHClass *hclass = JSHClass::Cast(hclassVal.GetTaggedObject());
|
|
||||||
object->SynchronizedSetClass(thread, hclass);
|
|
||||||
|
|
||||||
if (!thread->GetEcmaVM()->IsEnableElementsKind()) {
|
if (!thread->GetEcmaVM()->IsEnableElementsKind()) {
|
||||||
// Update TrackInfo
|
// Update TrackInfo
|
||||||
if (!thread->IsPGOProfilerEnable()) {
|
if (!thread->IsPGOProfilerEnable()) {
|
||||||
return true;
|
|
||||||
}
|
|
||||||
auto trackInfoVal = JSHandle<JSArray>(object)->GetTrackInfo();
|
|
||||||
thread->GetEcmaVM()->GetPGOProfiler()->UpdateTrackElementsKind(trackInfoVal, newKind);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
auto trackInfoVal = JSHandle<JSArray>(object)->GetTrackInfo();
|
||||||
|
thread->GetEcmaVM()->GetPGOProfiler()->UpdateTrackElementsKind(trackInfoVal, newKind);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
TransitionResult JSHClass::ConvertOrTransitionWithRep(const JSThread *thread,
|
TransitionResult JSHClass::ConvertOrTransitionWithRep(const JSThread *thread,
|
||||||
|
@ -427,6 +427,8 @@ public:
|
|||||||
static JSHandle<JSHClass> Clone(const JSThread *thread, const JSHandle<JSHClass> &jshclass,
|
static JSHandle<JSHClass> Clone(const JSThread *thread, const JSHandle<JSHClass> &jshclass,
|
||||||
bool withoutInlinedProperties = false, uint32_t incInlinedProperties = 0);
|
bool withoutInlinedProperties = false, uint32_t incInlinedProperties = 0);
|
||||||
static JSHandle<JSHClass> CloneWithoutInlinedProperties(const JSThread *thread, const JSHandle<JSHClass> &jshclass);
|
static JSHandle<JSHClass> CloneWithoutInlinedProperties(const JSThread *thread, const JSHandle<JSHClass> &jshclass);
|
||||||
|
static JSHandle<JSHClass> CloneWithElementsKind(const JSThread *thread, const JSHandle<JSHClass> &jshclass,
|
||||||
|
const ElementsKind kind, bool isPrototype);
|
||||||
|
|
||||||
static void TransitionElementsToDictionary(const JSThread *thread, const JSHandle<JSObject> &obj);
|
static void TransitionElementsToDictionary(const JSThread *thread, const JSHandle<JSObject> &obj);
|
||||||
static void OptimizeAsFastElements(const JSThread *thread, JSHandle<JSObject> obj);
|
static void OptimizeAsFastElements(const JSThread *thread, JSHandle<JSObject> obj);
|
||||||
@ -463,7 +465,8 @@ public:
|
|||||||
const JSHandle<JSTaggedValue> &key, PropertyAttributes attr);
|
const JSHandle<JSTaggedValue> &key, PropertyAttributes attr);
|
||||||
static void TransitionForElementsKindChange(const JSThread *thread, const JSHandle<JSObject> &receiver,
|
static void TransitionForElementsKindChange(const JSThread *thread, const JSHandle<JSObject> &receiver,
|
||||||
const ElementsKind newKind);
|
const ElementsKind newKind);
|
||||||
static JSHClass* GetInitialArrayHClassWithElementsKind(const JSThread *thread, const ElementsKind kind);
|
static bool IsInitialArrayHClassWithElementsKind(const JSThread *thread, const JSHClass *targetHClass,
|
||||||
|
const ElementsKind targetKind);
|
||||||
static bool PUBLIC_API TransitToElementsKindUncheck(const JSThread *thread, const JSHandle<JSObject> &obj,
|
static bool PUBLIC_API TransitToElementsKindUncheck(const JSThread *thread, const JSHandle<JSObject> &obj,
|
||||||
ElementsKind newKind);
|
ElementsKind newKind);
|
||||||
static void PUBLIC_API TransitToElementsKind(const JSThread *thread, const JSHandle<JSArray> &array,
|
static void PUBLIC_API TransitToElementsKind(const JSThread *thread, const JSHandle<JSArray> &array,
|
||||||
@ -2040,6 +2043,10 @@ public:
|
|||||||
static JSHandle<JSHClass> CreateSPrototypeHClass(JSThread *thread, const std::vector<PropertyDescriptor> &descs);
|
static JSHandle<JSHClass> CreateSPrototypeHClass(JSThread *thread, const std::vector<PropertyDescriptor> &descs);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
static inline bool ProtoIsFastJSArray(const JSThread *thread, const JSHandle<JSTaggedValue> proto,
|
||||||
|
const JSHandle<JSHClass> hclass);
|
||||||
|
|
||||||
static void CreateSInlinedLayout(JSThread *thread,
|
static void CreateSInlinedLayout(JSThread *thread,
|
||||||
const std::vector<PropertyDescriptor> &descs,
|
const std::vector<PropertyDescriptor> &descs,
|
||||||
const JSHandle<JSHClass> &hclass,
|
const JSHandle<JSHClass> &hclass,
|
||||||
|
@ -619,11 +619,11 @@ JSHClass *JSThread::GetBuiltinExtraHClass(BuiltinTypeId type) const
|
|||||||
return glueData_.builtinHClassEntries_.entries[index].extraHClass;
|
return glueData_.builtinHClassEntries_.entries[index].extraHClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSHClass *JSThread::GetArrayInstanceHClass(ElementsKind kind) const
|
JSHClass *JSThread::GetArrayInstanceHClass(ElementsKind kind, bool isPrototype) const
|
||||||
{
|
{
|
||||||
auto iter = GetArrayHClassIndexMap().find(kind);
|
auto iter = GetArrayHClassIndexMap().find(kind);
|
||||||
ASSERT(iter != GetArrayHClassIndexMap().end());
|
ASSERT(iter != GetArrayHClassIndexMap().end());
|
||||||
auto index = static_cast<size_t>(iter->second);
|
auto index = isPrototype ? static_cast<size_t>(iter->second.second) : static_cast<size_t>(iter->second.first);
|
||||||
auto exceptArrayHClass = GlobalConstants()->GetGlobalConstantObject(index);
|
auto exceptArrayHClass = GlobalConstants()->GetGlobalConstantObject(index);
|
||||||
auto exceptRecvHClass = JSHClass::Cast(exceptArrayHClass.GetTaggedObject());
|
auto exceptRecvHClass = JSHClass::Cast(exceptArrayHClass.GetTaggedObject());
|
||||||
ASSERT(exceptRecvHClass->IsJSArray());
|
ASSERT(exceptRecvHClass->IsJSArray());
|
||||||
|
@ -316,7 +316,7 @@ public:
|
|||||||
return &glueData_.builtinEntries_;
|
return &glueData_.builtinEntries_;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CMap<ElementsKind, ConstantIndex> &GetArrayHClassIndexMap() const
|
const CMap<ElementsKind, std::pair<ConstantIndex, ConstantIndex>> &GetArrayHClassIndexMap() const
|
||||||
{
|
{
|
||||||
return arrayHClassIndexMap_;
|
return arrayHClassIndexMap_;
|
||||||
}
|
}
|
||||||
@ -346,7 +346,7 @@ public:
|
|||||||
|
|
||||||
JSHClass *GetBuiltinInstanceHClass(BuiltinTypeId type) const;
|
JSHClass *GetBuiltinInstanceHClass(BuiltinTypeId type) const;
|
||||||
JSHClass *GetBuiltinExtraHClass(BuiltinTypeId type) const;
|
JSHClass *GetBuiltinExtraHClass(BuiltinTypeId type) const;
|
||||||
JSHClass *GetArrayInstanceHClass(ElementsKind kind) const;
|
JSHClass *GetArrayInstanceHClass(ElementsKind kind, bool isPrototype) const;
|
||||||
|
|
||||||
PUBLIC_API JSHClass *GetBuiltinPrototypeHClass(BuiltinTypeId type) const;
|
PUBLIC_API JSHClass *GetBuiltinPrototypeHClass(BuiltinTypeId type) const;
|
||||||
PUBLIC_API JSHClass *GetBuiltinPrototypeOfPrototypeHClass(BuiltinTypeId type) const;
|
PUBLIC_API JSHClass *GetBuiltinPrototypeOfPrototypeHClass(BuiltinTypeId type) const;
|
||||||
@ -1522,7 +1522,7 @@ private:
|
|||||||
glueData_.currentContext_ = context;
|
glueData_.currentContext_ = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetArrayHClassIndexMap(const CMap<ElementsKind, ConstantIndex> &map)
|
void SetArrayHClassIndexMap(const CMap<ElementsKind, std::pair<ConstantIndex, ConstantIndex>> &map)
|
||||||
{
|
{
|
||||||
arrayHClassIndexMap_ = map;
|
arrayHClassIndexMap_ = map;
|
||||||
}
|
}
|
||||||
@ -1607,7 +1607,8 @@ private:
|
|||||||
bool isMainThread_ {false};
|
bool isMainThread_ {false};
|
||||||
bool fullMarkRequest_ {false};
|
bool fullMarkRequest_ {false};
|
||||||
|
|
||||||
CMap<ElementsKind, ConstantIndex> arrayHClassIndexMap_;
|
// { ElementsKind, (hclass, hclassWithProto) }
|
||||||
|
CMap<ElementsKind, std::pair<ConstantIndex, ConstantIndex>> arrayHClassIndexMap_;
|
||||||
CMap<JSHClass *, GlobalIndex> ctorHclassEntries_;
|
CMap<JSHClass *, GlobalIndex> ctorHclassEntries_;
|
||||||
|
|
||||||
CVector<EcmaContext *> contexts_;
|
CVector<EcmaContext *> contexts_;
|
||||||
|
@ -271,7 +271,9 @@ void PGOProfiler::UpdateTrackElementsKind(JSTaggedValue trackInfoVal, ElementsKi
|
|||||||
trackInfo->SetElementsKind(mixKind);
|
trackInfo->SetElementsKind(mixKind);
|
||||||
auto thread = vm_->GetJSThread();
|
auto thread = vm_->GetJSThread();
|
||||||
auto globalConst = thread->GlobalConstants();
|
auto globalConst = thread->GlobalConstants();
|
||||||
auto constantId = thread->GetArrayHClassIndexMap().at(mixKind);
|
// Since trackinfo is only used at define point,
|
||||||
|
// we update cachedHClass with initial array hclass which does not have IsPrototype set.
|
||||||
|
auto constantId = thread->GetArrayHClassIndexMap().at(mixKind).first;
|
||||||
auto hclass = globalConst->GetGlobalConstantObject(static_cast<size_t>(constantId));
|
auto hclass = globalConst->GetGlobalConstantObject(static_cast<size_t>(constantId));
|
||||||
trackInfo->SetCachedHClass(vm_->GetJSThread(), hclass);
|
trackInfo->SetCachedHClass(vm_->GetJSThread(), hclass);
|
||||||
UpdateTrackInfo(JSTaggedValue(trackInfo));
|
UpdateTrackInfo(JSTaggedValue(trackInfo));
|
||||||
@ -1684,7 +1686,8 @@ bool PGOProfiler::AddBuiltinsInfoByNameInInstance(ApEntityId abcId, const CStrin
|
|||||||
}
|
}
|
||||||
JSHClass *exceptRecvHClass = nullptr;
|
JSHClass *exceptRecvHClass = nullptr;
|
||||||
if (builtinsId == BuiltinTypeId::ARRAY) {
|
if (builtinsId == BuiltinTypeId::ARRAY) {
|
||||||
exceptRecvHClass = thread->GetArrayInstanceHClass(receiver->GetElementsKind());
|
bool receiverIsPrototype = receiver->IsPrototype();
|
||||||
|
exceptRecvHClass = thread->GetArrayInstanceHClass(receiver->GetElementsKind(), receiverIsPrototype);
|
||||||
} else if (builtinsId == BuiltinTypeId::STRING) {
|
} else if (builtinsId == BuiltinTypeId::STRING) {
|
||||||
exceptRecvHClass = receiver;
|
exceptRecvHClass = receiver;
|
||||||
} else {
|
} else {
|
||||||
@ -1720,7 +1723,8 @@ bool PGOProfiler::AddBuiltinsInfoByNameInProt(ApEntityId abcId, const CString &r
|
|||||||
auto thread = vm_->GetJSThread();
|
auto thread = vm_->GetJSThread();
|
||||||
JSHClass *exceptRecvHClass = nullptr;
|
JSHClass *exceptRecvHClass = nullptr;
|
||||||
if (builtinsId == BuiltinTypeId::ARRAY) {
|
if (builtinsId == BuiltinTypeId::ARRAY) {
|
||||||
exceptRecvHClass = thread->GetArrayInstanceHClass(receiver->GetElementsKind());
|
bool receiverIsPrototype = receiver->IsPrototype();
|
||||||
|
exceptRecvHClass = thread->GetArrayInstanceHClass(receiver->GetElementsKind(), receiverIsPrototype);
|
||||||
} else if (builtinsId == BuiltinTypeId::STRING) {
|
} else if (builtinsId == BuiltinTypeId::STRING) {
|
||||||
exceptRecvHClass = receiver;
|
exceptRecvHClass = receiver;
|
||||||
} else {
|
} else {
|
||||||
|
@ -637,22 +637,20 @@ DEF_RUNTIME_STUBS(UpdateHClassForElementsKind)
|
|||||||
JSTaggedType elementsKind = GetTArg(argv, argc, 1); // 1: means the first parameter
|
JSTaggedType elementsKind = GetTArg(argv, argc, 1); // 1: means the first parameter
|
||||||
ASSERT(receiver->IsJSArray());
|
ASSERT(receiver->IsJSArray());
|
||||||
ElementsKind kind = Elements::FixElementsKind(static_cast<ElementsKind>(elementsKind));
|
ElementsKind kind = Elements::FixElementsKind(static_cast<ElementsKind>(elementsKind));
|
||||||
auto arrayIndexMap = thread->GetArrayHClassIndexMap();
|
auto array = JSHandle<JSArray>(receiver);
|
||||||
if (arrayIndexMap.find(kind) != arrayIndexMap.end()) {
|
ASSERT(JSHClass::IsInitialArrayHClassWithElementsKind(thread, receiver->GetTaggedObject()->GetClass(),
|
||||||
auto index = thread->GetArrayHClassIndexMap().at(kind);
|
receiver->GetTaggedObject()->GetClass()->GetElementsKind()));
|
||||||
auto globalConst = thread->GlobalConstants();
|
if (!JSHClass::TransitToElementsKindUncheck(thread, JSHandle<JSObject>(array), kind)) {
|
||||||
auto targetHClassValue = globalConst->GetGlobalConstantObject(static_cast<size_t>(index));
|
return JSTaggedValue::Hole().GetRawData();
|
||||||
auto hclass = JSHClass::Cast(targetHClassValue.GetTaggedObject());
|
}
|
||||||
auto array = JSHandle<JSArray>(receiver);
|
|
||||||
array->SynchronizedSetClass(thread, hclass);
|
if (!thread->GetEcmaVM()->IsEnableElementsKind()) {
|
||||||
if (!thread->GetEcmaVM()->IsEnableElementsKind()) {
|
// Update TrackInfo
|
||||||
// Update TrackInfo
|
if (!thread->IsPGOProfilerEnable()) {
|
||||||
if (!thread->IsPGOProfilerEnable()) {
|
return JSTaggedValue::Hole().GetRawData();
|
||||||
return JSTaggedValue::Hole().GetRawData();
|
|
||||||
}
|
|
||||||
auto trackInfoVal = array->GetTrackInfo();
|
|
||||||
thread->GetEcmaVM()->GetPGOProfiler()->UpdateTrackElementsKind(trackInfoVal, kind);
|
|
||||||
}
|
}
|
||||||
|
auto trackInfoVal = JSHandle<JSArray>(receiver)->GetTrackInfo();
|
||||||
|
thread->GetEcmaVM()->GetPGOProfiler()->UpdateTrackElementsKind(trackInfoVal, kind);
|
||||||
}
|
}
|
||||||
return JSTaggedValue::Hole().GetRawData();
|
return JSTaggedValue::Hole().GetRawData();
|
||||||
}
|
}
|
||||||
|
@ -88,3 +88,31 @@ function testArrayUsedAsProto() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
testArrayUsedAsProto();
|
testArrayUsedAsProto();
|
||||||
|
|
||||||
|
function testProto1() {
|
||||||
|
let a = [1, 2, 3];
|
||||||
|
let obj = {};
|
||||||
|
obj.__proto__ = a;
|
||||||
|
print(a[0]);
|
||||||
|
print(ArkTools.getElementsKind(a));
|
||||||
|
}
|
||||||
|
|
||||||
|
print(ArkTools.isAOTCompiled(testProto1));
|
||||||
|
testProto1();
|
||||||
|
|
||||||
|
|
||||||
|
function testProto2() {
|
||||||
|
let obj = {};
|
||||||
|
for (let i = 0; i < 4; i++) {
|
||||||
|
let a = [1, 2, 3];
|
||||||
|
if (i == 2) {
|
||||||
|
obj.__proto__ = a;
|
||||||
|
a[1] = 1.5
|
||||||
|
}
|
||||||
|
print(a[0] + 1);
|
||||||
|
print(ArkTools.getElementsKind(a));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
print(ArkTools.isAOTCompiled(testProto2));
|
||||||
|
testProto2();
|
||||||
|
@ -19,4 +19,17 @@ undefined
|
|||||||
2
|
2
|
||||||
0
|
0
|
||||||
success
|
success
|
||||||
testArrayUsedAsProto success
|
testArrayUsedAsProto success
|
||||||
|
true
|
||||||
|
1
|
||||||
|
2
|
||||||
|
true
|
||||||
|
2
|
||||||
|
6
|
||||||
|
2
|
||||||
|
6
|
||||||
|
2
|
||||||
|
6
|
||||||
|
2
|
||||||
|
6
|
||||||
|
|
||||||
|
@ -19,4 +19,17 @@ undefined
|
|||||||
2
|
2
|
||||||
0
|
0
|
||||||
success
|
success
|
||||||
testArrayUsedAsProto success
|
testArrayUsedAsProto success
|
||||||
|
false
|
||||||
|
1
|
||||||
|
2
|
||||||
|
false
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
6
|
||||||
|
2
|
||||||
|
6
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user