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