1/* 2 * Copyright (c) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#ifndef ECMASCRIPT_ELEMENT_ACCESSOR_INL_H 17#define ECMASCRIPT_ELEMENT_ACCESSOR_INL_H 18 19#include "ecmascript/element_accessor.h" 20 21#include "ecmascript/mem/barriers-inl.h" 22#include "ecmascript/js_tagged_value-inl.h" 23#include "ecmascript/js_thread.h" 24#include "ecmascript/tagged_array.h" 25 26namespace panda::ecmascript { 27 28template<typename T> 29inline void ElementAccessor::Set(const JSThread *thread, JSHandle<JSObject> receiver, uint32_t idx, 30 const JSHandle<T> &value, bool needTransition, ElementsKind extraKind) 31{ 32 // Change elementsKind 33 ElementsKind oldKind = receiver->GetClass()->GetElementsKind(); 34 if (needTransition && JSHClass::TransitToElementsKind(thread, receiver, 35 JSHandle<JSTaggedValue>(value), extraKind)) { 36 ElementsKind newKind = receiver->GetClass()->GetElementsKind(); 37 // GC might happen when migrating Array 38 Elements::MigrateArrayWithKind(thread, receiver, oldKind, newKind); 39 } 40 41 TaggedArray *elements = TaggedArray::Cast(receiver->GetElements()); 42 ASSERT(idx < elements->GetLength()); 43 size_t offset = JSTaggedValue::TaggedTypeSize() * idx; 44 45 ElementsKind kind = receiver->GetClass()->GetElementsKind(); 46 if (!elements->GetClass()->IsMutantTaggedArray()) { 47 kind = ElementsKind::GENERIC; 48 } 49 50 JSTaggedType convertedValue = ConvertTaggedValueWithElementsKind(value.GetTaggedValue(), kind); 51 // NOLINTNEXTLINE(readability-braces-around-statements, bugprone-suspicious-semicolon) 52 if (value.GetTaggedValue().IsHeapObject()) { 53 Barriers::SetObject<true>(thread, elements->GetData(), offset, convertedValue); 54 } else { // NOLINTNEXTLINE(readability-misleading-indentation) 55 Barriers::SetPrimitive<JSTaggedType>(elements->GetData(), offset, convertedValue); 56 } 57} 58 59template<typename T> 60void ElementAccessor::FastSet(const JSThread *thread, JSHandle<TaggedArray> elements, uint32_t idx, 61 const JSHandle<T> &value, ElementsKind kind) 62{ 63 ASSERT(idx < elements->GetLength()); 64 size_t offset = JSTaggedValue::TaggedTypeSize() * idx; 65 JSTaggedValue rawValue = value.GetTaggedValue(); 66 switch (kind) { 67 case ElementsKind::INT: 68 Barriers::SetPrimitive<JSTaggedType>(elements->GetData(), offset, 69 static_cast<JSTaggedType>(rawValue.GetInt())); 70 break; 71 case ElementsKind::NUMBER: 72 if (rawValue.IsInt()) { 73 int intValue = rawValue.GetInt(); 74 Barriers::SetPrimitive<JSTaggedType>(elements->GetData(), offset, 75 base::bit_cast<JSTaggedType>(static_cast<double>(intValue))); 76 } else { 77 Barriers::SetPrimitive<JSTaggedType>(elements->GetData(), offset, 78 base::bit_cast<JSTaggedType>(rawValue.GetDouble())); 79 } 80 break; 81 case ElementsKind::TAGGED: 82 if (value.GetTaggedValue().IsHeapObject()) { 83 Barriers::SetObject<true>(thread, elements->GetData(), offset, rawValue.GetRawData()); 84 } else { // NOLINTNEXTLINE(readability-misleading-indentation) 85 Barriers::SetPrimitive<JSTaggedType>(elements->GetData(), offset, rawValue.GetRawData()); 86 } 87 break; 88 default: 89 LOG_ECMA(FATAL) << "Trying to Convert TaggedValue With Unknown ElementsKind"; 90 UNREACHABLE(); 91 break; 92 } 93} 94} // namespace panda::ecmascript 95#endif // ECMASCRIPT_ELEMENT_ACCESSOR_INL_H 96