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 "class_init.h"
17 #include <iostream>
18 #include <fstream>
19
20 namespace {
21 constexpr char kINFOFilename[] = "INFO_filename";
22 constexpr char kCoreAll[] = "core-all";
23 constexpr char kMCCPreClinitCheck[] = "MCC_PreClinitCheck";
24 constexpr char kMCCPostClinitCheck[] = "MCC_PostClinitCheck";
25 } // namespace
26
27 // This phase does two things.
28 // 1. Insert clinit(class initialization) check, a intrinsic call INTRN_MPL_CLINIT_CHECK
29 // for place where needed.
30 // Insert clinit check for static native methods which are not private.
31 namespace maple {
CanRemoveClinitCheck(const std::string & clinitClassname) const32 bool ClassInit::CanRemoveClinitCheck(const std::string &clinitClassname) const
33 {
34 if (!Options::usePreloadedClass) {
35 return false;
36 }
37 if (clinitClassname.empty()) {
38 return false;
39 }
40 uint32 dexNameIdx =
41 GetMIRModule().GetFileinfo(GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(kINFOFilename));
42 const std::string &dexName = GlobalTables::GetStrTable().GetStringFromStrIdx(GStrIdx(dexNameIdx));
43 if (dexName.find(kCoreAll) != std::string::npos) {
44 return false;
45 }
46 return IsSystemPreloadedClass(clinitClassname);
47 }
48
GenClassInitCheckProfile(MIRFunction & func,const MIRSymbol & classInfo,StmtNode * clinit) const49 void ClassInit::GenClassInitCheckProfile(MIRFunction &func, const MIRSymbol &classInfo, StmtNode *clinit) const
50 {
51 GenPreClassInitCheck(func, classInfo, clinit);
52 GenPostClassInitCheck(func, classInfo, clinit);
53 }
54
GenPreClassInitCheck(MIRFunction & func,const MIRSymbol & classInfo,const StmtNode * clinit) const55 void ClassInit::GenPreClassInitCheck(MIRFunction &func, const MIRSymbol &classInfo, const StmtNode *clinit) const
56 {
57 MIRFunction *preClinit = builder->GetOrCreateFunction(kMCCPreClinitCheck, (TyIdx)(PTY_void));
58 BaseNode *classInfoNode = builder->CreateExprAddrof(0, classInfo);
59 MapleVector<BaseNode *> args(builder->GetCurrentFuncCodeMpAllocator()->Adapter());
60 args.push_back(classInfoNode);
61 CallNode *callPreclinit = builder->CreateStmtCall(preClinit->GetPuidx(), args);
62 func.GetBody()->InsertBefore(clinit, callPreclinit);
63 }
64
GenPostClassInitCheck(MIRFunction & func,const MIRSymbol & classInfo,const StmtNode * clinit) const65 void ClassInit::GenPostClassInitCheck(MIRFunction &func, const MIRSymbol &classInfo, const StmtNode *clinit) const
66 {
67 MIRFunction *postClinit = builder->GetOrCreateFunction(kMCCPostClinitCheck, (TyIdx)(PTY_void));
68 BaseNode *classInfoNode = builder->CreateExprAddrof(0, classInfo);
69 MapleVector<BaseNode *> args(builder->GetCurrentFuncCodeMpAllocator()->Adapter());
70 args.push_back(classInfoNode);
71 CallNode *callPostClinit = builder->CreateStmtCall(postClinit->GetPuidx(), args);
72 func.GetBody()->InsertAfter(clinit, callPostClinit);
73 }
74
GetClassInfo(const std::string & classname)75 MIRSymbol *ClassInit::GetClassInfo(const std::string &classname)
76 {
77 const std::string &classInfoName = CLASSINFO_PREFIX_STR + classname;
78 MIRType *classInfoType =
79 GlobalTables::GetTypeTable().GetOrCreateClassType(namemangler::kClassMetadataTypeName, GetMIRModule());
80 MIRSymbol *classInfo = builder->GetOrCreateGlobalDecl(classInfoName, *classInfoType);
81 Klass *klass = klassHierarchy->GetKlassFromName(classname);
82 if (klass == nullptr || !klass->GetMIRStructType()->IsLocal()) {
83 classInfo->SetStorageClass(kScExtern);
84 }
85 return classInfo;
86 }
87
88 } // namespace maple
89