• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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/builtins/builtins_ark_tools.h"
17 
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <fcntl.h>
21 #include "ecmascript/js_function.h"
22 #include "ecmascript/base/string_helper.h"
23 #include "ecmascript/js_tagged_value-inl.h"
24 #include "ecmascript/mem/tagged_object-inl.h"
25 #include "ecmascript/napi/include/dfx_jsnapi.h"
26 
27 namespace panda::ecmascript::builtins {
28 using StringHelper = base::StringHelper;
29 
30 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
31 constexpr char FILEDIR[] = "/data/storage/el2/base/files/";
32 #endif
ObjectDump(EcmaRuntimeCallInfo * info)33 JSTaggedValue BuiltinsArkTools::ObjectDump(EcmaRuntimeCallInfo *info)
34 {
35     ASSERT(info);
36     JSThread *thread = info->GetThread();
37     [[maybe_unused]] EcmaHandleScope handleScope(thread);
38 
39     JSHandle<EcmaString> str = JSTaggedValue::ToString(thread, GetCallArg(info, 0));
40     // The default log level of ace_engine and js_runtime is error
41     LOG_ECMA(ERROR) << ": " << EcmaStringAccessor(str).ToStdString();
42 
43     uint32_t numArgs = info->GetArgsNumber();
44     for (uint32_t i = 1; i < numArgs; i++) {
45         JSHandle<JSTaggedValue> obj = GetCallArg(info, i);
46         std::ostringstream oss;
47         obj->Dump(oss);
48 
49         // The default log level of ace_engine and js_runtime is error
50         LOG_ECMA(ERROR) << ": " << oss.str();
51     }
52 
53     return JSTaggedValue::Undefined();
54 }
55 
CompareHClass(EcmaRuntimeCallInfo * info)56 JSTaggedValue BuiltinsArkTools::CompareHClass(EcmaRuntimeCallInfo *info)
57 {
58     ASSERT(info);
59     JSThread *thread = info->GetThread();
60     [[maybe_unused]] EcmaHandleScope handleScope(thread);
61 
62     JSHandle<JSTaggedValue> obj1 = GetCallArg(info, 0);
63     JSHandle<JSTaggedValue> obj2 = GetCallArg(info, 1);
64     JSHClass* obj1Hclass = obj1->GetTaggedObject()->GetClass();
65     JSHClass* obj2Hclass = obj2->GetTaggedObject()->GetClass();
66     std::ostringstream oss;
67     obj1Hclass->Dump(oss);
68     obj2Hclass->Dump(oss);
69     bool res = (obj1Hclass == obj2Hclass);
70     if (!res) {
71         LOG_ECMA(ERROR) << "These two object don't share the same hclass:" << oss.str();
72     }
73     return JSTaggedValue(res);
74 }
75 
DumpHClass(EcmaRuntimeCallInfo * info)76 JSTaggedValue BuiltinsArkTools::DumpHClass(EcmaRuntimeCallInfo *info)
77 {
78     ASSERT(info);
79     JSThread *thread = info->GetThread();
80     [[maybe_unused]] EcmaHandleScope handleScope(thread);
81 
82     JSHandle<JSTaggedValue> obj = GetCallArg(info, 0);
83     JSHClass* objHclass = obj->GetTaggedObject()->GetClass();
84     std::ostringstream oss;
85     objHclass->Dump(oss);
86 
87     LOG_ECMA(ERROR) << "hclass:" << oss.str();
88     return JSTaggedValue::Undefined();
89 }
90 
IsTSHClass(EcmaRuntimeCallInfo * info)91 JSTaggedValue BuiltinsArkTools::IsTSHClass(EcmaRuntimeCallInfo *info)
92 {
93     ASSERT(info);
94     JSThread *thread = info->GetThread();
95     [[maybe_unused]] EcmaHandleScope handleScope(thread);
96 
97     ASSERT(info->GetArgsNumber() == 1);
98     JSHandle<JSTaggedValue> object = GetCallArg(info, 0);
99     JSHClass* hclass = object->GetTaggedObject()->GetClass();
100     bool isTSHClass = hclass->IsTS();
101     return GetTaggedBoolean(isTSHClass);
102 }
103 
GetHClass(EcmaRuntimeCallInfo * info)104 JSTaggedValue BuiltinsArkTools::GetHClass(EcmaRuntimeCallInfo *info)
105 {
106     ASSERT(info);
107     JSThread *thread = info->GetThread();
108     [[maybe_unused]] EcmaHandleScope handleScope(thread);
109 
110     ASSERT(info->GetArgsNumber() == 1);
111     JSHandle<JSTaggedValue> object = GetCallArg(info, 0);
112     JSHClass* hclass = object->GetTaggedObject()->GetClass();
113     return JSTaggedValue(hclass);
114 }
115 
ForceFullGC(EcmaRuntimeCallInfo * info)116 JSTaggedValue BuiltinsArkTools::ForceFullGC(EcmaRuntimeCallInfo *info)
117 {
118     ASSERT(info);
119     const_cast<Heap *>(info->GetThread()->GetEcmaVM()->GetHeap())->CollectGarbage(TriggerGCType::FULL_GC);
120     return JSTaggedValue::True();
121 }
122 
RemoveAOTFlag(EcmaRuntimeCallInfo * info)123 JSTaggedValue BuiltinsArkTools::RemoveAOTFlag(EcmaRuntimeCallInfo *info)
124 {
125     ASSERT(info);
126     JSThread *thread = info->GetThread();
127     [[maybe_unused]] EcmaHandleScope handleScope(thread);
128 
129     ASSERT(info->GetArgsNumber() == 1);
130     JSHandle<JSTaggedValue> object = GetCallArg(info, 0);
131     JSHandle<JSFunction> func = JSHandle<JSFunction>::Cast(object);
132     JSHandle<Method> method = JSHandle<Method>(thread, func->GetMethod());
133     method->SetAotCodeBit(false);
134 
135     return JSTaggedValue::Undefined();
136 }
137 
138 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
StartCpuProfiler(EcmaRuntimeCallInfo * info)139 JSTaggedValue BuiltinsArkTools::StartCpuProfiler(EcmaRuntimeCallInfo *info)
140 {
141     ASSERT(info);
142     JSThread *thread = info->GetThread();
143     [[maybe_unused]] EcmaHandleScope handleScope(thread);
144 
145     auto vm = thread->GetEcmaVM();
146 
147     // get file name
148     JSHandle<JSTaggedValue> fileNameValue = GetCallArg(info, 0);
149     std::string fileName = "";
150     if (fileNameValue->IsString()) {
151         JSHandle<EcmaString> str = JSTaggedValue::ToString(thread, fileNameValue);
152         fileName = EcmaStringAccessor(str).ToStdString() + ".cpuprofile";
153     } else {
154         fileName = GetProfileName();
155     }
156 
157     if (!CreateFile(fileName)) {
158         LOG_ECMA(ERROR) << "CreateFile failed " << fileName;
159     }
160 
161     // get sampling interval
162     JSHandle<JSTaggedValue> samplingIntervalValue = GetCallArg(info, 1);
163     uint32_t interval = 500; // 500:Default Sampling interval 500 microseconds
164     if (samplingIntervalValue->IsNumber()) {
165         interval = JSTaggedValue::ToUint32(thread, samplingIntervalValue);
166     }
167 
168     DFXJSNApi::StartCpuProfilerForFile(vm, fileName, interval);
169     return JSTaggedValue::Undefined();
170 }
171 
StopCpuProfiler(EcmaRuntimeCallInfo * info)172 JSTaggedValue BuiltinsArkTools::StopCpuProfiler(EcmaRuntimeCallInfo *info)
173 {
174     JSThread *thread = info->GetThread();
175     [[maybe_unused]] EcmaHandleScope handleScope(thread);
176     auto vm = thread->GetEcmaVM();
177     DFXJSNApi::StopCpuProfilerForFile(vm);
178 
179     return JSTaggedValue::Undefined();
180 }
181 
GetProfileName()182 std::string BuiltinsArkTools::GetProfileName()
183 {
184     char time1[16] = {0}; // 16:Time format length
185     char time2[16] = {0}; // 16:Time format length
186     time_t timep = std::time(nullptr);
187     struct tm nowTime1;
188     localtime_r(&timep, &nowTime1);
189     size_t result = 0;
190     result = strftime(time1, sizeof(time1), "%Y%m%d", &nowTime1);
191     if (result == 0) {
192         LOG_ECMA(ERROR) << "get time failed";
193         return "";
194     }
195     result = strftime(time2, sizeof(time2), "%H%M%S", &nowTime1);
196     if (result == 0) {
197         LOG_ECMA(ERROR) << "get time failed";
198         return "";
199     }
200     std::string profileName = "cpuprofile-";
201     profileName += time1;
202     profileName += "TO";
203     profileName += time2;
204     profileName += ".cpuprofile";
205     return profileName;
206 }
207 
CreateFile(std::string & fileName)208 bool BuiltinsArkTools::CreateFile(std::string &fileName)
209 {
210     std::string path = FILEDIR + fileName;
211     if (access(path.c_str(), F_OK) == 0) {
212         if (access(path.c_str(), W_OK) == 0) {
213             fileName = path;
214             return true;
215         }
216         LOG_ECMA(ERROR) << "file create failed, W_OK false";
217         return false;
218     }
219     const mode_t defaultMode = S_IRUSR | S_IWUSR | S_IRGRP; // -rw-r--
220     int fd = creat(path.c_str(), defaultMode);
221     if (fd == -1) {
222         fd = creat(fileName.c_str(), defaultMode);
223         if (fd == -1) {
224             LOG_ECMA(ERROR) << "file create failed, errno = "<< errno;
225             return false;
226         }
227         close(fd);
228         return true;
229     } else {
230         fileName = path;
231         close(fd);
232         return true;
233     }
234 }
235 #endif
236 
237 // It is used to check whether an object is a proto, and this function can be
238 // used to check whether the state machine of IC is faulty.
IsPrototype(EcmaRuntimeCallInfo * info)239 JSTaggedValue BuiltinsArkTools::IsPrototype(EcmaRuntimeCallInfo *info)
240 {
241     ASSERT(info);
242     JSThread *thread = info->GetThread();
243     [[maybe_unused]] EcmaHandleScope handleScope(thread);
244 
245     JSHandle<JSTaggedValue> obj = GetCallArg(info, 0);
246     JSHClass *objHclass = obj->GetTaggedObject()->GetClass();
247     return JSTaggedValue(objHclass->IsPrototype());
248 }
249 }  // namespace panda::ecmascript::builtins
250