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