1/* 2 * Copyright (c) 2022 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#include "ecmascript/compiler/ic_stub_builder.h" 16 17#include "ecmascript/compiler/builtins/builtins_typedarray_stub_builder.h" 18#include "ecmascript/compiler/stub_builder-inl.h" 19 20namespace panda::ecmascript::kungfu { 21void ICStubBuilder::NamedICAccessor(Variable* cachedHandler, Label *tryICHandler) 22{ 23 auto env = GetEnvironment(); 24 Label receiverIsHeapObject(env); 25 Label receiverNotHeapObject(env); 26 Label tryIC(env); 27 28 BRANCH(TaggedIsHeapObject(receiver_), &receiverIsHeapObject, &receiverNotHeapObject); 29 Bind(&receiverIsHeapObject); 30 { 31 BRANCH(TaggedIsUndefined(profileTypeInfo_), tryFastPath_, &tryIC); 32 Bind(&tryIC); 33 { 34 Label isHeapObject(env); 35 Label notHeapObject(env); 36 GateRef firstValue = GetValueFromTaggedArray( 37 profileTypeInfo_, slotId_); 38 BRANCH(TaggedIsHeapObject(firstValue), &isHeapObject, ¬HeapObject); 39 Bind(&isHeapObject); 40 { 41 GateRef secondValue = GetValueFromTaggedArray(profileTypeInfo_, Int32Add(slotId_, Int32(1))); 42 cachedHandler->WriteVariable(secondValue); 43 Label tryPoly(env); 44 GateRef hclass = LoadHClass(receiver_); 45 BRANCH(Equal(LoadObjectFromWeakRef(firstValue), hclass), 46 tryICHandler, 47 &tryPoly); 48 Bind(&tryPoly); 49 { 50 cachedHandler->WriteVariable(CheckPolyHClass(firstValue, hclass)); 51 BRANCH(TaggedIsHole(cachedHandler->ReadVariable()), slowPath_, tryICHandler); 52 } 53 } 54 Bind(¬HeapObject); 55 { 56 BRANCH(TaggedIsUndefined(firstValue), slowPath_, tryFastPath_); 57 } 58 } 59 } 60 Bind(&receiverNotHeapObject); 61 { 62 Label tryNumber(env); 63 Label profileNotUndefined(env); 64 BRANCH(TaggedIsNumber(receiver_), &tryNumber, slowPath_); 65 Bind(&tryNumber); 66 { 67 BRANCH(TaggedIsUndefined(profileTypeInfo_), slowPath_, &profileNotUndefined); 68 Bind(&profileNotUndefined); 69 { 70 GateRef firstValue = GetValueFromTaggedArray(profileTypeInfo_, slotId_); 71 GateRef secondValue = GetValueFromTaggedArray(profileTypeInfo_, Int32Add(slotId_, Int32(1))); 72 cachedHandler->WriteVariable(secondValue); 73 Label isHeapObject(env); 74 BRANCH(TaggedIsHeapObject(firstValue), &isHeapObject, slowPath_) 75 Bind(&isHeapObject); 76 { 77 GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit())); 78 GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue_, glueGlobalEnvOffset); 79 auto numberFunction = GetGlobalEnvValue(VariableType::JS_ANY(), 80 glueGlobalEnv, GlobalEnv::NUMBER_FUNCTION_INDEX); 81 GateRef ctorProtoOrHC = 82 Load(VariableType::JS_POINTER(), numberFunction, 83 IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET)); 84 BRANCH(Equal(LoadObjectFromWeakRef(firstValue), ctorProtoOrHC), tryICHandler, slowPath_); 85 } 86 } 87 } 88 } 89} 90 91void ICStubBuilder::ValuedICAccessor(Variable* cachedHandler, Label *tryICHandler, Label* tryElementIC) 92{ 93 auto env = GetEnvironment(); 94 Label receiverIsHeapObject(env); 95 96 BRANCH(TaggedIsHeapObject(receiver_), &receiverIsHeapObject, slowPath_); 97 Bind(&receiverIsHeapObject); 98 { 99 Label tryIC(env); 100 BRANCH(TaggedIsUndefined(profileTypeInfo_), tryFastPath_, &tryIC); 101 Bind(&tryIC); 102 { 103 Label isHeapObject(env); 104 Label notHeapObject(env); 105 GateRef firstValue = GetValueFromTaggedArray( 106 profileTypeInfo_, slotId_); 107 BRANCH(TaggedIsHeapObject(firstValue), &isHeapObject, ¬HeapObject); 108 Bind(&isHeapObject); 109 { 110 Label tryPoly(env); 111 Label tryWithElementPoly(env); 112 GateRef hclass = LoadHClass(receiver_); 113 BRANCH(Equal(LoadObjectFromWeakRef(firstValue), hclass), 114 tryElementIC, 115 &tryPoly); 116 Bind(&tryPoly); 117 { 118 Label firstIsKey(env); 119 BRANCH(Int64Equal(firstValue, propKey_), &firstIsKey, &tryWithElementPoly); 120 Bind(&firstIsKey); 121 { 122 GateRef handler = CheckPolyHClass(cachedHandler->ReadVariable(), hclass); 123 cachedHandler->WriteVariable(handler); 124 BRANCH(TaggedIsHole(cachedHandler->ReadVariable()), slowPath_, tryICHandler); 125 } 126 Bind(&tryWithElementPoly); 127 { 128 Label checkSecond(env); 129 Label checkPoly(env); 130 BRANCH(TaggedIsWeak(firstValue), slowPath_, &checkSecond); 131 Bind(&checkSecond); 132 { 133 BRANCH(TaggedIsHole(cachedHandler->ReadVariable()), &checkPoly, slowPath_); 134 } 135 Bind(&checkPoly); 136 { 137 cachedHandler->WriteVariable(CheckPolyHClass(firstValue, hclass)); 138 BRANCH(TaggedIsHole(cachedHandler->ReadVariable()), slowPath_, tryElementIC); 139 } 140 } 141 } 142 } 143 Bind(¬HeapObject); 144 { 145 BRANCH(TaggedIsUndefined(firstValue), slowPath_, tryFastPath_); 146 } 147 } 148 } 149} 150 151void ICStubBuilder::LoadICByName( 152 Variable *result, Label *tryFastPath, Label *slowPath, Label *success, ProfileOperation callback) 153{ 154 auto env = GetEnvironment(); 155 Label loadWithHandler(env); 156 157 SetLabels(tryFastPath, slowPath, success); 158 DEFVARIABLE(cachedHandler, VariableType::JS_ANY(), Undefined()); 159 NamedICAccessor(&cachedHandler, &loadWithHandler); 160 Bind(&loadWithHandler); 161 { 162 GateRef ret = LoadICWithHandler(glue_, receiver_, receiver_, *cachedHandler, callback); 163 result->WriteVariable(ret); 164 BRANCH(TaggedIsHole(ret), slowPath_, success_); 165 } 166} 167 168void ICStubBuilder::StoreICByName(Variable* result, Label* tryFastPath, Label *slowPath, Label *success) 169{ 170 auto env = GetEnvironment(); 171 Label storeWithHandler(env); 172 173 SetLabels(tryFastPath, slowPath, success); 174 GateRef secondValue = GetValueFromTaggedArray( 175 profileTypeInfo_, Int32Add(slotId_, Int32(1))); 176 DEFVARIABLE(cachedHandler, VariableType::JS_ANY(), secondValue); 177 NamedICAccessor(&cachedHandler, &storeWithHandler); 178 Bind(&storeWithHandler); 179 { 180 GateRef ret = StoreICWithHandler(glue_, receiver_, receiver_, value_, *cachedHandler, callback_); 181 result->WriteVariable(ret); 182 BRANCH(TaggedIsHole(ret), slowPath_, success_); 183 } 184} 185 186void ICStubBuilder::LoadICByValue( 187 Variable *result, Label *tryFastPath, Label *slowPath, Label *success, ProfileOperation callback) 188{ 189 auto env = GetEnvironment(); 190 Label loadWithHandler(env); 191 Label loadElement(env); 192 Label handlerInfoIsElement(env); 193 Label handlerInfoNotElement(env); 194 Label handlerInfoIsStringElement(env); 195 Label handlerInfoNotStringElement(env); 196 Label handlerInfoIsTypedArrayElement(env); 197 Label exit(env); 198 199 SetLabels(tryFastPath, slowPath, success); 200 GateRef secondValue = GetValueFromTaggedArray( 201 profileTypeInfo_, Int32Add(slotId_, Int32(1))); 202 DEFVARIABLE(cachedHandler, VariableType::JS_ANY(), secondValue); 203 DEFVARIABLE(ret, VariableType::JS_ANY(), secondValue); 204 205 ValuedICAccessor(&cachedHandler, &loadWithHandler, &loadElement); 206 Bind(&loadElement); 207 { 208 GateRef handlerInfo = GetInt64OfTInt(*cachedHandler); 209 BRANCH(IsElement(handlerInfo), &handlerInfoIsElement, &handlerInfoNotElement); 210 Bind(&handlerInfoIsElement); 211 { 212 ret = LoadElement(glue_, receiver_, propKey_); 213 Jump(&exit); 214 } 215 Bind(&handlerInfoNotElement); 216 { 217 BRANCH(IsStringElement(handlerInfo), &handlerInfoIsStringElement, &handlerInfoNotStringElement); 218 Bind(&handlerInfoIsStringElement); 219 { 220 ret = LoadStringElement(glue_, receiver_, propKey_); 221 Jump(&exit); 222 } 223 Bind(&handlerInfoNotStringElement); 224 { 225 BRANCH(IsTypedArrayElement(handlerInfo), &handlerInfoIsTypedArrayElement, &exit); 226 Bind(&handlerInfoIsTypedArrayElement); 227 { 228 GateRef hclass = LoadHClass(receiver_); 229 GateRef jsType = GetObjectType(hclass); 230 BuiltinsTypedArrayStubBuilder typedArrayBuilder(reinterpret_cast<StubBuilder*>(this)); 231 ret = typedArrayBuilder.LoadTypedArrayElement(glue_, receiver_, propKey_, jsType); 232 Jump(&exit); 233 } 234 } 235 } 236 } 237 Bind(&loadWithHandler); 238 { 239 ret = LoadICWithHandler(glue_, receiver_, receiver_, *cachedHandler, callback); 240 Jump(&exit); 241 } 242 Bind(&exit); 243 result->WriteVariable(*ret); 244 BRANCH(TaggedIsHole(*ret), slowPath_, success_); 245} 246 247void ICStubBuilder::StoreICByValue(Variable* result, Label* tryFastPath, Label *slowPath, Label *success) 248{ 249 auto env = GetEnvironment(); 250 Label storeWithHandler(env); 251 Label storeElement(env); 252 SetLabels(tryFastPath, slowPath, success); 253 GateRef secondValue = GetValueFromTaggedArray( 254 profileTypeInfo_, Int32Add(slotId_, Int32(1))); 255 DEFVARIABLE(cachedHandler, VariableType::JS_ANY(), secondValue); 256 ValuedICAccessor(&cachedHandler, &storeWithHandler, &storeElement); 257 Bind(&storeElement); 258 { 259 GateRef ret = ICStoreElement(glue_, receiver_, propKey_, value_, *cachedHandler, 260 true, profileTypeInfo_, Int32Add(slotId_, Int32(1))); 261 result->WriteVariable(ret); 262 BRANCH(TaggedIsHole(ret), slowPath_, success_); 263 } 264 Bind(&storeWithHandler); 265 { 266 GateRef ret = StoreICWithHandler(glue_, receiver_, receiver_, value_, *cachedHandler, callback_); 267 result->WriteVariable(ret); 268 BRANCH(TaggedIsHole(ret), slowPath_, success_); 269 } 270} 271 272void ICStubBuilder::TryLoadGlobalICByName(Variable* result, Label* tryFastPath, Label *slowPath, Label *success) 273{ 274 auto env = GetEnvironment(); 275 Label tryIC(env); 276 277 SetLabels(tryFastPath, slowPath, success); 278 BRANCH(TaggedIsUndefined(profileTypeInfo_), tryFastPath_, &tryIC); 279 Bind(&tryIC); 280 { 281 GateRef handler = GetValueFromTaggedArray(profileTypeInfo_, slotId_); 282 Label isHeapObject(env); 283 BRANCH(TaggedIsHeapObject(handler), &isHeapObject, slowPath_); 284 Bind(&isHeapObject); 285 { 286 GateRef ret = LoadGlobal(handler); 287 result->WriteVariable(ret); 288 BRANCH(TaggedIsHole(ret), slowPath_, success_); 289 } 290 } 291} 292 293void ICStubBuilder::TryStoreGlobalICByName(Variable* result, Label* tryFastPath, Label *slowPath, Label *success) 294{ 295 auto env = GetEnvironment(); 296 Label tryIC(env); 297 298 SetLabels(tryFastPath, slowPath, success); 299 BRANCH(TaggedIsUndefined(profileTypeInfo_), tryFastPath_, &tryIC); 300 Bind(&tryIC); 301 { 302 GateRef handler = GetValueFromTaggedArray(profileTypeInfo_, slotId_); 303 Label isHeapObject(env); 304 BRANCH(TaggedIsHeapObject(handler), &isHeapObject, slowPath_); 305 Bind(&isHeapObject); 306 { 307 GateRef ret = StoreGlobal(glue_, value_, handler); 308 result->WriteVariable(ret); 309 BRANCH(TaggedIsHole(ret), slowPath_, success_); 310 } 311 } 312} 313} // namespace panda::ecmascript::kungfu 314