• 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/object_operator.h"
17 
18 #include "ecmascript/accessor_data.h"
19 #include "ecmascript/ecma_vm.h"
20 #include "ecmascript/element_accessor-inl.h"
21 #include "ecmascript/global_dictionary-inl.h"
22 #include "ecmascript/global_dictionary.h"
23 #include "ecmascript/global_env.h"
24 #include "ecmascript/ic/property_box.h"
25 #include "ecmascript/js_array.h"
26 #include "ecmascript/js_function.h"
27 #include "ecmascript/js_hclass-inl.h"
28 #include "ecmascript/js_object-inl.h"
29 #include "ecmascript/js_primitive_ref.h"
30 #include "ecmascript/layout_info.h"
31 #include "ecmascript/mem/c_string.h"
32 #include "ecmascript/object_factory.h"
33 #include "ecmascript/object_fast_operator-inl.h"
34 #include "ecmascript/property_attributes.h"
35 #include "ecmascript/property_detector-inl.h"
36 #include "ecmascript/tagged_dictionary.h"
37 
38 namespace panda::ecmascript {
HandleKey(const JSHandle<JSTaggedValue> & key)39 void ObjectOperator::HandleKey(const JSHandle<JSTaggedValue> &key)
40 {
41     if (key->IsInt()) {
42         int32_t keyInt = key->GetInt();
43         if (keyInt >= 0) {
44             elementIndex_ = static_cast<uint32_t>(keyInt);
45             return;
46         }
47         key_ = JSHandle<JSTaggedValue>::Cast(base::NumberHelper::NumberToString(thread_, JSTaggedValue(keyInt)));
48         return;
49     }
50 
51     if (key->IsString()) {
52         keyFromStringType_ = true;
53         uint32_t index = 0;
54         if (JSTaggedValue::ToElementIndex(key.GetTaggedValue(), &index)) {
55             ASSERT(index < JSObject::MAX_ELEMENT_INDEX);
56             elementIndex_ = index;
57             return;
58         }
59         if (EcmaStringAccessor(key->GetTaggedObject()).IsInternString()) {
60             key_ = key;
61             return;
62         }
63         key_ = JSHandle<JSTaggedValue>(thread_, thread_->GetEcmaVM()->GetFactory()->InternString(key));
64         return;
65     }
66 
67     if (key->IsDouble()) {
68         double number = key->GetDouble();
69         if (number >= 0 && number < JSObject::MAX_ELEMENT_INDEX) {
70             auto integer = static_cast<uint32_t>(number);
71             if (integer == number) {
72                 elementIndex_ = static_cast<uint32_t>(number);
73                 return;
74             }
75         }
76         key_ = JSHandle<JSTaggedValue>::Cast(base::NumberHelper::NumberToString(thread_, key.GetTaggedValue()));
77         return;
78     }
79 
80     if (key->IsSymbol()) {
81         key_ = key;
82         return;
83     }
84 
85     JSHandle<JSTaggedValue> keyHandle(thread_, JSTaggedValue::ToPrimitive(thread_, key, PREFER_STRING));
86     if (key->IsSymbol()) {
87         key_ = keyHandle;
88         return;
89     }
90     key_ = JSHandle<JSTaggedValue>(thread_,
91                                    thread_->GetEcmaVM()->GetFactory()->InternString(
92                                        JSHandle<JSTaggedValue>::Cast(JSTaggedValue::ToString(thread_, keyHandle))));
93 }
94 
UpdateHolder()95 void ObjectOperator::UpdateHolder()
96 {
97     if (holder_->IsString() && (GetThroughElement() || GetStringLength())) {
98         JSHandle<JSTaggedValue> undefined = thread_->GlobalConstants()->GetHandledUndefined();
99         holder_.Update(JSPrimitiveRef::StringCreate(thread_, holder_, undefined).GetTaggedValue());
100     } else {
101         holder_.Update(JSTaggedValue::ToPrototypeOrObj(thread_, holder_).GetTaggedValue());
102     }
103 }
104 
UpdateIsTSHClass()105 void ObjectOperator::UpdateIsTSHClass()
106 {
107     if (!holder_->IsECMAObject()) {
108         SetIsTSHClass(false);
109         return;
110     }
111     auto hclass = JSHandle<JSObject>::Cast(holder_)->GetClass();
112     if (hclass->IsTS()) {
113         SetIsTSHClass(true);
114     }
115 }
116 
StartLookUp(OperatorType type)117 void ObjectOperator::StartLookUp(OperatorType type)
118 {
119     UpdateHolder();
120 
121     if (type == OperatorType::OWN) {
122         LookupPropertyInHolder();
123     } else {
124         LookupProperty();
125     }
126 }
127 
StartGlobalLookUp(OperatorType type)128 void ObjectOperator::StartGlobalLookUp(OperatorType type)
129 {
130     UpdateHolder();
131 
132     if (type == OperatorType::OWN) {
133         GlobalLookupPropertyInHolder();
134     } else {
135         GlobalLookupProperty();
136     }
137 }
138 
ObjectOperator(JSThread * thread,const JSHandle<JSTaggedValue> & key,OperatorType type)139 ObjectOperator::ObjectOperator(JSThread *thread, const JSHandle<JSTaggedValue> &key, OperatorType type)
140     : thread_(thread),
141       holder_(thread, thread->GetEcmaVM()->GetGlobalEnv()->GetGlobalObject()),
142       receiver_(thread, thread->GetEcmaVM()->GetGlobalEnv()->GetGlobalObject())
143 {
144     HandleKey(key);
145     StartGlobalLookUp(type);
146 }
147 
ObjectOperator(JSThread * thread,const JSHandle<JSObject> & holder,const JSHandle<JSTaggedValue> & key,OperatorType type)148 ObjectOperator::ObjectOperator(JSThread *thread, const JSHandle<JSObject> &holder, const JSHandle<JSTaggedValue> &key,
149                                OperatorType type)
150     : thread_(thread), holder_(thread, holder.GetTaggedValue()), receiver_(thread, holder.GetTaggedValue())
151 {
152     HandleKey(key);
153     StartLookUp(type);
154 }
155 
ObjectOperator(JSThread * thread,const JSHandle<JSTaggedValue> & holder,const JSHandle<JSTaggedValue> & key,OperatorType type)156 ObjectOperator::ObjectOperator(JSThread *thread, const JSHandle<JSTaggedValue> &holder,
157                                const JSHandle<JSTaggedValue> &key, OperatorType type)
158     : thread_(thread), holder_(thread, holder.GetTaggedValue()), receiver_(thread, holder.GetTaggedValue())
159 {
160     HandleKey(key);
161     StartLookUp(type);
162 }
163 
ObjectOperator(JSThread * thread,const JSHandle<JSTaggedValue> & holder,uint32_t index,OperatorType type)164 ObjectOperator::ObjectOperator(JSThread *thread, const JSHandle<JSTaggedValue> &holder, uint32_t index,
165                                OperatorType type)
166     : thread_(thread),
167       holder_(thread, holder.GetTaggedValue()),
168       receiver_(thread, holder.GetTaggedValue()),
169       elementIndex_(index)
170 {
171     StartLookUp(type);
172 }
173 
ObjectOperator(JSThread * thread,const JSHandle<JSTaggedValue> & holder,const JSHandle<JSTaggedValue> & receiver,const JSHandle<JSTaggedValue> & key,OperatorType type)174 ObjectOperator::ObjectOperator(JSThread *thread, const JSHandle<JSTaggedValue> &holder,
175                                const JSHandle<JSTaggedValue> &receiver, const JSHandle<JSTaggedValue> &key,
176                                OperatorType type)
177     : thread_(thread), holder_(thread, holder.GetTaggedValue()), receiver_(thread, receiver.GetTaggedValue())
178 {
179     SetHasReceiver(true);
180     HandleKey(key);
181     StartLookUp(type);
182 }
183 
184 // op for fast path
ObjectOperator(JSThread * thread,const JSTaggedValue & receiver,const JSTaggedValue & name,OperatorType type)185 ObjectOperator::ObjectOperator(JSThread *thread, const JSTaggedValue &receiver, const JSTaggedValue &name,
186                                OperatorType type)
187     : thread_(thread), holder_(thread, receiver), receiver_(thread, receiver), key_(thread, name)
188 {
189     ASSERT(name.IsStringOrSymbol());
190     StartLookUp(type);
191 }
FastGetValue()192 JSHandle<JSTaggedValue> ObjectOperator::FastGetValue()
193 {
194     ASSERT(IsFound() && !value_.IsEmpty());
195     if (value_->IsPropertyBox()) {
196         value_.Update(PropertyBox::Cast(value_->GetTaggedObject())->GetValue());
197     }
198     if (!IsAccessorDescriptor()) {
199         return value_;
200     }
201     AccessorData *accessor = AccessorData::Cast(value_->GetTaggedObject());
202     ASSERT(!accessor->IsInternal());
203     // 8. Return Call(getter, Receiver).
204     return JSHandle<JSTaggedValue>(thread_, JSObject::CallGetter(thread_, accessor, receiver_));
205 }
ObjectOperator(JSThread * thread,const JSTaggedValue & receiver,const JSTaggedValue & name,const PropertyAttributes & attr)206 ObjectOperator::ObjectOperator(JSThread *thread, const JSTaggedValue &receiver, const JSTaggedValue &name,
207                                const PropertyAttributes &attr)
208     : thread_(thread), receiver_(thread, receiver), key_(thread, name)
209 {
210     SetAttr(attr);
211 }
FastAdd(JSThread * thread,const JSTaggedValue & receiver,const JSTaggedValue & name,const JSHandle<JSTaggedValue> & value,const PropertyAttributes & attr)212 void ObjectOperator::FastAdd(JSThread *thread, const JSTaggedValue &receiver, const JSTaggedValue &name,
213                              const JSHandle<JSTaggedValue> &value, const PropertyAttributes &attr)
214 {
215     ObjectOperator op(thread, receiver, name, attr);
216     op.AddPropertyInternal(value);
217 }
218 
219 // static
UpdateDetectorOnSetPrototype(const JSThread * thread,JSTaggedValue receiver)220 void ObjectOperator::UpdateDetectorOnSetPrototype(const JSThread *thread, JSTaggedValue receiver)
221 {
222     // skip env prepare
223     if (!thread->IsReadyToUpdateDetector()) {
224         return;
225     }
226     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
227     JSHClass *hclass = receiver.GetTaggedObject()->GetClass();
228     JSType type = hclass->GetObjectType();
229     switch (type) {
230         case JSType::JS_REG_EXP: {
231             if (PropertyDetector::IsRegExpReplaceDetectorValid(env)) {
232                 PropertyDetector::InvalidateRegExpReplaceDetector(env);
233             }
234             if (PropertyDetector::IsRegExpSplitDetectorValid(env)) {
235                 PropertyDetector::InvalidateRegExpSplitDetector(env);
236             }
237             return;
238         }
239         case JSType::JS_MAP: {
240             if (PropertyDetector::IsMapIteratorDetectorValid(env)) {
241                 PropertyDetector::InvalidateMapIteratorDetector(env);
242             }
243             return;
244         }
245         case JSType::JS_SET: {
246             if (PropertyDetector::IsSetIteratorDetectorValid(env)) {
247                 PropertyDetector::InvalidateSetIteratorDetector(env);
248             }
249             return;
250         }
251         case JSType::JS_PRIMITIVE_REF: {
252             if (JSPrimitiveRef::Cast(receiver.GetTaggedObject())->IsString() &&
253                 PropertyDetector::IsStringIteratorDetectorValid(env)) {
254                 PropertyDetector::InvalidateStringIteratorDetector(env);
255             }
256             return;
257         }
258         case JSType::JS_ARRAY: {
259             if (PropertyDetector::IsArrayIteratorDetectorValid(env)) {
260                 PropertyDetector::InvalidateArrayIteratorDetector(env);
261             }
262             return;
263         }
264         case JSType::JS_INT8_ARRAY:
265         case JSType::JS_UINT8_ARRAY:
266         case JSType::JS_UINT8_CLAMPED_ARRAY:
267         case JSType::JS_INT16_ARRAY:
268         case JSType::JS_UINT16_ARRAY:
269         case JSType::JS_INT32_ARRAY:
270         case JSType::JS_UINT32_ARRAY:
271         case JSType::JS_FLOAT32_ARRAY:
272         case JSType::JS_FLOAT64_ARRAY:
273         case JSType::JS_BIGINT64_ARRAY:
274         case JSType::JS_BIGUINT64_ARRAY: {
275             if (PropertyDetector::IsTypedArrayIteratorDetectorValid(env)) {
276                 PropertyDetector::InvalidateTypedArrayIteratorDetector(env);
277             }
278             if (PropertyDetector::IsTypedArraySpeciesProtectDetectorValid(env)) {
279                 PropertyDetector::InvalidateTypedArraySpeciesProtectDetector(env);
280             }
281             return;
282         }
283         default:
284             break;
285     }
286 
287     if (hclass->IsPrototype() &&
288         (receiver == env->GetTaggedInt8ArrayFunctionPrototype() ||
289          receiver == env->GetTaggedUint8ArrayFunctionPrototype() ||
290          receiver == env->GetTaggedUint8ClampedArrayFunctionPrototype() ||
291          receiver == env->GetTaggedInt16ArrayFunctionPrototype() ||
292          receiver == env->GetTaggedUint16ArrayFunctionPrototype() ||
293          receiver == env->GetTaggedInt32ArrayFunctionPrototype() ||
294          receiver == env->GetTaggedUint32ArrayFunctionPrototype() ||
295          receiver == env->GetTaggedFloat32ArrayFunctionPrototype() ||
296          receiver == env->GetTaggedFloat64ArrayFunctionPrototype() ||
297          receiver == env->GetTaggedBigInt64ArrayFunctionPrototype() ||
298          receiver == env->GetTaggedBigUint64ArrayFunctionPrototype()) &&
299          PropertyDetector::IsTypedArrayIteratorDetectorValid(env)) {
300         PropertyDetector::InvalidateTypedArrayIteratorDetector(env);
301         return;
302     }
303 }
304 
UpdateDetector()305 void ObjectOperator::UpdateDetector()
306 {
307     if (IsElement()) {
308         return;
309     }
310     ObjectOperator::UpdateDetector(thread_, holder_.GetTaggedValue(), key_.GetTaggedValue());
311 }
312 
313 // static
UpdateDetector(const JSThread * thread,JSTaggedValue receiver,JSTaggedValue key)314 void ObjectOperator::UpdateDetector(const JSThread *thread, JSTaggedValue receiver, JSTaggedValue key)
315 {
316     // skip env prepare
317     if (!thread->IsReadyToUpdateDetector()) {
318         return;
319     }
320     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
321     bool maybeDetector = IsDetectorName(env, key);
322     if (!maybeDetector) {
323         return;
324     }
325     // only support symbol keys now
326     ASSERT(key.IsSymbol());
327     if (key == env->GetTaggedReplaceSymbol()) {
328         if (receiver.IsJSRegExp() || receiver == env->GetTaggedRegExpPrototype()) {
329             if (!PropertyDetector::IsRegExpReplaceDetectorValid(env)) {
330                 return;
331             }
332             PropertyDetector::InvalidateRegExpReplaceDetector(env);
333         }
334     } else if (key == env->GetTaggedSplitSymbol()) {
335         if (receiver.IsJSRegExp() || receiver == env->GetTaggedRegExpPrototype()) {
336             if (!PropertyDetector::IsRegExpSplitDetectorValid(env)) {
337                 return;
338             }
339             PropertyDetector::InvalidateRegExpSplitDetector(env);
340         }
341     } else if (key == env->GetTaggedIteratorSymbol()) {
342         if (receiver.IsJSMap() || receiver == env->GetTaggedMapPrototype()) {
343             if (!PropertyDetector::IsMapIteratorDetectorValid(env)) {
344                 return;
345             }
346             PropertyDetector::InvalidateMapIteratorDetector(env);
347         } else if (receiver.IsJSSet() || receiver == env->GetTaggedSetPrototype()) {
348             if (!PropertyDetector::IsSetIteratorDetectorValid(env)) {
349                 return;
350             }
351             PropertyDetector::InvalidateSetIteratorDetector(env);
352         } else if ((receiver.IsJSPrimitiveRef() && JSPrimitiveRef::Cast(receiver.GetTaggedObject())->IsString()) ||
353                    receiver == env->GetTaggedStringPrototype()) {
354             if (!PropertyDetector::IsStringIteratorDetectorValid(env)) {
355                 return;
356             }
357             PropertyDetector::InvalidateStringIteratorDetector(env);
358         } else if (receiver.IsJSArray() || receiver == env->GetTaggedArrayPrototype()) {
359             if (!PropertyDetector::IsArrayIteratorDetectorValid(env)) {
360                 return;
361             }
362             PropertyDetector::InvalidateArrayIteratorDetector(env);
363         } else if (receiver.IsTypedArray() ||
364                    receiver == env->GetTaggedArrayPrototype() ||
365                    receiver == env->GetTaggedInt8ArrayFunctionPrototype() ||
366                    receiver == env->GetTaggedUint8ArrayFunctionPrototype() ||
367                    receiver == env->GetTaggedUint8ClampedArrayFunctionPrototype() ||
368                    receiver == env->GetTaggedInt16ArrayFunctionPrototype() ||
369                    receiver == env->GetTaggedUint16ArrayFunctionPrototype() ||
370                    receiver == env->GetTaggedInt32ArrayFunctionPrototype() ||
371                    receiver == env->GetTaggedUint32ArrayFunctionPrototype() ||
372                    receiver == env->GetTaggedFloat32ArrayFunctionPrototype() ||
373                    receiver == env->GetTaggedFloat64ArrayFunctionPrototype() ||
374                    receiver == env->GetTaggedBigInt64ArrayFunctionPrototype() ||
375                    receiver == env->GetTaggedBigUint64ArrayFunctionPrototype()) {
376             if (!PropertyDetector::IsTypedArrayIteratorDetectorValid(env)) {
377                 return;
378             }
379             PropertyDetector::InvalidateTypedArrayIteratorDetector(env);
380         }
381     } else if (key == env->GetTaggedSpeciesSymbol()) {
382         if (receiver.IsJSObject()) {
383             if (!PropertyDetector::IsTypedArraySpeciesProtectDetectorValid(env)) {
384                 return;
385             }
386             PropertyDetector::InvalidateTypedArraySpeciesProtectDetector(env);
387         }
388     }
389 }
390 
391 // static
IsDetectorName(JSHandle<GlobalEnv> env,JSTaggedValue key)392 bool ObjectOperator::IsDetectorName(JSHandle<GlobalEnv> env, JSTaggedValue key)
393 {
394     uintptr_t start = GlobalEnv::GetFirstDetectorSymbolAddr(*env);
395     uintptr_t end = GlobalEnv::GetLastDetectorSymbolAddr(*env);
396     uintptr_t addr = key.GetRawData();
397     return (start <= addr) && (addr <= end);
398 }
399 
GetTrackType() const400 TrackType ObjectOperator::GetTrackType() const
401 {
402     return JSObject::Cast(holder_->GetTaggedObject())->GetJSHClass()->IsDictionaryMode()
403                               ? attributes_.GetDictTrackType()
404                               : attributes_.GetTrackType();
405 }
406 
ToPropertyDescriptor(PropertyDescriptor & desc) const407 void ObjectOperator::ToPropertyDescriptor(PropertyDescriptor &desc) const
408 {
409     DISALLOW_GARBAGE_COLLECTION;
410     if (!IsFound()) {
411         return;
412     }
413 
414     if (!IsAccessorDescriptor()) {
415         desc.SetWritable(IsWritable());
416         JSTaggedValue val = GetValue();
417         desc.SetValue(JSHandle<JSTaggedValue>(thread_, val));
418         desc.SetTrackType(GetTrackType());
419     } else {
420         auto result = GetValue();
421         bool isPropertyBox = result.IsPropertyBox();
422         if (isPropertyBox) {
423             result = PropertyBox::Cast(result.GetTaggedObject())->GetValue();
424         }
425         AccessorData *accessor = AccessorData::Cast(result.GetTaggedObject());
426 
427         if (UNLIKELY(accessor->IsInternal())) {
428             desc.SetWritable(IsWritable());
429             auto val = accessor->CallInternalGet(thread_, JSHandle<JSObject>::Cast(GetHolder()));
430             JSMutableHandle<JSTaggedValue> value(thread_, val);
431             if (isPropertyBox) {
432                 JSHandle<PropertyBox> cell(value_);
433                 cell->SetValue(thread_, val);
434                 value.Update(cell);
435             }
436             desc.SetValue(value);
437         } else {
438             desc.SetGetter(JSHandle<JSTaggedValue>(thread_, accessor->GetGetter()));
439             desc.SetSetter(JSHandle<JSTaggedValue>(thread_, accessor->GetSetter()));
440         }
441     }
442 
443     desc.SetEnumerable(IsEnumerable());
444     desc.SetConfigurable(IsConfigurable());
445 }
446 
GlobalLookupProperty()447 void ObjectOperator::GlobalLookupProperty()
448 {
449     GlobalLookupPropertyInHolder();
450     if (IsFound()) {
451         return;
452     }
453     JSTaggedValue proto = JSTaggedValue::GetPrototype(thread_, holder_);
454     RETURN_IF_ABRUPT_COMPLETION(thread_);
455     if (!proto.IsHeapObject()) {
456         return;
457     }
458     holder_.Update(proto);
459     if (holder_->IsJSProxy()) {
460         return;
461     }
462     SetIsOnPrototype(true);
463     LookupProperty();
464 }
465 
LookupProperty()466 void ObjectOperator::LookupProperty()
467 {
468     while (true) {
469         UpdateIsTSHClass();
470         LookupPropertyInHolder();
471         if (IsFound()) {
472             return;
473         }
474 
475         JSTaggedValue proto = JSTaggedValue::GetPrototype(thread_, holder_);
476         RETURN_IF_ABRUPT_COMPLETION(thread_);
477         if (!proto.IsHeapObject()) {
478             return;
479         }
480 
481         holder_.Update(proto);
482         if (holder_->IsJSProxy()) {
483             return;
484         }
485 
486         SetIsOnPrototype(true);
487     }
488 }
489 
LookupGlobal(const JSHandle<JSObject> & obj)490 void ObjectOperator::LookupGlobal(const JSHandle<JSObject> &obj)
491 {
492     ASSERT(obj->IsJSGlobalObject());
493     if (IsElement()) {
494         LookupElementInlinedProps(obj);
495         return;
496     }
497     TaggedArray *array = TaggedArray::Cast(obj->GetProperties().GetTaggedObject());
498     if (array->GetLength() == 0) {
499         return;
500     }
501     GlobalDictionary *dict = GlobalDictionary::Cast(array);
502     int entry = dict->FindEntry(key_.GetTaggedValue());
503     if (entry == -1) {
504         return;
505     }
506     JSTaggedValue value(dict->GetBox(entry));
507     uint32_t attr = dict->GetAttributes(entry).GetValue();
508     SetFound(entry, value, attr, true);
509 }
510 
LookupPropertyInlinedProps(const JSHandle<JSObject> & obj)511 void ObjectOperator::LookupPropertyInlinedProps(const JSHandle<JSObject> &obj)
512 {
513     if (IsElement()) {
514         LookupElementInlinedProps(obj);
515         return;
516     }
517 
518     if (!obj.GetTaggedValue().IsJSObject()) {
519         return;
520     }
521 
522     if (obj->IsJSGlobalObject()) {
523         DISALLOW_GARBAGE_COLLECTION;
524         TaggedArray *array = TaggedArray::Cast(obj->GetProperties().GetTaggedObject());
525         if (array->GetLength() == 0) {
526             return;
527         }
528 
529         GlobalDictionary *dict = GlobalDictionary::Cast(array);
530         int entry = dict->FindEntry(key_.GetTaggedValue());
531         if (entry == -1) {
532             return;
533         }
534 
535         JSTaggedValue value(dict->GetBox(entry));
536         uint32_t attr = dict->GetAttributes(entry).GetValue();
537         SetFound(entry, value, attr, true);
538         return;
539     }
540 
541     TaggedArray *array = TaggedArray::Cast(obj->GetProperties().GetTaggedObject());
542     if (!array->IsDictionaryMode()) {
543         JSHClass *jshclass = obj->GetJSHClass();
544         int entry = JSHClass::FindPropertyEntry(thread_, jshclass, key_.GetTaggedValue());
545         if (entry == -1) {
546             return;
547         }
548         JSTaggedValue attrs = jshclass->GetLayout();
549         LayoutInfo *layoutInfo = LayoutInfo::Cast(attrs.GetTaggedObject());
550         PropertyAttributes attr(layoutInfo->GetAttr(entry));
551         ASSERT(entry == static_cast<int>(attr.GetOffset()));
552         JSTaggedValue value;
553         if (attr.IsInlinedProps()) {
554             value = obj->GetPropertyInlinedPropsWithRep(entry, attr);
555             if (value.IsHole()) {
556                 if (receiverHoleEntry_ == -1 && receiver_ == holder_) {
557                     receiverHoleEntry_ = entry;
558                 }
559                 return;
560             }
561         } else {
562             entry -= static_cast<int>(jshclass->GetInlinedProperties());
563             value = array->Get(entry);
564         }
565 
566         SetFound(entry, value, attr.GetValue(), true);
567         return;
568     }
569 
570     NameDictionary *dict = NameDictionary::Cast(array);
571     int entry = dict->FindEntry(key_.GetTaggedValue());
572     if (entry == -1) {
573         return;
574     }
575 
576     JSTaggedValue value = dict->GetValue(entry);
577     uint32_t attr = dict->GetAttributes(entry).GetValue();
578     SetFound(entry, value, attr, false);
579 }
580 
TransitionForAttributeChanged(const JSHandle<JSObject> & receiver,PropertyAttributes attr)581 void ObjectOperator::TransitionForAttributeChanged(const JSHandle<JSObject> &receiver, PropertyAttributes attr)
582 {
583     if (IsElement()) {
584         uint32_t index = GetIndex();
585         if (!receiver->GetJSHClass()->IsDictionaryElement()) {
586             JSObject::ElementsToDictionary(thread_, receiver);
587             auto dict = NumberDictionary::Cast(receiver->GetElements().GetTaggedObject());
588             index = static_cast<uint32_t>(dict->FindEntry(JSTaggedValue(index)));
589             PropertyAttributes origin = dict->GetAttributes(index);
590             attr.SetDictionaryOrder(origin.GetDictionaryOrder());
591             dict->SetAttributes(thread_, index, attr);
592         } else {
593             auto dict = NumberDictionary::Cast(receiver->GetElements().GetTaggedObject());
594             dict->SetAttributes(thread_, index, attr);
595         }
596         // update found result
597         UpdateFound(index, attr.GetValue(), false, true);
598     } else if (receiver->IsJSGlobalObject()) {
599         JSHandle<GlobalDictionary> dictHandle(thread_, receiver->GetProperties());
600         GlobalDictionary::InvalidatePropertyBox(thread_, dictHandle, GetIndex());
601     } else {
602         uint32_t index = GetIndex();
603         if (!receiver->GetJSHClass()->IsDictionaryMode()) {
604             JSHandle<NameDictionary> dict(JSObject::TransitionToDictionary(thread_, receiver));
605             index = static_cast<uint32_t>(dict->FindEntry(key_.GetTaggedValue()));
606             PropertyAttributes origin = dict->GetAttributes(index);
607             attr.SetDictTrackType(attr.GetTrackType());
608             attr.SetDictionaryOrder(origin.GetDictionaryOrder());
609             dict->SetAttributes(thread_, index, attr);
610         } else {
611             auto dict = NameDictionary::Cast(receiver->GetProperties().GetTaggedObject());
612             dict->SetAttributes(thread_, index, attr);
613         }
614         // update found result
615         UpdateFound(index, attr.GetValue(), false, true);
616     }
617 }
618 
UpdateValueAndDetails(const JSHandle<JSObject> & receiver,const JSHandle<JSTaggedValue> & value,PropertyAttributes attr,bool attrChanged)619 bool ObjectOperator::UpdateValueAndDetails(const JSHandle<JSObject> &receiver, const JSHandle<JSTaggedValue> &value,
620                                            PropertyAttributes attr, bool attrChanged)
621 {
622     auto valueAccessor = GetValue();
623     if (valueAccessor.IsPropertyBox()) {
624         valueAccessor = PropertyBox::Cast(valueAccessor.GetTaggedObject())->GetValue();
625     }
626     bool isInternalAccessor = IsAccessorDescriptor()
627         && AccessorData::Cast(valueAccessor.GetTaggedObject())->IsInternal();
628     if (!attrChanged) {
629         return UpdateDataValue(receiver, value, isInternalAccessor);
630     }
631     if (attr.IsWritable()) {
632         TransitionForAttributeChanged(receiver, attr);
633         return UpdateDataValue(receiver, value, isInternalAccessor);
634     }
635     bool res = UpdateDataValue(receiver, value, isInternalAccessor);
636     if (res) {
637         TransitionForAttributeChanged(receiver, attr);
638     }
639     return res;
640 }
641 
UpdateDataValue(const JSHandle<JSObject> & receiver,const JSHandle<JSTaggedValue> & value,bool isInternalAccessor,bool mayThrow)642 bool ObjectOperator::UpdateDataValue(const JSHandle<JSObject> &receiver, const JSHandle<JSTaggedValue> &value,
643                                      bool isInternalAccessor, bool mayThrow)
644 {
645     if (IsElement()) {
646         TaggedArray *elements = TaggedArray::Cast(receiver->GetElements().GetTaggedObject());
647         if (!elements->IsDictionaryMode()) {
648             if (receiver.GetTaggedValue().IsJSCOWArray()) {
649                 JSArray::CheckAndCopyArray(thread_, JSHandle<JSArray>(receiver));
650             } else if (receiver->IsTypedArray()) {
651                 JSTaggedValue holder = receiver.GetTaggedValue();
652                 JSType jsType = holder.GetTaggedObject()->GetClass()->GetObjectType();
653                 JSTaggedValue typedArrayProperty = JSTypedArray::FastSetPropertyByIndex(thread_,
654                     receiver.GetTaggedValue(), GetIndex(), value.GetTaggedValue(), jsType);
655                 if (typedArrayProperty.IsHole()) {
656                     return false;
657                 }
658                 return true;
659             }
660             ElementsKind oldKind = receiver->GetClass()->GetElementsKind();
661             if (JSHClass::TransitToElementsKind(thread_, receiver, value)) {
662                 SetIsTransition(true);
663                 ElementsKind newKind = receiver->GetClass()->GetElementsKind();
664                 // newKind != currentKind, we need to convert the whole array to the newKind.
665                 Elements::MigrateArrayWithKind(thread_, receiver, oldKind, newKind);
666             }
667             ElementAccessor::Set(thread_, receiver, GetIndex(), value, false);
668             return true;
669         }
670 
671         NumberDictionary *dict = NumberDictionary::Cast(elements);
672         dict->UpdateValue(thread_, GetIndex(), value.GetTaggedValue());
673         return true;
674     }
675 
676     if (receiver->IsJSGlobalObject()) {
677         // need update cell type ?
678         auto *dict = GlobalDictionary::Cast(receiver->GetProperties().GetTaggedObject());
679         if (isInternalAccessor && !value->IsAccessor()) {
680             PropertyAttributes attr = dict->GetAttributes(GetIndex());
681             attr.SetIsAccessor(false);
682             dict->SetAttributes(thread_, GetIndex(), attr);
683         }
684         PropertyBox *cell = dict->GetBox(GetIndex());
685         cell->SetValue(thread_, value.GetTaggedValue());
686         return true;
687     }
688 
689     if (isInternalAccessor) {
690         auto accessor = AccessorData::Cast(GetValue().GetTaggedObject());
691         if (accessor->HasSetter()) {
692             bool res = accessor->CallInternalSet(thread_, JSHandle<JSObject>(receiver), value, mayThrow);
693             if (receiver->GetJSHClass()->IsDictionaryMode()) {
694                 SetIsInlinedProps(false);
695                 SetFastMode(false);
696             }
697             return res;
698         }
699     }
700 
701     JSMutableHandle<TaggedArray> properties(thread_, TaggedArray::Cast(receiver->GetProperties().GetTaggedObject()));
702     if (!properties->IsDictionaryMode()) {
703         PropertyAttributes attr = GetAttr();
704         uint32_t offset = index_;
705         if (!attr.IsInlinedProps()) {
706             auto *hclass = receiver_->GetTaggedObject()->GetClass();
707             offset += hclass->GetInlinedProperties();
708         }
709         attr.SetOffset(offset);
710 
711         auto actualValue =
712             JSHClass::ConvertOrTransitionWithRep(thread_, JSHandle<JSObject>(receiver_), key_, value, attr);
713         if (std::get<1>(actualValue)) {
714             SetIsTransition(true);
715         }
716         attributes_.SetRepresentation(attr.GetRepresentation());
717 
718         if (attr.IsInlinedProps()) {
719             receiver->SetPropertyInlinedPropsWithRep(thread_, GetIndex(), std::get<2>(actualValue));
720         } else {
721             if (receiver.GetTaggedValue().IsJSCOWArray()) {
722                 JSArray::CheckAndCopyArray(thread_, JSHandle<JSArray>(receiver));
723                 properties.Update(JSHandle<JSArray>(receiver)->GetProperties());
724             }
725             if (std::get<0>(actualValue)) {
726                 properties->Set<true>(thread_, GetIndex(), std::get<2>(actualValue));
727             } else {
728                 properties->Set<false>(thread_, GetIndex(), std::get<2>(actualValue));
729             }
730         }
731     } else {
732         properties.GetObject<NameDictionary>()->UpdateValue(thread_, GetIndex(), value.GetTaggedValue());
733     }
734     return true;
735 }
736 
WriteDataProperty(const JSHandle<JSObject> & receiver,const PropertyDescriptor & desc)737 bool ObjectOperator::WriteDataProperty(const JSHandle<JSObject> &receiver, const PropertyDescriptor &desc)
738 {
739     PropertyAttributes attr = GetAttr();
740     bool attrChanged = false;
741 
742     // composed new attribute from desc
743     if (desc.HasConfigurable() && attr.IsConfigurable() != desc.IsConfigurable()) {
744         attr.SetConfigurable(desc.IsConfigurable());
745         attrChanged = true;
746     }
747     if (desc.HasEnumerable() && attr.IsEnumerable() != desc.IsEnumerable()) {
748         attr.SetEnumerable(desc.IsEnumerable());
749         attrChanged = true;
750     }
751 
752     if (!desc.IsAccessorDescriptor()) {
753         if (desc.HasWritable() && attr.IsWritable() != desc.IsWritable()) {
754             attr.SetWritable(desc.IsWritable());
755             attrChanged = true;
756         }
757         if (!desc.HasValue()) {
758             if (attrChanged) {
759                 TransitionForAttributeChanged(receiver, attr);
760             }
761             return true;
762         }
763 
764         if (IsAccessorDescriptor()) {
765             auto accessor = AccessorData::Cast(GetValue().GetTaggedObject());
766             if (!accessor->IsInternal() || !accessor->HasSetter()) {
767                 attr.SetIsAccessor(false);
768                 attrChanged = true;
769             }
770         }
771 
772         return UpdateValueAndDetails(receiver, desc.GetValue(), attr, attrChanged);
773     } else {
774         if (IsAccessorDescriptor() && !IsElement()) {
775             TaggedArray *properties = TaggedArray::Cast(receiver->GetProperties().GetTaggedObject());
776             if (attrChanged && !properties->IsDictionaryMode()) {
777                 // as some accessorData is in globalEnv, we need to new accessorData.
778                 JSHandle<AccessorData> accessor = thread_->GetEcmaVM()->GetFactory()->NewAccessorData();
779 
780                 if (desc.HasGetter()) {
781                     accessor->SetGetter(thread_, desc.GetGetter().GetTaggedValue());
782                 } else {
783                     accessor->SetGetter(thread_, JSHandle<AccessorData>::Cast(value_)->GetGetter());
784                 }
785                 if (desc.HasSetter()) {
786                     accessor->SetSetter(thread_, desc.GetSetter().GetTaggedValue());
787                 } else {
788                     accessor->SetSetter(thread_, JSHandle<AccessorData>::Cast(value_)->GetSetter());
789                 }
790 
791                 JSHandle<NameDictionary> dict(JSObject::TransitionToDictionary(thread_, receiver));
792                 int entry = dict->FindEntry(key_.GetTaggedValue());
793                 ASSERT(entry != -1);
794                 dict->UpdateValueAndAttributes(thread_, entry, accessor.GetTaggedValue(), attr);
795                 return true;
796             }
797         }
798 
799         auto valueAccessor = GetValue();
800         if (valueAccessor.IsPropertyBox()) {
801             valueAccessor = PropertyBox::Cast(valueAccessor.GetTaggedObject())->GetValue();
802         }
803         JSHandle<AccessorData> accessor =
804             (IsAccessorDescriptor() && !JSHandle<AccessorData>(thread_, valueAccessor)->IsInternal()) ?
805             JSHandle<AccessorData>(thread_, valueAccessor) :
806             thread_->GetEcmaVM()->GetFactory()->NewAccessorData();
807         if (desc.HasGetter()) {
808             accessor->SetGetter(thread_, desc.GetGetter().GetTaggedValue());
809         }
810 
811         if (desc.HasSetter()) {
812             accessor->SetSetter(thread_, desc.GetSetter().GetTaggedValue());
813         }
814 
815         if (!IsAccessorDescriptor()) {
816             attr.SetIsAccessor(true);
817             attrChanged = true;
818         }
819 
820         JSHandle<JSTaggedValue> value = JSHandle<JSTaggedValue>::Cast(accessor);
821         bool success = UpdateValueAndDetails(receiver, value, attr, attrChanged);
822         if (success) {
823             JSHandle<JSObject> obj(receiver);
824             if (obj->GetJSHClass()->IsPrototype()) {
825                 JSHandle<ProtoChangeMarker> markerHandle = thread_->GetEcmaVM()->GetFactory()->NewProtoChangeMarker();
826                 obj->GetJSHClass()->SetProtoChangeMarker(thread_, markerHandle.GetTaggedValue());
827             }
828             JSHClass::NotifyAccessorChanged(thread_, JSHandle<JSHClass>(thread_, obj->GetJSHClass()));
829         }
830         return success;
831     }
832 }
833 
DeletePropertyInHolder()834 void ObjectOperator::DeletePropertyInHolder()
835 {
836     if (IsElement()) {
837         return DeleteElementInHolder();
838     }
839     ObjectOperator::UpdateDetector(thread_, holder_.GetTaggedValue(), key_.GetTaggedValue());
840     JSObject::DeletePropertyInternal(thread_, JSHandle<JSObject>(holder_), key_, GetIndex());
841 }
842 
AddProperty(const JSHandle<JSObject> & receiver,const JSHandle<JSTaggedValue> & value,PropertyAttributes attr)843 bool ObjectOperator::AddProperty(const JSHandle<JSObject> &receiver, const JSHandle<JSTaggedValue> &value,
844                                  PropertyAttributes attr)
845 {
846     if (IsElement()) {
847         bool ret = JSObject::AddElementInternal(thread_, receiver, elementIndex_, value, attr);
848         bool isDict = receiver->GetJSHClass()->IsDictionaryElement();
849         SetFound(elementIndex_, value.GetTaggedValue(), attr.GetValue(), !isDict);
850         return ret;
851     }
852 
853     ResetStateForAddProperty();
854     receiver_.Update(receiver.GetTaggedValue());
855     SetAttr(attr.GetValue());
856     AddPropertyInternal(value);
857     return true;
858 }
859 
WriteElement(const JSHandle<JSObject> & receiver,JSTaggedValue value) const860 void ObjectOperator::WriteElement(const JSHandle<JSObject> &receiver, JSTaggedValue value) const
861 {
862     ASSERT(IsElement() && GetIndex() < JSObject::MAX_ELEMENT_INDEX);
863 
864     if (!ElementAccessor::IsDictionaryMode(receiver)) {
865         ElementAccessor::Set(thread_, receiver, index_, value, true);
866         return;
867     }
868 
869     TaggedArray *elements = TaggedArray::Cast(receiver->GetElements().GetTaggedObject());
870     NumberDictionary *dictionary = NumberDictionary::Cast(elements);
871     dictionary->UpdateValue(thread_, GetIndex(), value);
872 }
873 
DeleteElementInHolder() const874 void ObjectOperator::DeleteElementInHolder() const
875 {
876     JSHandle<JSObject> obj(holder_);
877 
878     if (!ElementAccessor::IsDictionaryMode(obj)) {
879         ElementAccessor::Set(thread_, obj, index_, JSTaggedValue::Hole(), true, ElementsKind::HOLE);
880         JSObject::ElementsToDictionary(thread_, JSHandle<JSObject>(holder_));
881     } else {
882         TaggedArray *elements = TaggedArray::Cast(obj->GetElements().GetTaggedObject());
883         JSHandle<NumberDictionary> dictHandle(thread_, elements);
884         JSHandle<NumberDictionary> newDict = NumberDictionary::Remove(thread_, dictHandle, GetIndex());
885         obj->SetElements(thread_, newDict);
886     }
887 }
888 
SetFound(uint32_t index,JSTaggedValue value,uint32_t attr,bool mode,bool transition)889 void ObjectOperator::SetFound(uint32_t index, JSTaggedValue value, uint32_t attr, bool mode, bool transition)
890 {
891     SetIndex(index);
892     SetValue(value);
893     SetFastMode(mode);
894     SetIsTransition(transition);
895     SetAttr(attr);
896 }
897 
UpdateFound(uint32_t index,uint32_t attr,bool mode,bool transition)898 void ObjectOperator::UpdateFound(uint32_t index, uint32_t attr, bool mode, bool transition)
899 {
900     SetIndex(index);
901     SetFastMode(mode);
902     SetIsTransition(transition);
903     SetAttr(attr);
904 }
905 
ResetState()906 void ObjectOperator::ResetState()
907 {
908     // index may used by element
909     SetIndex(NOT_FOUND_INDEX);
910     SetValue(JSTaggedValue::Undefined());
911     SetFastMode(false);
912     SetAttr(0);
913     SetIsOnPrototype(false);
914     SetHasReceiver(false);
915     SetIsTSHClass(false);
916 }
917 
ResetStateForAddProperty()918 void ObjectOperator::ResetStateForAddProperty()
919 {
920     bool isOnPrototype = IsOnPrototype();
921     ResetState();
922     SetIsOnPrototype(isOnPrototype);
923 }
924 
LookupElementInlinedProps(const JSHandle<JSObject> & obj)925 void ObjectOperator::LookupElementInlinedProps(const JSHandle<JSObject> &obj)
926 {
927     // if is js string, do special.
928     if (obj->IsJSPrimitiveRef() && JSPrimitiveRef::Cast(obj.GetTaggedValue().GetTaggedObject())->IsString()) {
929         PropertyDescriptor desc(thread_);
930         bool status = JSPrimitiveRef::StringGetIndexProperty(thread_, obj, elementIndex_, &desc);
931         if (status) {
932             PropertyAttributes attr(desc);
933             SetFound(elementIndex_, desc.GetValue().GetTaggedValue(), attr.GetValue(), true);
934             return;
935         }
936     }
937     {
938         DISALLOW_GARBAGE_COLLECTION;
939         if (obj->IsTypedArray()) {
940             JSTaggedValue val = JSTypedArray::FastElementGet(thread_,
941                 JSHandle<JSTaggedValue>::Cast(obj), elementIndex_).GetValue().GetTaggedValue();
942             if (!val.IsHole()) {
943                 SetFound(elementIndex_, val, PropertyAttributes::GetDefaultAttributes(), true);
944             }
945             return;
946         }
947         TaggedArray *elements = TaggedArray::Cast(obj->GetElements().GetTaggedObject());
948         if (elements->GetLength() == 0) {
949             return;  // Empty Array
950         }
951 
952         if (!elements->IsDictionaryMode()) {
953             if (elements->GetLength() <= elementIndex_) {
954                 return;
955             }
956 
957             JSTaggedValue value = ElementAccessor::Get(obj, elementIndex_);
958             if (value.IsHole()) {
959                 return;
960             }
961             SetFound(elementIndex_, value, PropertyAttributes::GetDefaultAttributes(), true);
962         } else {
963             NumberDictionary *dictionary = NumberDictionary::Cast(obj->GetElements().GetTaggedObject());
964             JSTaggedValue key(static_cast<int>(elementIndex_));
965             int entry = dictionary->FindEntry(key);
966             if (entry == -1) {
967                 return;
968             }
969 
970             uint32_t attr = dictionary->GetAttributes(entry).GetValue();
971             SetFound(entry, dictionary->GetValue(entry), attr, false);
972         }
973     }
974 }
975 
AddPropertyInternal(const JSHandle<JSTaggedValue> & value)976 void ObjectOperator::AddPropertyInternal(const JSHandle<JSTaggedValue> &value)
977 {
978     ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
979     JSHandle<JSObject> obj(GetReceiver());
980     PropertyAttributes attr = GetAttr();
981     if (obj->IsJSGlobalObject()) {
982         JSMutableHandle<GlobalDictionary> dict(thread_, obj->GetProperties());
983         if (dict->GetLength() == 0) {
984             dict.Update(GlobalDictionary::Create(thread_));
985         }
986 
987         // Add PropertyBox to global dictionary
988         JSHandle<PropertyBox> cellHandle = factory->NewPropertyBox(key_);
989         cellHandle->SetValue(thread_, value.GetTaggedValue());
990         PropertyBoxType cellType = value->IsUndefined() ? PropertyBoxType::UNDEFINED : PropertyBoxType::CONSTANT;
991         attr.SetBoxType(cellType);
992 
993         JSHandle<GlobalDictionary> properties =
994             GlobalDictionary::PutIfAbsent(thread_, dict, key_, JSHandle<JSTaggedValue>(cellHandle), attr);
995         obj->SetProperties(thread_, properties);
996         // index and fastMode is not essential for global obj;
997         SetFound(0, cellHandle.GetTaggedValue(), attr.GetValue(), true);
998         return;
999     }
1000 
1001     // The property has already existed whose value is hole, initialized by speculative hclass.
1002     // Not need AddProperty,just SetProperty
1003     if (receiverHoleEntry_ != -1) {
1004         attr.SetOffset(receiverHoleEntry_);
1005         auto actualValue =
1006             JSHClass::ConvertOrTransitionWithRep(thread_, JSHandle<JSObject>(receiver_), key_, value, attr);
1007         if (std::get<1>(actualValue)) {
1008             SetIsTransition(true);
1009         }
1010         attributes_.SetRepresentation(attr.GetRepresentation());
1011         auto *hclass = receiver_->GetTaggedObject()->GetClass();
1012         if (std::get<0>(actualValue)) {
1013             JSObject::Cast(receiver_.GetTaggedValue())->SetProperty<true>(thread_, hclass, attr, std::get<2>(actualValue));
1014         } else {
1015             JSObject::Cast(receiver_.GetTaggedValue())->SetProperty<false>(thread_, hclass, attr, std::get<2>(actualValue));
1016         }
1017         uint32_t index = attr.IsInlinedProps() ? attr.GetOffset() :
1018                 attr.GetOffset() - obj->GetJSHClass()->GetInlinedProperties();
1019         SetIsTSHClass(true);
1020         SetIsOnPrototype(false);
1021         SetFound(index, value.GetTaggedValue(), attr.GetValue(), true);
1022         return;
1023     }
1024 
1025     attr = ObjectFastOperator::AddPropertyByName(thread_, obj, key_, value, attr);
1026     if (obj->GetJSHClass()->IsDictionaryMode()) {
1027         SetFound(0, value.GetTaggedValue(), attr.GetValue(), false);
1028     } else {
1029         uint32_t index = attr.IsInlinedProps() ? attr.GetOffset() :
1030                 attr.GetOffset() - obj->GetJSHClass()->GetInlinedProperties();
1031         SetFound(index, value.GetTaggedValue(), attr.GetValue(), true, true);
1032     }
1033 }
1034 
DefineSetter(const JSHandle<JSTaggedValue> & value)1035 void ObjectOperator::DefineSetter(const JSHandle<JSTaggedValue> &value)
1036 {
1037     ASSERT(IsAccessorDescriptor());
1038     JSHandle<AccessorData> accessor = JSHandle<AccessorData>::Cast(value_);
1039     accessor->SetSetter(thread_, value.GetTaggedValue());
1040     UpdateDataValue(JSHandle<JSObject>::Cast(receiver_), JSHandle<JSTaggedValue>::Cast(accessor), false);
1041 }
1042 
DefineGetter(const JSHandle<JSTaggedValue> & value)1043 void ObjectOperator::DefineGetter(const JSHandle<JSTaggedValue> &value)
1044 {
1045     ASSERT(IsAccessorDescriptor());
1046     JSHandle<AccessorData> accessor = JSHandle<AccessorData>::Cast(value_);
1047     accessor->SetGetter(thread_, value.GetTaggedValue());
1048     UpdateDataValue(JSHandle<JSObject>::Cast(receiver_), JSHandle<JSTaggedValue>::Cast(accessor), false);
1049 }
1050 }  // namespace panda::ecmascript
1051