/* * 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_ELEMENT_ACCESSOR_INL_H #define ECMASCRIPT_ELEMENT_ACCESSOR_INL_H #include "ecmascript/element_accessor.h" #include "ecmascript/mem/barriers-inl.h" #include "ecmascript/js_tagged_value-inl.h" #include "ecmascript/js_thread.h" #include "ecmascript/tagged_array.h" namespace panda::ecmascript { template inline void ElementAccessor::Set(const JSThread *thread, JSHandle receiver, uint32_t idx, const JSHandle &value, bool needTransition, ElementsKind extraKind) { // Change elementsKind ElementsKind oldKind = receiver->GetClass()->GetElementsKind(); if (needTransition && JSHClass::TransitToElementsKind(thread, receiver, JSHandle(value), extraKind)) { ElementsKind newKind = receiver->GetClass()->GetElementsKind(); // GC might happen when migrating Array Elements::MigrateArrayWithKind(thread, receiver, oldKind, newKind); } TaggedArray *elements = TaggedArray::Cast(receiver->GetElements(thread)); ASSERT(idx < elements->GetLength()); if (UNLIKELY(thread->IsEnableMutantArray())) { ElementsKind kind = receiver->GetClass()->GetElementsKind(); if (!elements->GetClass()->IsMutantTaggedArray()) { kind = ElementsKind::GENERIC; } JSTaggedType convertedValue = ConvertTaggedValueWithElementsKind(value.GetTaggedValue(), kind); size_t offset = JSTaggedValue::TaggedTypeSize() * idx; // NOLINTNEXTLINE(readability-braces-around-statements, bugprone-suspicious-semicolon) if (value.GetTaggedValue().IsHeapObject()) { Barriers::SetObject(thread, reinterpret_cast(elements), TaggedArray::DATA_OFFSET + offset, convertedValue); } else { // NOLINTNEXTLINE(readability-misleading-indentation) Barriers::SetPrimitive(elements->GetData(), offset, convertedValue); } } else { elements->Set(thread, idx, value); } } template void ElementAccessor::FastSet(const JSThread *thread, JSHandle elements, uint32_t idx, const JSHandle &value, ElementsKind kind) { ASSERT(idx < elements->GetLength()); size_t offset = JSTaggedValue::TaggedTypeSize() * idx; JSTaggedValue rawValue = value.GetTaggedValue(); switch (kind) { case ElementsKind::INT: Barriers::SetPrimitive(elements->GetData(), offset, static_cast(rawValue.GetInt())); break; case ElementsKind::NUMBER: if (rawValue.IsInt()) { int intValue = rawValue.GetInt(); Barriers::SetPrimitive(elements->GetData(), offset, base::bit_cast(static_cast(intValue))); } else { Barriers::SetPrimitive(elements->GetData(), offset, base::bit_cast(rawValue.GetDouble())); } break; case ElementsKind::TAGGED: if (value.GetTaggedValue().IsHeapObject()) { Barriers::SetObject(thread, elements->GetThis(), TaggedArray::DATA_OFFSET + offset, rawValue.GetRawData()); } else { // NOLINTNEXTLINE(readability-misleading-indentation) Barriers::SetPrimitive(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