• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2024 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/jspandafile/program_object.h"
17 
18 namespace panda::ecmascript {
19 
GetClassLiteralFromCache(JSThread * thread,JSHandle<ConstantPool> constpool,uint32_t literal,CString entry,JSHandle<JSTaggedValue> sendableEnv,ClassKind kind)20 JSTaggedValue ConstantPool::GetClassLiteralFromCache(JSThread *thread, JSHandle<ConstantPool> constpool,
21     uint32_t literal, CString entry, JSHandle<JSTaggedValue> sendableEnv, ClassKind kind)
22 {
23     [[maybe_unused]] EcmaHandleScope handleScope(thread);
24     // Do not use cache when sendable for get wrong obj from cache,
25     // shall be fix or refactor during shared object implements
26     JSTaggedValue val = constpool->GetObjectFromCache(thread, literal);
27     JSPandaFile *jsPandaFile = constpool->GetJSPandaFile();
28 
29     // For AOT
30     bool isLoadedAOT = jsPandaFile->IsLoadedAOT();
31     JSHandle<AOTLiteralInfo> entryIndexes(thread, JSTaggedValue::Undefined());
32     if (isLoadedAOT && val.IsAOTLiteralInfo()) {
33         entryIndexes = JSHandle<AOTLiteralInfo>(thread, val);
34         val = JSTaggedValue::Hole();
35     }
36 
37     if (val.IsHole()) {
38         EcmaVM *vm = thread->GetEcmaVM();
39         ObjectFactory *factory = vm->GetFactory();
40         ASSERT(jsPandaFile->IsNewVersion());
41         panda_file::File::EntityId literalId = constpool->GetEntityId(literal);
42         bool needSetAotFlag = isLoadedAOT && !entryIndexes.GetTaggedValue().IsUndefined();
43         JSHandle<TaggedArray> literalArray = LiteralDataExtractor::GetDatasIgnoreTypeForClass(thread,
44             jsPandaFile, literalId, constpool, entry, needSetAotFlag, entryIndexes, nullptr, sendableEnv, kind);
45         JSHandle<ClassLiteral> classLiteral;
46         if (kind == ClassKind::SENDABLE) {
47             classLiteral = factory->NewSClassLiteral();
48         } else {
49             classLiteral = factory->NewClassLiteral();
50         }
51         classLiteral->SetArray(thread, literalArray);
52         val = classLiteral.GetTaggedValue();
53         if (kind == ClassKind::SENDABLE) {
54             CASSetObjectToCache(thread, constpool.GetTaggedValue(), literal, val);
55         } else {
56             constpool->SetObjectToCache(thread, literal, val);
57         }
58     }
59 
60     return val;
61 }
62 
GetFieldLiteral(JSThread * thread,JSHandle<ConstantPool> constpool,uint32_t literal,CString entry)63 JSHandle<TaggedArray> ConstantPool::GetFieldLiteral(JSThread *thread, JSHandle<ConstantPool> constpool,
64                                                     uint32_t literal, CString entry)
65 {
66     JSPandaFile *jsPandaFile = constpool->GetJSPandaFile();
67     JSHandle<AOTLiteralInfo> entryIndexes(thread, JSTaggedValue::Undefined());
68     ASSERT(jsPandaFile->IsNewVersion());
69     panda_file::File::EntityId literalId(literal);
70     JSHandle<TaggedArray> literalArray = LiteralDataExtractor::GetDatasIgnoreType(
71         thread, jsPandaFile, literalId, constpool, entry, false, entryIndexes);
72     return literalArray;
73 }
74 
GetStringFromCacheForJit(JSThread * thread,JSTaggedValue constpool,uint32_t index,bool allowAlloc)75 JSTaggedValue ConstantPool::GetStringFromCacheForJit(JSThread *thread, JSTaggedValue constpool, uint32_t index,
76     bool allowAlloc)
77 {
78     const ConstantPool *taggedPool = ConstantPool::Cast(constpool.GetTaggedObject());
79     auto val = taggedPool->Get(thread, index);
80     if (!allowAlloc && val.IsHole()) {
81         return JSTaggedValue::Undefined();
82     }
83 
84     if (val.IsHole()) {
85         JSPandaFile *jsPandaFile = taggedPool->GetJSPandaFile();
86         panda_file::File::EntityId id = taggedPool->GetEntityId(index);
87         auto foundStr = jsPandaFile->GetStringData(id);
88         EcmaVM *vm = thread->GetEcmaVM();
89         ObjectFactory *factory = vm->GetFactory();
90         auto string = factory->GetRawStringFromStringTableWithoutJSHandle(foundStr, MemSpaceType::SHARED_OLD_SPACE);
91         val = JSTaggedValue(string);
92     }
93     return val;
94 }
95 
GetStringFromCache(JSThread * thread,JSTaggedValue constpool,uint32_t index)96 JSTaggedValue ConstantPool::GetStringFromCache(JSThread *thread, JSTaggedValue constpool, uint32_t index)
97 {
98     const ConstantPool *taggedPool = ConstantPool::Cast(constpool.GetTaggedObject());
99     auto val = taggedPool->Get(thread, index);
100     if (val.IsHole()) {
101         if (!taggedPool->GetJSPandaFile()->IsNewVersion()) {
102             JSTaggedValue unsharedCp = thread->GetEcmaVM()->FindOrCreateUnsharedConstpool(constpool);
103             taggedPool = ConstantPool::Cast(unsharedCp.GetTaggedObject());
104             return taggedPool->Get(thread, index);
105         }
106         [[maybe_unused]] EcmaHandleScope handleScope(thread);
107 
108         JSPandaFile *jsPandaFile = taggedPool->GetJSPandaFile();
109         panda_file::File::EntityId id = taggedPool->GetEntityId(index);
110         auto foundStr = jsPandaFile->GetStringData(id);
111 
112         EcmaVM *vm = thread->GetEcmaVM();
113         ObjectFactory *factory = vm->GetFactory();
114         JSHandle<ConstantPool> constpoolHandle(thread, constpool);
115         auto string = factory->GetRawStringFromStringTable(foundStr, MemSpaceType::SHARED_OLD_SPACE);
116 
117         val = JSTaggedValue(string);
118         CASSetObjectToCache(thread, constpoolHandle.GetTaggedValue(), index, val);
119     }
120 
121     return val;
122 }
123 
GetDeserializedConstantPool(EcmaVM * vm,const JSPandaFile * jsPandaFile,int32_t cpID)124 JSHandle<JSTaggedValue> ConstantPool::GetDeserializedConstantPool(EcmaVM *vm, const JSPandaFile *jsPandaFile,
125                                                                   int32_t cpID)
126 {
127     auto aotFileManager = vm->GetAOTFileManager();
128     auto constantPool = aotFileManager->GetDeserializedConstantPool(jsPandaFile, cpID);
129     MergeObjectLiteralHClassCache(vm, constantPool);
130     return constantPool;
131 }
132 
MergeObjectLiteralHClassCache(EcmaVM * vm,const JSHandle<JSTaggedValue> & constpool)133 void ConstantPool::MergeObjectLiteralHClassCache(EcmaVM *vm, const JSHandle<JSTaggedValue> &constpool)
134 {
135     if (constpool->IsHole()) {
136         return;
137     }
138     JSThread *thread = vm->GetJSThread();
139     JSHandle<ConstantPool> pool(constpool);
140     auto aotHCInfo = pool->GetAotHClassInfo(thread);
141     if (!aotHCInfo.IsTaggedArray()) {
142         return;
143     }
144     auto aotHCInfoArray = TaggedArray::Cast(aotHCInfo);
145     if (aotHCInfoArray->GetLength() <= 0) {
146         return;
147     }
148     auto last = aotHCInfoArray->Get(thread, aotHCInfoArray->GetLength() - 1);
149     if (!last.IsTaggedArray()) {
150         return;
151     }
152     auto snapshotCachedArray = TaggedArray::Cast(last);
153     auto curCached = vm->GetGlobalEnv()->GetObjectLiteralHClassCache();
154     auto length = snapshotCachedArray->GetLength();
155     auto prototype = vm->GetGlobalEnv()->GetObjectFunctionPrototype();
156     if (curCached->IsHole()) {
157         for (uint32_t i = 0; i < length; i++) {
158             auto newValue = snapshotCachedArray->Get(thread, i);
159             if (newValue.IsJSHClass()) {
160                 JSHClass::Cast(newValue.GetTaggedObject())->SetPrototype(thread, prototype);
161             }
162         }
163         vm->GetGlobalEnv()->SetObjectLiteralHClassCache(thread, last);
164         return;
165     }
166     auto curCachedArray = TaggedArray::Cast(curCached.GetTaggedValue());
167     for (uint32_t i = 0; i < length; i++) {
168         auto newValue = snapshotCachedArray->Get(thread, i);
169         if (newValue.IsHole()) {
170             continue;
171         }
172         auto curValue = curCachedArray->Get(thread, i);
173         // If already merged, stop to merge.
174         if (curValue.IsJSHClass() && JSHClass::Cast(curValue.GetTaggedObject())->IsAOT()) {
175             break;
176         }
177         JSHClass::Cast(newValue.GetTaggedObject())->SetPrototype(thread, prototype);
178         curCachedArray->Set(thread, i, newValue);
179     }
180 }
181 
GetMethodFromCache(JSTaggedValue constpool,uint32_t index,JSThread * thread)182 JSTaggedValue ConstantPool::GetMethodFromCache(JSTaggedValue constpool, uint32_t index, JSThread *thread)
183 {
184     const ConstantPool *taggedPool = ConstantPool::Cast(constpool.GetTaggedObject());
185     auto val = taggedPool->GetObjectFromCache(thread, index);
186     JSPandaFile *jsPandaFile = taggedPool->GetJSPandaFile();
187 
188     if (IsLoadingAOTMethodInfo(jsPandaFile, val)) {
189         val = JSTaggedValue::Hole();
190     }
191 
192     return val.IsHole() ? JSTaggedValue::Undefined() : val;
193 }
194 
IsAotMethodLiteralInfo(JSTaggedValue literalInfo)195 bool ConstantPool::IsAotMethodLiteralInfo(JSTaggedValue literalInfo)
196 {
197     return literalInfo.IsAOTLiteralInfo() && (AOTLiteralInfo::Cast(literalInfo.GetTaggedObject())->
198         GetLiteralType() == AOTLiteralInfo::METHOD_LITERAL_TYPE);
199 }
200 
GetIhcFromAOTLiteralInfo(JSThread * thread,JSTaggedValue constpool,uint32_t index)201 JSTaggedValue ConstantPool::GetIhcFromAOTLiteralInfo(JSThread *thread, JSTaggedValue constpool, uint32_t index)
202 {
203     ASSERT(constpool.IsConstantPool());
204     auto val = ConstantPool::Cast(constpool.GetTaggedObject())->Get(thread, index);
205     if (val.IsHeapObject() && val.IsAOTLiteralInfo()) {
206         return AOTLiteralInfo::Cast(val.GetTaggedObject())->GetIhc(thread);
207     }
208     return JSTaggedValue::Undefined();
209 }
UpdateConstpoolWhenDeserialAI(EcmaVM * vm,JSHandle<ConstantPool> aiCP,JSHandle<ConstantPool> sharedCP,JSHandle<ConstantPool> unsharedCP)210 void ConstantPool::UpdateConstpoolWhenDeserialAI(EcmaVM *vm, JSHandle<ConstantPool> aiCP,
211                                                  JSHandle<ConstantPool> sharedCP, JSHandle<ConstantPool> unsharedCP)
212 {
213     JSThread *thread = vm->GetJSThread();
214     uint32_t constpoolLen = aiCP->GetCacheLength();
215     auto aiCPLength = aiCP->GetLength();
216     JSMutableHandle<JSTaggedValue> valHandle(thread, JSTaggedValue::Undefined());
217     for (uint32_t i = 0; i < constpoolLen; i++) {
218         // We need preserve unshared constantPool index and shared constantPool id instead of fetching from ai.
219         // Because framework abc's ai does not contain those infos.
220         if (i == (aiCPLength - ConstantPool::UNSHARED_CONSTPOOL_INDEX) ||
221             i == (aiCPLength - ConstantPool::SHARED_CONSTPOOL_ID)) {
222             continue;
223         }
224         JSTaggedValue val = aiCP->GetObjectFromCache(thread, i);
225         valHandle.Update(val);
226         if (IsAotMethodLiteralInfo(valHandle.GetTaggedValue())) {
227             JSHandle<AOTLiteralInfo> value(thread, val);
228             JSHandle<AOTLiteralInfo> methodLiteral = CopySharedMethodAOTLiteralInfo(vm, value);
229             sharedCP->SetObjectToCache(thread, i, methodLiteral.GetTaggedValue());
230         } else if (valHandle->IsInt()) {
231             // For MethodInfo which does not have ihc infos, we store codeEntry directly.
232             sharedCP->SetObjectToCache(thread, i, valHandle.GetTaggedValue());
233             unsharedCP->SetObjectToCache(thread, i, valHandle.GetTaggedValue());
234         }
235         // update method, class and object aotliteralinfo
236         if (valHandle->IsAOTLiteralInfo()) {
237             unsharedCP->SetObjectToCache(thread, i, valHandle.GetTaggedValue());
238         }
239     }
240     unsharedCP->InitConstantPoolTail(vm->GetJSThread(), aiCP);
241 }
242 }
243