• 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 "runtime/tooling/inspector/object_repository.h"
17 
18 #include "runtime/handle_scope-inl.h"
19 #include "runtime/include/tooling/inspector_extension.h"
20 
21 namespace ark::tooling::inspector {
ObjectRepository()22 ObjectRepository::ObjectRepository()
23     : extension_(ManagedThread::GetCurrent()->GetLanguageContext().CreateInspectorExtension()),
24       scope_(ManagedThread::GetCurrent())
25 {
26 }
27 
CreateGlobalObject()28 RemoteObject ObjectRepository::CreateGlobalObject()
29 {
30     return RemoteObject::Object("[Global]", GLOBAL_OBJECT_ID, "Global object");
31 }
32 
CreateFrameObject(const PtFrame & frame,const std::map<std::string,TypedValue> & locals,std::optional<RemoteObject> & objThis)33 RemoteObject ObjectRepository::CreateFrameObject(const PtFrame &frame, const std::map<std::string, TypedValue> &locals,
34                                                  std::optional<RemoteObject> &objThis)
35 {
36     ASSERT(ManagedThread::GetCurrent()->GetMutatorLock()->HasLock());
37 
38     std::vector<PropertyDescriptor> properties;
39     properties.reserve(locals.size());
40     auto thisParamName = extension_->GetThisParameterName();
41     for (const auto &[paramName, value] : locals) {
42         auto obj = CreateObject(value);
43         if (paramName == thisParamName) {
44             objThis.emplace(std::move(obj));
45         } else {
46             properties.emplace_back(paramName, std::move(obj));
47         }
48     }
49 
50     auto id = counter_++;
51     frames_.emplace(id, std::move(properties));
52 
53     return RemoteObject::Object("", id, "Frame #" + std::to_string(frame.GetFrameId()));
54 }
55 
CreateObject(TypedValue value)56 RemoteObject ObjectRepository::CreateObject(TypedValue value)
57 {
58     ASSERT(ManagedThread::GetCurrent()->GetMutatorLock()->HasLock());
59 
60     switch (value.GetType()) {
61         case panda_file::Type::TypeId::INVALID:
62         case panda_file::Type::TypeId::VOID:
63             return RemoteObject::Undefined();
64         case panda_file::Type::TypeId::U1:
65             return RemoteObject::Boolean(value.GetAsU1());
66         case panda_file::Type::TypeId::I8:
67             return RemoteObject::Number(value.GetAsI8());
68         case panda_file::Type::TypeId::U8:
69             return RemoteObject::Number(value.GetAsU8());
70         case panda_file::Type::TypeId::I16:
71             return RemoteObject::Number(value.GetAsI16());
72         case panda_file::Type::TypeId::U16:
73             return RemoteObject::Number(value.GetAsU16());
74         case panda_file::Type::TypeId::I32:
75             return RemoteObject::Number(value.GetAsI32());
76         case panda_file::Type::TypeId::U32:
77             return RemoteObject::Number(value.GetAsU32());
78         case panda_file::Type::TypeId::F32:
79             return RemoteObject::Number(value.GetAsF32());
80         case panda_file::Type::TypeId::F64:
81             return RemoteObject::Number(value.GetAsF64());
82         case panda_file::Type::TypeId::I64:
83             return RemoteObject::Number(value.GetAsI64());
84         case panda_file::Type::TypeId::U64:
85             return RemoteObject::Number(value.GetAsU64());
86         case panda_file::Type::TypeId::REFERENCE:
87             return CreateObject(value.GetAsReference());
88         case panda_file::Type::TypeId::TAGGED:
89             return CreateObject(value.GetAsTagged());
90     }
91     UNREACHABLE();
92 }
93 
GetProperties(RemoteObjectId id,bool generatePreview)94 std::vector<PropertyDescriptor> ObjectRepository::GetProperties(RemoteObjectId id, bool generatePreview)
95 {
96     ASSERT(ManagedThread::GetCurrent()->GetMutatorLock()->HasLock());
97 
98     auto properties = GetProperties(id);
99 
100     if (generatePreview) {
101         for (auto &property : properties) {
102             if (property.IsAccessor()) {
103                 continue;
104             }
105 
106             auto &value = property.GetValue();
107             if (auto valueId = value.GetObjectId()) {
108                 value.GeneratePreview(GetProperties(*valueId));
109             }
110         }
111     }
112 
113     return properties;
114 }
115 
CreateObject(coretypes::TaggedValue value)116 RemoteObject ObjectRepository::CreateObject(coretypes::TaggedValue value)
117 {
118     if (value.IsHeapObject()) {
119         return CreateObject(value.GetHeapObject());
120     }
121     if (value.IsUndefined() || value.IsHole()) {
122         return RemoteObject::Undefined();
123     }
124     if (value.IsNull()) {
125         return RemoteObject::Null();
126     }
127     if (value.IsBoolean()) {
128         return RemoteObject::Boolean(value.IsTrue());
129     }
130     if (value.IsInt()) {
131         return RemoteObject::Number(value.GetInt());
132     }
133     if (value.IsDouble()) {
134         return RemoteObject::Number(value.GetDouble());
135     }
136     UNREACHABLE();
137 }
138 
CreateObject(ObjectHeader * object)139 RemoteObject ObjectRepository::CreateObject(ObjectHeader *object)
140 {
141     ASSERT(ManagedThread::GetCurrent()->GetMutatorLock()->HasLock());
142 
143     if (object == nullptr) {
144         return RemoteObject::Null();
145     }
146 
147     if (auto str = extension_->GetAsString(object)) {
148         return RemoteObject::String(*str);
149     }
150 
151     RemoteObjectId id;
152 
153     // SUPPRESS_CSA_NEXTLINE(alpha.core.WasteObjHeader)
154     auto it = std::find_if(objects_.begin(), objects_.end(), [object](auto &p) { return p.second.GetPtr() == object; });
155     if (it == objects_.end()) {
156         id = counter_++;
157 
158         objects_.emplace(std::piecewise_construct, std::forward_as_tuple(id),
159                          std::forward_as_tuple(ManagedThread::GetCurrent(), object));
160     } else {
161         id = it->first;
162     }
163 
164     // SUPPRESS_CSA_NEXTLINE(alpha.core.WasteObjHeader)
165     if (auto arrayLen = extension_->GetLengthIfArray(object)) {
166         // SUPPRESS_CSA_NEXTLINE(alpha.core.WasteObjHeader)
167         return RemoteObject::Array(extension_->GetClassName(object), *arrayLen, id);
168     }
169 
170     // SUPPRESS_CSA_NEXTLINE(alpha.core.WasteObjHeader)
171     return RemoteObject::Object(extension_->GetClassName(object), id);
172 }
173 
GetProperties(RemoteObjectId id)174 std::vector<PropertyDescriptor> ObjectRepository::GetProperties(RemoteObjectId id)
175 {
176     ASSERT(ManagedThread::GetCurrent()->GetMutatorLock()->HasLock());
177 
178     auto fIt = frames_.find(id);
179     if (fIt != frames_.end()) {
180         ASSERT(objects_.find(id) == objects_.end());
181         return fIt->second;
182     }
183 
184     std::vector<PropertyDescriptor> properties;
185     auto propertyHandler = [this, &properties](auto &name, auto value, auto isArrayElement, auto isFinal,
186                                                auto isAccessor) {
187         auto property = isAccessor ? PropertyDescriptor::Accessor(name, CreateObject(value))
188                                    : PropertyDescriptor(name, CreateObject(value), isArrayElement);
189         if (!isAccessor && isFinal) {
190             property.SetWritable(false);
191         }
192         properties.emplace_back(std::move(property));
193     };
194 
195     if (id == GLOBAL_OBJECT_ID) {
196         ASSERT(objects_.find(id) == objects_.end());
197         extension_->EnumerateGlobals(propertyHandler);
198     } else {
199         auto oIt = objects_.find(id);
200         if (oIt == objects_.end()) {
201             LOG(INFO, DEBUGGER) << "Unknown object ID " << id;
202             return {};
203         }
204 
205         extension_->EnumerateProperties(oIt->second.GetPtr(), propertyHandler);
206     }
207 
208     return properties;
209 }
210 }  // namespace ark::tooling::inspector
211