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#include "ecmascript/vtable.h" 17#include "ecmascript/layout_info-inl.h" 18 19namespace panda::ecmascript { 20VTable::Tuple VTable::CreateTuple(const JSThread *thread, JSTaggedValue phc, 21 const JSHandle<JSTaggedValue> &owner, uint32_t propIndex) 22{ 23 DISALLOW_GARBAGE_COLLECTION; 24 JSHClass *phcPoint = JSHClass::Cast(phc.GetTaggedObject()); 25 LayoutInfo *layoutInfo = LayoutInfo::Cast(phcPoint->GetLayout().GetTaggedObject()); 26 JSHandle<JSTaggedValue> name(thread, layoutInfo->GetKey(propIndex)); 27 28 // get type 29 JSTaggedValue typeVal; 30 PropertyAttributes attr = layoutInfo->GetAttr(propIndex); 31 if (attr.IsAccessor()) { 32 typeVal = JSTaggedValue(VTable::TypeKind::ACCESSOR); 33 } else { 34 typeVal = JSTaggedValue(VTable::TypeKind::FUNCTION); 35 } 36 JSHandle<JSTaggedValue> type(thread, typeVal); 37 38 // get offset 39 uint32_t propsNumber = phcPoint->NumberOfProps(); 40 int entry = layoutInfo->FindElementWithCache(thread, phcPoint, name.GetTaggedValue(), propsNumber); 41 ASSERT(entry != -1); 42 uint32_t offsetInt = phcPoint->GetInlinedPropertiesOffset(static_cast<uint32_t>(entry)); 43 JSHandle<JSTaggedValue> offset(thread, JSTaggedValue(offsetInt)); 44 45 CVector<JSHandle<JSTaggedValue>> vec {name, type, owner, offset}; 46 return VTable::Tuple(vec); 47} 48 49VTable::Tuple VTable::GetTuple(const JSThread *thread, uint32_t tupleIdx) const 50{ 51 CVector<JSHandle<JSTaggedValue>> vec; 52 for (uint32_t loc = 0; loc < ITEM_NUM; ++loc) { 53 JSTaggedValue val = Get(tupleIdx * TUPLE_SIZE + loc); 54 vec.emplace_back(JSHandle<JSTaggedValue>(thread, val)); 55 } 56 return Tuple(vec); 57} 58 59void VTable::SetByIndex(const JSThread *thread, uint32_t idx, const VTable::Tuple &tuple) 60{ 61 uint32_t beginIdx = idx * TUPLE_SIZE; 62 for (uint32_t i = 0; i < TUPLE_SIZE; ++i) { 63 uint32_t currIdx = beginIdx + i; 64 JSTaggedValue val = tuple.GetItem(TupleItem(i)).GetTaggedValue(); 65 Set(thread, currIdx, val); 66 } 67} 68 69void VTable::Trim(const JSThread *thread, uint32_t newLength) 70{ 71 TaggedArray::Trim(thread, newLength * VTable::TUPLE_SIZE); 72} 73 74int VTable::GetTupleIndexByName(JSTaggedValue name) const 75{ 76 DISALLOW_GARBAGE_COLLECTION; 77 uint32_t len = GetNumberOfTuples(); 78 if (len == 0) { 79 return -1; 80 } 81 82 [[maybe_unused]] EcmaString *str = EcmaString::Cast(name.GetTaggedObject()); 83 ASSERT_PRINT(EcmaStringAccessor(str).IsInternString(), "The name of the property is not an intern string"); 84 85 for (uint32_t index = 0; index < len; ++index) { 86 JSTaggedValue nameVal = GetTupleItem(index, VTable::TupleItem::NAME); 87 if (nameVal == name) { 88 return index; 89 } 90 } 91 92 return -1; 93} 94 95bool VTable::Find(JSTaggedValue name) const 96{ 97 return GetTupleIndexByName(name) != -1; 98} 99 100JSHandle<VTable> VTable::Copy(const JSThread *thread, const JSHandle<VTable> &vtable) 101{ 102 uint32_t length = vtable->GetLength(); 103 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 104 JSHandle<TaggedArray> copyVtable = factory->CopyArray(JSHandle<TaggedArray>(vtable), length, length); 105 return JSHandle<VTable>(copyVtable); 106} 107} // namespace panda::ecmascript 108