• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef ECMASCRIPT_IC_IC_RUNTIME_STUB_INL_H_
17 #define ECMASCRIPT_IC_IC_RUNTIME_STUB_INL_H_
18 
19 #include "ecmascript/base/config.h"
20 #include "ic_runtime_stub.h"
21 #include "ic_handler.h"
22 #include "ic_runtime.h"
23 #include "ecmascript/js_tagged_value-inl.h"
24 #include "ecmascript/js_array.h"
25 #include "ecmascript/js_hclass-inl.h"
26 #include "ecmascript/global_dictionary-inl.h"
27 #include "ecmascript/js_function.h"
28 #include "ecmascript/js_proxy.h"
29 #include "ecmascript/global_env.h"
30 #include "ecmascript/object_factory-inl.h"
31 #include "ecmascript/js_handle.h"
32 #include "ecmascript/interpreter/fast_runtime_stub-inl.h"
33 #include "ecmascript/ic/proto_change_details.h"
34 
35 #include "ecmascript/runtime_call_id.h"
36 
37 namespace panda::ecmascript {
LoadGlobalICByName(JSThread * thread,ProfileTypeInfo * profileTypeInfo,JSTaggedValue globalValue,JSTaggedValue key,uint32_t slotId)38 JSTaggedValue ICRuntimeStub::LoadGlobalICByName(JSThread *thread, ProfileTypeInfo *profileTypeInfo,
39                                                 JSTaggedValue globalValue, JSTaggedValue key, uint32_t slotId)
40 {
41     INTERPRETER_TRACE(thread, LoadGlobalICByName);
42     JSTaggedValue handler = profileTypeInfo->Get(slotId);
43     if (handler.IsHeapObject()) {
44         auto result = LoadGlobal(handler);
45         if (!result.IsHole()) {
46             return result;
47         }
48     }
49     return LoadMiss(thread, profileTypeInfo, globalValue, key, slotId, ICKind::NamedGlobalLoadIC);
50 }
51 
StoreGlobalICByName(JSThread * thread,ProfileTypeInfo * profileTypeInfo,JSTaggedValue globalValue,JSTaggedValue key,JSTaggedValue value,uint32_t slotId)52 JSTaggedValue ICRuntimeStub::StoreGlobalICByName(JSThread *thread, ProfileTypeInfo *profileTypeInfo,
53                                                  JSTaggedValue globalValue, JSTaggedValue key,
54                                                  JSTaggedValue value, uint32_t slotId)
55 {
56     INTERPRETER_TRACE(thread, StoreGlobalICByName);
57     JSTaggedValue handler = profileTypeInfo->Get(slotId);
58     if (handler.IsHeapObject()) {
59         auto result = StoreGlobal(thread, value, handler);
60         if (!result.IsHole()) {
61             return result;
62         }
63     }
64     return StoreMiss(thread, profileTypeInfo, globalValue, key, value, slotId, ICKind::NamedGlobalStoreIC);
65 }
66 
CheckPolyHClass(JSTaggedValue cachedValue,JSHClass * hclass)67 JSTaggedValue ICRuntimeStub::CheckPolyHClass(JSTaggedValue cachedValue, JSHClass* hclass)
68 {
69     if (!cachedValue.IsWeak()) {
70         ASSERT(cachedValue.IsTaggedArray());
71         TaggedArray *array = TaggedArray::Cast(cachedValue.GetHeapObject());
72         uint32_t length = array->GetLength();
73         for (uint32_t i = 0; i < length; i += 2) {  // 2 means one ic, two slot
74             auto result = array->Get(i);
75             if (result != JSTaggedValue::Undefined() && result.GetWeakReferent() == hclass) {
76                 return array->Get(i + 1);
77             }
78         }
79     }
80     return JSTaggedValue::Hole();
81 }
82 
TryLoadICByName(JSThread * thread,JSTaggedValue receiver,JSTaggedValue firstValue,JSTaggedValue secondValue)83 ARK_INLINE JSTaggedValue ICRuntimeStub::TryLoadICByName(JSThread *thread, JSTaggedValue receiver,
84                                                         JSTaggedValue firstValue, JSTaggedValue secondValue)
85 {
86     INTERPRETER_TRACE(thread, TryLoadICByName);
87     if (LIKELY(receiver.IsHeapObject())) {
88         auto hclass = receiver.GetTaggedObject()->GetClass();
89         if (LIKELY(firstValue.GetWeakReferentUnChecked() == hclass)) {
90             return LoadICWithHandler(thread, receiver, receiver, secondValue);
91         }
92         JSTaggedValue cachedHandler = CheckPolyHClass(firstValue, hclass);
93         if (!cachedHandler.IsHole()) {
94             return LoadICWithHandler(thread, receiver, receiver, cachedHandler);
95         }
96     }
97     return JSTaggedValue::Hole();
98 }
99 
LoadICByName(JSThread * thread,ProfileTypeInfo * profileTypeInfo,JSTaggedValue receiver,JSTaggedValue key,uint32_t slotId)100 ARK_NOINLINE JSTaggedValue ICRuntimeStub::LoadICByName(JSThread *thread, ProfileTypeInfo *profileTypeInfo,
101                                                        JSTaggedValue receiver, JSTaggedValue key, uint32_t slotId)
102 {
103     INTERPRETER_TRACE(thread, LoadICByName);
104     return LoadMiss(thread, profileTypeInfo, receiver, key, slotId, ICKind::NamedLoadIC);
105 }
106 
TryLoadICByValue(JSThread * thread,JSTaggedValue receiver,JSTaggedValue key,JSTaggedValue firstValue,JSTaggedValue secondValue)107 ARK_INLINE JSTaggedValue ICRuntimeStub::TryLoadICByValue(JSThread *thread, JSTaggedValue receiver, JSTaggedValue key,
108                                                          JSTaggedValue firstValue, JSTaggedValue secondValue)
109 {
110     INTERPRETER_TRACE(thread, TryLoadICByValue);
111     if (receiver.IsHeapObject()) {
112         auto hclass = receiver.GetTaggedObject()->GetClass();
113         if (firstValue.GetWeakReferentUnChecked() == hclass) {
114             ASSERT(HandlerBase::IsElement(secondValue.GetInt()));
115             return LoadElement(JSObject::Cast(receiver.GetHeapObject()), key);
116         }
117         // Check key
118         if (firstValue == key) {
119             JSTaggedValue cachedHandler = CheckPolyHClass(secondValue, hclass);
120             if (!cachedHandler.IsHole()) {
121                 return LoadICWithHandler(thread, receiver, receiver, cachedHandler);
122             }
123         }
124     }
125     return JSTaggedValue::Hole();
126 }
127 
LoadICByValue(JSThread * thread,ProfileTypeInfo * profileTypeInfo,JSTaggedValue receiver,JSTaggedValue key,uint32_t slotId)128 ARK_NOINLINE JSTaggedValue ICRuntimeStub::LoadICByValue(JSThread *thread, ProfileTypeInfo *profileTypeInfo,
129                                                         JSTaggedValue receiver, JSTaggedValue key, uint32_t slotId)
130 {
131     INTERPRETER_TRACE(thread, LoadICByValue);
132     return LoadMiss(thread, profileTypeInfo, receiver, key, slotId, ICKind::LoadIC);
133 }
134 
TryStoreICByValue(JSThread * thread,JSTaggedValue receiver,JSTaggedValue key,JSTaggedValue firstValue,JSTaggedValue secondValue,JSTaggedValue value)135 ARK_INLINE JSTaggedValue ICRuntimeStub::TryStoreICByValue(JSThread *thread, JSTaggedValue receiver,
136                                                           JSTaggedValue key, JSTaggedValue firstValue,
137                                                           JSTaggedValue secondValue, JSTaggedValue value)
138 {
139     INTERPRETER_TRACE(thread, TryStoreICByValue);
140     if (receiver.IsHeapObject()) {
141         auto hclass = receiver.GetTaggedObject()->GetClass();
142         if (firstValue.GetWeakReferentUnChecked() == hclass) {
143             return StoreElement(thread, JSObject::Cast(receiver.GetHeapObject()), key, value, secondValue);
144         }
145         // Check key
146         if (firstValue == key) {
147             JSTaggedValue cachedHandler = CheckPolyHClass(secondValue, hclass);
148             if (!cachedHandler.IsHole()) {
149                 return StoreICWithHandler(thread, receiver, receiver, value, cachedHandler);
150             }
151         }
152     }
153 
154     return JSTaggedValue::Hole();
155 }
156 
StoreICByValue(JSThread * thread,ProfileTypeInfo * profileTypeInfo,JSTaggedValue receiver,JSTaggedValue key,JSTaggedValue value,uint32_t slotId)157 ARK_NOINLINE JSTaggedValue ICRuntimeStub::StoreICByValue(JSThread *thread, ProfileTypeInfo *profileTypeInfo,
158                                                          JSTaggedValue receiver, JSTaggedValue key,
159                                                          JSTaggedValue value, uint32_t slotId)
160 {
161     INTERPRETER_TRACE(thread, StoreICByValue);
162     return StoreMiss(thread, profileTypeInfo, receiver, key, value, slotId, ICKind::StoreIC);
163 }
164 
TryStoreICByName(JSThread * thread,JSTaggedValue receiver,JSTaggedValue firstValue,JSTaggedValue secondValue,JSTaggedValue value)165 ARK_INLINE JSTaggedValue ICRuntimeStub::TryStoreICByName(JSThread *thread, JSTaggedValue receiver,
166                                                          JSTaggedValue firstValue, JSTaggedValue secondValue,
167                                                          JSTaggedValue value)
168 {
169     INTERPRETER_TRACE(thread, TryStoreICByName);
170     if (receiver.IsHeapObject()) {
171         auto hclass = receiver.GetTaggedObject()->GetClass();
172         if (firstValue.GetWeakReferentUnChecked() == hclass) {
173             return StoreICWithHandler(thread, receiver, receiver, value, secondValue);
174         }
175         JSTaggedValue cachedHandler = CheckPolyHClass(firstValue, hclass);
176         if (!cachedHandler.IsHole()) {
177             return StoreICWithHandler(thread, receiver, receiver, value, cachedHandler);
178         }
179     }
180     return JSTaggedValue::Hole();
181 }
182 
StoreICByName(JSThread * thread,ProfileTypeInfo * profileTypeInfo,JSTaggedValue receiver,JSTaggedValue key,JSTaggedValue value,uint32_t slotId)183 ARK_NOINLINE JSTaggedValue ICRuntimeStub::StoreICByName(JSThread *thread, ProfileTypeInfo *profileTypeInfo,
184                                                         JSTaggedValue receiver, JSTaggedValue key,
185                                                         JSTaggedValue value, uint32_t slotId)
186 {
187     INTERPRETER_TRACE(thread, StoreICByName);
188     return StoreMiss(thread, profileTypeInfo, receiver, key, value, slotId, ICKind::NamedStoreIC);
189 }
190 
StoreICWithHandler(JSThread * thread,JSTaggedValue receiver,JSTaggedValue holder,JSTaggedValue value,JSTaggedValue handler)191 ARK_INLINE JSTaggedValue ICRuntimeStub::StoreICWithHandler(JSThread *thread, JSTaggedValue receiver,
192                                                            JSTaggedValue holder,
193                                                            JSTaggedValue value, JSTaggedValue handler)
194 {
195     INTERPRETER_TRACE(thread, StoreICWithHandler);
196     if (handler.IsInt()) {
197         auto handlerInfo = static_cast<uint32_t>(handler.GetInt());
198         if (HandlerBase::IsField(handlerInfo)) {
199             StoreField(thread, JSObject::Cast(receiver.GetHeapObject()), value, handlerInfo);
200             return JSTaggedValue::Undefined();
201         }
202         ASSERT(HandlerBase::IsAccessor(handlerInfo) || HandlerBase::IsInternalAccessor(handlerInfo));
203         auto accessor = LoadFromField(JSObject::Cast(holder.GetHeapObject()), handlerInfo);
204         return FastRuntimeStub::CallSetter(thread, JSTaggedValue(receiver), value, accessor);
205     }
206     if (handler.IsTransitionHandler()) {
207         StoreWithTransition(thread, JSObject::Cast(receiver.GetHeapObject()), value, handler);
208         return JSTaggedValue::Undefined();
209     }
210     if (handler.IsPrototypeHandler()) {
211         return StorePrototype(thread, receiver, value, handler);
212     }
213     if (handler.IsPropertyBox()) {
214         return StoreGlobal(thread, value, handler);
215     }
216     return JSTaggedValue::Undefined();
217 }
218 
StorePrototype(JSThread * thread,JSTaggedValue receiver,JSTaggedValue value,JSTaggedValue handler)219 JSTaggedValue ICRuntimeStub::StorePrototype(JSThread *thread, JSTaggedValue receiver,
220                                             JSTaggedValue value, JSTaggedValue handler)
221 {
222     INTERPRETER_TRACE(thread, StorePrototype);
223     ASSERT(handler.IsPrototypeHandler());
224     PrototypeHandler *prototypeHandler = PrototypeHandler::Cast(handler.GetTaggedObject());
225     auto cellValue = prototypeHandler->GetProtoCell();
226     ASSERT(cellValue.IsProtoChangeMarker());
227     ProtoChangeMarker *cell = ProtoChangeMarker::Cast(cellValue.GetHeapObject());
228     if (cell->GetHasChanged()) {
229         return JSTaggedValue::Hole();
230     }
231     auto holder = prototypeHandler->GetHolder();
232     JSTaggedValue handlerInfo = prototypeHandler->GetHandlerInfo();
233     return StoreICWithHandler(thread, receiver, holder, value, handlerInfo);
234 }
235 
StoreWithTransition(JSThread * thread,JSObject * receiver,JSTaggedValue value,JSTaggedValue handler)236 void ICRuntimeStub::StoreWithTransition(JSThread *thread, JSObject *receiver, JSTaggedValue value,
237                                         JSTaggedValue handler)
238 {
239     INTERPRETER_TRACE(thread, StoreWithTransition);
240     TransitionHandler *transitionHandler = TransitionHandler::Cast(handler.GetTaggedObject());
241     JSHClass *newHClass = JSHClass::Cast(transitionHandler->GetTransitionHClass().GetTaggedObject());
242     receiver->SetClass(newHClass);
243     uint32_t handlerInfo = transitionHandler->GetHandlerInfo().GetInt();
244     ASSERT(HandlerBase::IsField(handlerInfo));
245 
246     if (!HandlerBase::IsInlinedProps(handlerInfo)) {
247         TaggedArray *array = TaggedArray::Cast(receiver->GetProperties().GetHeapObject());
248         int capacity = array->GetLength();
249         int index = HandlerBase::GetOffset(handlerInfo);
250         if (index >= capacity) {
251             ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
252             JSHandle<TaggedArray> properties;
253             JSHandle<JSObject> objHandle(thread, receiver);
254             JSHandle<JSTaggedValue> valueHandle(thread, value);
255             if (capacity == 0) {
256                 capacity = JSObject::MIN_PROPERTIES_LENGTH;
257                 properties = factory->NewTaggedArray(capacity);
258             } else {
259                 auto arrayHandle = JSHandle<TaggedArray>(thread, array);
260                 properties = factory->CopyArray(arrayHandle, capacity,
261                                                 JSObject::ComputePropertyCapacity(capacity));
262             }
263             properties->Set(thread, index, valueHandle);
264             objHandle->SetProperties(thread, properties);
265             return;
266         }
267         array->Set(thread, index, value);
268         return;
269     }
270     StoreField(thread, receiver, value, handlerInfo);
271 }
272 
StoreField(JSThread * thread,JSObject * receiver,JSTaggedValue value,uint32_t handler)273 ARK_INLINE void ICRuntimeStub::StoreField(JSThread *thread, JSObject *receiver, JSTaggedValue value, uint32_t handler)
274 {
275     INTERPRETER_TRACE(thread, StoreField);
276     int index = HandlerBase::GetOffset(handler);
277     if (HandlerBase::IsInlinedProps(handler)) {
278         SET_VALUE_WITH_BARRIER(thread, receiver, index * JSTaggedValue::TaggedTypeSize(), value);
279         return;
280     }
281     TaggedArray *array = TaggedArray::Cast(receiver->GetProperties().GetHeapObject());
282     ASSERT(index < static_cast<int>(array->GetLength()));
283     array->Set(thread, index, value);
284 }
285 
LoadFromField(JSObject * receiver,uint32_t handlerInfo)286 ARK_INLINE JSTaggedValue ICRuntimeStub::LoadFromField(JSObject *receiver, uint32_t handlerInfo)
287 {
288     int index = HandlerBase::GetOffset(handlerInfo);
289     if (HandlerBase::IsInlinedProps(handlerInfo)) {
290         return JSTaggedValue(GET_VALUE(receiver, index * JSTaggedValue::TaggedTypeSize()));
291     }
292     return TaggedArray::Cast(receiver->GetProperties().GetHeapObject())->Get(index);
293 }
294 
LoadGlobal(JSTaggedValue handler)295 ARK_INLINE JSTaggedValue ICRuntimeStub::LoadGlobal(JSTaggedValue handler)
296 {
297     ASSERT(handler.IsPropertyBox());
298     PropertyBox *cell = PropertyBox::Cast(handler.GetHeapObject());
299     if (cell->IsInvalid()) {
300         return JSTaggedValue::Hole();
301     }
302     JSTaggedValue ret = cell->GetValue();
303     ASSERT(!ret.IsAccessorData());
304     return ret;
305 }
306 
StoreGlobal(JSThread * thread,JSTaggedValue value,JSTaggedValue handler)307 ARK_INLINE JSTaggedValue ICRuntimeStub::StoreGlobal(JSThread *thread, JSTaggedValue value, JSTaggedValue handler)
308 {
309     INTERPRETER_TRACE(thread, StoreGlobal);
310     ASSERT(handler.IsPropertyBox());
311     PropertyBox *cell = PropertyBox::Cast(handler.GetHeapObject());
312     if (cell->IsInvalid()) {
313         return JSTaggedValue::Hole();
314     }
315     ASSERT(!cell->GetValue().IsAccessorData());
316     cell->SetValue(thread, value);
317     return JSTaggedValue::Undefined();
318 }
319 
LoadPrototype(JSThread * thread,JSTaggedValue receiver,JSTaggedValue handler)320 JSTaggedValue ICRuntimeStub::LoadPrototype(JSThread *thread, JSTaggedValue receiver, JSTaggedValue handler)
321 {
322     INTERPRETER_TRACE(thread, LoadPrototype);
323     ASSERT(handler.IsPrototypeHandler());
324     PrototypeHandler *prototypeHandler = PrototypeHandler::Cast(handler.GetTaggedObject());
325     auto cellValue = prototypeHandler->GetProtoCell();
326     ASSERT(cellValue.IsProtoChangeMarker());
327     ProtoChangeMarker *cell = ProtoChangeMarker::Cast(cellValue.GetHeapObject());
328     if (cell->GetHasChanged()) {
329         return JSTaggedValue::Hole();
330     }
331     auto holder = prototypeHandler->GetHolder();
332     JSTaggedValue handlerInfo = prototypeHandler->GetHandlerInfo();
333     return LoadICWithHandler(thread, receiver, holder, handlerInfo);
334 }
335 
LoadICWithHandler(JSThread * thread,JSTaggedValue receiver,JSTaggedValue holder,JSTaggedValue handler)336 ARK_INLINE JSTaggedValue ICRuntimeStub::LoadICWithHandler(JSThread *thread, JSTaggedValue receiver,
337                                                           JSTaggedValue holder, JSTaggedValue handler)
338 {
339     INTERPRETER_TRACE(thread, LoadICWithHandler);
340     if (LIKELY(handler.IsInt())) {
341         auto handlerInfo = static_cast<uint32_t>(handler.GetInt());
342         if (LIKELY(HandlerBase::IsField(handlerInfo))) {
343             return LoadFromField(JSObject::Cast(holder.GetHeapObject()), handlerInfo);
344         }
345         if (HandlerBase::IsNonExist(handlerInfo)) {
346             return JSTaggedValue::Undefined();
347         }
348         ASSERT(HandlerBase::IsAccessor(handlerInfo) || HandlerBase::IsInternalAccessor(handlerInfo));
349         auto accessor = LoadFromField(JSObject::Cast(holder.GetHeapObject()), handlerInfo);
350         return FastRuntimeStub::CallGetter(thread, receiver, holder, accessor);
351     }
352 
353     if (handler.IsPrototypeHandler()) {
354         return LoadPrototype(thread, receiver, handler);
355     }
356 
357     return LoadGlobal(handler);
358 }
359 
LoadElement(JSObject * receiver,JSTaggedValue key)360 ARK_INLINE JSTaggedValue ICRuntimeStub::LoadElement(JSObject *receiver, JSTaggedValue key)
361 {
362     auto index = TryToElementsIndex(key);
363     if (index < 0) {
364         return JSTaggedValue::Hole();
365     }
366     uint32_t elementIndex = index;
367     TaggedArray *elements = TaggedArray::Cast(receiver->GetElements().GetHeapObject());
368     if (elements->GetLength() <= elementIndex) {
369         return JSTaggedValue::Hole();
370     }
371 
372     JSTaggedValue value = elements->Get(elementIndex);
373     // TaggedArray elements
374     return value;
375 }
376 
StoreElement(JSThread * thread,JSObject * receiver,JSTaggedValue key,JSTaggedValue value,JSTaggedValue handler)377 JSTaggedValue ICRuntimeStub::StoreElement(JSThread *thread, JSObject *receiver, JSTaggedValue key,
378                                           JSTaggedValue value, JSTaggedValue handler)
379 {
380     INTERPRETER_TRACE(thread, StoreElement);
381     auto index = TryToElementsIndex(key);
382     if (index < 0) {
383         return JSTaggedValue::Hole();
384     }
385     uint32_t elementIndex = index;
386     if (handler.IsInt()) {
387         auto handlerInfo = static_cast<uint32_t>(handler.GetInt());
388         if (HandlerBase::IsJSArray(handlerInfo)) {
389             JSArray *arr = JSArray::Cast(receiver);
390             uint32_t oldLength = arr->GetArrayLength();
391             if (elementIndex >= oldLength) {
392                 arr->SetArrayLength(thread, elementIndex + 1);
393             }
394         }
395         TaggedArray *elements = TaggedArray::Cast(receiver->GetElements().GetHeapObject());
396         uint32_t capacity = elements->GetLength();
397         if (elementIndex >= capacity) {
398             if (JSObject::ShouldTransToDict(capacity, elementIndex)) {
399                 return JSTaggedValue::Hole();
400             }
401             [[maybe_unused]] EcmaHandleScope handleScope(thread);
402             JSHandle<JSObject> receiverHandle(thread, receiver);
403             JSHandle<JSTaggedValue> valueHandle(thread, value);
404             elements = *JSObject::GrowElementsCapacity(thread, receiverHandle,
405                                                        JSObject::ComputeElementCapacity(elementIndex + 1));
406             receiverHandle->SetElements(thread, JSTaggedValue(elements));
407             elements->Set(thread, elementIndex, valueHandle);
408             return JSTaggedValue::Undefined();
409         }
410         elements->Set(thread, elementIndex, value);
411     } else {
412         ASSERT(handler.IsPrototypeHandler());
413         PrototypeHandler *prototypeHandler = PrototypeHandler::Cast(handler.GetTaggedObject());
414         auto cellValue = prototypeHandler->GetProtoCell();
415         ASSERT(cellValue.IsProtoChangeMarker());
416         ProtoChangeMarker *cell = ProtoChangeMarker::Cast(cellValue.GetHeapObject());
417         if (cell->GetHasChanged()) {
418             return JSTaggedValue::Hole();
419         }
420         JSTaggedValue handlerInfo = prototypeHandler->GetHandlerInfo();
421         return StoreElement(thread, receiver, key, value, handlerInfo);
422     }
423     return JSTaggedValue::Undefined();
424 }
425 
TryToElementsIndex(JSTaggedValue key)426 ARK_INLINE int32_t ICRuntimeStub::TryToElementsIndex(JSTaggedValue key)
427 {
428     if (LIKELY(key.IsInt())) {
429         return key.GetInt();
430     }
431 
432     if (key.IsString()) {
433         uint32_t index = 0;
434         if (JSTaggedValue::StringToElementIndex(key, &index)) {
435             return static_cast<int32_t>(index);
436         }
437     }
438 
439     if (key.IsDouble()) {
440         double number = key.GetDouble();
441         auto integer = static_cast<int32_t>(number);
442         if (number == integer) {
443             return integer;
444         }
445     }
446 
447     return -1;
448 }
449 
LoadMiss(JSThread * thread,ProfileTypeInfo * profileTypeInfo,JSTaggedValue receiver,JSTaggedValue key,uint32_t slotId,ICKind kind)450 JSTaggedValue ICRuntimeStub::LoadMiss(JSThread *thread, ProfileTypeInfo *profileTypeInfo, JSTaggedValue receiver,
451                                       JSTaggedValue key, uint32_t slotId, ICKind kind)
452 {
453     [[maybe_unused]] EcmaHandleScope handleScope(thread);
454     auto keyHandle = JSHandle<JSTaggedValue>(thread, key);
455     auto receiverHandle = JSHandle<JSTaggedValue>(thread, receiver);
456     auto profileInfoHandle = JSHandle<JSTaggedValue>(thread, profileTypeInfo);
457     LoadICRuntime icRuntime(thread, JSHandle<ProfileTypeInfo>::Cast(profileInfoHandle), slotId, kind);
458     return icRuntime.LoadMiss(receiverHandle, keyHandle);
459 }
460 
StoreMiss(JSThread * thread,ProfileTypeInfo * profileTypeInfo,JSTaggedValue receiver,JSTaggedValue key,JSTaggedValue value,uint32_t slotId,ICKind kind)461 JSTaggedValue ICRuntimeStub::StoreMiss(JSThread *thread, ProfileTypeInfo *profileTypeInfo, JSTaggedValue receiver,
462                                        JSTaggedValue key, JSTaggedValue value, uint32_t slotId, ICKind kind)
463 {
464     [[maybe_unused]] EcmaHandleScope handleScope(thread);
465     auto keyHandle = JSHandle<JSTaggedValue>(thread, key);
466     auto receiverHandle = JSHandle<JSTaggedValue>(thread, receiver);
467     auto valueHandle = JSHandle<JSTaggedValue>(thread, value);
468     auto profileInfoHandle = JSHandle<JSTaggedValue>(thread, profileTypeInfo);
469     StoreICRuntime icRuntime(thread, JSHandle<ProfileTypeInfo>::Cast(profileInfoHandle), slotId, kind);
470     return icRuntime.StoreMiss(receiverHandle, keyHandle, valueHandle);
471 }
472 }  // namespace panda::ecmascript
473 
474 #endif  // ECMASCRIPT_IC_IC_RUNTIME_STUB_INL_H_
475