• 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 #include "ecmascript/mem/clock_scope.h"
27 
28 namespace panda::ecmascript::builtins {
29 using StringHelper = base::StringHelper;
30 
31 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
32 constexpr char FILEDIR[] = "/data/storage/el2/base/files/";
33 #endif
ObjectDump(EcmaRuntimeCallInfo * info)34 JSTaggedValue BuiltinsArkTools::ObjectDump(EcmaRuntimeCallInfo *info)
35 {
36     ASSERT(info);
37     JSThread *thread = info->GetThread();
38     [[maybe_unused]] EcmaHandleScope handleScope(thread);
39 
40     JSHandle<EcmaString> str = JSTaggedValue::ToString(thread, GetCallArg(info, 0));
41     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
42     // The default log level of ace_engine and js_runtime is error
43     LOG_ECMA(ERROR) << ": " << EcmaStringAccessor(str).ToStdString();
44 
45     uint32_t numArgs = info->GetArgsNumber();
46     for (uint32_t i = 1; i < numArgs; i++) {
47         JSHandle<JSTaggedValue> obj = GetCallArg(info, i);
48         std::ostringstream oss;
49         obj->Dump(oss);
50 
51         // The default log level of ace_engine and js_runtime is error
52         LOG_ECMA(ERROR) << ": " << oss.str();
53     }
54 
55     return JSTaggedValue::Undefined();
56 }
57 
CompareHClass(EcmaRuntimeCallInfo * info)58 JSTaggedValue BuiltinsArkTools::CompareHClass(EcmaRuntimeCallInfo *info)
59 {
60     ASSERT(info);
61     JSThread *thread = info->GetThread();
62     [[maybe_unused]] EcmaHandleScope handleScope(thread);
63 
64     JSHandle<JSTaggedValue> obj1 = GetCallArg(info, 0);
65     JSHandle<JSTaggedValue> obj2 = GetCallArg(info, 1);
66     JSHClass *obj1Hclass = obj1->GetTaggedObject()->GetClass();
67     JSHClass *obj2Hclass = obj2->GetTaggedObject()->GetClass();
68     std::ostringstream oss;
69     obj1Hclass->Dump(oss);
70     obj2Hclass->Dump(oss);
71     bool res = (obj1Hclass == obj2Hclass);
72     if (!res) {
73         LOG_ECMA(ERROR) << "These two object don't share the same hclass:" << oss.str();
74     }
75     return JSTaggedValue(res);
76 }
77 
DumpHClass(EcmaRuntimeCallInfo * info)78 JSTaggedValue BuiltinsArkTools::DumpHClass(EcmaRuntimeCallInfo *info)
79 {
80     ASSERT(info);
81     JSThread *thread = info->GetThread();
82     [[maybe_unused]] EcmaHandleScope handleScope(thread);
83 
84     JSHandle<JSTaggedValue> obj = GetCallArg(info, 0);
85     JSHClass *objHclass = obj->GetTaggedObject()->GetClass();
86     std::ostringstream oss;
87     objHclass->Dump(oss);
88 
89     LOG_ECMA(ERROR) << "hclass:" << oss.str();
90     return JSTaggedValue::Undefined();
91 }
92 
IsTSHClass(EcmaRuntimeCallInfo * info)93 JSTaggedValue BuiltinsArkTools::IsTSHClass(EcmaRuntimeCallInfo *info)
94 {
95     ASSERT(info);
96     JSThread *thread = info->GetThread();
97     [[maybe_unused]] EcmaHandleScope handleScope(thread);
98 
99     ASSERT(info->GetArgsNumber() == 1);
100     JSHandle<JSTaggedValue> object = GetCallArg(info, 0);
101     JSHClass *hclass = object->GetTaggedObject()->GetClass();
102     bool isTSHClass = hclass->IsTS();
103     return GetTaggedBoolean(isTSHClass);
104 }
105 
GetHClass(EcmaRuntimeCallInfo * info)106 JSTaggedValue BuiltinsArkTools::GetHClass(EcmaRuntimeCallInfo *info)
107 {
108     ASSERT(info);
109     JSThread *thread = info->GetThread();
110     [[maybe_unused]] EcmaHandleScope handleScope(thread);
111 
112     ASSERT(info->GetArgsNumber() == 1);
113     JSHandle<JSTaggedValue> object = GetCallArg(info, 0);
114     JSHClass *hclass = object->GetTaggedObject()->GetClass();
115     return JSTaggedValue(hclass);
116 }
117 
HasTSSubtyping(EcmaRuntimeCallInfo * info)118 JSTaggedValue BuiltinsArkTools::HasTSSubtyping(EcmaRuntimeCallInfo *info)
119 {
120     ASSERT(info);
121     JSThread *thread = info->GetThread();
122     [[maybe_unused]] EcmaHandleScope handleScope(thread);
123 
124     ASSERT(info->GetArgsNumber() == 1);
125     JSHandle<JSTaggedValue> object = GetCallArg(info, 0);
126     JSHClass *hclass = object->GetTaggedObject()->GetClass();
127     return GetTaggedBoolean(hclass->HasTSSubtyping());
128 }
129 
IsNotHoleProperty(EcmaRuntimeCallInfo * info)130 JSTaggedValue BuiltinsArkTools::IsNotHoleProperty(EcmaRuntimeCallInfo *info)
131 {
132     [[maybe_unused]] DisallowGarbageCollection noGc;
133     ASSERT(info);
134     JSThread *thread = info->GetThread();
135     [[maybe_unused]] EcmaHandleScope handleScope(thread);
136 
137     ASSERT(info->GetArgsNumber() == 2);  // 2 : object and key
138     JSHandle<JSTaggedValue> object = GetCallArg(info, 0);
139     JSTaggedValue key = GetCallArg(info, 1).GetTaggedValue();
140     JSHClass *hclass = object->GetTaggedObject()->GetClass();
141     int entry = JSHClass::FindPropertyEntry(thread, hclass, key);
142     if (entry == -1) {
143         return GetTaggedBoolean(false);
144     }
145     PropertyAttributes attr = LayoutInfo::Cast(hclass->GetLayout().GetTaggedObject())->GetAttr(entry);
146     return GetTaggedBoolean(attr.IsNotHole());
147 }
148 
ExcutePendingJob(EcmaRuntimeCallInfo * info)149 JSTaggedValue BuiltinsArkTools::ExcutePendingJob(EcmaRuntimeCallInfo *info)
150 {
151     ASSERT(info);
152     JSThread *thread = info->GetThread();
153     [[maybe_unused]] EcmaHandleScope handleScope(thread);
154 
155     thread->GetCurrentEcmaContext()->ExecutePromisePendingJob();
156     return JSTaggedValue::True();
157 }
158 
GetLexicalEnv(EcmaRuntimeCallInfo * info)159 JSTaggedValue BuiltinsArkTools::GetLexicalEnv(EcmaRuntimeCallInfo *info)
160 {
161     ASSERT(info);
162     JSThread *thread = info->GetThread();
163     [[maybe_unused]] EcmaHandleScope handleScope(thread);
164 
165     ASSERT(info->GetArgsNumber() == 1);
166     JSHandle<JSTaggedValue> object = GetCallArg(info, 0);
167     if (object->IsHeapObject() && object->IsJSFunction()) {
168         JSHandle<JSFunction> function = JSHandle<JSFunction>::Cast(object);
169         return function->GetLexicalEnv();
170     }
171     return JSTaggedValue::Null();
172 }
173 
ForceFullGC(EcmaRuntimeCallInfo * info)174 JSTaggedValue BuiltinsArkTools::ForceFullGC(EcmaRuntimeCallInfo *info)
175 {
176     ASSERT(info);
177     const_cast<Heap *>(info->GetThread()->GetEcmaVM()->GetHeap())->CollectGarbage(
178         TriggerGCType::FULL_GC, GCReason::EXTERNAL_TRIGGER);
179     return JSTaggedValue::True();
180 }
181 
RemoveAOTFlag(EcmaRuntimeCallInfo * info)182 JSTaggedValue BuiltinsArkTools::RemoveAOTFlag(EcmaRuntimeCallInfo *info)
183 {
184     ASSERT(info);
185     JSThread *thread = info->GetThread();
186     [[maybe_unused]] EcmaHandleScope handleScope(thread);
187 
188     ASSERT(info->GetArgsNumber() == 1);
189     JSHandle<JSTaggedValue> object = GetCallArg(info, 0);
190     if (object->IsHeapObject() && object->IsJSFunction()) {
191         JSHandle<JSFunction> func = JSHandle<JSFunction>::Cast(object);
192         JSHandle<Method> method = JSHandle<Method>(thread, func->GetMethod());
193         method->SetAotCodeBit(false);
194     }
195 
196     return JSTaggedValue::Undefined();
197 }
198 
199 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
StartCpuProfiler(EcmaRuntimeCallInfo * info)200 JSTaggedValue BuiltinsArkTools::StartCpuProfiler(EcmaRuntimeCallInfo *info)
201 {
202     ASSERT(info);
203     JSThread *thread = info->GetThread();
204     [[maybe_unused]] EcmaHandleScope handleScope(thread);
205 
206     auto vm = thread->GetEcmaVM();
207 
208     // get file name
209     JSHandle<JSTaggedValue> fileNameValue = GetCallArg(info, 0);
210     std::string fileName = "";
211     if (fileNameValue->IsString()) {
212         JSHandle<EcmaString> str = JSTaggedValue::ToString(thread, fileNameValue);
213         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
214         fileName = EcmaStringAccessor(str).ToStdString() + ".cpuprofile";
215     } else {
216         fileName = GetProfileName();
217     }
218 
219     if (!CreateFile(fileName)) {
220         LOG_ECMA(ERROR) << "CreateFile failed " << fileName;
221     }
222 
223     // get sampling interval
224     JSHandle<JSTaggedValue> samplingIntervalValue = GetCallArg(info, 1);
225     uint32_t interval = 500; // 500:Default Sampling interval 500 microseconds
226     if (samplingIntervalValue->IsNumber()) {
227         interval = JSTaggedValue::ToUint32(thread, samplingIntervalValue);
228     }
229 
230     DFXJSNApi::StartCpuProfilerForFile(vm, fileName, interval);
231     return JSTaggedValue::Undefined();
232 }
233 
StopCpuProfiler(EcmaRuntimeCallInfo * info)234 JSTaggedValue BuiltinsArkTools::StopCpuProfiler(EcmaRuntimeCallInfo *info)
235 {
236     JSThread *thread = info->GetThread();
237     [[maybe_unused]] EcmaHandleScope handleScope(thread);
238     auto vm = thread->GetEcmaVM();
239     DFXJSNApi::StopCpuProfilerForFile(vm);
240 
241     return JSTaggedValue::Undefined();
242 }
243 
GetProfileName()244 std::string BuiltinsArkTools::GetProfileName()
245 {
246     char time1[16] = {0}; // 16:Time format length
247     char time2[16] = {0}; // 16:Time format length
248     time_t timep = std::time(nullptr);
249     struct tm nowTime1;
250     localtime_r(&timep, &nowTime1);
251     size_t result = 0;
252     result = strftime(time1, sizeof(time1), "%Y%m%d", &nowTime1);
253     if (result == 0) {
254         LOG_ECMA(ERROR) << "get time failed";
255         return "";
256     }
257     result = strftime(time2, sizeof(time2), "%H%M%S", &nowTime1);
258     if (result == 0) {
259         LOG_ECMA(ERROR) << "get time failed";
260         return "";
261     }
262     std::string profileName = "cpuprofile-";
263     profileName += time1;
264     profileName += "TO";
265     profileName += time2;
266     profileName += ".cpuprofile";
267     return profileName;
268 }
269 
CreateFile(std::string & fileName)270 bool BuiltinsArkTools::CreateFile(std::string &fileName)
271 {
272     std::string path = FILEDIR + fileName;
273     if (access(path.c_str(), F_OK) == 0) {
274         if (access(path.c_str(), W_OK) == 0) {
275             fileName = path;
276             return true;
277         }
278         LOG_ECMA(ERROR) << "file create failed, W_OK false";
279         return false;
280     }
281     const mode_t defaultMode = S_IRUSR | S_IWUSR | S_IRGRP; // -rw-r--
282     int fd = creat(path.c_str(), defaultMode);
283     if (fd == -1) {
284         fd = creat(fileName.c_str(), defaultMode);
285         if (fd == -1) {
286             LOG_ECMA(ERROR) << "file create failed, errno = "<< errno;
287             return false;
288         }
289         close(fd);
290         return true;
291     } else {
292         fileName = path;
293         close(fd);
294         return true;
295     }
296 }
297 #endif
298 
299 // It is used to check whether an object is a proto, and this function can be
300 // used to check whether the state machine of IC is faulty.
IsPrototype(EcmaRuntimeCallInfo * info)301 JSTaggedValue BuiltinsArkTools::IsPrototype(EcmaRuntimeCallInfo *info)
302 {
303     ASSERT(info);
304     JSThread *thread = info->GetThread();
305     [[maybe_unused]] EcmaHandleScope handleScope(thread);
306 
307     JSHandle<JSTaggedValue> obj = GetCallArg(info, 0);
308     JSHClass *objHclass = obj->GetTaggedObject()->GetClass();
309     return JSTaggedValue(objHclass->IsPrototype());
310 }
311 
TimeInUs(EcmaRuntimeCallInfo * info)312 JSTaggedValue BuiltinsArkTools::TimeInUs([[maybe_unused]] EcmaRuntimeCallInfo *info)
313 {
314     ClockScope scope;
315     return JSTaggedValue(scope.GetCurTime());
316 }
317 }  // namespace panda::ecmascript::builtins
318