• 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 #ifndef ECMASCRIPT_JSOBJECT_INL_H
17 #define ECMASCRIPT_JSOBJECT_INL_H
18 
19 #include "ecmascript/js_hclass-inl.h"
20 #include "ecmascript/js_object.h"
21 #include "ecmascript/js_tagged_value-inl.h"
22 #include "ecmascript/js_typed_array.h"
23 #include "ecmascript/tagged_array-inl.h"
24 
25 namespace panda::ecmascript {
SetBuiltinsCtorMode()26 inline void ECMAObject::SetBuiltinsCtorMode()
27 {
28     GetClass()->SetBuiltinsCtor(true);
29 }
30 
IsBuiltinsConstructor()31 inline bool ECMAObject::IsBuiltinsConstructor() const
32 {
33     return GetClass()->IsBuiltinsCtor();
34 }
35 
SetCallable(bool flag)36 inline void ECMAObject::SetCallable(bool flag)
37 {
38     GetClass()->SetCallable(flag);
39 }
40 
IsCallable()41 inline bool ECMAObject::IsCallable() const
42 {
43     return GetClass()->IsCallable();
44 }
45 
46 // JSObject
IsExtensible()47 inline bool JSObject::IsExtensible() const
48 {
49     return GetJSHClass()->IsExtensible();
50 }
51 
FillElementsWithHoles(const JSThread * thread,uint32_t start,uint32_t end)52 inline void JSObject::FillElementsWithHoles(const JSThread *thread, uint32_t start, uint32_t end)
53 {
54     if (start >= end) {
55         return;
56     }
57 
58     TaggedArray *elements = TaggedArray::Cast(GetElements().GetTaggedObject());
59     for (uint32_t i = start; i < end; i++) {
60         elements->Set(thread, i, JSTaggedValue::Hole());
61     }
62 }
63 
GetJSHClass()64 inline JSHClass *JSObject::GetJSHClass() const
65 {
66     return GetClass();
67 }
68 
IsJSGlobalObject()69 inline bool JSObject::IsJSGlobalObject() const
70 {
71     return GetJSHClass()->IsJSGlobalObject();
72 }
73 
IsConstructor()74 inline bool JSObject::IsConstructor() const
75 {
76     return GetJSHClass()->IsConstructor();
77 }
78 
IsECMAObject()79 inline bool JSObject::IsECMAObject() const
80 {
81     return GetJSHClass()->IsECMAObject();
82 }
83 
IsJSError()84 inline bool JSObject::IsJSError() const
85 {
86     return GetJSHClass()->IsJSError();
87 }
88 
IsArguments()89 inline bool JSObject::IsArguments() const
90 {
91     return GetJSHClass()->IsArguments();
92 }
93 
IsDate()94 inline bool JSObject::IsDate() const
95 {
96     return GetJSHClass()->IsDate();
97 }
98 
IsJSArray()99 inline bool JSObject::IsJSArray() const
100 {
101     return GetJSHClass()->IsJSArray();
102 }
103 
IsJSMap()104 inline bool JSObject::IsJSMap() const
105 {
106     return GetJSHClass()->IsJSMap();
107 }
108 
IsJSSet()109 inline bool JSObject::IsJSSet() const
110 {
111     return GetJSHClass()->IsJSSet();
112 }
113 
IsJSRegExp()114 inline bool JSObject::IsJSRegExp() const
115 {
116     return GetJSHClass()->IsJSRegExp();
117 }
118 
IsJSFunction()119 inline bool JSObject::IsJSFunction() const
120 {
121     return GetJSHClass()->IsJSFunction();
122 }
123 
IsBoundFunction()124 inline bool JSObject::IsBoundFunction() const
125 {
126     return GetJSHClass()->IsJsBoundFunction();
127 }
128 
IsJSIntlBoundFunction()129 inline bool JSObject::IsJSIntlBoundFunction() const
130 {
131     return GetJSHClass()->IsJSIntlBoundFunction();
132 }
133 
IsProxyRevocFunction()134 inline bool JSObject::IsProxyRevocFunction() const
135 {
136     return GetJSHClass()->IsJSProxyRevocFunction();
137 }
138 
IsAccessorData()139 inline bool JSObject::IsAccessorData() const
140 {
141     return GetJSHClass()->IsAccessorData();
142 }
143 
IsJSGlobalEnv()144 inline bool JSObject::IsJSGlobalEnv() const
145 {
146     return GetJSHClass()->IsJsGlobalEnv();
147 }
148 
IsJSProxy()149 inline bool JSObject::IsJSProxy() const
150 {
151     return GetJSHClass()->IsJSProxy();
152 }
153 
IsGeneratorObject()154 inline bool JSObject::IsGeneratorObject() const
155 {
156     return GetJSHClass()->IsGeneratorObject();
157 }
158 
IsForinIterator()159 inline bool JSObject::IsForinIterator() const
160 {
161     return GetJSHClass()->IsForinIterator();
162 }
163 
IsJSSetIterator()164 inline bool JSObject::IsJSSetIterator() const
165 {
166     return GetJSHClass()->IsJSSetIterator();
167 }
168 
IsJSMapIterator()169 inline bool JSObject::IsJSMapIterator() const
170 {
171     return GetJSHClass()->IsJSMapIterator();
172 }
173 
IsJSArrayIterator()174 inline bool JSObject::IsJSArrayIterator() const
175 {
176     return GetJSHClass()->IsJSArrayIterator();
177 }
178 
IsJSAPIArrayListIterator()179 inline bool JSObject::IsJSAPIArrayListIterator() const
180 {
181     return GetJSHClass()->IsJSAPIArrayListIterator();
182 }
183 
IsJSPrimitiveRef()184 inline bool JSObject::IsJSPrimitiveRef() const
185 {
186     return GetJSHClass()->IsJsPrimitiveRef();
187 }
188 
IsElementDict()189 inline bool JSObject::IsElementDict() const
190 {
191     return TaggedArray::Cast(GetElements().GetTaggedObject())->IsDictionaryMode();
192 }
193 
IsPropertiesDict()194 inline bool JSObject::IsPropertiesDict() const
195 {
196     return TaggedArray::Cast(GetProperties().GetTaggedObject())->IsDictionaryMode();
197 }
198 
IsTypedArray()199 inline bool JSObject::IsTypedArray() const
200 {
201     return GetJSHClass()->IsTypedArray();
202 }
203 
SetPropertyInlinedProps(const JSThread * thread,uint32_t index,JSTaggedValue value)204 void JSObject::SetPropertyInlinedProps(const JSThread *thread, uint32_t index, JSTaggedValue value)
205 {
206     SetPropertyInlinedProps(thread, GetJSHClass(), index, value);
207 }
208 
GetPropertyInlinedProps(uint32_t index)209 JSTaggedValue JSObject::GetPropertyInlinedProps(uint32_t index) const
210 {
211     return GetPropertyInlinedProps(GetJSHClass(), index);
212 }
213 
SetPropertyInlinedProps(const JSThread * thread,const JSHClass * hclass,uint32_t index,JSTaggedValue value)214 void JSObject::SetPropertyInlinedProps(const JSThread *thread, const JSHClass *hclass, uint32_t index,
215                                        JSTaggedValue value)
216 {
217     uint32_t offset = hclass->GetInlinedPropertiesOffset(index);
218     SET_VALUE_WITH_BARRIER(thread, this, offset, value);
219 }
220 
GetPropertyInlinedProps(const JSHClass * hclass,uint32_t index)221 JSTaggedValue JSObject::GetPropertyInlinedProps(const JSHClass *hclass, uint32_t index) const
222 {
223     uint32_t offset = hclass->GetInlinedPropertiesOffset(index);
224     return JSTaggedValue(GET_VALUE(this, offset));
225 }
226 
GetProperty(const JSHClass * hclass,PropertyAttributes attr)227 JSTaggedValue JSObject::GetProperty(const JSHClass *hclass, PropertyAttributes attr) const
228 {
229     if (attr.IsInlinedProps()) {
230         return GetPropertyInlinedProps(hclass, attr.GetOffset());
231     }
232     TaggedArray *array = TaggedArray::Cast(GetProperties().GetTaggedObject());
233     return array->Get(attr.GetOffset() - hclass->GetInlinedProperties());
234 }
235 
SetProperty(const JSThread * thread,const JSHClass * hclass,PropertyAttributes attr,JSTaggedValue value)236 void JSObject::SetProperty(const JSThread *thread, const JSHClass *hclass, PropertyAttributes attr, JSTaggedValue value)
237 {
238     if (attr.IsInlinedProps()) {
239         SetPropertyInlinedProps(thread, hclass, attr.GetOffset(), value);
240     } else {
241         TaggedArray *array = TaggedArray::Cast(GetProperties().GetTaggedObject());
242         array->Set(thread, attr.GetOffset() - hclass->GetInlinedProperties(), value);
243     }
244 }
245 
ShouldTransToDict(uint32_t capacity,uint32_t index)246 inline bool JSObject::ShouldTransToDict(uint32_t capacity, uint32_t index)
247 {
248     if (index < capacity) {
249         return false;
250     }
251     if (index - capacity > MAX_GAP) {
252         return true;
253     }
254 
255     if (capacity >= MIN_GAP) {
256         return index > capacity * FAST_ELEMENTS_FACTOR;
257     }
258 
259     return false;
260 }
261 
ComputeElementCapacity(uint32_t oldCapacity)262 inline uint32_t JSObject::ComputeElementCapacity(uint32_t oldCapacity)
263 {
264     uint32_t newCapacity = oldCapacity + (oldCapacity >> 1U);
265     return newCapacity > MIN_ELEMENTS_LENGTH ? newCapacity : MIN_ELEMENTS_LENGTH;
266 }
267 
ComputePropertyCapacity(uint32_t oldCapacity)268 inline uint32_t JSObject::ComputePropertyCapacity(uint32_t oldCapacity)
269 {
270     uint32_t newCapacity = oldCapacity + PROPERTIES_GROW_SIZE;
271     return newCapacity > JSHClass::MAX_CAPACITY_OF_OUT_OBJECTS ? JSHClass::MAX_CAPACITY_OF_OUT_OBJECTS
272                                                                : newCapacity;
273 }
274 
275 // static
276 template<ElementTypes types>
CreateListFromArrayLike(JSThread * thread,const JSHandle<JSTaggedValue> & obj)277 JSHandle<JSTaggedValue> JSObject::CreateListFromArrayLike(JSThread *thread, const JSHandle<JSTaggedValue> &obj)
278 {
279     // 3. If Type(obj) is not Object, throw a TypeError exception.
280     if (!obj->IsECMAObject()) {
281         THROW_TYPE_ERROR_AND_RETURN(thread, "CreateListFromArrayLike must accept object",
282                                     JSHandle<JSTaggedValue>(thread, JSTaggedValue::Exception()));
283     }
284     // 4. Let len be ToLength(Get(obj, "length")).
285     JSHandle<JSTaggedValue> lengthKeyHandle = thread->GlobalConstants()->GetHandledLengthString();
286 
287     JSHandle<JSTaggedValue> value = GetProperty(thread, obj, lengthKeyHandle).GetValue();
288     JSTaggedNumber number = JSTaggedValue::ToLength(thread, value);
289     // 5. ReturnIfAbrupt(len).
290     RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
291     if (number.GetNumber() > MAX_ELEMENT_INDEX) {
292         THROW_TYPE_ERROR_AND_RETURN(thread, "len is bigger than 2^32 - 1",
293                                     JSHandle<JSTaggedValue>(thread, JSTaggedValue::Exception()));
294     }
295 
296     uint32_t len = number.ToUint32();
297     // 6. Let list be an empty List.
298     JSHandle<TaggedArray> array = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(len);
299 
300     if (obj->IsTypedArray()) {
301         JSTypedArray::FastCopyElementToArray(thread, obj, array);
302         // c. ReturnIfAbrupt(next).
303         RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
304         return JSHandle<JSTaggedValue>(array);
305     }
306     // 8. Repeat while index < len
307     for (uint32_t i = 0; i < len; i++) {
308         JSTaggedValue next = JSTaggedValue::GetProperty(thread, obj, i).GetValue().GetTaggedValue();
309         // c. ReturnIfAbrupt(next).
310         RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
311 
312         if constexpr (types == ElementTypes::STRING_AND_SYMBOL) {
313             if (!next.IsString() && !next.IsSymbol()) {
314                 THROW_TYPE_ERROR_AND_RETURN(thread, "CreateListFromArrayLike: not an element of elementTypes",
315                                             JSHandle<JSTaggedValue>(thread, JSTaggedValue::Exception()));
316             }
317         }
318 
319         array->Set(thread, i, next);
320     }
321     return JSHandle<JSTaggedValue>(array);
322 }
323 
ShouldGetValueFromBox(ObjectOperator * op)324 inline JSTaggedValue JSObject::ShouldGetValueFromBox(ObjectOperator *op)
325 {
326     JSTaggedValue result = op->GetValue();
327     if (result.IsPropertyBox()) {
328         result = PropertyBox::Cast(result.GetTaggedObject())->GetValue();
329     }
330     return result;
331 }
332 }  //  namespace panda::ecmascript
333 #endif  // ECMASCRIPT_JSOBJECT_INL_H
334