/* * Copyright (c) 2022 Huawei Device Co., Ltd. * 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. */ #include "ecmascript/compiler/ic_stub_builder.h" #include "ecmascript/compiler/stub_builder-inl.h" namespace panda::ecmascript::kungfu { void ICStubBuilder::NamedICAccessor(Variable* cachedHandler, Label *tryICHandler) { auto env = GetEnvironment(); Label receiverIsHeapObject(env); Label tryIC(env); Branch(TaggedIsHeapObject(receiver_), &receiverIsHeapObject, slowPath_); Bind(&receiverIsHeapObject); { Branch(TaggedIsUndefined(profileTypeInfo_), tryFastPath_, &tryIC); Bind(&tryIC); { Label isHeapObject(env); Label notHeapObject(env); GateRef firstValue = GetValueFromTaggedArray( profileTypeInfo_, slotId_); Branch(TaggedIsHeapObject(firstValue), &isHeapObject, ¬HeapObject); Bind(&isHeapObject); { Label tryPoly(env); GateRef hclass = LoadHClass(receiver_); Branch(Equal(LoadObjectFromWeakRef(firstValue), hclass), tryICHandler, &tryPoly); Bind(&tryPoly); { cachedHandler->WriteVariable(CheckPolyHClass(firstValue, hclass)); Branch(TaggedIsHole(cachedHandler->ReadVariable()), slowPath_, tryICHandler); } } Bind(¬HeapObject); { Branch(TaggedIsUndefined(firstValue), slowPath_, tryFastPath_); } } } } void ICStubBuilder::ValuedICAccessor(Variable* cachedHandler, Label *tryICHandler, Label* tryElementIC) { auto env = GetEnvironment(); Label receiverIsHeapObject(env); Branch(TaggedIsHeapObject(receiver_), &receiverIsHeapObject, slowPath_); Bind(&receiverIsHeapObject); { Label tryIC(env); Branch(TaggedIsUndefined(profileTypeInfo_), tryFastPath_, &tryIC); Bind(&tryIC); { Label isHeapObject(env); Label notHeapObject(env); GateRef firstValue = GetValueFromTaggedArray( profileTypeInfo_, slotId_); Branch(TaggedIsHeapObject(firstValue), &isHeapObject, ¬HeapObject); Bind(&isHeapObject); { Label tryPoly(env); GateRef hclass = LoadHClass(receiver_); Branch(Equal(LoadObjectFromWeakRef(firstValue), hclass), tryElementIC, &tryPoly); Bind(&tryPoly); { Label firstIsKey(env); Branch(Int64Equal(firstValue, propKey_), &firstIsKey, slowPath_); Bind(&firstIsKey); GateRef handler = CheckPolyHClass(cachedHandler->ReadVariable(), hclass); cachedHandler->WriteVariable(handler); Branch(TaggedIsHole(cachedHandler->ReadVariable()), slowPath_, tryICHandler); } } Bind(¬HeapObject); { Branch(TaggedIsUndefined(firstValue), slowPath_, tryFastPath_); } } } } void ICStubBuilder::LoadICByName( Variable *result, Label *tryFastPath, Label *slowPath, Label *success, ProfileOperation callback) { auto env = GetEnvironment(); Label loadWithHandler(env); SetLabels(tryFastPath, slowPath, success); GateRef secondValue = GetValueFromTaggedArray( profileTypeInfo_, Int32Add(slotId_, Int32(1))); DEFVARIABLE(cachedHandler, VariableType::JS_ANY(), secondValue); NamedICAccessor(&cachedHandler, &loadWithHandler); Bind(&loadWithHandler); { GateRef ret = LoadICWithHandler(glue_, receiver_, receiver_, *cachedHandler, callback); result->WriteVariable(ret); Branch(TaggedIsHole(ret), slowPath_, success_); } } void ICStubBuilder::StoreICByName(Variable* result, Label* tryFastPath, Label *slowPath, Label *success) { auto env = GetEnvironment(); Label storeWithHandler(env); SetLabels(tryFastPath, slowPath, success); GateRef secondValue = GetValueFromTaggedArray( profileTypeInfo_, Int32Add(slotId_, Int32(1))); DEFVARIABLE(cachedHandler, VariableType::JS_ANY(), secondValue); NamedICAccessor(&cachedHandler, &storeWithHandler); Bind(&storeWithHandler); { GateRef ret = StoreICWithHandler(glue_, receiver_, receiver_, value_, *cachedHandler, callback_); result->WriteVariable(ret); Branch(TaggedIsHole(ret), slowPath_, success_); } } void ICStubBuilder::LoadICByValue( Variable *result, Label *tryFastPath, Label *slowPath, Label *success, ProfileOperation callback) { auto env = GetEnvironment(); Label loadWithHandler(env); Label loadElement(env); SetLabels(tryFastPath, slowPath, success); GateRef secondValue = GetValueFromTaggedArray( profileTypeInfo_, Int32Add(slotId_, Int32(1))); DEFVARIABLE(cachedHandler, VariableType::JS_ANY(), secondValue); ValuedICAccessor(&cachedHandler, &loadWithHandler, &loadElement); Bind(&loadElement); { GateRef ret = LoadElement(glue_, receiver_, propKey_, callback); result->WriteVariable(ret); Branch(TaggedIsHole(ret), slowPath_, success_); } Bind(&loadWithHandler); { GateRef ret = LoadICWithHandler(glue_, receiver_, receiver_, *cachedHandler, callback); result->WriteVariable(ret); Branch(TaggedIsHole(ret), slowPath_, success_); } } void ICStubBuilder::StoreICByValue(Variable* result, Label* tryFastPath, Label *slowPath, Label *success) { auto env = GetEnvironment(); Label storeWithHandler(env); Label storeElement(env); SetLabels(tryFastPath, slowPath, success); GateRef secondValue = GetValueFromTaggedArray( profileTypeInfo_, Int32Add(slotId_, Int32(1))); DEFVARIABLE(cachedHandler, VariableType::JS_ANY(), secondValue); ValuedICAccessor(&cachedHandler, &storeWithHandler, &storeElement); Bind(&storeElement); { GateRef ret = ICStoreElement(glue_, receiver_, propKey_, value_, secondValue, callback_); result->WriteVariable(ret); Branch(TaggedIsHole(ret), slowPath_, success_); } Bind(&storeWithHandler); { GateRef ret = StoreICWithHandler(glue_, receiver_, receiver_, value_, *cachedHandler, callback_); result->WriteVariable(ret); Branch(TaggedIsHole(ret), slowPath_, success_); } } void ICStubBuilder::TryLoadGlobalICByName(Variable* result, Label* tryFastPath, Label *slowPath, Label *success) { auto env = GetEnvironment(); Label tryIC(env); SetLabels(tryFastPath, slowPath, success); Branch(TaggedIsUndefined(profileTypeInfo_), tryFastPath_, &tryIC); Bind(&tryIC); { GateRef handler = GetValueFromTaggedArray(profileTypeInfo_, slotId_); Label isHeapObject(env); Branch(TaggedIsHeapObject(handler), &isHeapObject, slowPath_); Bind(&isHeapObject); { GateRef ret = LoadGlobal(handler); result->WriteVariable(ret); Branch(TaggedIsHole(ret), slowPath_, success_); } } } void ICStubBuilder::TryStoreGlobalICByName(Variable* result, Label* tryFastPath, Label *slowPath, Label *success) { auto env = GetEnvironment(); Label tryIC(env); SetLabels(tryFastPath, slowPath, success); Branch(TaggedIsUndefined(profileTypeInfo_), tryFastPath_, &tryIC); Bind(&tryIC); { GateRef handler = GetValueFromTaggedArray(profileTypeInfo_, slotId_); Label isHeapObject(env); Branch(TaggedIsHeapObject(handler), &isHeapObject, slowPath_); Bind(&isHeapObject); { GateRef ret = StoreGlobal(glue_, value_, handler); result->WriteVariable(ret); Branch(TaggedIsHole(ret), slowPath_, success_); } } } } // namespace panda::ecmascript::kungfu