• 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(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(index);
80     if (!allowAlloc && val.IsHole()) {
81         return JSTaggedValue::Undefined();
82     }
83     if (val.IsHole()) {
84         JSPandaFile *jsPandaFile = taggedPool->GetJSPandaFile();
85         panda_file::File::EntityId id = taggedPool->GetEntityId(index);
86         auto foundStr = jsPandaFile->GetStringData(id);
87         EcmaVM *vm = thread->GetEcmaVM();
88         ObjectFactory *factory = vm->GetFactory();
89         auto string = factory->GetRawStringFromStringTableWithoutJSHandle(foundStr, MemSpaceType::SHARED_OLD_SPACE,
90             jsPandaFile->IsFirstMergedAbc(), id.GetOffset());
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(index);
100     if (val.IsHole()) {
101         if (!taggedPool->GetJSPandaFile()->IsNewVersion()) {
102             JSTaggedValue unsharedCp = thread->GetCurrentEcmaContext()->FindOrCreateUnsharedConstpool(constpool);
103             taggedPool = ConstantPool::Cast(unsharedCp.GetTaggedObject());
104             return taggedPool->Get(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             jsPandaFile->IsFirstMergedAbc(), id.GetOffset());
117 
118         val = JSTaggedValue(string);
119         CASSetObjectToCache(thread, constpoolHandle.GetTaggedValue(), index, val);
120     }
121 
122     return val;
123 }
124 
GetDeserializedConstantPool(EcmaVM * vm,const JSPandaFile * jsPandaFile,int32_t cpID)125 JSHandle<JSTaggedValue> ConstantPool::GetDeserializedConstantPool(EcmaVM *vm, const JSPandaFile *jsPandaFile,
126                                                                   int32_t cpID)
127 {
128     auto aotFileManager = vm->GetAOTFileManager();
129     auto constantPool = aotFileManager->GetDeserializedConstantPool(jsPandaFile, cpID);
130     MergeObjectLiteralHClassCache(vm, constantPool);
131     return constantPool;
132 }
133 
MergeObjectLiteralHClassCache(EcmaVM * vm,const JSHandle<JSTaggedValue> & constpool)134 void ConstantPool::MergeObjectLiteralHClassCache(EcmaVM *vm, const JSHandle<JSTaggedValue> &constpool)
135 {
136     if (constpool->IsHole()) {
137         return;
138     }
139     JSHandle<ConstantPool> pool(constpool);
140     auto aotHCInfo = pool->GetAotHClassInfo();
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(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     JSThread *thread = vm->GetJSThread();
157     if (curCached->IsHole()) {
158         for (uint32_t i = 0; i < length; i++) {
159             auto newValue = snapshotCachedArray->Get(i);
160             if (newValue.IsJSHClass()) {
161                 JSHClass::Cast(newValue.GetTaggedObject())->SetPrototype(thread, prototype);
162             }
163         }
164         vm->GetGlobalEnv()->SetObjectLiteralHClassCache(thread, last);
165         return;
166     }
167     auto curCachedArray = TaggedArray::Cast(curCached.GetTaggedValue());
168     for (uint32_t i = 0; i < length; i++) {
169         auto newValue = snapshotCachedArray->Get(i);
170         if (newValue.IsHole()) {
171             continue;
172         }
173         auto curValue = curCachedArray->Get(i);
174         // If already merged, stop to merge.
175         if (curValue.IsJSHClass() && JSHClass::Cast(curValue.GetTaggedObject())->IsAOT()) {
176             break;
177         }
178         JSHClass::Cast(newValue.GetTaggedObject())->SetPrototype(thread, prototype);
179         curCachedArray->Set(thread, i, newValue);
180     }
181 }
182 
GetMethodFromCache(JSTaggedValue constpool,uint32_t index)183 JSTaggedValue ConstantPool::GetMethodFromCache(JSTaggedValue constpool, uint32_t index)
184 {
185     const ConstantPool *taggedPool = ConstantPool::Cast(constpool.GetTaggedObject());
186     auto val = taggedPool->GetObjectFromCache(index);
187     JSPandaFile *jsPandaFile = taggedPool->GetJSPandaFile();
188 
189     if (IsLoadedMethodInfoFromAOT(jsPandaFile, val)) {
190         val = JSTaggedValue::Hole();
191     }
192 
193     return val.IsHole() ? JSTaggedValue::Undefined() : val;
194 }
195 
IsAotMethodLiteralInfo(JSTaggedValue literalInfo)196 bool ConstantPool::IsAotMethodLiteralInfo(JSTaggedValue literalInfo)
197 {
198     return literalInfo.IsAOTLiteralInfo() && (AOTLiteralInfo::Cast(literalInfo.GetTaggedObject())->
199         GetLiteralType() == AOTLiteralInfo::METHOD_LITERAL_TYPE);
200 }
201 
UpdateConstpoolWhenDeserialAI(EcmaVM * vm,JSHandle<ConstantPool> aiCP,JSHandle<ConstantPool> sharedCP,JSHandle<ConstantPool> unsharedCP)202 void ConstantPool::UpdateConstpoolWhenDeserialAI(EcmaVM *vm, JSHandle<ConstantPool> aiCP,
203                                                  JSHandle<ConstantPool> sharedCP, JSHandle<ConstantPool> unsharedCP)
204 {
205     uint32_t constpoolLen = aiCP->GetCacheLength();
206     auto aiCPLength = aiCP->GetLength();
207     JSMutableHandle<JSTaggedValue> valHandle(vm->GetJSThread(), JSTaggedValue::Undefined());
208     for (uint32_t i = 0; i < constpoolLen; i++) {
209         // We need preserve unshared constantPool index and shared constantPool id instead of fetching from ai.
210         // Because framework abc's ai does not contain those infos.
211         if (i == (aiCPLength - ConstantPool::UNSHARED_CONSTPOOL_INDEX) ||
212             i == (aiCPLength - ConstantPool::SHARED_CONSTPOOL_ID)) {
213             continue;
214         }
215         JSThread *thread = vm->GetJSThread();
216         JSTaggedValue val = aiCP->GetObjectFromCache(i);
217         valHandle.Update(val);
218         if (IsAotMethodLiteralInfo(valHandle.GetTaggedValue())) {
219             JSHandle<AOTLiteralInfo> value(thread, val);
220             JSHandle<AOTLiteralInfo> methodLiteral = CopySharedMethodAOTLiteralInfo(vm, value);
221             sharedCP->SetObjectToCache(thread, i, methodLiteral.GetTaggedValue());
222         } else if (valHandle->IsInt()) {
223             // For MethodInfo which does not have ihc infos, we store codeEntry directly.
224             sharedCP->SetObjectToCache(thread, i, valHandle.GetTaggedValue());
225             unsharedCP->SetObjectToCache(thread, i, valHandle.GetTaggedValue());
226         }
227         // update method, class and object aotliteralinfo
228         if (valHandle->IsAOTLiteralInfo()) {
229             unsharedCP->SetObjectToCache(thread, i, valHandle.GetTaggedValue());
230         }
231     }
232     unsharedCP->InitConstantPoolTail(vm->GetJSThread(), aiCP);
233 }
234 }
235