• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 "ecmascript/ic/ic_runtime.h"
17 
18 #include "ecmascript/ic/ic_handler.h"
19 #include "ecmascript/interpreter/interpreter.h"
20 #include "ecmascript/interpreter/slow_runtime_stub.h"
21 #include "ecmascript/js_primitive_ref.h"
22 #include "ecmascript/shared_objects/js_shared_array.h"
23 
24 namespace panda::ecmascript {
25 #define TRACE_IC 0  // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
26 
UpdateLoadHandler(const ObjectOperator & op,JSHandle<JSTaggedValue> key,JSHandle<JSTaggedValue> receiver)27 void ICRuntime::UpdateLoadHandler(const ObjectOperator &op, JSHandle<JSTaggedValue> key,
28                                   JSHandle<JSTaggedValue> receiver)
29 {
30     if (icAccessor_.GetICState() == ProfileTypeAccessor::ICState::MEGA) {
31         return;
32     }
33     if (IsNamedIC(GetICKind())) {
34         key = JSHandle<JSTaggedValue>();
35     }
36     JSHandle<JSTaggedValue> handlerValue;
37     ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
38     JSHandle<JSHClass> originhclass;
39     if (receiver->IsNumber()) {
40         receiver = JSHandle<JSTaggedValue>::Cast(factory->NewJSPrimitiveRef(PrimitiveType::PRIMITIVE_NUMBER, receiver));
41     } else if (receiver->IsString()) {
42         originhclass = JSHandle<JSHClass>(thread_, receiver->GetTaggedObject()->GetClass());
43         receiver = JSHandle<JSTaggedValue>::Cast(factory->NewJSPrimitiveRef(PrimitiveType::PRIMITIVE_STRING, receiver));
44     }
45     JSHandle<JSHClass> hclass(GetThread(), receiver->GetTaggedObject()->GetClass());
46     // When a transition occurs without the shadow property, AOT does not trigger the
47     // notifyprototypechange behavior, so for the case where the property does not
48     // exist and the Hclass is AOT, IC needs to be abandoned.
49     if (hclass->IsTS() && !op.IsFound()) {
50         return;
51     }
52     if (op.IsElement()) {
53         if (!op.IsFound() && hclass->IsDictionaryElement()) {
54             return;
55         }
56         handlerValue = LoadHandler::LoadElement(thread_, op);
57     } else {
58         if (!op.IsFound()) {
59             JSTaggedValue proto = hclass->GetPrototype();
60             if (!proto.IsECMAObject()) {
61                 handlerValue = LoadHandler::LoadProperty(thread_, op);
62             } else {
63                 handlerValue = PrototypeHandler::LoadPrototype(thread_, op, hclass);
64             }
65         } else if (!op.IsOnPrototype()) {
66             handlerValue = LoadHandler::LoadProperty(thread_, op);
67         } else {
68             // do not support global prototype ic
69             if (IsGlobalLoadIC(GetICKind())) {
70                 return;
71             }
72             handlerValue = PrototypeHandler::LoadPrototype(thread_, op, hclass);
73         }
74     }
75 
76     if (!originhclass.GetTaggedValue().IsUndefined()) {
77         hclass = originhclass;
78     }
79     if (key.IsEmpty()) {
80         icAccessor_.AddHandlerWithoutKey(JSHandle<JSTaggedValue>::Cast(hclass), handlerValue);
81     } else if (op.IsElement()) {
82         // do not support global element ic
83         if (IsGlobalLoadIC(GetICKind())) {
84             return;
85         }
86         icAccessor_.AddElementHandler(JSHandle<JSTaggedValue>::Cast(hclass), handlerValue);
87     } else {
88         icAccessor_.AddHandlerWithKey(key, JSHandle<JSTaggedValue>::Cast(hclass), handlerValue);
89     }
90 }
91 
UpdateLoadStringHandler(JSHandle<JSTaggedValue> receiver)92 void ICRuntime::UpdateLoadStringHandler(JSHandle<JSTaggedValue> receiver)
93 {
94     if (icAccessor_.GetICState() == ProfileTypeAccessor::ICState::MEGA) {
95         return;
96     }
97     JSHandle<JSTaggedValue> handlerValue = LoadHandler::LoadStringElement(thread_);
98     JSHandle<JSHClass> hclass(GetThread(), receiver->GetTaggedObject()->GetClass());
99     icAccessor_.AddElementHandler(JSHandle<JSTaggedValue>::Cast(hclass), handlerValue);
100 }
101 
UpdateTypedArrayHandler(JSHandle<JSTaggedValue> receiver)102 void ICRuntime::UpdateTypedArrayHandler(JSHandle<JSTaggedValue> receiver)
103 {
104     if (icAccessor_.GetICState() == ProfileTypeAccessor::ICState::MEGA) {
105         return;
106     }
107     JSHandle<JSTaggedValue> handlerValue =
108         LoadHandler::LoadTypedArrayElement(thread_, JSHandle<JSTypedArray>(receiver));
109     JSHandle<JSHClass> hclass(GetThread(), receiver->GetTaggedObject()->GetClass());
110     icAccessor_.AddElementHandler(JSHandle<JSTaggedValue>::Cast(hclass), handlerValue);
111 }
112 
UpdateStoreHandler(const ObjectOperator & op,JSHandle<JSTaggedValue> key,JSHandle<JSTaggedValue> receiver)113 void ICRuntime::UpdateStoreHandler(const ObjectOperator &op, JSHandle<JSTaggedValue> key,
114                                    JSHandle<JSTaggedValue> receiver)
115 {
116     if (icAccessor_.GetICState() == ProfileTypeAccessor::ICState::MEGA) {
117         return;
118     }
119     if (IsNamedIC(GetICKind())) {
120         key = JSHandle<JSTaggedValue>();
121     }
122     JSHandle<JSTaggedValue> handlerValue;
123     ASSERT(op.IsFound());
124 
125     if (op.IsTransition()) {
126         if (op.IsOnPrototype()) {
127             JSHandle<JSHClass> hclass(thread_, JSHandle<JSObject>::Cast(receiver)->GetClass());
128             handlerValue = TransWithProtoHandler::StoreTransition(thread_, op, hclass);
129         } else {
130             handlerValue = TransitionHandler::StoreTransition(thread_, op);
131         }
132     } else if (op.IsOnPrototype()) {
133         // do not support global prototype ic
134         if (IsGlobalStoreIC(GetICKind())) {
135             return;
136         }
137         JSHandle<JSHClass> hclass(thread_, JSHandle<JSObject>::Cast(receiver)->GetClass());
138         handlerValue = PrototypeHandler::StorePrototype(thread_, op, hclass);
139     } else {
140         handlerValue = StoreHandler::StoreProperty(thread_, op);
141     }
142 
143     if (key.IsEmpty()) {
144         icAccessor_.AddHandlerWithoutKey(receiverHClass_, handlerValue);
145     } else if (op.IsElement()) {
146         // do not support global element ic
147         if (IsGlobalStoreIC(GetICKind())) {
148             return;
149         }
150         icAccessor_.AddElementHandler(receiverHClass_, handlerValue);
151     } else {
152         icAccessor_.AddHandlerWithKey(key, receiverHClass_, handlerValue);
153     }
154 }
155 
TraceIC(JSHandle<JSTaggedValue> receiver,JSHandle<JSTaggedValue> key) const156 void ICRuntime::TraceIC([[maybe_unused]] JSHandle<JSTaggedValue> receiver,
157                         [[maybe_unused]] JSHandle<JSTaggedValue> key) const
158 {
159 #if TRACE_IC
160     auto kind = ICKindToString(GetICKind());
161     auto state = ProfileTypeAccessor::ICStateToString(icAccessor_.GetICState());
162     if (key->IsString()) {
163         auto keyStrHandle = JSHandle<EcmaString>::Cast(key);
164         LOG_ECMA(ERROR) << kind << " miss key is: " << EcmaStringAccessor(keyStrHandle).ToCString()
165                             << ", receiver is " << receiver->GetTaggedObject()->GetClass()->IsDictionaryMode()
166                             << ", state is " << state;
167     } else {
168         LOG_ECMA(ERROR) << kind << " miss " << ", state is "
169                             << ", receiver is " << receiver->GetTaggedObject()->GetClass()->IsDictionaryMode()
170                             << state;
171     }
172 #endif
173 }
174 
LoadValueMiss(JSHandle<JSTaggedValue> receiver,JSHandle<JSTaggedValue> key)175 JSTaggedValue LoadICRuntime::LoadValueMiss(JSHandle<JSTaggedValue> receiver, JSHandle<JSTaggedValue> key)
176 {
177     JSTaggedValue::RequireObjectCoercible(thread_, receiver, "Cannot load property of null or undefined");
178     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread_);
179 
180     if ((!receiver->IsJSObject() || receiver->HasOrdinaryGet()) && !receiver->IsString()) {
181         icAccessor_.SetAsMega();
182         JSHandle<JSTaggedValue> propKey = JSTaggedValue::ToPropertyKey(thread_, key);
183         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread_);
184         return JSTaggedValue::GetProperty(thread_, receiver, propKey).GetValue().GetTaggedValue();
185     }
186     if (receiver->IsTypedArray() || receiver->IsSharedTypedArray()) {
187         return LoadTypedArrayValueMiss(receiver, key);
188     }
189     // fixme(hzzhouzebin) Open IC for SharedArray later.
190     if (receiver->IsJSSharedArray()) {
191         return JSSharedArray::GetProperty(thread_, receiver, key, SCheckMode::CHECK).GetValue().GetTaggedValue();
192     }
193     ObjectOperator op(GetThread(), receiver, key);
194     auto result = JSHandle<JSTaggedValue>(thread_, JSObject::GetProperty(GetThread(), &op));
195     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread_);
196 
197     if (receiver->IsString()) {
198          // do not cache element
199         if (!op.IsFastMode()) {
200             icAccessor_.SetAsMega();
201             return result.GetTaggedValue();
202         }
203         UpdateLoadStringHandler(receiver);
204     } else {
205         if (op.GetValue().IsAccessor()) {
206             op = ObjectOperator(GetThread(), receiver, key);
207         }
208         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(GetThread());
209         // ic-switch
210         if (!GetThread()->GetEcmaVM()->ICEnabled()) {
211             icAccessor_.SetAsMega();
212             return result.GetTaggedValue();
213         }
214         TraceIC(receiver, key);
215         // do not cache element
216         if (!op.IsFastMode()) {
217             icAccessor_.SetAsMega();
218             return result.GetTaggedValue();
219         }
220         UpdateLoadHandler(op, key, receiver);
221     }
222 
223     return result.GetTaggedValue();
224 }
225 
LoadMiss(JSHandle<JSTaggedValue> receiver,JSHandle<JSTaggedValue> key)226 JSTaggedValue LoadICRuntime::LoadMiss(JSHandle<JSTaggedValue> receiver, JSHandle<JSTaggedValue> key)
227 {
228     if ((!receiver->IsJSObject() || receiver->HasOrdinaryGet()) &&
229          !receiver->IsString() && !receiver->IsNumber()) {
230         return LoadOrdinaryGet(receiver, key);
231     }
232 
233     ICKind kind = GetICKind();
234     // global variable find from global record firstly
235     if (kind == ICKind::NamedGlobalLoadIC || kind == ICKind::NamedGlobalTryLoadIC) {
236         JSTaggedValue box = SlowRuntimeStub::LdGlobalRecord(thread_, key.GetTaggedValue());
237         if (!box.IsUndefined()) {
238             ASSERT(box.IsPropertyBox());
239             if (icAccessor_.GetICState() != ProfileTypeAccessor::ICState::MEGA) {
240                 icAccessor_.AddGlobalRecordHandler(JSHandle<JSTaggedValue>(thread_, box));
241             }
242             return PropertyBox::Cast(box.GetTaggedObject())->GetValue();
243         }
244     }
245 
246     if (key->IsJSFunction()) { // key is a private getter
247         return LoadGetter(receiver, key);
248     }
249 
250     if (key->IsSymbol() && JSSymbol::Cast(key->GetTaggedObject())->IsPrivate()) {
251         PropertyDescriptor desc(thread_);
252         if (!JSTaggedValue::IsPropertyKey(key) ||
253             !JSTaggedValue::GetOwnProperty(thread_, receiver, key, desc)) {
254             THROW_TYPE_ERROR_AND_RETURN(thread_, "invalid or cannot find private key", JSTaggedValue::Exception());
255         }
256     }
257 
258     ObjectOperator op(GetThread(), receiver, key);
259     auto result = JSHandle<JSTaggedValue>(thread_, JSObject::GetProperty(GetThread(), &op));
260     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread_);
261     if (op.GetValue().IsAccessor()) {
262         op = ObjectOperator(GetThread(), receiver, key);
263     }
264     if (!op.IsFound() && kind == ICKind::NamedGlobalTryLoadIC) {
265         return SlowRuntimeStub::ThrowReferenceError(GetThread(), key.GetTaggedValue(), " is not defined");
266     }
267     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(GetThread());
268     // ic-switch
269     if (!GetThread()->GetEcmaVM()->ICEnabled()) {
270         icAccessor_.SetAsMega();
271         return result.GetTaggedValue();
272     }
273     TraceIC(receiver, key);
274     // do not cache element
275     if (!op.IsFastMode()) {
276         icAccessor_.SetAsMega();
277         return result.GetTaggedValue();
278     }
279 
280     UpdateLoadHandler(op, key, receiver);
281     return result.GetTaggedValue();
282 }
283 
LoadOrdinaryGet(JSHandle<JSTaggedValue> receiver,JSHandle<JSTaggedValue> key)284 JSTaggedValue LoadICRuntime::LoadOrdinaryGet(JSHandle<JSTaggedValue> receiver, JSHandle<JSTaggedValue> key)
285 {
286     icAccessor_.SetAsMega();
287     JSHandle<JSTaggedValue> propKey = JSTaggedValue::ToPropertyKey(thread_, key);
288     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread_);
289     return JSTaggedValue::GetProperty(thread_, receiver, propKey).GetValue().GetTaggedValue();
290 }
291 
LoadGetter(JSHandle<JSTaggedValue> receiver,JSHandle<JSTaggedValue> key)292 JSTaggedValue LoadICRuntime::LoadGetter(JSHandle<JSTaggedValue> receiver, JSHandle<JSTaggedValue> key)
293 {
294     JSHandle<JSTaggedValue> undefined = thread_->GlobalConstants()->GetHandledUndefined();
295     EcmaRuntimeCallInfo* info =
296         EcmaInterpreter::NewRuntimeCallInfo(thread_, key, receiver, undefined, 0); // 0: getter has 0 argument
297     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread_);
298     JSTaggedValue resGetter = JSFunction::Call(info);
299     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread_);
300     return resGetter;
301 }
302 
LoadTypedArrayValueMiss(JSHandle<JSTaggedValue> receiver,JSHandle<JSTaggedValue> key)303 JSTaggedValue LoadICRuntime::LoadTypedArrayValueMiss(JSHandle<JSTaggedValue> receiver, JSHandle<JSTaggedValue> key)
304 {
305     JSHandle<JSTaggedValue> propKey = JSTaggedValue::ToPropertyKey(GetThread(), key);
306     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(GetThread());
307     JSTaggedValue numericIndex = JSTaggedValue::CanonicalNumericIndexString(GetThread(), propKey);
308     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(GetThread());
309     if (!numericIndex.IsUndefined()) {
310         if (!JSTypedArray::IsValidIntegerIndex(receiver, numericIndex) || !GetThread()->GetEcmaVM()->ICEnabled()) {
311             icAccessor_.SetAsMega();
312             return JSTaggedValue::GetProperty(GetThread(), receiver, propKey).GetValue().GetTaggedValue();
313         }
314         UpdateTypedArrayHandler(receiver);
315         JSHandle<JSTaggedValue> indexHandle(GetThread(), numericIndex);
316         uint32_t index = static_cast<uint32_t>(JSTaggedValue::ToInteger(GetThread(), indexHandle).ToInt32());
317         JSType type = receiver->GetTaggedObject()->GetClass()->GetObjectType();
318         return JSTypedArray::FastGetPropertyByIndex(GetThread(), receiver.GetTaggedValue(), index, type);
319     } else {
320         ObjectOperator op(GetThread(), receiver, key);
321         auto result = JSHandle<JSTaggedValue>(GetThread(), JSObject::GetProperty(GetThread(), &op));
322         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(GetThread());
323         if (op.GetValue().IsAccessor()) {
324             op = ObjectOperator(GetThread(), receiver, key);
325         }
326         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(GetThread());
327         // ic-switch
328         if (!GetThread()->GetEcmaVM()->ICEnabled()) {
329             icAccessor_.SetAsMega();
330             return result.GetTaggedValue();
331         }
332         TraceIC(receiver, key);
333         // do not cache element
334         if (!op.IsFastMode()) {
335             icAccessor_.SetAsMega();
336             return result.GetTaggedValue();
337         }
338         UpdateLoadHandler(op, key, receiver);
339         return result.GetTaggedValue();
340     }
341 }
342 
StoreMiss(JSHandle<JSTaggedValue> receiver,JSHandle<JSTaggedValue> key,JSHandle<JSTaggedValue> value)343 JSTaggedValue StoreICRuntime::StoreMiss(JSHandle<JSTaggedValue> receiver, JSHandle<JSTaggedValue> key,
344                                         JSHandle<JSTaggedValue> value)
345 {
346     ICKind kind = GetICKind();
347     if (IsValueIC(kind)) {
348         key = JSTaggedValue::ToPropertyKey(GetThread(), key);
349     }
350     if (!receiver->IsJSObject() || receiver->HasOrdinaryGet()) {
351         icAccessor_.SetAsMega();
352         bool success = JSTaggedValue::SetProperty(GetThread(), receiver, key, value, true);
353         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread_);
354         return success ? JSTaggedValue::Undefined() : JSTaggedValue::Exception();
355     }
356     if (receiver->IsTypedArray() || receiver->IsSharedTypedArray()) {
357         return StoreTypedArrayValueMiss(receiver, key, value);
358     }
359 
360     // global variable find from global record firstly
361     if (kind == ICKind::NamedGlobalStoreIC || kind == ICKind::NamedGlobalTryStoreIC) {
362         JSTaggedValue box = SlowRuntimeStub::LdGlobalRecord(thread_, key.GetTaggedValue());
363         if (!box.IsUndefined()) {
364             ASSERT(box.IsPropertyBox());
365             SlowRuntimeStub::TryUpdateGlobalRecord(thread_, key.GetTaggedValue(), value.GetTaggedValue());
366             RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread_);
367             if (icAccessor_.GetICState() != ProfileTypeAccessor::ICState::MEGA) {
368                 icAccessor_.AddGlobalRecordHandler(JSHandle<JSTaggedValue>(thread_, box));
369             }
370             return JSTaggedValue::Undefined();
371         }
372     }
373     UpdateReceiverHClass(JSHandle<JSTaggedValue>(GetThread(), JSHandle<JSObject>::Cast(receiver)->GetClass()));
374 
375     // fixme(hzzhouzebin) Open IC for SharedArray later.
376     if (receiver->IsJSSharedArray()) {
377         bool success = JSSharedArray::SetProperty(thread_, receiver, key, value, true, SCheckMode::CHECK);
378         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread_);
379         if (success) {
380             return JSTaggedValue::Undefined();
381         }
382         return JSTaggedValue::Exception();
383     }
384     if (key->IsJSFunction()) { // key is a private setter
385         JSHandle<JSTaggedValue> undefined = thread_->GlobalConstants()->GetHandledUndefined();
386         EcmaRuntimeCallInfo* info =
387             EcmaInterpreter::NewRuntimeCallInfo(thread_, key, receiver, undefined, 1); // 1: setter has 1 argument
388         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread_);
389         info->SetCallArg(value.GetTaggedValue());
390         JSTaggedValue resSetter = JSFunction::Call(info);
391         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread_);
392         return resSetter;
393     }
394 
395     ObjectOperator op(GetThread(), receiver, key);
396     if (!op.IsFound()) {
397         if (kind == ICKind::NamedGlobalStoreIC) {
398             PropertyAttributes attr = PropertyAttributes::Default(true, true, false);
399             op.SetAttr(attr);
400         } else if (kind == ICKind::NamedGlobalTryStoreIC) {
401             return SlowRuntimeStub::ThrowReferenceError(GetThread(), key.GetTaggedValue(), " is not defined");
402         }
403     }
404     bool success = JSObject::SetProperty(&op, value, true);
405     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread_);
406     // ic-switch
407     if (!GetThread()->GetEcmaVM()->ICEnabled()) {
408         icAccessor_.SetAsMega();
409         return success ? JSTaggedValue::Undefined() : JSTaggedValue::Exception();
410     }
411     TraceIC(receiver, key);
412     // do not cache element
413     if (!op.IsFastMode()) {
414         icAccessor_.SetAsMega();
415         return success ? JSTaggedValue::Undefined() : JSTaggedValue::Exception();
416     }
417     if (success) {
418         UpdateStoreHandler(op, key, receiver);
419         return JSTaggedValue::Undefined();
420     }
421     return JSTaggedValue::Exception();
422 }
423 
StoreTypedArrayValueMiss(JSHandle<JSTaggedValue> receiver,JSHandle<JSTaggedValue> key,JSHandle<JSTaggedValue> value)424 JSTaggedValue StoreICRuntime::StoreTypedArrayValueMiss(JSHandle<JSTaggedValue> receiver, JSHandle<JSTaggedValue> key,
425                                                        JSHandle<JSTaggedValue> value)
426 {
427     JSHandle<JSTaggedValue> propKey = JSTaggedValue::ToPropertyKey(GetThread(), key);
428     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(GetThread());
429     JSTaggedValue numericIndex = JSTaggedValue::CanonicalNumericIndexString(GetThread(), propKey);
430     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(GetThread());
431     if (!numericIndex.IsUndefined()) {
432         if (!JSTypedArray::IsValidIntegerIndex(receiver, numericIndex) || value->IsECMAObject() ||
433             !GetThread()->GetEcmaVM()->ICEnabled()) {
434             icAccessor_.SetAsMega();
435             bool success = JSTaggedValue::SetProperty(GetThread(), receiver, propKey, value, true);
436             RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(GetThread());
437             return success ? JSTaggedValue::Undefined() : JSTaggedValue::Exception();
438         }
439         UpdateTypedArrayHandler(receiver);
440         JSHandle<JSTaggedValue> indexHandle(GetThread(), numericIndex);
441         uint32_t index = static_cast<uint32_t>(JSTaggedValue::ToInteger(GetThread(), indexHandle).ToInt32());
442         JSType type = receiver->GetTaggedObject()->GetClass()->GetObjectType();
443         return JSTypedArray::FastSetPropertyByIndex(GetThread(), receiver.GetTaggedValue(), index,
444                                                     value.GetTaggedValue(), type);
445     } else {
446         UpdateReceiverHClass(JSHandle<JSTaggedValue>(GetThread(), JSHandle<JSObject>::Cast(receiver)->GetClass()));
447         ObjectOperator op(GetThread(), receiver, key);
448         bool success = JSObject::SetProperty(&op, value, true);
449         if (op.GetValue().IsAccessor()) {
450             op = ObjectOperator(GetThread(), receiver, key);
451         }
452         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(GetThread());
453         // ic-switch
454         if (!GetThread()->GetEcmaVM()->ICEnabled()) {
455             icAccessor_.SetAsMega();
456             return success ? JSTaggedValue::Undefined() : JSTaggedValue::Exception();
457         }
458         TraceIC(receiver, key);
459         // do not cache element
460         if (!op.IsFastMode()) {
461             icAccessor_.SetAsMega();
462             return success ? JSTaggedValue::Undefined() : JSTaggedValue::Exception();
463         }
464         if (success) {
465             UpdateStoreHandler(op, key, receiver);
466             return JSTaggedValue::Undefined();
467         }
468         return JSTaggedValue::Exception();
469     }
470 }
471 }  // namespace panda::ecmascript
472