2021-09-04 08:06:49 +00:00
|
|
|
/*
|
2023-08-11 09:05:35 +00:00
|
|
|
* Copyright (c) 2021-2023 Huawei Device Co., Ltd.
|
2021-09-04 08:06:49 +00:00
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
2023-08-11 09:05:35 +00:00
|
|
|
#ifndef ECMASCRIPT_IC_IC_RUNTIME_STUB_INL_H
|
|
|
|
#define ECMASCRIPT_IC_IC_RUNTIME_STUB_INL_H
|
2021-09-04 08:06:49 +00:00
|
|
|
|
2021-09-07 14:24:16 +00:00
|
|
|
#include "ecmascript/base/config.h"
|
2022-07-23 10:33:33 +00:00
|
|
|
#include "ecmascript/global_env.h"
|
|
|
|
#include "ecmascript/global_dictionary-inl.h"
|
|
|
|
#include "ecmascript/ic/ic_runtime_stub.h"
|
|
|
|
#include "ecmascript/ic/ic_handler.h"
|
|
|
|
#include "ecmascript/ic/ic_runtime.h"
|
|
|
|
#include "ecmascript/interpreter/fast_runtime_stub-inl.h"
|
|
|
|
#include "ecmascript/ic/proto_change_details.h"
|
2021-09-04 08:06:49 +00:00
|
|
|
#include "ecmascript/js_tagged_value-inl.h"
|
|
|
|
#include "ecmascript/js_array.h"
|
|
|
|
#include "ecmascript/js_hclass-inl.h"
|
|
|
|
#include "ecmascript/js_function.h"
|
|
|
|
#include "ecmascript/js_proxy.h"
|
|
|
|
#include "ecmascript/js_handle.h"
|
2022-07-23 10:33:33 +00:00
|
|
|
#include "ecmascript/object_factory-inl.h"
|
2021-09-07 14:24:16 +00:00
|
|
|
#include "ecmascript/runtime_call_id.h"
|
|
|
|
|
2021-09-04 08:06:49 +00:00
|
|
|
namespace panda::ecmascript {
|
|
|
|
JSTaggedValue ICRuntimeStub::LoadGlobalICByName(JSThread *thread, ProfileTypeInfo *profileTypeInfo,
|
2022-10-24 11:32:00 +00:00
|
|
|
JSTaggedValue globalValue, JSTaggedValue key, uint32_t slotId,
|
|
|
|
bool tryLoad)
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
2021-09-16 03:25:47 +00:00
|
|
|
INTERPRETER_TRACE(thread, LoadGlobalICByName);
|
2021-09-04 08:06:49 +00:00
|
|
|
JSTaggedValue handler = profileTypeInfo->Get(slotId);
|
|
|
|
if (handler.IsHeapObject()) {
|
|
|
|
auto result = LoadGlobal(handler);
|
|
|
|
if (!result.IsHole()) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
2022-10-24 11:32:00 +00:00
|
|
|
ICKind kind = tryLoad ? ICKind::NamedGlobalTryLoadIC : ICKind::NamedGlobalLoadIC;
|
|
|
|
return LoadMiss(thread, profileTypeInfo, globalValue, key, slotId, kind);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
JSTaggedValue ICRuntimeStub::StoreGlobalICByName(JSThread *thread, ProfileTypeInfo *profileTypeInfo,
|
|
|
|
JSTaggedValue globalValue, JSTaggedValue key,
|
2022-10-24 11:32:00 +00:00
|
|
|
JSTaggedValue value, uint32_t slotId, bool tryStore)
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
2021-09-16 03:25:47 +00:00
|
|
|
INTERPRETER_TRACE(thread, StoreGlobalICByName);
|
2021-09-04 08:06:49 +00:00
|
|
|
JSTaggedValue handler = profileTypeInfo->Get(slotId);
|
|
|
|
if (handler.IsHeapObject()) {
|
|
|
|
auto result = StoreGlobal(thread, value, handler);
|
|
|
|
if (!result.IsHole()) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
2022-10-24 11:32:00 +00:00
|
|
|
ICKind kind = tryStore ? ICKind::NamedGlobalTryStoreIC : ICKind::NamedGlobalStoreIC;
|
|
|
|
return StoreMiss(thread, profileTypeInfo, globalValue, key, value, slotId, kind);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
JSTaggedValue ICRuntimeStub::CheckPolyHClass(JSTaggedValue cachedValue, JSHClass* hclass)
|
|
|
|
{
|
|
|
|
if (!cachedValue.IsWeak()) {
|
|
|
|
ASSERT(cachedValue.IsTaggedArray());
|
2022-06-16 15:10:50 +00:00
|
|
|
TaggedArray *array = TaggedArray::Cast(cachedValue.GetTaggedObject());
|
2022-01-14 13:50:26 +00:00
|
|
|
uint32_t length = array->GetLength();
|
|
|
|
for (uint32_t i = 0; i < length; i += 2) { // 2 means one ic, two slot
|
2021-12-17 09:18:10 +00:00
|
|
|
auto result = array->Get(i);
|
2023-01-14 01:29:02 +00:00
|
|
|
if (!result.IsUndefined() && result.GetWeakReferent() == hclass) {
|
2021-09-04 08:06:49 +00:00
|
|
|
return array->Get(i + 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return JSTaggedValue::Hole();
|
|
|
|
}
|
|
|
|
|
2021-09-07 14:24:16 +00:00
|
|
|
ARK_INLINE JSTaggedValue ICRuntimeStub::TryLoadICByName(JSThread *thread, JSTaggedValue receiver,
|
|
|
|
JSTaggedValue firstValue, JSTaggedValue secondValue)
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
2021-09-07 14:24:16 +00:00
|
|
|
INTERPRETER_TRACE(thread, TryLoadICByName);
|
|
|
|
if (LIKELY(receiver.IsHeapObject())) {
|
|
|
|
auto hclass = receiver.GetTaggedObject()->GetClass();
|
|
|
|
if (LIKELY(firstValue.GetWeakReferentUnChecked() == hclass)) {
|
|
|
|
return LoadICWithHandler(thread, receiver, receiver, secondValue);
|
|
|
|
}
|
|
|
|
JSTaggedValue cachedHandler = CheckPolyHClass(firstValue, hclass);
|
|
|
|
if (!cachedHandler.IsHole()) {
|
|
|
|
return LoadICWithHandler(thread, receiver, receiver, cachedHandler);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
}
|
2021-09-07 14:24:16 +00:00
|
|
|
return JSTaggedValue::Hole();
|
|
|
|
}
|
2021-09-04 08:06:49 +00:00
|
|
|
|
2021-09-07 14:24:16 +00:00
|
|
|
ARK_NOINLINE JSTaggedValue ICRuntimeStub::LoadICByName(JSThread *thread, ProfileTypeInfo *profileTypeInfo,
|
|
|
|
JSTaggedValue receiver, JSTaggedValue key, uint32_t slotId)
|
|
|
|
{
|
|
|
|
INTERPRETER_TRACE(thread, LoadICByName);
|
2022-02-16 03:05:56 +00:00
|
|
|
return LoadMiss(thread, profileTypeInfo, receiver, key, slotId, ICKind::NamedLoadIC);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
2021-09-07 14:24:16 +00:00
|
|
|
ARK_INLINE JSTaggedValue ICRuntimeStub::TryLoadICByValue(JSThread *thread, JSTaggedValue receiver, JSTaggedValue key,
|
|
|
|
JSTaggedValue firstValue, JSTaggedValue secondValue)
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
2021-09-07 14:24:16 +00:00
|
|
|
INTERPRETER_TRACE(thread, TryLoadICByValue);
|
2021-09-04 08:06:49 +00:00
|
|
|
if (receiver.IsHeapObject()) {
|
2021-09-07 14:24:16 +00:00
|
|
|
auto hclass = receiver.GetTaggedObject()->GetClass();
|
|
|
|
if (firstValue.GetWeakReferentUnChecked() == hclass) {
|
|
|
|
ASSERT(HandlerBase::IsElement(secondValue.GetInt()));
|
2022-06-16 15:10:50 +00:00
|
|
|
return LoadElement(JSObject::Cast(receiver.GetTaggedObject()), key);
|
2021-09-07 14:24:16 +00:00
|
|
|
}
|
|
|
|
// Check key
|
|
|
|
if (firstValue == key) {
|
|
|
|
JSTaggedValue cachedHandler = CheckPolyHClass(secondValue, hclass);
|
|
|
|
if (!cachedHandler.IsHole()) {
|
|
|
|
return LoadICWithHandler(thread, receiver, receiver, cachedHandler);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-09-07 14:24:16 +00:00
|
|
|
return JSTaggedValue::Hole();
|
|
|
|
}
|
|
|
|
|
|
|
|
ARK_NOINLINE JSTaggedValue ICRuntimeStub::LoadICByValue(JSThread *thread, ProfileTypeInfo *profileTypeInfo,
|
|
|
|
JSTaggedValue receiver, JSTaggedValue key, uint32_t slotId)
|
|
|
|
{
|
|
|
|
INTERPRETER_TRACE(thread, LoadICByValue);
|
2022-02-16 03:05:56 +00:00
|
|
|
return LoadMiss(thread, profileTypeInfo, receiver, key, slotId, ICKind::LoadIC);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
2021-09-07 14:24:16 +00:00
|
|
|
ARK_INLINE JSTaggedValue ICRuntimeStub::TryStoreICByValue(JSThread *thread, JSTaggedValue receiver,
|
|
|
|
JSTaggedValue key, JSTaggedValue firstValue,
|
|
|
|
JSTaggedValue secondValue, JSTaggedValue value)
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
2021-09-07 14:24:16 +00:00
|
|
|
INTERPRETER_TRACE(thread, TryStoreICByValue);
|
2021-09-04 08:06:49 +00:00
|
|
|
if (receiver.IsHeapObject()) {
|
2021-09-07 14:24:16 +00:00
|
|
|
auto hclass = receiver.GetTaggedObject()->GetClass();
|
|
|
|
if (firstValue.GetWeakReferentUnChecked() == hclass) {
|
2022-06-16 15:10:50 +00:00
|
|
|
return StoreElement(thread, JSObject::Cast(receiver.GetTaggedObject()), key, value, secondValue);
|
2021-09-07 14:24:16 +00:00
|
|
|
}
|
|
|
|
// Check key
|
|
|
|
if (firstValue == key) {
|
|
|
|
JSTaggedValue cachedHandler = CheckPolyHClass(secondValue, hclass);
|
|
|
|
if (!cachedHandler.IsHole()) {
|
|
|
|
return StoreICWithHandler(thread, receiver, receiver, value, cachedHandler);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-07 14:24:16 +00:00
|
|
|
return JSTaggedValue::Hole();
|
|
|
|
}
|
|
|
|
|
|
|
|
ARK_NOINLINE JSTaggedValue ICRuntimeStub::StoreICByValue(JSThread *thread, ProfileTypeInfo *profileTypeInfo,
|
|
|
|
JSTaggedValue receiver, JSTaggedValue key,
|
|
|
|
JSTaggedValue value, uint32_t slotId)
|
|
|
|
{
|
|
|
|
INTERPRETER_TRACE(thread, StoreICByValue);
|
2022-02-16 03:05:56 +00:00
|
|
|
return StoreMiss(thread, profileTypeInfo, receiver, key, value, slotId, ICKind::StoreIC);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
2021-09-07 14:24:16 +00:00
|
|
|
ARK_INLINE JSTaggedValue ICRuntimeStub::TryStoreICByName(JSThread *thread, JSTaggedValue receiver,
|
|
|
|
JSTaggedValue firstValue, JSTaggedValue secondValue,
|
|
|
|
JSTaggedValue value)
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
2021-09-07 14:24:16 +00:00
|
|
|
INTERPRETER_TRACE(thread, TryStoreICByName);
|
2021-09-04 08:06:49 +00:00
|
|
|
if (receiver.IsHeapObject()) {
|
2021-09-07 14:24:16 +00:00
|
|
|
auto hclass = receiver.GetTaggedObject()->GetClass();
|
|
|
|
if (firstValue.GetWeakReferentUnChecked() == hclass) {
|
|
|
|
return StoreICWithHandler(thread, receiver, receiver, value, secondValue);
|
|
|
|
}
|
|
|
|
JSTaggedValue cachedHandler = CheckPolyHClass(firstValue, hclass);
|
|
|
|
if (!cachedHandler.IsHole()) {
|
|
|
|
return StoreICWithHandler(thread, receiver, receiver, value, cachedHandler);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
}
|
2021-09-07 14:24:16 +00:00
|
|
|
return JSTaggedValue::Hole();
|
|
|
|
}
|
|
|
|
|
|
|
|
ARK_NOINLINE JSTaggedValue ICRuntimeStub::StoreICByName(JSThread *thread, ProfileTypeInfo *profileTypeInfo,
|
|
|
|
JSTaggedValue receiver, JSTaggedValue key,
|
|
|
|
JSTaggedValue value, uint32_t slotId)
|
|
|
|
{
|
|
|
|
INTERPRETER_TRACE(thread, StoreICByName);
|
2022-02-16 03:05:56 +00:00
|
|
|
return StoreMiss(thread, profileTypeInfo, receiver, key, value, slotId, ICKind::NamedStoreIC);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
2021-09-07 14:24:16 +00:00
|
|
|
ARK_INLINE JSTaggedValue ICRuntimeStub::StoreICWithHandler(JSThread *thread, JSTaggedValue receiver,
|
|
|
|
JSTaggedValue holder,
|
|
|
|
JSTaggedValue value, JSTaggedValue handler)
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
2021-09-16 03:25:47 +00:00
|
|
|
INTERPRETER_TRACE(thread, StoreICWithHandler);
|
2021-09-04 08:06:49 +00:00
|
|
|
if (handler.IsInt()) {
|
|
|
|
auto handlerInfo = static_cast<uint32_t>(handler.GetInt());
|
|
|
|
if (HandlerBase::IsField(handlerInfo)) {
|
2022-06-16 15:10:50 +00:00
|
|
|
StoreField(thread, JSObject::Cast(receiver.GetTaggedObject()), value, handlerInfo);
|
2021-09-04 08:06:49 +00:00
|
|
|
return JSTaggedValue::Undefined();
|
|
|
|
}
|
|
|
|
ASSERT(HandlerBase::IsAccessor(handlerInfo) || HandlerBase::IsInternalAccessor(handlerInfo));
|
2022-06-16 15:10:50 +00:00
|
|
|
auto accessor = LoadFromField(JSObject::Cast(holder.GetTaggedObject()), handlerInfo);
|
2021-09-04 08:06:49 +00:00
|
|
|
return FastRuntimeStub::CallSetter(thread, JSTaggedValue(receiver), value, accessor);
|
|
|
|
}
|
|
|
|
if (handler.IsTransitionHandler()) {
|
2022-06-16 15:10:50 +00:00
|
|
|
StoreWithTransition(thread, JSObject::Cast(receiver.GetTaggedObject()), value, handler);
|
2021-09-04 08:06:49 +00:00
|
|
|
return JSTaggedValue::Undefined();
|
|
|
|
}
|
2023-01-13 10:19:25 +00:00
|
|
|
if (handler.IsTransWithProtoHandler()) {
|
|
|
|
return StoreTransWithProto(thread, JSObject::Cast(receiver.GetTaggedObject()), value, handler);
|
|
|
|
}
|
2021-09-04 08:06:49 +00:00
|
|
|
if (handler.IsPrototypeHandler()) {
|
|
|
|
return StorePrototype(thread, receiver, value, handler);
|
|
|
|
}
|
|
|
|
if (handler.IsPropertyBox()) {
|
|
|
|
return StoreGlobal(thread, value, handler);
|
|
|
|
}
|
2023-01-13 10:19:25 +00:00
|
|
|
if (handler.IsStoreTSHandler()) {
|
|
|
|
return StoreWithTS(thread, receiver, value, handler);
|
|
|
|
}
|
2021-09-04 08:06:49 +00:00
|
|
|
return JSTaggedValue::Undefined();
|
|
|
|
}
|
|
|
|
|
|
|
|
JSTaggedValue ICRuntimeStub::StorePrototype(JSThread *thread, JSTaggedValue receiver,
|
|
|
|
JSTaggedValue value, JSTaggedValue handler)
|
|
|
|
{
|
2021-09-16 03:25:47 +00:00
|
|
|
INTERPRETER_TRACE(thread, StorePrototype);
|
2021-09-04 08:06:49 +00:00
|
|
|
ASSERT(handler.IsPrototypeHandler());
|
|
|
|
PrototypeHandler *prototypeHandler = PrototypeHandler::Cast(handler.GetTaggedObject());
|
|
|
|
auto cellValue = prototypeHandler->GetProtoCell();
|
|
|
|
ASSERT(cellValue.IsProtoChangeMarker());
|
2022-06-16 15:10:50 +00:00
|
|
|
ProtoChangeMarker *cell = ProtoChangeMarker::Cast(cellValue.GetTaggedObject());
|
2021-09-04 08:06:49 +00:00
|
|
|
if (cell->GetHasChanged()) {
|
|
|
|
return JSTaggedValue::Hole();
|
|
|
|
}
|
|
|
|
auto holder = prototypeHandler->GetHolder();
|
|
|
|
JSTaggedValue handlerInfo = prototypeHandler->GetHandlerInfo();
|
|
|
|
return StoreICWithHandler(thread, receiver, holder, value, handlerInfo);
|
|
|
|
}
|
|
|
|
|
2023-01-13 10:19:25 +00:00
|
|
|
JSTaggedValue ICRuntimeStub::StoreWithTS(JSThread *thread, JSTaggedValue receiver,
|
|
|
|
JSTaggedValue value, JSTaggedValue handler)
|
|
|
|
{
|
|
|
|
INTERPRETER_TRACE(thread, StoreWithAOT);
|
|
|
|
ASSERT(handler.IsStoreTSHandler());
|
|
|
|
StoreTSHandler *storeTSHandler = StoreTSHandler::Cast(handler.GetTaggedObject());
|
|
|
|
auto cellValue = storeTSHandler->GetProtoCell();
|
|
|
|
ASSERT(cellValue.IsProtoChangeMarker());
|
|
|
|
ProtoChangeMarker *cell = ProtoChangeMarker::Cast(cellValue.GetTaggedObject());
|
|
|
|
if (cell->GetHasChanged()) {
|
|
|
|
return JSTaggedValue::Hole();
|
|
|
|
}
|
|
|
|
auto holder = storeTSHandler->GetHolder();
|
|
|
|
JSTaggedValue handlerInfo = storeTSHandler->GetHandlerInfo();
|
|
|
|
auto handlerInfoInt = static_cast<uint32_t>(handlerInfo.GetInt());
|
|
|
|
if (HandlerBase::IsField(handlerInfoInt)) {
|
|
|
|
StoreField(thread, JSObject::Cast(receiver.GetTaggedObject()), value, handlerInfoInt);
|
|
|
|
return JSTaggedValue::Undefined();
|
|
|
|
}
|
|
|
|
ASSERT(HandlerBase::IsAccessor(handlerInfoInt) || HandlerBase::IsInternalAccessor(handlerInfoInt));
|
|
|
|
auto accessor = LoadFromField(JSObject::Cast(holder.GetTaggedObject()), handlerInfoInt);
|
|
|
|
return FastRuntimeStub::CallSetter(thread, JSTaggedValue(receiver), value, accessor);
|
|
|
|
}
|
|
|
|
|
2021-09-04 08:06:49 +00:00
|
|
|
void ICRuntimeStub::StoreWithTransition(JSThread *thread, JSObject *receiver, JSTaggedValue value,
|
2023-01-13 10:19:25 +00:00
|
|
|
JSTaggedValue handler, bool withPrototype)
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
2021-09-16 03:25:47 +00:00
|
|
|
INTERPRETER_TRACE(thread, StoreWithTransition);
|
2023-01-13 10:19:25 +00:00
|
|
|
|
|
|
|
JSHClass *newHClass = nullptr;
|
|
|
|
uint32_t handlerInfo = 0;
|
|
|
|
|
|
|
|
if (withPrototype) {
|
|
|
|
TransWithProtoHandler *transWithProtoHandler = TransWithProtoHandler::Cast(handler.GetTaggedObject());
|
|
|
|
newHClass = JSHClass::Cast(transWithProtoHandler->GetTransitionHClass().GetTaggedObject());
|
|
|
|
handlerInfo = static_cast<uint32_t>(transWithProtoHandler->GetHandlerInfo().GetInt());
|
|
|
|
} else {
|
|
|
|
TransitionHandler *transitionHandler = TransitionHandler::Cast(handler.GetTaggedObject());
|
|
|
|
newHClass = JSHClass::Cast(transitionHandler->GetTransitionHClass().GetTaggedObject());
|
|
|
|
handlerInfo = static_cast<uint32_t>(transitionHandler->GetHandlerInfo().GetInt());
|
|
|
|
}
|
|
|
|
|
2023-08-07 02:55:02 +00:00
|
|
|
receiver->SynchronizedSetClass(newHClass);
|
2021-09-04 08:06:49 +00:00
|
|
|
ASSERT(HandlerBase::IsField(handlerInfo));
|
|
|
|
|
|
|
|
if (!HandlerBase::IsInlinedProps(handlerInfo)) {
|
2022-06-16 15:10:50 +00:00
|
|
|
TaggedArray *array = TaggedArray::Cast(receiver->GetProperties().GetTaggedObject());
|
2022-04-11 02:41:49 +00:00
|
|
|
int capacity = static_cast<int>(array->GetLength());
|
2021-09-04 08:06:49 +00:00
|
|
|
int index = HandlerBase::GetOffset(handlerInfo);
|
|
|
|
if (index >= capacity) {
|
|
|
|
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
2022-10-28 09:28:36 +00:00
|
|
|
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
2021-09-04 08:06:49 +00:00
|
|
|
JSHandle<TaggedArray> properties;
|
|
|
|
JSHandle<JSObject> objHandle(thread, receiver);
|
2021-09-07 14:24:16 +00:00
|
|
|
JSHandle<JSTaggedValue> valueHandle(thread, value);
|
2021-09-04 08:06:49 +00:00
|
|
|
if (capacity == 0) {
|
|
|
|
capacity = JSObject::MIN_PROPERTIES_LENGTH;
|
|
|
|
properties = factory->NewTaggedArray(capacity);
|
|
|
|
} else {
|
2021-09-07 14:24:16 +00:00
|
|
|
auto arrayHandle = JSHandle<TaggedArray>(thread, array);
|
|
|
|
properties = factory->CopyArray(arrayHandle, capacity,
|
2021-09-04 08:06:49 +00:00
|
|
|
JSObject::ComputePropertyCapacity(capacity));
|
|
|
|
}
|
2021-09-07 14:24:16 +00:00
|
|
|
properties->Set(thread, index, valueHandle);
|
2021-09-04 08:06:49 +00:00
|
|
|
objHandle->SetProperties(thread, properties);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
array->Set(thread, index, value);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
StoreField(thread, receiver, value, handlerInfo);
|
|
|
|
}
|
|
|
|
|
2023-01-13 10:19:25 +00:00
|
|
|
JSTaggedValue ICRuntimeStub::StoreTransWithProto(JSThread *thread, JSObject *receiver, JSTaggedValue value,
|
|
|
|
JSTaggedValue handler)
|
|
|
|
{
|
|
|
|
INTERPRETER_TRACE(thread, StoreTransWithProto);
|
|
|
|
ASSERT(handler.IsTransWithProtoHandler());
|
|
|
|
TransWithProtoHandler *transWithProtoHandler = TransWithProtoHandler::Cast(handler.GetTaggedObject());
|
|
|
|
auto cellValue = transWithProtoHandler->GetProtoCell();
|
|
|
|
ASSERT(cellValue.IsProtoChangeMarker());
|
|
|
|
ProtoChangeMarker *cell = ProtoChangeMarker::Cast(cellValue.GetTaggedObject());
|
|
|
|
if (cell->GetHasChanged()) {
|
|
|
|
return JSTaggedValue::Hole();
|
|
|
|
}
|
|
|
|
|
|
|
|
StoreWithTransition(thread, receiver, value, handler, true);
|
|
|
|
return JSTaggedValue::Undefined();
|
|
|
|
}
|
|
|
|
|
2021-09-07 14:24:16 +00:00
|
|
|
ARK_INLINE void ICRuntimeStub::StoreField(JSThread *thread, JSObject *receiver, JSTaggedValue value, uint32_t handler)
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
2021-09-16 03:25:47 +00:00
|
|
|
INTERPRETER_TRACE(thread, StoreField);
|
2021-09-04 08:06:49 +00:00
|
|
|
int index = HandlerBase::GetOffset(handler);
|
|
|
|
if (HandlerBase::IsInlinedProps(handler)) {
|
2022-04-11 02:41:49 +00:00
|
|
|
SET_VALUE_WITH_BARRIER(thread, receiver, static_cast<uint32_t>(index) * JSTaggedValue::TaggedTypeSize(), value);
|
2021-09-04 08:06:49 +00:00
|
|
|
return;
|
|
|
|
}
|
2022-06-16 15:10:50 +00:00
|
|
|
TaggedArray *array = TaggedArray::Cast(receiver->GetProperties().GetTaggedObject());
|
2021-09-04 08:06:49 +00:00
|
|
|
ASSERT(index < static_cast<int>(array->GetLength()));
|
|
|
|
array->Set(thread, index, value);
|
|
|
|
}
|
|
|
|
|
2021-09-07 14:24:16 +00:00
|
|
|
ARK_INLINE JSTaggedValue ICRuntimeStub::LoadFromField(JSObject *receiver, uint32_t handlerInfo)
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
|
|
|
int index = HandlerBase::GetOffset(handlerInfo);
|
|
|
|
if (HandlerBase::IsInlinedProps(handlerInfo)) {
|
2022-04-11 02:41:49 +00:00
|
|
|
return JSTaggedValue(GET_VALUE(receiver, static_cast<size_t>(index) * JSTaggedValue::TaggedTypeSize()));
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
2022-06-16 15:10:50 +00:00
|
|
|
return TaggedArray::Cast(receiver->GetProperties().GetTaggedObject())->Get(index);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
2021-09-07 14:24:16 +00:00
|
|
|
ARK_INLINE JSTaggedValue ICRuntimeStub::LoadGlobal(JSTaggedValue handler)
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
|
|
|
ASSERT(handler.IsPropertyBox());
|
2022-06-16 15:10:50 +00:00
|
|
|
PropertyBox *cell = PropertyBox::Cast(handler.GetTaggedObject());
|
2021-09-04 08:06:49 +00:00
|
|
|
if (cell->IsInvalid()) {
|
|
|
|
return JSTaggedValue::Hole();
|
|
|
|
}
|
|
|
|
JSTaggedValue ret = cell->GetValue();
|
|
|
|
ASSERT(!ret.IsAccessorData());
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2021-09-07 14:24:16 +00:00
|
|
|
ARK_INLINE JSTaggedValue ICRuntimeStub::StoreGlobal(JSThread *thread, JSTaggedValue value, JSTaggedValue handler)
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
2021-09-16 03:25:47 +00:00
|
|
|
INTERPRETER_TRACE(thread, StoreGlobal);
|
2021-09-04 08:06:49 +00:00
|
|
|
ASSERT(handler.IsPropertyBox());
|
2022-06-16 15:10:50 +00:00
|
|
|
PropertyBox *cell = PropertyBox::Cast(handler.GetTaggedObject());
|
2021-09-04 08:06:49 +00:00
|
|
|
if (cell->IsInvalid()) {
|
|
|
|
return JSTaggedValue::Hole();
|
|
|
|
}
|
|
|
|
ASSERT(!cell->GetValue().IsAccessorData());
|
|
|
|
cell->SetValue(thread, value);
|
|
|
|
return JSTaggedValue::Undefined();
|
|
|
|
}
|
|
|
|
|
|
|
|
JSTaggedValue ICRuntimeStub::LoadPrototype(JSThread *thread, JSTaggedValue receiver, JSTaggedValue handler)
|
|
|
|
{
|
2021-09-16 03:25:47 +00:00
|
|
|
INTERPRETER_TRACE(thread, LoadPrototype);
|
2021-09-04 08:06:49 +00:00
|
|
|
ASSERT(handler.IsPrototypeHandler());
|
|
|
|
PrototypeHandler *prototypeHandler = PrototypeHandler::Cast(handler.GetTaggedObject());
|
|
|
|
auto cellValue = prototypeHandler->GetProtoCell();
|
|
|
|
ASSERT(cellValue.IsProtoChangeMarker());
|
2022-06-16 15:10:50 +00:00
|
|
|
ProtoChangeMarker *cell = ProtoChangeMarker::Cast(cellValue.GetTaggedObject());
|
2021-09-04 08:06:49 +00:00
|
|
|
if (cell->GetHasChanged()) {
|
|
|
|
return JSTaggedValue::Hole();
|
|
|
|
}
|
|
|
|
auto holder = prototypeHandler->GetHolder();
|
|
|
|
JSTaggedValue handlerInfo = prototypeHandler->GetHandlerInfo();
|
|
|
|
return LoadICWithHandler(thread, receiver, holder, handlerInfo);
|
|
|
|
}
|
|
|
|
|
2021-09-07 14:24:16 +00:00
|
|
|
ARK_INLINE JSTaggedValue ICRuntimeStub::LoadICWithHandler(JSThread *thread, JSTaggedValue receiver,
|
|
|
|
JSTaggedValue holder, JSTaggedValue handler)
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
2021-09-16 03:25:47 +00:00
|
|
|
INTERPRETER_TRACE(thread, LoadICWithHandler);
|
2021-09-04 08:06:49 +00:00
|
|
|
if (LIKELY(handler.IsInt())) {
|
|
|
|
auto handlerInfo = static_cast<uint32_t>(handler.GetInt());
|
|
|
|
if (LIKELY(HandlerBase::IsField(handlerInfo))) {
|
2022-06-16 15:10:50 +00:00
|
|
|
return LoadFromField(JSObject::Cast(holder.GetTaggedObject()), handlerInfo);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
if (HandlerBase::IsNonExist(handlerInfo)) {
|
|
|
|
return JSTaggedValue::Undefined();
|
|
|
|
}
|
|
|
|
ASSERT(HandlerBase::IsAccessor(handlerInfo) || HandlerBase::IsInternalAccessor(handlerInfo));
|
2022-06-16 15:10:50 +00:00
|
|
|
auto accessor = LoadFromField(JSObject::Cast(holder.GetTaggedObject()), handlerInfo);
|
2021-09-04 08:06:49 +00:00
|
|
|
return FastRuntimeStub::CallGetter(thread, receiver, holder, accessor);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (handler.IsPrototypeHandler()) {
|
|
|
|
return LoadPrototype(thread, receiver, handler);
|
|
|
|
}
|
|
|
|
|
|
|
|
return LoadGlobal(handler);
|
|
|
|
}
|
|
|
|
|
2021-09-07 14:24:16 +00:00
|
|
|
ARK_INLINE JSTaggedValue ICRuntimeStub::LoadElement(JSObject *receiver, JSTaggedValue key)
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
|
|
|
auto index = TryToElementsIndex(key);
|
|
|
|
if (index < 0) {
|
|
|
|
return JSTaggedValue::Hole();
|
|
|
|
}
|
2022-04-11 02:41:49 +00:00
|
|
|
uint32_t elementIndex = static_cast<uint32_t>(index);
|
2022-06-16 15:10:50 +00:00
|
|
|
TaggedArray *elements = TaggedArray::Cast(receiver->GetElements().GetTaggedObject());
|
2021-09-04 08:06:49 +00:00
|
|
|
if (elements->GetLength() <= elementIndex) {
|
|
|
|
return JSTaggedValue::Hole();
|
|
|
|
}
|
|
|
|
|
|
|
|
JSTaggedValue value = elements->Get(elementIndex);
|
2021-09-07 14:24:16 +00:00
|
|
|
// TaggedArray elements
|
2021-09-04 08:06:49 +00:00
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
JSTaggedValue ICRuntimeStub::StoreElement(JSThread *thread, JSObject *receiver, JSTaggedValue key,
|
2022-02-19 02:09:52 +00:00
|
|
|
JSTaggedValue value, JSTaggedValue handler)
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
2021-09-16 03:25:47 +00:00
|
|
|
INTERPRETER_TRACE(thread, StoreElement);
|
2021-09-04 08:06:49 +00:00
|
|
|
auto index = TryToElementsIndex(key);
|
|
|
|
if (index < 0) {
|
|
|
|
return JSTaggedValue::Hole();
|
|
|
|
}
|
2022-04-11 02:41:49 +00:00
|
|
|
uint32_t elementIndex = static_cast<uint32_t>(index);
|
2022-02-19 02:09:52 +00:00
|
|
|
if (handler.IsInt()) {
|
|
|
|
auto handlerInfo = static_cast<uint32_t>(handler.GetInt());
|
2022-10-26 02:39:13 +00:00
|
|
|
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
|
|
|
JSHandle<JSObject> receiverHandle(thread, receiver);
|
2022-02-19 02:09:52 +00:00
|
|
|
if (HandlerBase::IsJSArray(handlerInfo)) {
|
2022-10-26 02:39:13 +00:00
|
|
|
JSTaggedValue receiveValue = receiverHandle.GetTaggedValue();
|
|
|
|
if (receiveValue.IsJSCOWArray()) {
|
|
|
|
// Copy on write array.
|
|
|
|
JSArray::CheckAndCopyArray(thread, JSHandle<JSArray>::Cast(receiverHandle));
|
|
|
|
}
|
|
|
|
JSArray *arr = JSArray::Cast(*receiverHandle);
|
2022-02-19 02:09:52 +00:00
|
|
|
uint32_t oldLength = arr->GetArrayLength();
|
|
|
|
if (elementIndex >= oldLength) {
|
|
|
|
arr->SetArrayLength(thread, elementIndex + 1);
|
|
|
|
}
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
2022-10-26 02:39:13 +00:00
|
|
|
TaggedArray *elements = TaggedArray::Cast(receiverHandle->GetElements().GetTaggedObject());
|
2022-02-19 02:09:52 +00:00
|
|
|
uint32_t capacity = elements->GetLength();
|
|
|
|
if (elementIndex >= capacity) {
|
|
|
|
if (JSObject::ShouldTransToDict(capacity, elementIndex)) {
|
|
|
|
return JSTaggedValue::Hole();
|
|
|
|
}
|
|
|
|
JSHandle<JSTaggedValue> valueHandle(thread, value);
|
2023-03-21 07:42:21 +00:00
|
|
|
elements = *JSObject::GrowElementsCapacity(thread, receiverHandle, elementIndex + 1);
|
2022-02-19 02:09:52 +00:00
|
|
|
receiverHandle->SetElements(thread, JSTaggedValue(elements));
|
|
|
|
elements->Set(thread, elementIndex, valueHandle);
|
|
|
|
return JSTaggedValue::Undefined();
|
|
|
|
}
|
|
|
|
elements->Set(thread, elementIndex, value);
|
|
|
|
} else {
|
|
|
|
ASSERT(handler.IsPrototypeHandler());
|
|
|
|
PrototypeHandler *prototypeHandler = PrototypeHandler::Cast(handler.GetTaggedObject());
|
|
|
|
auto cellValue = prototypeHandler->GetProtoCell();
|
|
|
|
ASSERT(cellValue.IsProtoChangeMarker());
|
2022-06-16 15:10:50 +00:00
|
|
|
ProtoChangeMarker *cell = ProtoChangeMarker::Cast(cellValue.GetTaggedObject());
|
2022-02-19 02:09:52 +00:00
|
|
|
if (cell->GetHasChanged()) {
|
2021-09-04 08:06:49 +00:00
|
|
|
return JSTaggedValue::Hole();
|
|
|
|
}
|
2022-02-19 02:09:52 +00:00
|
|
|
JSTaggedValue handlerInfo = prototypeHandler->GetHandlerInfo();
|
|
|
|
return StoreElement(thread, receiver, key, value, handlerInfo);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
return JSTaggedValue::Undefined();
|
|
|
|
}
|
|
|
|
|
Cherry-pick !4555, !4637, !4638, !4648, !4653, !4665, !4688, !4699, !4737, !4747, !4811 to 4.0-Release
Cherry-pick
Issue: #I8453T
Signed-off-by: lichenshuai <lichenshuai@huawei.com>
Change-Id: Ib4639fe5a47adfc579d4439a9becd4b8b8ed619e
2023-09-25 06:51:37 +00:00
|
|
|
ARK_INLINE int64_t ICRuntimeStub::TryToElementsIndex(JSTaggedValue key)
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
|
|
|
if (LIKELY(key.IsInt())) {
|
|
|
|
return key.GetInt();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (key.IsString()) {
|
|
|
|
uint32_t index = 0;
|
|
|
|
if (JSTaggedValue::StringToElementIndex(key, &index)) {
|
Cherry-pick !4555, !4637, !4638, !4648, !4653, !4665, !4688, !4699, !4737, !4747, !4811 to 4.0-Release
Cherry-pick
Issue: #I8453T
Signed-off-by: lichenshuai <lichenshuai@huawei.com>
Change-Id: Ib4639fe5a47adfc579d4439a9becd4b8b8ed619e
2023-09-25 06:51:37 +00:00
|
|
|
return static_cast<int64_t>(index);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (key.IsDouble()) {
|
|
|
|
double number = key.GetDouble();
|
|
|
|
auto integer = static_cast<int32_t>(number);
|
|
|
|
if (number == integer) {
|
|
|
|
return integer;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
2022-02-16 03:05:56 +00:00
|
|
|
|
|
|
|
JSTaggedValue ICRuntimeStub::LoadMiss(JSThread *thread, ProfileTypeInfo *profileTypeInfo, JSTaggedValue receiver,
|
|
|
|
JSTaggedValue key, uint32_t slotId, ICKind kind)
|
|
|
|
{
|
|
|
|
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
|
|
|
auto keyHandle = JSHandle<JSTaggedValue>(thread, key);
|
|
|
|
auto receiverHandle = JSHandle<JSTaggedValue>(thread, receiver);
|
|
|
|
auto profileInfoHandle = JSHandle<JSTaggedValue>(thread, profileTypeInfo);
|
|
|
|
LoadICRuntime icRuntime(thread, JSHandle<ProfileTypeInfo>::Cast(profileInfoHandle), slotId, kind);
|
|
|
|
return icRuntime.LoadMiss(receiverHandle, keyHandle);
|
|
|
|
}
|
|
|
|
|
|
|
|
JSTaggedValue ICRuntimeStub::StoreMiss(JSThread *thread, ProfileTypeInfo *profileTypeInfo, JSTaggedValue receiver,
|
|
|
|
JSTaggedValue key, JSTaggedValue value, uint32_t slotId, ICKind kind)
|
|
|
|
{
|
|
|
|
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
|
|
|
auto keyHandle = JSHandle<JSTaggedValue>(thread, key);
|
|
|
|
auto receiverHandle = JSHandle<JSTaggedValue>(thread, receiver);
|
|
|
|
auto valueHandle = JSHandle<JSTaggedValue>(thread, value);
|
|
|
|
auto profileInfoHandle = JSHandle<JSTaggedValue>(thread, profileTypeInfo);
|
|
|
|
StoreICRuntime icRuntime(thread, JSHandle<ProfileTypeInfo>::Cast(profileInfoHandle), slotId, kind);
|
|
|
|
return icRuntime.StoreMiss(receiverHandle, keyHandle, valueHandle);
|
|
|
|
}
|
2021-09-04 08:06:49 +00:00
|
|
|
} // namespace panda::ecmascript
|
|
|
|
|
2023-08-11 09:05:35 +00:00
|
|
|
#endif // ECMASCRIPT_IC_IC_RUNTIME_STUB_INL_H
|