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 16#include "ecmascript/compiler/new_object_stub_builder.h" 17 18#include "ecmascript/compiler/builtins/builtins_function_stub_builder.h" 19#include "ecmascript/compiler/builtins/builtins_proxy_stub_builder.h" 20#include "ecmascript/compiler/number_gate_info.h" 21#include "ecmascript/compiler/stub_builder-inl.h" 22#include "ecmascript/compiler/stub_builder.h" 23#include "ecmascript/ecma_string.h" 24#include "ecmascript/global_env.h" 25#include "ecmascript/global_env_constants.h" 26#include "ecmascript/js_arguments.h" 27#include "ecmascript/js_object.h" 28#include "ecmascript/js_thread.h" 29#include "ecmascript/lexical_env.h" 30#include "ecmascript/mem/mem.h" 31#include "ecmascript/js_array_iterator.h" 32#include "ecmascript/js_map_iterator.h" 33#include "ecmascript/js_set_iterator.h" 34#include "ecmascript/js_set.h" 35#include "ecmascript/js_map.h" 36 37namespace panda::ecmascript::kungfu { 38void NewObjectStubBuilder::NewLexicalEnv(Variable *result, Label *exit, GateRef numSlots, GateRef parent) 39{ 40 auto env = GetEnvironment(); 41 42 auto length = Int32Add(numSlots, Int32(LexicalEnv::RESERVED_ENV_LENGTH)); 43 size_ = ComputeTaggedArraySize(ZExtInt32ToPtr(length)); 44 // Be careful. NO GC is allowed when initization is not complete. 45 Label hasPendingException(env); 46 Label noException(env); 47 auto hclass = GetGlobalConstantValue( 48 VariableType::JS_POINTER(), glue_, ConstantIndex::ENV_CLASS_INDEX); 49 AllocateInYoung(result, &hasPendingException, &noException, hclass); 50 Bind(&noException); 51 { 52 StoreHClass(glue_, result->ReadVariable(), hclass); 53 Label afterInitialize(env); 54 InitializeTaggedArrayWithSpeicalValue(&afterInitialize, 55 result->ReadVariable(), Hole(), Int32(LexicalEnv::RESERVED_ENV_LENGTH), length); 56 Bind(&afterInitialize); 57 SetValueToTaggedArray(VariableType::INT64(), 58 glue_, result->ReadVariable(), Int32(LexicalEnv::SCOPE_INFO_INDEX), Hole()); 59 SetValueToTaggedArray(VariableType::JS_POINTER(), 60 glue_, result->ReadVariable(), Int32(LexicalEnv::PARENT_ENV_INDEX), parent); 61 Jump(exit); 62 } 63 Bind(&hasPendingException); 64 { 65 Jump(exit); 66 } 67} 68 69GateRef NewObjectStubBuilder::NewJSArrayWithSize(GateRef hclass, GateRef size) 70{ 71 auto env = GetEnvironment(); 72 Label entry(env); 73 Label exit(env); 74 env->SubCfgEntry(&entry); 75 76 GateRef result = NewJSObject(glue_, hclass); 77 Label enabledElementsKind(env); 78 Label notEmptyArray(env); 79 Label initObj(env); 80 GateRef isElementsKindEnabled = IsEnableElementsKind(glue_); 81 BRANCH(isElementsKindEnabled, &enabledElementsKind, &initObj); 82 Bind(&enabledElementsKind); 83 { 84 // For new Array(Len), the elementsKind should be Hole 85 BRANCH(Equal(TruncInt64ToInt32(size), Int32(0)), &initObj, ¬EmptyArray); 86 Bind(¬EmptyArray); 87 { 88 #if ECMASCRIPT_ENABLE_ELEMENTSKIND_ALWAY_GENERIC 89 GateRef holeKindArrayClass = GetGlobalConstantValue(VariableType::JS_ANY(), glue_, 90 ConstantIndex::ELEMENT_HOLE_TAGGED_HCLASS_INDEX); 91 StoreHClass(glue_, result, holeKindArrayClass); 92 #else 93 GateRef holeKindArrayClass = GetGlobalConstantValue(VariableType::JS_ANY(), glue_, 94 ConstantIndex::ELEMENT_HOLE_HCLASS_INDEX); 95 StoreHClass(glue_, result, holeKindArrayClass); 96 #endif 97 Jump(&initObj); 98 } 99 } 100 Bind(&initObj); 101 DEFVARIABLE(array, VariableType::JS_ANY(), Undefined()); 102 NewTaggedArrayChecked(&array, TruncInt64ToInt32(size), &exit); 103 Bind(&exit); 104 auto arrayRet = *array; 105 env->SubCfgExit(); 106 SetElementsArray(VariableType::JS_POINTER(), glue_, result, arrayRet); 107 return result; 108} 109 110GateRef NewObjectStubBuilder::NewJSFunctionByHClass(GateRef glue, 111 GateRef method, GateRef hclass, FunctionKind targetKind) 112{ 113 GateRef result = NewJSObject(glue, hclass); 114 SetExtensibleToBitfield(glue, hclass, true); 115 GateRef kind = GetFuncKind(method); 116 BuiltinsFunctionStubBuilder builtinsFunctionStubBuilder(this); 117 builtinsFunctionStubBuilder.InitializeJSFunction(glue, result, kind, targetKind); 118 builtinsFunctionStubBuilder.InitializeFunctionWithMethod(glue, result, method, hclass); 119 return result; 120} 121 122GateRef NewObjectStubBuilder::NewSFunctionByHClass(GateRef glue, 123 GateRef method, GateRef hclass, FunctionKind targetKind) 124{ 125 GateRef result = result = NewSObject(glue, hclass); 126 GateRef kind = GetFuncKind(method); 127 BuiltinsFunctionStubBuilder builtinsFunctionStubBuilder(this); 128 builtinsFunctionStubBuilder.InitializeSFunction(glue, result, kind, targetKind); 129 builtinsFunctionStubBuilder.InitializeFunctionWithMethod(glue, result, method, hclass); 130 return result; 131} 132 133GateRef NewObjectStubBuilder::CloneJSFunction(GateRef glue, GateRef value) 134{ 135 GateRef hclass = LoadHClass(value); 136 GateRef method = GetMethodFromFunction(value); 137 GateRef cloneFunc = NewJSFunctionByHClass(glue, method, hclass); 138 GateRef length = GetPropertyInlinedProps(value, hclass, 139 Int32(JSFunction::LENGTH_INLINE_PROPERTY_INDEX)); 140 SetPropertyInlinedProps(glue, value, hclass, length, 141 Int32(JSFunction::LENGTH_INLINE_PROPERTY_INDEX), 142 VariableType::JS_ANY()); 143 SetLengthToFunction(glue, cloneFunc, GetLengthFromFunction(value)); 144 SetModuleToFunction(glue, cloneFunc, GetModuleFromFunction(value)); 145 return cloneFunc; 146} 147 148GateRef NewObjectStubBuilder::CloneProperties(GateRef glue, GateRef currentEnv, 149 GateRef elements, GateRef obj) 150{ 151 auto env = GetEnvironment(); 152 Label entry(env); 153 env->SubCfgEntry(&entry); 154 Label exit(env); 155 Label isZero(env); 156 Label notZero(env); 157 Label initialize(env); 158 Label afterInitialize(env); 159 Label begin(env); 160 Label body(env); 161 Label isJSFunction(env); 162 Label notJSFunction(env); 163 Label endLoop(env); 164 Label isJSFCondition(env); 165 166 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined()); 167 DEFVARIABLE(i, VariableType::INT32(), Int32(0)); 168 GateRef length = GetLengthOfTaggedArray(elements); 169 BRANCH(Int32Equal(length, Int32(0)), &isZero, ¬Zero); 170 Bind(&isZero); 171 { 172 result = GetEmptyArray(glue); 173 Jump(&exit); 174 } 175 Bind(¬Zero); 176 { 177 GateRef hclass = LoadHClass(elements); 178 size_ = ComputeTaggedArraySize(ZExtInt32ToPtr(length)); 179 HeapAlloc(&result, &initialize, RegionSpaceFlag::IN_YOUNG_SPACE, hclass); 180 } 181 Bind(&initialize); 182 { 183 GateRef hclass = LoadHClass(elements); 184 Store(VariableType::JS_POINTER(), glue, result.ReadVariable(), IntPtr(0), hclass); 185 InitializeTaggedArrayWithSpeicalValue(&afterInitialize, result.ReadVariable(), Hole(), Int32(0), length); 186 } 187 Bind(&afterInitialize); 188 { 189 Jump(&begin); 190 } 191 LoopBegin(&begin); 192 { 193 BRANCH(Int32UnsignedLessThan(*i, length), &body, &exit); 194 Bind(&body); 195 { 196 GateRef value = GetValueFromTaggedArray(elements, *i); 197 BRANCH(TaggedIsHeapObject(value), &isJSFCondition, ¬JSFunction); 198 Bind(&isJSFCondition); 199 { 200 BRANCH(IsJSFunction(value), &isJSFunction, ¬JSFunction); 201 } 202 Bind(&isJSFunction); 203 { 204 GateRef newFunc = CloneJSFunction(glue, value); 205 SetLexicalEnvToFunction(glue, newFunc, currentEnv); 206 SetHomeObjectToFunction(glue, newFunc, obj); 207 SetValueToTaggedArray(VariableType::JS_ANY(), glue, *result, *i, newFunc); 208 Jump(&endLoop); 209 } 210 Bind(¬JSFunction); 211 { 212 SetValueToTaggedArray(VariableType::JS_ANY(), glue, *result, *i, value); 213 Jump(&endLoop); 214 } 215 Bind(&endLoop); 216 i = Int32Add(*i, Int32(1)); 217 LoopEnd(&begin); 218 } 219 } 220 221 Bind(&exit); 222 auto ret = *result; 223 env->SubCfgExit(); 224 return ret; 225} 226 227GateRef NewObjectStubBuilder::NewAccessorData(GateRef glue) 228{ 229 auto env = GetEnvironment(); 230 Label entry(env); 231 env->SubCfgEntry(&entry); 232 Label exit(env); 233 Label noException(env); 234 235 GateRef hclass = GetGlobalConstantValue( 236 VariableType::JS_POINTER(), glue, ConstantIndex::ACCESSOR_DATA_CLASS_INDEX); 237 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined()); 238 size_ = GetObjectSizeFromHClass(hclass); 239 HeapAlloc(&result, &noException, RegionSpaceFlag::IN_YOUNG_SPACE, hclass); 240 Bind(&noException); 241 { 242 Store(VariableType::JS_POINTER(), glue, result.ReadVariable(), IntPtr(0), hclass); 243 Store(VariableType::JS_ANY(), glue, *result, IntPtr(AccessorData::GETTER_OFFSET), Undefined()); 244 Store(VariableType::JS_ANY(), glue, *result, IntPtr(AccessorData::SETTER_OFFSET), Undefined()); 245 Jump(&exit); 246 } 247 248 Bind(&exit); 249 auto ret = *result; 250 env->SubCfgExit(); 251 return ret; 252} 253 254GateRef NewObjectStubBuilder::CloneObjectLiteral(GateRef glue, GateRef literal, GateRef currentEnv) 255{ 256 auto env = GetEnvironment(); 257 Label entry(env); 258 env->SubCfgEntry(&entry); 259 // canShareHClass is true default 260 GateRef hclass = LoadHClass(literal); 261 Label exit(env); 262 Label less(env); 263 Label greater(env); 264 Label startLoop(env); 265 Label begin(env); 266 Label body(env); 267 Label isTaggedRep(env); 268 Label notTaggedRep(env); 269 Label isJSFunction(env); 270 Label notJSFunction(env); 271 Label endLoop(env); 272 Label isAccessorData(env); 273 Label notAccessorData(env); 274 Label middleCondition(env); 275 Label isJSFCondition(env); 276 Label isACCCondition(env); 277 Label isAccessorJudgment(env); 278 279 DEFVARIABLE(length, VariableType::INT32(), Int32(0)); 280 DEFVARIABLE(i, VariableType::INT32(), Int32(0)); 281 DEFVARIABLE(value, VariableType::JS_ANY(), Undefined()); 282 GateRef result = NewJSObject(glue, hclass); 283 284 GateRef elements = GetElementsArray(literal); 285 GateRef newElements = CloneProperties(glue, currentEnv, elements, result); 286 SetElementsArray(VariableType::JS_ANY(), glue, result, newElements); 287 288 GateRef properties = GetPropertiesArray(literal); 289 GateRef newProperties = CloneProperties(glue, currentEnv, properties, result); 290 SetPropertiesArray(VariableType::JS_ANY(), glue, result, newProperties); 291 292 GateRef inlineProps = GetInlinedPropertiesFromHClass(hclass); 293 GateRef numberOfProps = GetNumberOfPropsFromHClass(hclass); 294 BRANCH(Int32UnsignedLessThan(inlineProps, numberOfProps), &less, &greater); 295 Bind(&less); 296 { 297 length = inlineProps; 298 Jump(&startLoop); 299 } 300 Bind(&greater); 301 { 302 length = numberOfProps; 303 Jump(&startLoop); 304 } 305 Bind(&startLoop); 306 { 307 Jump(&begin); 308 } 309 LoopBegin(&begin); 310 { 311 BRANCH(Int32UnsignedLessThan(*i, *length), &body, &exit); 312 Bind(&body); 313 { 314 GateRef layout = GetLayoutFromHClass(hclass); 315 value = GetPropertyInlinedProps(literal, hclass, *i); 316 GateRef attr = GetPropAttrFromLayoutInfo(layout, *i); 317 BRANCH(BoolNot(IsTaggedRepInPropAttr(attr)), ¬TaggedRep, &middleCondition); 318 } 319 Bind(&middleCondition); 320 { 321 BRANCH(TaggedIsHeapObject(*value), &isJSFCondition, &isTaggedRep); 322 } 323 Bind(&isJSFCondition); 324 { 325 BRANCH(IsJSFunction(*value), &isJSFunction, &isAccessorJudgment); 326 } 327 Bind(&isAccessorJudgment); 328 { 329 BRANCH(Int32Equal(GetObjectType(LoadHClass(*value)), Int32(static_cast<int32_t>(JSType::ACCESSOR_DATA))), 330 &isAccessorData, &isTaggedRep); 331 } 332 Bind(&isJSFunction); 333 { 334 GateRef newFunc = CloneJSFunction(glue, *value); 335 SetLexicalEnvToFunction(glue, newFunc, currentEnv); 336 SetHomeObjectToFunction(glue, newFunc, result); 337 SetPropertyInlinedProps(glue, result, hclass, newFunc, *i, 338 VariableType::JS_ANY()); 339 Jump(&endLoop); 340 } 341 Bind(&isAccessorData); 342 { 343 auto objLiteral = NewAccessorData(glue); 344 value = objLiteral; 345 Jump(&isTaggedRep); 346 } 347 Bind(¬TaggedRep); 348 { 349 SetPropertyInlinedProps(glue, result, hclass, *value, *i, 350 VariableType::JS_ANY(), MemoryAttribute::NoBarrier()); 351 Jump(&endLoop); 352 } 353 Bind(&isTaggedRep); 354 { 355 SetPropertyInlinedProps(glue, result, hclass, *value, *i); 356 Jump(&endLoop); 357 } 358 Bind(&endLoop); 359 i = Int32Add(*i, Int32(1)); 360 LoopEnd(&begin); 361 } 362 Bind(&exit); 363 auto ret = result; 364 env->SubCfgExit(); 365 return ret; 366} 367 368GateRef NewObjectStubBuilder::CreateObjectHavingMethod(GateRef glue, GateRef literal, GateRef currentEnv) 369{ 370 auto env = GetEnvironment(); 371 Label entry(env); 372 env->SubCfgEntry(&entry); 373 Label isPendingException(env); 374 Label exit(env); 375 auto objLiteral = CloneObjectLiteral(glue, literal, currentEnv); 376 DEFVARIABLE(result, VariableType::JS_ANY(), objLiteral); 377 BRANCH(HasPendingException(glue), &isPendingException, &exit); 378 Bind(&isPendingException); 379 { 380 result = Exception(); 381 Jump(&exit); 382 } 383 Bind(&exit); 384 auto ret = *result; 385 env->SubCfgExit(); 386 return ret; 387} 388 389void NewObjectStubBuilder::NewJSObject(Variable *result, Label *exit, GateRef hclass) 390{ 391 auto env = GetEnvironment(); 392 393 size_ = GetObjectSizeFromHClass(hclass); 394 // Be careful. NO GC is allowed when initization is not complete. 395 Label hasPendingException(env); 396 Label noException(env); 397 AllocateInYoung(result, &hasPendingException, &noException, hclass); 398 Bind(&noException); 399 { 400 StoreHClass(glue_, result->ReadVariable(), hclass); 401 DEFVARIABLE(initValue, VariableType::JS_ANY(), Undefined()); 402 Label isTS(env); 403 Label initialize(env); 404 BRANCH(IsTSHClass(hclass), &isTS, &initialize); 405 Bind(&isTS); 406 { 407 // The object which created by AOT speculative hclass, should be initialized as hole, means does not exist, 408 // to follow ECMA spec. 409 initValue = Hole(); 410 Jump(&initialize); 411 } 412 Bind(&initialize); 413 Label afterInitialize(env); 414 InitializeWithSpeicalValue(&afterInitialize, 415 result->ReadVariable(), *initValue, Int32(JSObject::SIZE), ChangeIntPtrToInt32(size_), 416 MemoryAttribute::NoBarrier()); 417 Bind(&afterInitialize); 418 auto emptyArray = GetGlobalConstantValue( 419 VariableType::JS_POINTER(), glue_, ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX); 420 SetHash(glue_, result->ReadVariable(), Int64(JSTaggedValue(0).GetRawData())); 421 SetPropertiesArray(VariableType::INT64(), 422 glue_, result->ReadVariable(), emptyArray, MemoryAttribute::NoBarrier()); 423 SetElementsArray(VariableType::INT64(), 424 glue_, result->ReadVariable(), emptyArray, MemoryAttribute::NoBarrier()); 425 Jump(exit); 426 } 427 Bind(&hasPendingException); 428 { 429 Jump(exit); 430 } 431} 432 433void NewObjectStubBuilder::NewSObject(Variable *result, Label *exit, GateRef hclass) 434{ 435 auto env = GetEnvironment(); 436 437 size_ = GetObjectSizeFromHClass(hclass); 438 Label afterAllocate(env); 439 AllocateInSOld(result, &afterAllocate, hclass); 440 Bind(&afterAllocate); 441 { 442 StoreHClass(glue_, result->ReadVariable(), hclass); 443 DEFVARIABLE(initValue, VariableType::JS_ANY(), Undefined()); 444 Label isTS(env); 445 Label initialize(env); 446 BRANCH(IsTSHClass(hclass), &isTS, &initialize); 447 Bind(&isTS); 448 { 449 // The object which created by AOT speculative hclass, should be initialized as hole, means does not exist, 450 // to follow ECMA spec. 451 initValue = Hole(); 452 Jump(&initialize); 453 } 454 Bind(&initialize); 455 Label afterInitialize(env); 456 InitializeWithSpeicalValue(&afterInitialize, 457 result->ReadVariable(), *initValue, Int32(JSObject::SIZE), ChangeIntPtrToInt32(size_), 458 MemoryAttribute::NoBarrier()); 459 Bind(&afterInitialize); 460 auto emptyArray = GetGlobalConstantValue( 461 VariableType::JS_POINTER(), glue_, ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX); 462 SetHash(glue_, result->ReadVariable(), Int64(JSTaggedValue(0).GetRawData())); 463 SetPropertiesArray(VariableType::INT64(), 464 glue_, result->ReadVariable(), emptyArray, MemoryAttribute::NoBarrier()); 465 SetElementsArray(VariableType::INT64(), 466 glue_, result->ReadVariable(), emptyArray, MemoryAttribute::NoBarrier()); 467 Jump(exit); 468 } 469} 470 471GateRef NewObjectStubBuilder::NewJSProxy(GateRef glue, GateRef target, GateRef handler) 472{ 473 auto env = GetEnvironment(); 474 Label entry(env); 475 env->SubCfgEntry(&entry); 476 Label exit(env); 477 Label isCallable(env); 478 Label notCallable(env); 479 Label noException(env); 480 Label allocateProxy(env); 481 482 DEFVARIABLE(result, VariableType::JS_ANY(), Exception()); 483 DEFVARIABLE(hclass, VariableType::JS_ANY(), Undefined()); 484 GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit())); 485 GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset); 486 GateRef objectFunctionPrototype = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, 487 GlobalEnv::OBJECT_FUNCTION_PROTOTYPE_INDEX); 488 GateRef emptyObject = OrdinaryNewJSObjectCreate(glue, objectFunctionPrototype); 489 BRANCH(IsCallable(target), &isCallable, ¬Callable); 490 Bind(&isCallable); 491 { 492 Label isConstructor(env); 493 Label notConstructor(env); 494 BRANCH(IsConstructor(target), &isConstructor, ¬Constructor); 495 Bind(&isConstructor); 496 { 497 hclass = GetGlobalConstantValue( 498 VariableType::JS_POINTER(), glue, ConstantIndex::JS_PROXY_CONSTRUCT_CLASS_INDEX); 499 Jump(&allocateProxy); 500 } 501 Bind(¬Constructor); 502 { 503 hclass = GetGlobalConstantValue( 504 VariableType::JS_POINTER(), glue, ConstantIndex::JS_PROXY_CALLABLE_CLASS_INDEX); 505 Jump(&allocateProxy); 506 } 507 } 508 Bind(¬Callable); 509 { 510 hclass = GetGlobalConstantValue( 511 VariableType::JS_POINTER(), glue, ConstantIndex::JS_PROXY_ORDINARY_CLASS_INDEX); 512 Jump(&allocateProxy); 513 } 514 Bind(&allocateProxy); 515 { 516 size_ = GetObjectSizeFromHClass(*hclass); 517 AllocateInYoung(&result, &exit, &noException, *hclass); 518 } 519 Bind(&noException); 520 { 521 GateRef hashOffset = IntPtr(ECMAObject::HASH_OFFSET); 522 Store(VariableType::INT64(), glue, *result, hashOffset, Int64(JSTaggedValue(0).GetRawData())); 523 GateRef proxyMethod = GetGlobalConstantValue( 524 VariableType::JS_POINTER(), glue, ConstantIndex::PROXY_METHOD_INDEX); 525 StoreHClassWithoutBarrier(glue_, *result, *hclass); 526 BuiltinsProxyStubBuilder builtinsProxyStubBuilder(this); 527 builtinsProxyStubBuilder.SetMethod(glue, *result, proxyMethod); 528 builtinsProxyStubBuilder.SetTarget(glue, *result, target); 529 builtinsProxyStubBuilder.SetHandler(glue, *result, handler); 530 builtinsProxyStubBuilder.SetPrivateField(glue, *result, emptyObject); 531 builtinsProxyStubBuilder.SetIsRevoked(glue, *result, False()); 532 Jump(&exit); 533 } 534 Bind(&exit); 535 auto ret = *result; 536 env->SubCfgExit(); 537 return ret; 538} 539 540void NewObjectStubBuilder::NewJSObject(Variable *result, Label *exit, GateRef hclass, GateRef size) 541{ 542 auto env = GetEnvironment(); 543 size_ = size; 544 Label initialize(env); 545 HeapAlloc(result, &initialize, RegionSpaceFlag::IN_YOUNG_SPACE, hclass); 546 Bind(&initialize); 547 StoreHClassWithoutBarrier(glue_, result->ReadVariable(), hclass); 548 DEFVARIABLE(initValue, VariableType::JS_ANY(), Undefined()); 549 Label afterInitialize(env); 550 InitializeWithSpeicalValue(&afterInitialize, 551 result->ReadVariable(), *initValue, Int32(JSObject::SIZE), ChangeIntPtrToInt32(size_), 552 MemoryAttribute::NoBarrier()); 553 Bind(&afterInitialize); 554 auto emptyArray = GetGlobalConstantValue( 555 VariableType::JS_POINTER(), glue_, ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX); 556 SetHash(glue_, result->ReadVariable(), Int64(JSTaggedValue(0).GetRawData())); 557 SetPropertiesArray(VariableType::INT64(), 558 glue_, result->ReadVariable(), emptyArray, MemoryAttribute::NoBarrier()); 559 SetElementsArray(VariableType::INT64(), 560 glue_, result->ReadVariable(), emptyArray, MemoryAttribute::NoBarrier()); 561 Jump(exit); 562} 563 564GateRef NewObjectStubBuilder::NewJSObject(GateRef glue, GateRef hclass) 565{ 566 auto env = GetEnvironment(); 567 Label entry(env); 568 env->SubCfgEntry(&entry); 569 Label exit(env); 570 571 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined()); 572 SetGlue(glue); 573 NewJSObject(&result, &exit, hclass); 574 575 Bind(&exit); 576 auto ret = *result; 577 env->SubCfgExit(); 578 return ret; 579} 580 581GateRef NewObjectStubBuilder::NewSObject(GateRef glue, GateRef hclass) 582{ 583 auto env = GetEnvironment(); 584 Label entry(env); 585 env->SubCfgEntry(&entry); 586 Label exit(env); 587 588 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined()); 589 SetGlue(glue); 590 NewSObject(&result, &exit, hclass); 591 592 Bind(&exit); 593 auto ret = *result; 594 env->SubCfgExit(); 595 return ret; 596} 597 598void NewObjectStubBuilder::NewTaggedArrayChecked(Variable *result, GateRef len, Label *exit) 599{ 600 auto env = GetEnvironment(); 601 Label overflow(env); 602 Label notOverflow(env); 603 BRANCH(Int32UnsignedGreaterThan(len, Int32(INT32_MAX)), &overflow, ¬Overflow); 604 Bind(&overflow); 605 { 606 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(LenGreaterThanMax)); 607 CallRuntime(glue_, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) }); 608 result->WriteVariable(Exception()); 609 Jump(exit); 610 } 611 Bind(¬Overflow); 612 size_ = ComputeTaggedArraySize(ZExtInt32ToPtr(len)); 613 // Be careful. NO GC is allowed when initization is not complete. 614 Label noException(env); 615 auto hclass = GetGlobalConstantValue( 616 VariableType::JS_POINTER(), glue_, ConstantIndex::ARRAY_CLASS_INDEX); 617 AllocateInYoung(result, exit, &noException, hclass); 618 Bind(&noException); 619 { 620 StoreBuiltinHClass(glue_, result->ReadVariable(), hclass); 621 Label afterInitialize(env); 622 InitializeTaggedArrayWithSpeicalValue(&afterInitialize, 623 result->ReadVariable(), Hole(), Int32(0), len); 624 Bind(&afterInitialize); 625 Jump(exit); 626 } 627} 628 629void NewObjectStubBuilder::NewMutantTaggedArrayChecked(Variable *result, GateRef len, Label *exit) 630{ 631 auto env = GetEnvironment(); 632 size_ = ComputeTaggedArraySize(ZExtInt32ToPtr(len)); 633 Label afterAllocate(env); 634 auto hclass = GetGlobalConstantValue( 635 VariableType::JS_POINTER(), glue_, ConstantIndex::MUTANT_TAGGED_ARRAY_CLASS_INDEX); 636 // Be careful. NO GC is allowed when initization is not complete. 637 AllocateInYoung(result, &afterAllocate, hclass); 638 Bind(&afterAllocate); 639 Label noException(env); 640 BRANCH(TaggedIsException(result->ReadVariable()), exit, &noException); 641 Bind(&noException); 642 { 643 StoreHClass(glue_, result->ReadVariable(), hclass); 644 Label afterInitialize(env); 645 InitializeTaggedArrayWithSpeicalValue(&afterInitialize, 646 result->ReadVariable(), SpecialHole(), Int32(0), len); 647 Bind(&afterInitialize); 648 Jump(exit); 649 } 650} 651 652GateRef NewObjectStubBuilder::NewTaggedArray(GateRef glue, GateRef len) 653{ 654 auto env = GetEnvironment(); 655 Label entry(env); 656 env->SubCfgEntry(&entry); 657 Label exit(env); 658 Label isEmpty(env); 659 Label notEmpty(env); 660 661 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined()); 662 SetGlue(glue); 663 BRANCH(Int32Equal(len, Int32(0)), &isEmpty, ¬Empty); 664 Bind(&isEmpty); 665 { 666 result = GetGlobalConstantValue( 667 VariableType::JS_POINTER(), glue_, ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX); 668 Jump(&exit); 669 } 670 Bind(¬Empty); 671 { 672 Label next(env); 673 Label slowPath(env); 674 BRANCH(Int32LessThan(len, Int32(MAX_TAGGED_ARRAY_LENGTH)), &next, &slowPath); 675 Bind(&next); 676 { 677 NewTaggedArrayChecked(&result, len, &exit); 678 } 679 Bind(&slowPath); 680 { 681 result = CallRuntime(glue_, RTSTUB_ID(NewTaggedArray), { IntToTaggedInt(len) }); 682 Jump(&exit); 683 } 684 } 685 686 Bind(&exit); 687 auto ret = *result; 688 env->SubCfgExit(); 689 return ret; 690} 691 692GateRef NewObjectStubBuilder::NewMutantTaggedArray(GateRef glue, GateRef len) 693{ 694 auto env = GetEnvironment(); 695 Label entry(env); 696 env->SubCfgEntry(&entry); 697 Label exit(env); 698 Label isEmpty(env); 699 Label notEmpty(env); 700 701 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined()); 702 SetGlue(glue); 703 BRANCH(Int32Equal(len, Int32(0)), &isEmpty, ¬Empty); 704 Bind(&isEmpty); 705 { 706 result = GetGlobalConstantValue( 707 VariableType::JS_POINTER(), glue_, ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX); 708 Jump(&exit); 709 } 710 Bind(¬Empty); 711 { 712 Label next(env); 713 Label slowPath(env); 714 BRANCH(Int32LessThan(len, Int32(MAX_TAGGED_ARRAY_LENGTH)), &next, &slowPath); 715 Bind(&next); 716 { 717 NewMutantTaggedArrayChecked(&result, len, &exit); 718 } 719 Bind(&slowPath); 720 { 721 result = CallRuntime(glue_, RTSTUB_ID(NewMutantTaggedArray), { IntToTaggedInt(len) }); 722 Jump(&exit); 723 } 724 } 725 726 Bind(&exit); 727 auto ret = *result; 728 env->SubCfgExit(); 729 return ret; 730} 731 732void NewObjectStubBuilder::ExtendArray(Variable *res, GateRef glue, GateRef elements, 733 GateRef newLen, Label *exit, RegionSpaceFlag spaceType, bool isMutantArray) 734{ 735 auto env = GetEnvironment(); 736 SetGlue(glue); 737 DEFVARIABLE(index, VariableType::INT32(), Int32(0)); 738 DEFVARIABLE(array, VariableType::JS_ANY(), Undefined()); 739 size_ = ComputeTaggedArraySize(ZExtInt32ToPtr(newLen)); 740 // Be careful. NO GC is allowed when initization is not complete. 741 Label allocArray(env); 742 Label afterAllocate(env); 743 auto hclass = GetGlobalConstantValue( 744 VariableType::JS_POINTER(), glue_, 745 isMutantArray ? ConstantIndex::MUTANT_TAGGED_ARRAY_CLASS_INDEX : ConstantIndex::ARRAY_CLASS_INDEX); 746 HeapAlloc(&array, &allocArray, spaceType, hclass); 747 Bind(&allocArray); 748 { 749 StoreBuiltinHClass(glue_, array.ReadVariable(), hclass); 750 InitializeTaggedArrayWithSpeicalValue(&afterAllocate, 751 array.ReadVariable(), isMutantArray ? SpecialHole() : Hole(), Int32(0), newLen); 752 } 753 Bind(&afterAllocate); 754 Store(VariableType::INT32(), glue, *array, IntPtr(TaggedArray::LENGTH_OFFSET), newLen); 755 GateRef oldExtractLen = GetExtractLengthOfTaggedArray(elements); 756 Store(VariableType::INT32(), glue, *array, IntPtr(TaggedArray::EXTRA_LENGTH_OFFSET), oldExtractLen); 757 GateRef oldL = GetLengthOfTaggedArray(elements); 758 Label loopHead(env); 759 Label loopEnd(env); 760 Label afterLoop(env); 761 Label storeValue(env); 762 Jump(&loopHead); 763 LoopBegin(&loopHead); 764 { 765 BRANCH(Int32UnsignedLessThan(*index, oldL), &storeValue, &afterLoop); 766 Bind(&storeValue); 767 { 768 if (isMutantArray) { 769 GateRef value = GetValueFromMutantTaggedArray(elements, *index); 770 SetValueToTaggedArray(VariableType::INT64(), glue, *array, *index, value); 771 } else { 772 GateRef value = GetValueFromTaggedArray(elements, *index); 773 SetValueToTaggedArray(VariableType::JS_ANY(), glue, *array, *index, value); 774 } 775 index = Int32Add(*index, Int32(1)); 776 Jump(&loopEnd); 777 } 778 } 779 Bind(&loopEnd); 780 LoopEnd(&loopHead, env, glue); 781 Bind(&afterLoop); 782 { 783 *res = *array; 784 Jump(exit); 785 } 786} 787 788GateRef NewObjectStubBuilder::ExtendArrayCheck(GateRef glue, GateRef elements, GateRef newLen, 789 RegionSpaceFlag spaceType) 790{ 791 auto env = GetEnvironment(); 792 Label subEntry(env); 793 env->SubCfgEntry(&subEntry); 794 SetGlue(glue); 795 Label extendMutantArray(env); 796 Label extendNormalArray(env); 797 Label exit(env); 798 DEFVARIABLE(res, VariableType::JS_ANY(), Hole()); 799 BRANCH(IsMutantTaggedArray(elements), 800 &extendMutantArray, &extendNormalArray); 801 Bind(&extendNormalArray); 802 ExtendArray(&res, glue, elements, newLen, &exit, spaceType); 803 Bind(&extendMutantArray); 804 ExtendArray(&res, glue, elements, newLen, &exit, spaceType, true); 805 Bind(&exit); 806 auto ret = *res; 807 env->SubCfgExit(); 808 return ret; 809} 810 811GateRef NewObjectStubBuilder::CopyArray(GateRef glue, GateRef elements, GateRef oldLen, 812 GateRef newLen, RegionSpaceFlag spaceType) 813{ 814 auto env = GetEnvironment(); 815 Label subEntry(env); 816 env->SubCfgEntry(&subEntry); 817 Label exit(env); 818 DEFVARIABLE(result, VariableType::JS_ANY(), Hole()); 819 NewObjectStubBuilder newBuilder(this); 820 Label emptyArray(env); 821 Label notEmptyArray(env); 822 BRANCH(Int32Equal(newLen, Int32(0)), &emptyArray, ¬EmptyArray); 823 Bind(&emptyArray); 824 result = GetEmptyArray(glue); 825 Jump(&exit); 826 Bind(¬EmptyArray); 827 { 828 Label extendArray(env); 829 Label notExtendArray(env); 830 BRANCH(Int32GreaterThan(newLen, oldLen), &extendArray, ¬ExtendArray); 831 Bind(&extendArray); 832 { 833 result = ExtendArrayCheck(glue, elements, newLen, spaceType); 834 Jump(&exit); 835 } 836 Bind(¬ExtendArray); 837 { 838 DEFVARIABLE(array, VariableType::JS_ANY(), elements); 839 Label isMutantTaggedArray(env); 840 Label isNotMutantTaggedArray(env); 841 Label afterInitializeElements(env); 842 GateRef checkIsMutantTaggedArray = IsMutantTaggedArray(*array); 843 BRANCH(checkIsMutantTaggedArray, &isMutantTaggedArray, &isNotMutantTaggedArray); 844 Bind(&isMutantTaggedArray); 845 { 846 array = newBuilder.NewMutantTaggedArray(glue, newLen); 847 Jump(&afterInitializeElements); 848 } 849 Bind(&isNotMutantTaggedArray); 850 { 851 array = newBuilder.NewTaggedArray(glue, newLen); 852 Jump(&afterInitializeElements); 853 } 854 Bind(&afterInitializeElements); 855 Store(VariableType::INT32(), glue, *array, IntPtr(TaggedArray::LENGTH_OFFSET), newLen); 856 GateRef oldExtractLen = GetExtractLengthOfTaggedArray(elements); 857 Store(VariableType::INT32(), glue, *array, IntPtr(TaggedArray::EXTRA_LENGTH_OFFSET), oldExtractLen); 858 Label afterCopy(env); 859 860 Label copyToTaggedArray(env); 861 Label copyToMutantTaggedArray(env); 862 BRANCH(checkIsMutantTaggedArray, ©ToMutantTaggedArray, ©ToTaggedArray); 863 Bind(©ToTaggedArray); 864 { 865 ArrayCopy<NotOverlap>(glue, GetDataPtrInTaggedArray(elements), GetDataPtrInTaggedArray(*array), 866 newLen); 867 Jump(&afterCopy); 868 } 869 Bind(©ToMutantTaggedArray); 870 { 871 ArrayCopy<NotOverlap>(glue, GetDataPtrInTaggedArray(elements), GetDataPtrInTaggedArray(*array), newLen, 872 MemoryAttribute::NoBarrier()); 873 Jump(&afterCopy); 874 } 875 Bind(&afterCopy); 876 { 877 result = *array; 878 Jump(&exit); 879 } 880 } 881 } 882 Bind(&exit); 883 auto ret = *result; 884 env->SubCfgExit(); 885 return ret; 886} 887 888GateRef NewObjectStubBuilder::NewJSForinIterator(GateRef glue, GateRef receiver, GateRef keys, GateRef cachedHclass) 889{ 890 auto env = GetEnvironment(); 891 GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit())); 892 GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset); 893 GateRef hclass = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::FOR_IN_ITERATOR_CLASS_INDEX); 894 GateRef iter = NewJSObject(glue, hclass); 895 // init JSForinIterator 896 SetObjectOfForInIterator(glue, iter, receiver); 897 SetCachedHclassOfForInIterator(glue, iter, cachedHclass); 898 SetKeysOfForInIterator(glue, iter, keys); 899 SetIndexOfForInIterator(glue, iter, Int32(EnumCache::ENUM_CACHE_HEADER_SIZE)); 900 GateRef length = GetLengthOfTaggedArray(keys); 901 SetLengthOfForInIterator(glue, iter, length); 902 return iter; 903} 904 905GateRef NewObjectStubBuilder::LoadHClassFromMethod(GateRef glue, GateRef method) 906{ 907 auto env = GetEnvironment(); 908 Label entry(env); 909 env->SubCfgEntry(&entry); 910 DEFVARIABLE(hclass, VariableType::JS_ANY(), Undefined()); 911 GateRef kind = GetFuncKind(method); 912 Label exit(env); 913 Label defaultLabel(env); 914 Label isNormal(env); 915 Label notNormal(env); 916 Label isAsync(env); 917 Label notAsync(env); 918 919 Label labelBuffer[2] = { Label(env), Label(env) }; 920 Label labelBuffer1[3] = { Label(env), Label(env), Label(env) }; 921 int64_t valueBuffer[2] = { 922 static_cast<int64_t>(FunctionKind::NORMAL_FUNCTION), static_cast<int64_t>(FunctionKind::ARROW_FUNCTION) }; 923 int64_t valueBuffer1[3] = { 924 static_cast<int64_t>(FunctionKind::BASE_CONSTRUCTOR), static_cast<int64_t>(FunctionKind::GENERATOR_FUNCTION), 925 static_cast<int64_t>(FunctionKind::ASYNC_GENERATOR_FUNCTION) }; 926 GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit())); 927 GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset); 928 BRANCH(Int32LessThanOrEqual(kind, Int32(static_cast<int32_t>(FunctionKind::ARROW_FUNCTION))), 929 &isNormal, ¬Normal); 930 Bind(&isNormal); 931 { 932 // 2 : this switch has 2 case 933 Switch(kind, &defaultLabel, valueBuffer, labelBuffer, 2); 934 Bind(&labelBuffer[0]); 935 { 936 hclass = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::FUNCTION_CLASS_WITH_PROTO); 937 Jump(&exit); 938 } 939 Bind(&labelBuffer[1]); 940 { 941 hclass = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::FUNCTION_CLASS_WITHOUT_PROTO); 942 Jump(&exit); 943 } 944 } 945 Bind(¬Normal); 946 { 947 BRANCH(Int32LessThanOrEqual(kind, Int32(static_cast<int32_t>(FunctionKind::ASYNC_FUNCTION))), 948 &isAsync, ¬Async); 949 Bind(&isAsync); 950 { 951 hclass = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::ASYNC_FUNCTION_CLASS); 952 Jump(&exit); 953 } 954 Bind(¬Async); 955 { 956 // 3 : this switch has 3 case 957 Switch(kind, &defaultLabel, valueBuffer1, labelBuffer1, 3); 958 Bind(&labelBuffer1[0]); 959 { 960 hclass = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::FUNCTION_CLASS_WITH_PROTO); 961 Jump(&exit); 962 } 963 Bind(&labelBuffer1[1]); 964 { 965 hclass = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::GENERATOR_FUNCTION_CLASS); 966 Jump(&exit); 967 } 968 // 2 : index of kind 969 Bind(&labelBuffer1[2]); 970 { 971 hclass = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, 972 GlobalEnv::ASYNC_GENERATOR_FUNCTION_CLASS); 973 Jump(&exit); 974 } 975 } 976 } 977 Bind(&defaultLabel); 978 { 979 FatalPrint(glue, { Int32(GET_MESSAGE_STRING_ID(ThisBranchIsUnreachable)) }); 980 Jump(&exit); 981 } 982 Bind(&exit); 983 auto ret = *hclass; 984 env->SubCfgExit(); 985 return ret; 986} 987 988GateRef NewObjectStubBuilder::LoadSHClassFromMethod(GateRef glue, GateRef method) 989{ 990 auto env = GetEnvironment(); 991 Label entry(env); 992 env->SubCfgEntry(&entry); 993 DEFVARIABLE(hclass, VariableType::JS_ANY(), Undefined()); 994 GateRef kind = GetFuncKind(method); 995 Label exit(env); 996 Label isSendableFunc(env); 997 Label isNotSendableFunc(env); 998 Label isNormal(env); 999 Label notNormal(env); 1000 1001 GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit())); 1002 GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset); 1003 BRANCH(IsSendableFunction(method), &isSendableFunc, &isNotSendableFunc); 1004 Bind(&isSendableFunc); 1005 { 1006 BRANCH(Int32Equal(kind, Int32(static_cast<int32_t>(FunctionKind::BASE_CONSTRUCTOR))), &isNormal, ¬Normal); 1007 Bind(&isNormal); 1008 { 1009 hclass = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, 1010 GlobalEnv::SHARED_FUNCTION_CLASS_WITH_PROTO); 1011 Jump(&exit); 1012 } 1013 Bind(¬Normal); 1014 { 1015 hclass = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, 1016 GlobalEnv::SHARED_ASYNC_FUNCTION_CLASS); 1017 Jump(&exit); 1018 } 1019 } 1020 Bind(&isNotSendableFunc); 1021 { 1022 FatalPrint(glue, { Int32(GET_MESSAGE_STRING_ID(ThisBranchIsUnreachable)) }); 1023 Jump(&exit); 1024 } 1025 Bind(&exit); 1026 auto ret = *hclass; 1027 env->SubCfgExit(); 1028 return ret; 1029} 1030 1031GateRef NewObjectStubBuilder::NewJSFunction(GateRef glue, GateRef method, FunctionKind targetKind) 1032{ 1033 GateRef hclass = LoadHClassFromMethod(glue, method); 1034 return NewJSFunctionByHClass(glue, method, hclass, targetKind); 1035} 1036 1037GateRef NewObjectStubBuilder::NewJSSendableFunction(GateRef glue, GateRef method, FunctionKind targetKind) 1038{ 1039 GateRef hclass = LoadSHClassFromMethod(glue, method); 1040 return NewSFunctionByHClass(glue, method, hclass, targetKind); 1041} 1042 1043void NewObjectStubBuilder::NewJSFunction(GateRef glue, GateRef jsFunc, GateRef index, GateRef length, GateRef lexEnv, 1044 Variable *result, Label *success, Label *failed, GateRef slotId, 1045 FunctionKind targetKind) 1046{ 1047 auto env = GetEnvironment(); 1048 Label hasException(env); 1049 Label notException(env); 1050 Label isSendableFunc(env); 1051 Label isNotSendableFunc(env); 1052 Label afterSendableFunc(env); 1053 GateRef constPool = GetConstPoolFromFunction(jsFunc); 1054 SetGlue(glue); 1055 result->WriteVariable(DefineFunc(glue, constPool, index, targetKind)); 1056 BRANCH(HasPendingException(glue), &hasException, ¬Exception); 1057 Bind(&hasException); 1058 { 1059 Jump(failed); 1060 } 1061 Bind(¬Exception); 1062 { 1063 GateRef module = GetModuleFromFunction(jsFunc); 1064 SetLengthToFunction(glue, result->ReadVariable(), length); 1065 BRANCH(IsSendableFunction(GetMethodFromFunction(result->ReadVariable())), &isSendableFunc, &isNotSendableFunc); 1066 Bind(&isSendableFunc); 1067 { 1068 GateRef smodule = CallRuntime(glue, RTSTUB_ID(GetSharedModule), { module }); 1069 SetSendableEnvToModule(glue, smodule, GetSendableEnvFromModule(module)); 1070 SetModuleToFunction(glue, result->ReadVariable(), smodule); 1071 Jump(&afterSendableFunc); 1072 } 1073 Bind(&isNotSendableFunc); 1074 { 1075 SetLexicalEnvToFunction(glue, result->ReadVariable(), lexEnv); 1076 SetModuleToFunction(glue, result->ReadVariable(), module); 1077 SetHomeObjectToFunction(glue, result->ReadVariable(), GetHomeObjectFromFunction(jsFunc)); 1078#if ECMASCRIPT_ENABLE_IC 1079 SetProfileTypeInfoCellToFunction(jsFunc, result->ReadVariable(), slotId); 1080#endif 1081 Jump(&afterSendableFunc); 1082 } 1083 Bind(&afterSendableFunc); 1084 Jump(success); 1085 } 1086} 1087 1088void NewObjectStubBuilder::SetProfileTypeInfoCellToFunction(GateRef jsFunc, GateRef definedFunc, GateRef slotId) 1089{ 1090 auto env = GetEnvironment(); 1091 Label entry(env); 1092 env->SubCfgEntry(&entry); 1093 Label isValidSlotId(env); 1094 Label exit(env); 1095 1096 BRANCH(Equal(slotId, Int32(ProfileTypeInfo::INVALID_SLOT_INDEX)), &exit, &isValidSlotId); 1097 Bind(&isValidSlotId); 1098 { 1099 Label isUndefined(env); 1100 Label notUndefined(env); 1101 DEFVARIABLE(profileTypeInfo, VariableType::JS_ANY(), GetProfileTypeInfo(jsFunc)); 1102 BRANCH(TaggedIsUndefined(*profileTypeInfo), &isUndefined, ¬Undefined); 1103 Bind(&isUndefined); 1104 { 1105 profileTypeInfo = CallRuntime(glue_, RTSTUB_ID(UpdateHotnessCounter), { jsFunc }); 1106 Jump(¬Undefined); 1107 } 1108 Bind(¬Undefined); 1109 { 1110 UpdateProfileTypeInfoCellToFunction(glue_, definedFunc, *profileTypeInfo, slotId); 1111 Jump(&exit); 1112 } 1113 } 1114 Bind(&exit); 1115 env->SubCfgExit(); 1116 return; 1117} 1118 1119GateRef NewObjectStubBuilder::NewJSBoundFunction(GateRef glue, GateRef target, GateRef boundThis, GateRef args) 1120{ 1121 auto env = GetEnvironment(); 1122 Label subentry(env); 1123 env->SubCfgEntry(&subentry); 1124 Label exit(env); 1125 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined()); 1126 1127 GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit())); 1128 GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset); 1129 GateRef hclass = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::BOUND_FUNCTION_CLASS); 1130 result = NewJSObject(glue, hclass); 1131 GateRef nameAccessor = GetGlobalConstantValue(VariableType::JS_POINTER(), glue, 1132 ConstantIndex::FUNCTION_NAME_ACCESSOR); 1133 SetPropertyInlinedProps(glue, *result, hclass, nameAccessor, 1134 Int32(JSFunction::NAME_INLINE_PROPERTY_INDEX), VariableType::JS_ANY(), 1135 MemoryAttribute::NoBarrier()); 1136 GateRef lengthAccessor = GetGlobalConstantValue(VariableType::JS_POINTER(), glue, 1137 ConstantIndex::FUNCTION_LENGTH_ACCESSOR); 1138 SetPropertyInlinedProps(glue, *result, hclass, lengthAccessor, 1139 Int32(JSFunction::LENGTH_INLINE_PROPERTY_INDEX), VariableType::JS_ANY(), 1140 MemoryAttribute::NoBarrier()); 1141 SetJSObjectTaggedField(glue, *result, JSBoundFunction::BOUND_TARGET_OFFSET, target); 1142 SetJSObjectTaggedField(glue, *result, JSBoundFunction::BOUND_THIS_OFFSET, boundThis); 1143 SetJSObjectTaggedField(glue, *result, JSBoundFunction::BOUND_ARGUMENTS_OFFSET, args); 1144 GateRef method = GetGlobalConstantValue(VariableType::JS_POINTER(), glue, 1145 ConstantIndex::BOUND_FUNCTION_METHOD_INDEX); 1146 SetMethodToFunction(glue, *result, method); 1147 1148 Label targetIsHeapObject(env); 1149 Label targetIsConstructor(env); 1150 BRANCH(TaggedIsHeapObject(target), &targetIsHeapObject, &exit); 1151 Bind(&targetIsHeapObject); 1152 BRANCH(IsConstructor(target), &targetIsConstructor, &exit); 1153 Bind(&targetIsConstructor); 1154 { 1155 GateRef resultHClass = LoadHClass(*result); 1156 SetHClassBit<JSHClass::ConstructorBit>(glue, resultHClass, Int32(1)); 1157 Jump(&exit); 1158 } 1159 1160 Bind(&exit); 1161 auto ret = *result; 1162 env->SubCfgExit(); 1163 return ret; 1164} 1165 1166GateRef NewObjectStubBuilder::EnumerateObjectProperties(GateRef glue, GateRef obj) 1167{ 1168 auto env = GetEnvironment(); 1169 Label entry(env); 1170 env->SubCfgEntry(&entry); 1171 Label exit(env); 1172 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined()); 1173 DEFVARIABLE(object, VariableType::JS_ANY(), Undefined()); 1174 1175 Label isString(env); 1176 Label isNotString(env); 1177 Label afterObjectTransform(env); 1178 Label slowpath(env); 1179 Label empty(env); 1180 Label tryGetEnumCache(env); 1181 Label cacheHit(env); 1182 BRANCH(TaggedIsString(obj), &isString, &isNotString); 1183 Bind(&isString); 1184 { 1185 object = CallRuntime(glue, RTSTUB_ID(PrimitiveStringCreate), { obj }); 1186 Jump(&afterObjectTransform); 1187 } 1188 Bind(&isNotString); 1189 { 1190 object = ToPrototypeOrObj(glue, obj); 1191 Jump(&afterObjectTransform); 1192 } 1193 Bind(&afterObjectTransform); 1194 BRANCH(TaggedIsUndefinedOrNull(*object), &empty, &tryGetEnumCache); 1195 Bind(&tryGetEnumCache); 1196 GateRef enumCache = TryGetEnumCache(glue, *object); 1197 BRANCH(TaggedIsUndefined(enumCache), &slowpath, &cacheHit); 1198 Bind(&cacheHit); 1199 { 1200 GateRef hclass = LoadHClass(*object); 1201 result = NewJSForinIterator(glue, *object, enumCache, hclass); 1202 Jump(&exit); 1203 } 1204 Bind(&empty); 1205 { 1206 GateRef emptyArray = GetEmptyArray(glue); 1207 result = NewJSForinIterator(glue, Undefined(), emptyArray, Undefined()); 1208 Jump(&exit); 1209 } 1210 1211 Bind(&slowpath); 1212 { 1213 result = CallRuntime(glue, RTSTUB_ID(GetPropIteratorSlowpath), { *object }); 1214 Jump(&exit); 1215 } 1216 Bind(&exit); 1217 auto ret = *result; 1218 env->SubCfgExit(); 1219 return ret; 1220} 1221 1222void NewObjectStubBuilder::FillArgumentsList(GateRef argumentsList, 1223 GateRef sp, GateRef startIdx, GateRef numArgs) 1224{ 1225 auto env = GetEnvironment(); 1226 Label entry(env); 1227 env->SubCfgEntry(&entry); 1228 Label exit(env); 1229 1230 DEFVARIABLE(i, VariableType::INT32(), Int32(0)); 1231 Label setArgumentsBegin(env); 1232 Label setArgumentsAgain(env); 1233 Label setArgumentsEnd(env); 1234 BRANCH(Int32UnsignedLessThan(*i, numArgs), &setArgumentsBegin, &setArgumentsEnd); 1235 LoopBegin(&setArgumentsBegin); 1236 GateRef idx = ZExtInt32ToPtr(Int32Add(startIdx, *i)); 1237 GateRef argument = Load(VariableType::JS_ANY(), sp, PtrMul(IntPtr(sizeof(JSTaggedType)), idx)); 1238 SetValueToTaggedArray(VariableType::JS_ANY(), glue_, argumentsList, *i, argument); 1239 i = Int32Add(*i, Int32(1)); 1240 BRANCH(Int32UnsignedLessThan(*i, numArgs), &setArgumentsAgain, &setArgumentsEnd); 1241 Bind(&setArgumentsAgain); 1242 LoopEnd(&setArgumentsBegin); 1243 Bind(&setArgumentsEnd); 1244 Jump(&exit); 1245 Bind(&exit); 1246 env->SubCfgExit(); 1247 return; 1248} 1249 1250GateRef NewObjectStubBuilder::NewArgumentsListObj(GateRef numArgs) 1251{ 1252 auto env = GetEnvironment(); 1253 Label entry(env); 1254 env->SubCfgEntry(&entry); 1255 Label exit(env); 1256 Label setHClass(env); 1257 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined()); 1258 size_ = ComputeTaggedArraySize(ZExtInt32ToPtr(numArgs)); 1259 GateRef arrayClass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_, 1260 ConstantIndex::ARRAY_CLASS_INDEX); 1261 AllocateInYoung(&result, &exit, &setHClass, arrayClass); 1262 Bind(&setHClass); 1263 StoreHClass(glue_, *result, arrayClass); 1264 Store(VariableType::INT32(), glue_, *result, IntPtr(TaggedArray::LENGTH_OFFSET), numArgs); 1265 Store(VariableType::INT32(), glue_, *result, IntPtr(TaggedArray::EXTRA_LENGTH_OFFSET), Int32(0)); 1266 Jump(&exit); 1267 Bind(&exit); 1268 auto ret = *result; 1269 env->SubCfgExit(); 1270 return ret; 1271} 1272 1273void NewObjectStubBuilder::NewArgumentsList(Variable *result, Label *exit, 1274 GateRef sp, GateRef startIdx, GateRef numArgs) 1275{ 1276 auto env = GetEnvironment(); 1277 Label hasException(env); 1278 Label notException(env); 1279 1280 GateRef argumentsList = NewArgumentsListObj(numArgs); 1281 result->WriteVariable(argumentsList); 1282 Branch(TaggedIsException(argumentsList), &hasException, ¬Exception); 1283 Bind(&hasException); 1284 Jump(exit); 1285 Bind(¬Exception); 1286 FillArgumentsList(argumentsList, sp, startIdx, numArgs); 1287 Jump(exit); 1288} 1289 1290void NewObjectStubBuilder::NewArgumentsObj(Variable *result, Label *exit, 1291 GateRef argumentsList, GateRef numArgs) 1292{ 1293 auto env = GetEnvironment(); 1294 1295 GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit())); 1296 GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue_, glueGlobalEnvOffset); 1297 GateRef argumentsClass = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, 1298 GlobalEnv::ARGUMENTS_CLASS); 1299 Label afterNewObject(env); 1300 NewJSObject(result, &afterNewObject, argumentsClass); 1301 Bind(&afterNewObject); 1302 Label setArgumentsObjProperties(env); 1303 BRANCH(TaggedIsException(result->ReadVariable()), exit, &setArgumentsObjProperties); 1304 Bind(&setArgumentsObjProperties); 1305 SetPropertyInlinedProps(glue_, result->ReadVariable(), argumentsClass, IntToTaggedInt(numArgs), 1306 Int32(JSArguments::LENGTH_INLINE_PROPERTY_INDEX)); 1307 SetElementsArray(VariableType::JS_ANY(), glue_, result->ReadVariable(), argumentsList); 1308 GateRef arrayProtoValuesFunction = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, 1309 GlobalEnv::ARRAY_PROTO_VALUES_FUNCTION_INDEX); 1310 SetPropertyInlinedProps(glue_, result->ReadVariable(), argumentsClass, arrayProtoValuesFunction, 1311 Int32(JSArguments::ITERATOR_INLINE_PROPERTY_INDEX)); 1312 GateRef accessorCaller = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, 1313 GlobalEnv::ARGUMENTS_CALLER_ACCESSOR); 1314 SetPropertyInlinedProps(glue_, result->ReadVariable(), argumentsClass, accessorCaller, 1315 Int32(JSArguments::CALLER_INLINE_PROPERTY_INDEX)); 1316 GateRef accessorCallee = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, 1317 GlobalEnv::ARGUMENTS_CALLEE_ACCESSOR); 1318 SetPropertyInlinedProps(glue_, result->ReadVariable(), argumentsClass, accessorCallee, 1319 Int32(JSArguments::CALLEE_INLINE_PROPERTY_INDEX)); 1320 Jump(exit); 1321} 1322 1323void NewObjectStubBuilder::AssignRestArg(Variable *result, Label *exit, 1324 GateRef sp, GateRef startIdx, GateRef numArgs, GateRef intialHClass) 1325{ 1326 auto env = GetEnvironment(); 1327 DEFVARIABLE(i, VariableType::INT32(), Int32(0)); 1328 GateRef lengthOffset = IntPtr(JSArray::LENGTH_OFFSET); 1329 Store(VariableType::INT32(), glue_, result->ReadVariable(), lengthOffset, TruncInt64ToInt32(numArgs)); 1330 GateRef accessor = GetGlobalConstantValue(VariableType::JS_ANY(), glue_, ConstantIndex::ARRAY_LENGTH_ACCESSOR); 1331 SetPropertyInlinedProps(glue_, result->ReadVariable(), intialHClass, accessor, 1332 Int32(JSArray::LENGTH_INLINE_PROPERTY_INDEX)); 1333 SetExtensibleToBitfield(glue_, result->ReadVariable(), true); 1334 Label setArgumentsBegin(env); 1335 Label setArgumentsAgain(env); 1336 Label setArgumentsEnd(env); 1337 GateRef elements = GetElementsArray(result->ReadVariable()); 1338 BRANCH(Int32UnsignedLessThan(*i, numArgs), &setArgumentsBegin, &setArgumentsEnd); 1339 LoopBegin(&setArgumentsBegin); 1340 { 1341 GateRef idx = ZExtInt32ToPtr(Int32Add(startIdx, *i)); 1342 GateRef receiver = Load(VariableType::JS_ANY(), sp, PtrMul(IntPtr(JSTaggedValue::TaggedTypeSize()), idx)); 1343 SetValueToTaggedArray(VariableType::JS_ANY(), glue_, elements, *i, receiver); 1344 i = Int32Add(*i, Int32(1)); 1345 BRANCH(Int32UnsignedLessThan(*i, numArgs), &setArgumentsAgain, &setArgumentsEnd); 1346 Bind(&setArgumentsAgain); 1347 } 1348 LoopEnd(&setArgumentsBegin); 1349 Bind(&setArgumentsEnd); 1350 Jump(exit); 1351} 1352 1353void NewObjectStubBuilder::NewJSArrayLiteral(Variable *result, Label *exit, RegionSpaceFlag spaceType, GateRef obj, 1354 GateRef hclass, GateRef trackInfo, bool isEmptyArray) 1355{ 1356 auto env = GetEnvironment(); 1357 Label initializeArray(env); 1358 Label afterInitialize(env); 1359 HeapAlloc(result, &initializeArray, spaceType, hclass); 1360 Bind(&initializeArray); 1361 Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), IntPtr(0), hclass); 1362 InitializeWithSpeicalValue(&afterInitialize, result->ReadVariable(), Undefined(), Int32(JSArray::SIZE), 1363 TruncInt64ToInt32(size_), MemoryAttribute::NoBarrier()); 1364 Bind(&afterInitialize); 1365 GateRef hashOffset = IntPtr(ECMAObject::HASH_OFFSET); 1366 Store(VariableType::INT64(), glue_, result->ReadVariable(), hashOffset, Int64(JSTaggedValue(0).GetRawData())); 1367 1368 GateRef propertiesOffset = IntPtr(JSObject::PROPERTIES_OFFSET); 1369 GateRef elementsOffset = IntPtr(JSObject::ELEMENTS_OFFSET); 1370 GateRef lengthOffset = IntPtr(JSArray::LENGTH_OFFSET); 1371 GateRef trackInfoOffset = IntPtr(JSArray::TRACK_INFO_OFFSET); 1372 if (isEmptyArray) { 1373 Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), propertiesOffset, obj); 1374 Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), elementsOffset, obj); 1375 Store(VariableType::INT32(), glue_, result->ReadVariable(), lengthOffset, Int32(0)); 1376 } else { 1377 auto newProperties = Load(VariableType::JS_POINTER(), obj, propertiesOffset); 1378 Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), propertiesOffset, newProperties); 1379 1380 auto newElements = Load(VariableType::JS_POINTER(), obj, elementsOffset); 1381 Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), elementsOffset, newElements); 1382 1383 GateRef arrayLength = Load(VariableType::INT32(), obj, lengthOffset); 1384 Store(VariableType::INT32(), glue_, result->ReadVariable(), lengthOffset, arrayLength); 1385 } 1386 Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), trackInfoOffset, trackInfo); 1387 1388 auto accessor = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_, ConstantIndex::ARRAY_LENGTH_ACCESSOR); 1389 SetPropertyInlinedProps(glue_, result->ReadVariable(), hclass, accessor, 1390 Int32(JSArray::LENGTH_INLINE_PROPERTY_INDEX), VariableType::JS_POINTER(), MemoryAttribute::NoBarrier()); 1391 Jump(exit); 1392} 1393 1394void NewObjectStubBuilder::HeapAlloc(Variable *result, Label *exit, RegionSpaceFlag spaceType, GateRef hclass) 1395{ 1396 switch (spaceType) { 1397 case RegionSpaceFlag::IN_YOUNG_SPACE: 1398 AllocateInYoung(result, exit, hclass); 1399 break; 1400 case RegionSpaceFlag::IN_SHARED_OLD_SPACE: 1401 AllocateInSOld(result, exit, hclass); 1402 break; 1403 default: 1404 *result = CallRuntime(glue_, RTSTUB_ID(HeapAlloc), 1405 { Int64ToTaggedInt(size_), hclass, IntToTaggedInt(Int64(spaceType))}); 1406 break; 1407 } 1408} 1409 1410void NewObjectStubBuilder::AllocateInSOldPrologue([[maybe_unused]] Variable *result, 1411 Label *callRuntime, [[maybe_unused]] Label *exit) 1412{ 1413 auto env = GetEnvironment(); 1414 Label success(env); 1415 Label next(env); 1416 1417#ifdef ARK_ASAN_ON 1418 Jump(callRuntime); 1419#else 1420#ifdef ECMASCRIPT_SUPPORT_HEAPSAMPLING 1421 auto isStartHeapSamplingOffset = JSThread::GlueData::GetIsStartHeapSamplingOffset(env->Is32Bit()); 1422 auto isStartHeapSampling = Load(VariableType::JS_ANY(), glue_, IntPtr(isStartHeapSamplingOffset)); 1423 BRANCH(TaggedIsTrue(isStartHeapSampling), callRuntime, &next); 1424 Bind(&next); 1425#endif 1426 auto topOffset = JSThread::GlueData::GetSOldSpaceAllocationTopAddressOffset(env->Is32Bit()); 1427 auto endOffset = JSThread::GlueData::GetSOldSpaceAllocationEndAddressOffset(env->Is32Bit()); 1428 auto topAddress = Load(VariableType::NATIVE_POINTER(), glue_, IntPtr(topOffset)); 1429 auto endAddress = Load(VariableType::NATIVE_POINTER(), glue_, IntPtr(endOffset)); 1430 auto top = Load(VariableType::JS_POINTER(), topAddress, IntPtr(0)); 1431 auto end = Load(VariableType::JS_POINTER(), endAddress, IntPtr(0)); 1432 auto newTop = PtrAdd(top, size_); 1433 BRANCH(IntPtrGreaterThan(newTop, end), callRuntime, &success); 1434 Bind(&success); 1435 { 1436 Store(VariableType::NATIVE_POINTER(), glue_, topAddress, IntPtr(0), newTop); 1437 if (env->Is32Bit()) { 1438 top = ZExtInt32ToInt64(top); 1439 } 1440 result->WriteVariable(top); 1441 Jump(exit); 1442 } 1443#endif 1444} 1445 1446void NewObjectStubBuilder::AllocateInSOld(Variable *result, Label *exit, GateRef hclass) 1447{ 1448 auto env = GetEnvironment(); 1449 Label callRuntime(env); 1450 AllocateInSOldPrologue(result, &callRuntime, exit); 1451 Bind(&callRuntime); 1452 { 1453 DEFVARIABLE(ret, VariableType::JS_ANY(), Undefined()); 1454 ret = CallRuntime(glue_, RTSTUB_ID(AllocateInSOld), {IntToTaggedInt(size_), hclass}); 1455 result->WriteVariable(*ret); 1456 Jump(exit); 1457 } 1458} 1459 1460void NewObjectStubBuilder::AllocateInYoungPrologue([[maybe_unused]] Variable *result, 1461 Label *callRuntime, [[maybe_unused]] Label *exit) 1462{ 1463 auto env = GetEnvironment(); 1464 Label success(env); 1465 Label next(env); 1466 1467#ifdef ARK_ASAN_ON 1468 Jump(callRuntime); 1469#else 1470#ifdef ECMASCRIPT_SUPPORT_HEAPSAMPLING 1471 auto isStartHeapSamplingOffset = JSThread::GlueData::GetIsStartHeapSamplingOffset(env->Is32Bit()); 1472 auto isStartHeapSampling = Load(VariableType::JS_ANY(), glue_, IntPtr(isStartHeapSamplingOffset)); 1473 BRANCH(TaggedIsTrue(isStartHeapSampling), callRuntime, &next); 1474 Bind(&next); 1475#endif 1476 auto topOffset = JSThread::GlueData::GetNewSpaceAllocationTopAddressOffset(env->Is32Bit()); 1477 auto endOffset = JSThread::GlueData::GetNewSpaceAllocationEndAddressOffset(env->Is32Bit()); 1478 auto topAddress = Load(VariableType::NATIVE_POINTER(), glue_, IntPtr(topOffset)); 1479 auto endAddress = Load(VariableType::NATIVE_POINTER(), glue_, IntPtr(endOffset)); 1480 auto top = Load(VariableType::JS_POINTER(), topAddress, IntPtr(0)); 1481 auto end = Load(VariableType::JS_POINTER(), endAddress, IntPtr(0)); 1482 auto newTop = PtrAdd(top, size_); 1483 BRANCH(IntPtrGreaterThan(newTop, end), callRuntime, &success); 1484 Bind(&success); 1485 { 1486 Store(VariableType::NATIVE_POINTER(), glue_, topAddress, IntPtr(0), newTop, MemoryAttribute::NoBarrier()); 1487 if (env->Is32Bit()) { 1488 top = ZExtInt32ToInt64(top); 1489 } 1490 result->WriteVariable(top); 1491 Jump(exit); 1492 } 1493#endif 1494} 1495 1496void NewObjectStubBuilder::AllocateInYoung(Variable *result, Label *exit, GateRef hclass) 1497{ 1498 auto env = GetEnvironment(); 1499 Label callRuntime(env); 1500 AllocateInYoungPrologue(result, &callRuntime, exit); 1501 Bind(&callRuntime); 1502 { 1503 DEFVARIABLE(ret, VariableType::JS_ANY(), Undefined()); 1504 ret = CallRuntime(glue_, RTSTUB_ID(AllocateInYoung), { 1505 Int64ToTaggedInt(size_), hclass }); 1506 result->WriteVariable(*ret); 1507 Jump(exit); 1508 } 1509} 1510 1511void NewObjectStubBuilder::AllocateInYoung(Variable *result, Label *error, Label *noError, GateRef hclass) 1512{ 1513 auto env = GetEnvironment(); 1514 Label callRuntime(env); 1515 AllocateInYoungPrologue(result, &callRuntime, noError); 1516 Bind(&callRuntime); 1517 { 1518 DEFVARIABLE(ret, VariableType::JS_ANY(), Undefined()); 1519 ret = CallRuntime(glue_, RTSTUB_ID(AllocateInYoung), { 1520 Int64ToTaggedInt(size_), hclass }); 1521 result->WriteVariable(*ret); 1522 BRANCH(TaggedIsException(*ret), error, noError); 1523 } 1524} 1525 1526GateRef NewObjectStubBuilder::NewTrackInfo(GateRef glue, GateRef cachedHClass, GateRef cachedFunc, 1527 RegionSpaceFlag spaceFlag, GateRef arraySize) 1528{ 1529 auto env = GetEnvironment(); 1530 Label entry(env); 1531 env->SubCfgEntry(&entry); 1532 1533 Label initialize(env); 1534 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined()); 1535 auto hclass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue, ConstantIndex::TRACK_INFO_CLASS_INDEX); 1536 GateRef size = GetObjectSizeFromHClass(hclass); 1537 SetParameters(glue, size); 1538 HeapAlloc(&result, &initialize, RegionSpaceFlag::IN_YOUNG_SPACE, hclass); 1539 Bind(&initialize); 1540 Store(VariableType::JS_POINTER(), glue_, *result, IntPtr(0), hclass); 1541 GateRef cachedHClassOffset = IntPtr(TrackInfo::CACHED_HCLASS_OFFSET); 1542 Store(VariableType::JS_POINTER(), glue, *result, cachedHClassOffset, cachedHClass); 1543 GateRef cachedFuncOffset = IntPtr(TrackInfo::CACHED_FUNC_OFFSET); 1544 GateRef weakCachedFunc = env->GetBuilder()->CreateWeakRef(cachedFunc); 1545 Store(VariableType::JS_POINTER(), glue, *result, cachedFuncOffset, weakCachedFunc); 1546 GateRef arrayLengthOffset = IntPtr(TrackInfo::ARRAY_LENGTH_OFFSET); 1547 Store(VariableType::INT32(), glue, *result, arrayLengthOffset, arraySize); 1548 SetSpaceFlagToTrackInfo(glue, *result, Int32(spaceFlag)); 1549 auto elementsKind = GetElementsKindFromHClass(cachedHClass); 1550 SetElementsKindToTrackInfo(glue, *result, elementsKind); 1551 auto ret = *result; 1552 env->SubCfgExit(); 1553 return ret; 1554} 1555 1556void NewObjectStubBuilder::InitializeWithSpeicalValue(Label *exit, GateRef object, GateRef value, GateRef start, 1557 GateRef end, MemoryAttribute mAttr) 1558{ 1559 { 1560 ASM_ASSERT(GET_MESSAGE_STRING_ID(InitializeWithSpeicalValue), 1561 Int32Equal(Int32Mod(Int32Sub(end, start), Int32(JSTaggedValue::TaggedTypeSize())), Int32(0))); 1562 } 1563 auto env = GetEnvironment(); 1564 Label begin(env); 1565 Label storeValue(env); 1566 Label endLoop(env); 1567 Label storeHead(env); 1568 Label enterLoop(env); 1569 DEFVARIABLE(startOffset, VariableType::INT32(), start); 1570 const auto tSize = static_cast<int32_t>(JSTaggedValue::TaggedTypeSize()); 1571 static_assert((tSize & (tSize - 1)) == 0 && "tSize must be power of 2"); 1572 GateRef length = Int32Sub(end, start); 1573 GateRef remainder = Int32And(length, Int32(LOOP_UNROLL_FACTOR * tSize - 1)); 1574 BRANCH(Int32NotEqual(remainder, Int32(0)), &storeHead, &enterLoop); 1575 Bind(&storeHead); 1576 { 1577 // Now use 2 as loop unroll factor, so only store once if reminder is not 0. 1578 // But if using other loop unroll factor, the store head should also be refactored. 1579 Store(VariableType::INT64(), glue_, object, ZExtInt32ToPtr(start), value, mAttr); 1580 startOffset = Int32Add(start, Int32(tSize)); 1581 Jump(&enterLoop); 1582 } 1583 Bind(&enterLoop); 1584 { 1585 Jump(&begin); 1586 } 1587 LoopBegin(&begin); 1588 { 1589 BRANCH(Int32UnsignedLessThan(*startOffset, end), &storeValue, exit); 1590 Bind(&storeValue); 1591 { 1592 auto off = *startOffset; 1593 for (auto i = 0; i < LOOP_UNROLL_FACTOR; i++) { 1594 Store(VariableType::INT64(), glue_, object, ZExtInt32ToPtr(off), value, mAttr); 1595 off = Int32Add(off, Int32(tSize)); 1596 } 1597 startOffset = Int32Add(*startOffset, Int32(LOOP_UNROLL_FACTOR * tSize)); 1598 Jump(&endLoop); 1599 } 1600 Bind(&endLoop); 1601 LoopEnd(&begin); 1602 } 1603} 1604 1605void NewObjectStubBuilder::InitializeTaggedArrayWithSpeicalValue(Label *exit, 1606 GateRef array, GateRef value, GateRef start, GateRef length) 1607{ 1608 Store(VariableType::INT32(), glue_, array, IntPtr(TaggedArray::LENGTH_OFFSET), length); 1609 Store(VariableType::INT32(), glue_, array, IntPtr(TaggedArray::EXTRA_LENGTH_OFFSET), Int32(0)); 1610 auto offset = Int32Mul(start, Int32(JSTaggedValue::TaggedTypeSize())); 1611 auto dataOffset = Int32Add(offset, Int32(TaggedArray::DATA_OFFSET)); 1612 offset = Int32Mul(length, Int32(JSTaggedValue::TaggedTypeSize())); 1613 auto endOffset = Int32Add(offset, Int32(TaggedArray::DATA_OFFSET)); 1614 InitializeWithSpeicalValue(exit, array, value, dataOffset, endOffset); 1615} 1616 1617void NewObjectStubBuilder::AllocLineStringObject(Variable *result, Label *exit, GateRef length, bool compressed) 1618{ 1619 auto env = GetEnvironment(); 1620 if (compressed) { 1621 size_ = AlignUp(ComputeSizeUtf8(ZExtInt32ToPtr(length)), 1622 IntPtr(static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT))); 1623 } else { 1624 size_ = AlignUp(ComputeSizeUtf16(ZExtInt32ToPtr(length)), 1625 IntPtr(static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT))); 1626 } 1627 Label afterAllocate(env); 1628 GateRef stringClass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_, 1629 ConstantIndex::LINE_STRING_CLASS_INDEX); 1630 AllocateInSOld(result, &afterAllocate, stringClass); 1631 1632 Bind(&afterAllocate); 1633 StoreHClass(glue_, result->ReadVariable(), stringClass); 1634 SetLength(glue_, result->ReadVariable(), length, compressed); 1635 SetRawHashcode(glue_, result->ReadVariable(), Int32(0), False()); 1636 Jump(exit); 1637} 1638 1639void NewObjectStubBuilder::AllocSlicedStringObject(Variable *result, Label *exit, GateRef from, GateRef length, 1640 FlatStringStubBuilder *flatString) 1641{ 1642 auto env = GetEnvironment(); 1643 1644 size_ = AlignUp(IntPtr(SlicedString::SIZE), IntPtr(static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT))); 1645 Label afterAllocate(env); 1646 GateRef stringClass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_, 1647 ConstantIndex::SLICED_STRING_CLASS_INDEX); 1648 AllocateInSOld(result, &afterAllocate, stringClass); 1649 1650 Bind(&afterAllocate); 1651 StoreHClass(glue_, result->ReadVariable(), stringClass); 1652 GateRef mixLength = Load(VariableType::INT32(), flatString->GetFlatString(), IntPtr(EcmaString::MIX_LENGTH_OFFSET)); 1653 GateRef isCompressed = Int32And(Int32(EcmaString::STRING_COMPRESSED_BIT), mixLength); 1654 SetLength(glue_, result->ReadVariable(), length, isCompressed); 1655 SetRawHashcode(glue_, result->ReadVariable(), Int32(0), False()); 1656 BuiltinsStringStubBuilder builtinsStringStubBuilder(this); 1657 builtinsStringStubBuilder.StoreParent(glue_, result->ReadVariable(), flatString->GetFlatString()); 1658 builtinsStringStubBuilder.StoreStartIndex(glue_, result->ReadVariable(), 1659 Int32Add(from, flatString->GetStartIndex())); 1660 builtinsStringStubBuilder.StoreHasBackingStore(glue_, result->ReadVariable(), Int32(0)); 1661 Jump(exit); 1662} 1663 1664void NewObjectStubBuilder::AllocTreeStringObject(Variable *result, Label *exit, GateRef first, GateRef second, 1665 GateRef length, bool compressed) 1666{ 1667 auto env = GetEnvironment(); 1668 1669 size_ = AlignUp(IntPtr(TreeEcmaString::SIZE), IntPtr(static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT))); 1670 Label afterAllocate(env); 1671 GateRef stringClass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_, 1672 ConstantIndex::TREE_STRING_CLASS_INDEX); 1673 AllocateInSOld(result, &afterAllocate, stringClass); 1674 1675 Bind(&afterAllocate); 1676 StoreHClass(glue_, result->ReadVariable(), stringClass); 1677 SetLength(glue_, result->ReadVariable(), length, compressed); 1678 SetRawHashcode(glue_, result->ReadVariable(), Int32(0), False()); 1679 Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), IntPtr(TreeEcmaString::FIRST_OFFSET), first); 1680 Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), IntPtr(TreeEcmaString::SECOND_OFFSET), second); 1681 Jump(exit); 1682} 1683 1684GateRef NewObjectStubBuilder::FastNewThisObject(GateRef glue, GateRef ctor) 1685{ 1686 auto env = GetEnvironment(); 1687 Label entry(env); 1688 env->SubCfgEntry(&entry); 1689 Label exit(env); 1690 Label isHeapObject(env); 1691 Label callRuntime(env); 1692 Label checkJSObject(env); 1693 Label newObject(env); 1694 Label isJSObject(env); 1695 1696 DEFVARIABLE(thisObj, VariableType::JS_ANY(), Undefined()); 1697 auto protoOrHclass = Load(VariableType::JS_ANY(), ctor, 1698 IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET)); 1699 BRANCH(TaggedIsHeapObject(protoOrHclass), &isHeapObject, &callRuntime); 1700 Bind(&isHeapObject); 1701 BRANCH(IsJSHClass(protoOrHclass), &checkJSObject, &callRuntime); 1702 Bind(&checkJSObject); 1703 auto objectType = GetObjectType(protoOrHclass); 1704 BRANCH(Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_OBJECT))), &isJSObject, &callRuntime); 1705 Bind(&isJSObject); 1706 { 1707 auto funcProto = GetPrototypeFromHClass(protoOrHclass); 1708 BRANCH(IsEcmaObject(funcProto), &newObject, &callRuntime); 1709 } 1710 Bind(&newObject); 1711 { 1712 SetParameters(glue, 0); 1713 NewJSObject(&thisObj, &exit, protoOrHclass); 1714 } 1715 Bind(&callRuntime); 1716 { 1717 thisObj = CallRuntime(glue, RTSTUB_ID(NewThisObject), {ctor, Undefined()}); 1718 Jump(&exit); 1719 } 1720 Bind(&exit); 1721 auto ret = *thisObj; 1722 env->SubCfgExit(); 1723 return ret; 1724} 1725 1726GateRef NewObjectStubBuilder::FastSuperAllocateThis(GateRef glue, GateRef superCtor, GateRef newTarget) 1727{ 1728 auto env = GetEnvironment(); 1729 Label entry(env); 1730 env->SubCfgEntry(&entry); 1731 Label exit(env); 1732 Label isHeapObject(env); 1733 Label checkJSObject(env); 1734 Label callRuntime(env); 1735 Label newObject(env); 1736 Label isFunction(env); 1737 1738 BRANCH(IsJSFunction(newTarget), &isFunction, &callRuntime); 1739 Bind(&isFunction); 1740 DEFVARIABLE(thisObj, VariableType::JS_ANY(), Undefined()); 1741 DEFVARIABLE(protoOrHclass, VariableType::JS_ANY(), Undefined()); 1742 protoOrHclass = Load(VariableType::JS_ANY(), newTarget, 1743 IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET)); 1744 BRANCH(TaggedIsHeapObject(*protoOrHclass), &isHeapObject, &callRuntime); 1745 Bind(&isHeapObject); 1746 BRANCH(IsJSHClass(*protoOrHclass), &checkJSObject, &callRuntime); 1747 Bind(&checkJSObject); 1748 auto objectType = GetObjectType(*protoOrHclass); 1749 BRANCH(Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_OBJECT))), 1750 &newObject, &callRuntime); 1751 Bind(&newObject); 1752 { 1753 SetParameters(glue, 0); 1754 NewJSObject(&thisObj, &exit, *protoOrHclass); 1755 } 1756 Bind(&callRuntime); 1757 { 1758 thisObj = CallRuntime(glue, RTSTUB_ID(NewThisObject), {superCtor, newTarget}); 1759 Jump(&exit); 1760 } 1761 Bind(&exit); 1762 auto ret = *thisObj; 1763 env->SubCfgExit(); 1764 return ret; 1765} 1766 1767GateRef NewObjectStubBuilder::NewThisObjectChecked(GateRef glue, GateRef ctor) 1768{ 1769 auto env = GetEnvironment(); 1770 Label entry(env); 1771 env->SubCfgEntry(&entry); 1772 Label exit(env); 1773 1774 Label ctorIsHeapObject(env); 1775 Label ctorIsJSFunction(env); 1776 Label fastPath(env); 1777 Label slowPath(env); 1778 Label ctorIsBase(env); 1779 1780 DEFVARIABLE(thisObj, VariableType::JS_ANY(), Undefined()); 1781 1782 BRANCH(TaggedIsHeapObject(ctor), &ctorIsHeapObject, &slowPath); 1783 Bind(&ctorIsHeapObject); 1784 BRANCH(IsJSFunction(ctor), &ctorIsJSFunction, &slowPath); 1785 Bind(&ctorIsJSFunction); 1786 BRANCH(IsConstructor(ctor), &fastPath, &slowPath); 1787 Bind(&fastPath); 1788 { 1789 BRANCH(IsBase(ctor), &ctorIsBase, &exit); 1790 Bind(&ctorIsBase); 1791 { 1792 thisObj = FastNewThisObject(glue, ctor); 1793 Jump(&exit); 1794 } 1795 } 1796 Bind(&slowPath); 1797 { 1798 thisObj = Hole(); 1799 Jump(&exit); 1800 } 1801 Bind(&exit); 1802 auto ret = *thisObj; 1803 env->SubCfgExit(); 1804 return ret; 1805} 1806 1807// The caller should ensure that the IC slot for LoadTrackInfo is valid (slotId is not 0xff or slotValue is not Hole). 1808GateRef NewObjectStubBuilder::LoadTrackInfo(GateRef glue, GateRef jsFunc, TraceIdInfo traceIdInfo, 1809 GateRef profileTypeInfo, GateRef slotId, GateRef slotValue, GateRef arrayLiteral, ProfileOperation callback) 1810{ 1811 auto env = GetEnvironment(); 1812 Label entry(env); 1813 env->SubCfgEntry(&entry); 1814 Label exit(env); 1815 DEFVARIABLE(ret, VariableType::JS_POINTER(), Undefined()); 1816 1817 Label uninitialized(env); 1818 Label fastpath(env); 1819 BRANCH(TaggedIsHeapObject(slotValue), &fastpath, &uninitialized); 1820 Bind(&fastpath); 1821 { 1822 ret = slotValue; 1823 Jump(&exit); 1824 } 1825 Bind(&uninitialized); 1826 { 1827 auto hclass = LoadArrayHClassSlowPath(glue, jsFunc, traceIdInfo, arrayLiteral, callback); 1828 // emptyarray 1829 if (arrayLiteral == Circuit::NullGate()) { 1830 ret = NewTrackInfo(glue, hclass, jsFunc, RegionSpaceFlag::IN_YOUNG_SPACE, Int32(0)); 1831 } else { 1832 GateRef arrayLength = GetArrayLength(arrayLiteral); 1833 ret = NewTrackInfo(glue, hclass, jsFunc, RegionSpaceFlag::IN_YOUNG_SPACE, arrayLength); 1834 } 1835 1836 SetValueToTaggedArray(VariableType::JS_POINTER(), glue, profileTypeInfo, slotId, *ret); 1837 callback.TryPreDump(); 1838 Jump(&exit); 1839 } 1840 Bind(&exit); 1841 auto result = *ret; 1842 env->SubCfgExit(); 1843 return result; 1844} 1845 1846GateRef NewObjectStubBuilder::LoadArrayHClassSlowPath( 1847 GateRef glue, GateRef jsFunc, TraceIdInfo traceIdInfo, GateRef arrayLiteral, ProfileOperation callback) 1848{ 1849 auto env = GetEnvironment(); 1850 Label entry(env); 1851 env->SubCfgEntry(&entry); 1852 Label exit(env); 1853 Label originLoad(env); 1854 1855 DEFVARIABLE(ret, VariableType::JS_POINTER(), Undefined()); 1856 1857 auto hcIndexInfos = LoadHCIndexInfosFromConstPool(jsFunc); 1858 auto indexInfosLength = GetLengthOfTaggedArray(hcIndexInfos); 1859 Label aotLoad(env); 1860 BRANCH(Int32Equal(indexInfosLength, Int32(0)), &originLoad, &aotLoad); 1861 Bind(&aotLoad); 1862 { 1863 GateRef traceId = 0; 1864 if (traceIdInfo.isPc) { 1865 auto pfAddr = LoadPfHeaderFromConstPool(jsFunc); 1866 traceId = TruncPtrToInt32(PtrSub(traceIdInfo.pc, pfAddr)); 1867 } else { 1868 traceId = traceIdInfo.traceId; 1869 } 1870 1871 GateRef hcIndex = LoadHCIndexFromConstPool(hcIndexInfos, indexInfosLength, traceId, &originLoad); 1872 GateRef gConstAddr = Load(VariableType::JS_ANY(), glue, 1873 IntPtr(JSThread::GlueData::GetGlobalConstOffset(env->Is32Bit()))); 1874 GateRef offset = Int32Mul(Int32(sizeof(JSTaggedValue)), hcIndex); 1875 ret = Load(VariableType::JS_POINTER(), gConstAddr, offset); 1876 Jump(&exit); 1877 } 1878 Bind(&originLoad); 1879 { 1880 // emptyarray 1881 if (arrayLiteral == Circuit::NullGate()) { 1882 if (callback.IsEmpty()) { 1883 GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit())); 1884 GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset); 1885 auto arrayFunc = 1886 GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::ARRAY_FUNCTION_INDEX); 1887 ret = Load(VariableType::JS_POINTER(), arrayFunc, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET)); 1888 } else { 1889 ret = 1890 GetGlobalConstantValue(VariableType::JS_POINTER(), glue, ConstantIndex::ELEMENT_NONE_HCLASS_INDEX); 1891 } 1892 } else { 1893 ret = LoadHClass(arrayLiteral); 1894 } 1895 Jump(&exit); 1896 } 1897 Bind(&exit); 1898 auto result = *ret; 1899 env->SubCfgExit(); 1900 return result; 1901} 1902 1903GateRef NewObjectStubBuilder::CreateEmptyArrayCommon(GateRef glue, GateRef hclass, GateRef trackInfo) 1904{ 1905 auto env = GetEnvironment(); 1906 Label entry(env); 1907 env->SubCfgEntry(&entry); 1908 Label exit(env); 1909 1910 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined()); 1911 1912 GateRef size = GetObjectSizeFromHClass(hclass); 1913 GateRef emptyArray = GetGlobalConstantValue( 1914 VariableType::JS_POINTER(), glue, ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX); 1915 SetParameters(glue, size); 1916 NewJSArrayLiteral(&result, &exit, RegionSpaceFlag::IN_YOUNG_SPACE, emptyArray, hclass, trackInfo, true); 1917 Bind(&exit); 1918 GateRef ret = *result; 1919 env->SubCfgExit(); 1920 return ret; 1921} 1922 1923GateRef NewObjectStubBuilder::CreateEmptyObject(GateRef glue) 1924{ 1925 auto env = GetEnvironment(); 1926 GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit())); 1927 GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset); 1928 GateRef objectFunc = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::OBJECT_FUNCTION_INDEX); 1929 GateRef hclass = Load(VariableType::JS_POINTER(), objectFunc, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET)); 1930 return NewJSObject(glue, hclass); 1931} 1932 1933GateRef NewObjectStubBuilder::CreateEmptyArray(GateRef glue) 1934{ 1935 auto env = GetEnvironment(); 1936 DEFVARIABLE(trackInfo, VariableType::JS_ANY(), Undefined()); 1937 GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit())); 1938 GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset); 1939 GateRef arrayFunc = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::ARRAY_FUNCTION_INDEX); 1940 GateRef hclass = Load(VariableType::JS_POINTER(), arrayFunc, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET)); 1941 return CreateEmptyArrayCommon(glue, hclass, *trackInfo); 1942} 1943 1944GateRef NewObjectStubBuilder::CreateEmptyArray(GateRef glue, GateRef jsFunc, TraceIdInfo traceIdInfo, 1945 GateRef profileTypeInfo, GateRef slotId, ProfileOperation callback) 1946{ 1947 auto env = GetEnvironment(); 1948 Label entry(env); 1949 env->SubCfgEntry(&entry); 1950 1951 DEFVARIABLE(trackInfo, VariableType::JS_ANY(), Undefined()); 1952 DEFVARIABLE(hclass, VariableType::JS_ANY(), Undefined()); 1953 Label slowpath(env); 1954 Label mayFastpath(env); 1955 Label createArray(env); 1956 Label profileNotUndefined(env); 1957 BRANCH(TaggedIsUndefined(profileTypeInfo), &slowpath, &profileNotUndefined); 1958 Bind(&profileNotUndefined); 1959 GateRef slotValue = GetValueFromTaggedArray(profileTypeInfo, slotId); 1960 BRANCH(TaggedIsHole(slotValue), &slowpath, &mayFastpath); 1961 Bind(&mayFastpath); 1962 { 1963 trackInfo = LoadTrackInfo(glue, jsFunc, traceIdInfo, profileTypeInfo, 1964 slotId, slotValue, Circuit::NullGate(), callback); 1965 hclass = Load(VariableType::JS_ANY(), *trackInfo, IntPtr(TrackInfo::CACHED_HCLASS_OFFSET)); 1966 trackInfo = env->GetBuilder()->CreateWeakRef(*trackInfo); 1967 Jump(&createArray); 1968 } 1969 Bind(&slowpath); 1970 { 1971 hclass = LoadArrayHClassSlowPath(glue, jsFunc, traceIdInfo, Circuit::NullGate(), callback); 1972 Jump(&createArray); 1973 } 1974 Bind(&createArray); 1975 GateRef result = CreateEmptyArrayCommon(glue, *hclass, *trackInfo); 1976 env->SubCfgExit(); 1977 return result; 1978} 1979 1980GateRef NewObjectStubBuilder::CreateArrayWithBuffer(GateRef glue, GateRef index, GateRef jsFunc, 1981 TraceIdInfo traceIdInfo, GateRef profileTypeInfo, GateRef slotId, ProfileOperation callback) 1982{ 1983 auto env = GetEnvironment(); 1984 Label entry(env); 1985 env->SubCfgEntry(&entry); 1986 Label exit(env); 1987 1988 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined()); 1989 DEFVARIABLE(trackInfo, VariableType::JS_ANY(), Undefined()); 1990 DEFVARIABLE(hclass, VariableType::JS_ANY(), Undefined()); 1991 1992 GateRef method = GetMethodFromFunction(jsFunc); 1993 GateRef constPool = Load(VariableType::JS_ANY(), method, IntPtr(Method::CONSTANT_POOL_OFFSET)); 1994 GateRef module = GetModuleFromFunction(jsFunc); 1995 1996 auto obj = GetArrayLiteralFromConstPool(glue, constPool, index, module); 1997 1998 Label slowpath(env); 1999 Label mayFastpath(env); 2000 Label createArray(env); 2001 Label profileNotUndefined(env); 2002 BRANCH(TaggedIsUndefined(profileTypeInfo), &slowpath, &profileNotUndefined); 2003 Bind(&profileNotUndefined); 2004 GateRef slotValue = GetValueFromTaggedArray(profileTypeInfo, slotId); 2005 BRANCH(TaggedIsHole(slotValue), &slowpath, &mayFastpath); 2006 Bind(&mayFastpath); 2007 { 2008 trackInfo = LoadTrackInfo(glue, jsFunc, traceIdInfo, profileTypeInfo, slotId, slotValue, obj, callback); 2009 hclass = Load(VariableType::JS_ANY(), *trackInfo, IntPtr(TrackInfo::CACHED_HCLASS_OFFSET)); 2010 trackInfo = env->GetBuilder()->CreateWeakRef(*trackInfo); 2011 Jump(&createArray); 2012 } 2013 Bind(&slowpath); 2014 { 2015 hclass = LoadArrayHClassSlowPath(glue, jsFunc, traceIdInfo, obj, callback); 2016 Jump(&createArray); 2017 } 2018 Bind(&createArray); 2019 GateRef size = GetObjectSizeFromHClass(*hclass); 2020 2021 SetParameters(glue, size); 2022 NewJSArrayLiteral(&result, &exit, RegionSpaceFlag::IN_YOUNG_SPACE, obj, *hclass, *trackInfo, false); 2023 2024 Bind(&exit); 2025 auto ret = *result; 2026 env->SubCfgExit(); 2027 return ret; 2028} 2029 2030template <typename IteratorType, typename CollectionType> 2031void NewObjectStubBuilder::CreateJSCollectionIterator( 2032 Variable *result, Label *exit, GateRef thisValue, GateRef kind) 2033{ 2034 ASSERT_PRINT((std::is_same_v<IteratorType, JSSetIterator> || std::is_same_v<IteratorType, JSMapIterator>), 2035 "IteratorType must be JSSetIterator or JSMapIterator type"); 2036 auto env = GetEnvironment(); 2037 ConstantIndex iterClassIdx = static_cast<ConstantIndex>(0); 2038 int32_t iterOffset = 0; // ITERATED_SET_OFFSET 2039 size_t linkedOffset = 0; // LINKED_MAP_OFFSET 2040 if constexpr (std::is_same_v<IteratorType, JSSetIterator>) { 2041 iterClassIdx = ConstantIndex::JS_SET_ITERATOR_CLASS_INDEX; 2042 iterOffset = IteratorType::ITERATED_SET_OFFSET; 2043 linkedOffset = CollectionType::LINKED_SET_OFFSET; 2044 size_ = IntPtr(JSSetIterator::SIZE); 2045 } else { 2046 iterClassIdx = ConstantIndex::JS_MAP_ITERATOR_CLASS_INDEX; 2047 iterOffset = IteratorType::ITERATED_MAP_OFFSET; 2048 linkedOffset = CollectionType::LINKED_MAP_OFFSET; 2049 size_ = IntPtr(JSMapIterator::SIZE); 2050 } 2051 GateRef iteratorHClass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_, iterClassIdx); 2052 2053 Label noException(env); 2054 // Be careful. NO GC is allowed when initization is not complete. 2055 AllocateInYoung(result, exit, &noException, iteratorHClass); 2056 Bind(&noException); 2057 { 2058 StoreBuiltinHClass(glue_, result->ReadVariable(), iteratorHClass); 2059 SetHash(glue_, result->ReadVariable(), Int64(JSTaggedValue(0).GetRawData())); 2060 auto emptyArray = GetGlobalConstantValue( 2061 VariableType::JS_POINTER(), glue_, ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX); 2062 SetPropertiesArray(VariableType::INT64(), glue_, result->ReadVariable(), emptyArray); 2063 SetElementsArray(VariableType::INT64(), glue_, result->ReadVariable(), emptyArray); 2064 2065 // GetLinked 2066 GateRef linked = Load(VariableType::JS_ANY(), thisValue, IntPtr(linkedOffset)); 2067 // SetIterated 2068 GateRef iteratorOffset = IntPtr(iterOffset); 2069 Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), iteratorOffset, linked, 2070 MemoryAttribute::UnknownBarrier()); 2071 2072 // SetIteratorNextIndex 2073 GateRef nextIndexOffset = IntPtr(IteratorType::NEXT_INDEX_OFFSET); 2074 Store(VariableType::INT32(), glue_, result->ReadVariable(), nextIndexOffset, Int32(0)); 2075 2076 // SetIterationKind 2077 GateRef kindBitfieldOffset = IntPtr(IteratorType::BIT_FIELD_OFFSET); 2078 Store(VariableType::INT32(), glue_, result->ReadVariable(), kindBitfieldOffset, kind); 2079 Jump(exit); 2080 } 2081} 2082 2083template void NewObjectStubBuilder::CreateJSCollectionIterator<JSSetIterator, JSSet>( 2084 Variable *result, Label *exit, GateRef set, GateRef kind); 2085template void NewObjectStubBuilder::CreateJSCollectionIterator<JSMapIterator, JSMap>( 2086 Variable *result, Label *exit, GateRef set, GateRef kind); 2087 2088void NewObjectStubBuilder::CreateJSTypedArrayIterator(Variable *result, Label *exit, GateRef thisValue, GateRef kind) 2089{ 2090 auto env = GetEnvironment(); 2091 size_ = IntPtr(JSArrayIterator::SIZE); 2092 2093 ConstantIndex iterClassIdx = ConstantIndex::JS_ARRAY_ITERATOR_CLASS_INDEX; 2094 GateRef iteratorHClass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_, iterClassIdx); 2095 2096 Label thisExists(env); 2097 Label isEcmaObject(env); 2098 Label isTypedArray(env); 2099 Label throwTypeError(env); 2100 2101 BRANCH(TaggedIsUndefinedOrNullOrHole(thisValue), &throwTypeError, &thisExists); 2102 Bind(&thisExists); 2103 BRANCH(IsEcmaObject(thisValue), &isEcmaObject, &throwTypeError); 2104 Bind(&isEcmaObject); 2105 BRANCH(IsTypedArray(thisValue), &isTypedArray, &throwTypeError); 2106 Bind(&isTypedArray); 2107 2108 Label noException(env); 2109 // Be careful. NO GC is allowed when initization is not complete. 2110 AllocateInYoung(result, exit, &noException, iteratorHClass); 2111 Bind(&noException); 2112 { 2113 StoreBuiltinHClass(glue_, result->ReadVariable(), iteratorHClass); 2114 SetHash(glue_, result->ReadVariable(), Int64(JSTaggedValue(0).GetRawData())); 2115 auto emptyArray = GetGlobalConstantValue( 2116 VariableType::JS_POINTER(), glue_, ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX); 2117 SetPropertiesArray(VariableType::INT64(), glue_, result->ReadVariable(), emptyArray); 2118 SetElementsArray(VariableType::INT64(), glue_, result->ReadVariable(), emptyArray); 2119 2120 GateRef iteratorOffset = IntPtr(JSArrayIterator::ITERATED_ARRAY_OFFSET); 2121 Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), iteratorOffset, thisValue, 2122 MemoryAttribute::NeedBarrier()); 2123 2124 // SetIteratorNextIndex 2125 GateRef nextIndexOffset = IntPtr(JSArrayIterator::NEXT_INDEX_OFFSET); 2126 Store(VariableType::INT32(), glue_, result->ReadVariable(), nextIndexOffset, Int32(0)); 2127 2128 // SetIterationKind 2129 GateRef kindBitfieldOffset = IntPtr(JSArrayIterator::BIT_FIELD_OFFSET); 2130 Store(VariableType::INT32(), glue_, result->ReadVariable(), kindBitfieldOffset, kind); 2131 Jump(exit); 2132 } 2133 2134 Bind(&throwTypeError); 2135 { 2136 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(TargetTypeNotTypedArray)); 2137 CallRuntime(glue_, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) }); 2138 result->WriteVariable(Exception()); 2139 Jump(exit); 2140 } 2141} 2142 2143GateRef NewObjectStubBuilder::NewTaggedSubArray(GateRef glue, GateRef srcTypedArray, 2144 GateRef elementSize, GateRef newLength, GateRef beginIndex, GateRef arrayCls, GateRef buffer) 2145{ 2146 auto env = GetEnvironment(); 2147 Label entry(env); 2148 env->SubCfgEntry(&entry); 2149 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined()); 2150 GateRef constructorName = Load(VariableType::JS_POINTER(), srcTypedArray, 2151 IntPtr(JSTypedArray::TYPED_ARRAY_NAME_OFFSET)); 2152 GateRef srcByteOffset = Load(VariableType::INT32(), srcTypedArray, IntPtr(JSTypedArray::BYTE_OFFSET_OFFSET)); 2153 GateRef contentType = Load(VariableType::INT32(), srcTypedArray, IntPtr(JSTypedArray::CONTENT_TYPE_OFFSET)); 2154 GateRef beginByteOffset = Int32Add(srcByteOffset, Int32Mul(beginIndex, elementSize)); 2155 2156 GateRef obj = NewJSObject(glue, arrayCls); 2157 result = obj; 2158 GateRef newByteLength = Int32Mul(elementSize, newLength); 2159 Store(VariableType::JS_POINTER(), glue, obj, IntPtr(JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET), buffer); 2160 Store(VariableType::JS_POINTER(), glue, obj, IntPtr(JSTypedArray::TYPED_ARRAY_NAME_OFFSET), constructorName); 2161 Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::BYTE_LENGTH_OFFSET), newByteLength); 2162 Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::BYTE_OFFSET_OFFSET), beginByteOffset); 2163 Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::ARRAY_LENGTH_OFFSET), newLength); 2164 Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::CONTENT_TYPE_OFFSET), contentType); 2165 auto ret = *result; 2166 env->SubCfgExit(); 2167 return ret; 2168} 2169 2170GateRef NewObjectStubBuilder::NewTypedArray(GateRef glue, GateRef srcTypedArray, GateRef srcType, GateRef length) 2171{ 2172 auto env = GetEnvironment(); 2173 Label entry(env); 2174 env->SubCfgEntry(&entry); 2175 2176 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined()); 2177 Label slowPath(env); 2178 Label defaultConstr(env); 2179 Label markerCellValid(env); 2180 Label isProtoChangeMarker(env); 2181 Label accessorNotChanged(env); 2182 Label exit(env); 2183 BRANCH(HasConstructor(srcTypedArray), &slowPath, &defaultConstr); 2184 Bind(&defaultConstr); 2185 GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit())); 2186 GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset); 2187 GateRef markerCell = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, 2188 GlobalEnv::TYPED_ARRAY_SPECIES_PROTECT_DETECTOR_INDEX); 2189 BRANCH(IsMarkerCellValid(markerCell), &markerCellValid, &slowPath); 2190 Bind(&markerCellValid); 2191 GateRef marker = GetProtoChangeMarkerFromHClass(LoadHClass(srcTypedArray)); 2192 BRANCH(TaggedIsProtoChangeMarker(marker), &isProtoChangeMarker, &accessorNotChanged); 2193 Bind(&isProtoChangeMarker); 2194 BRANCH(GetAccessorHasChanged(marker), &slowPath, &accessorNotChanged); 2195 2196 Bind(&accessorNotChanged); 2197 { 2198 DEFVARIABLE(buffer, VariableType::JS_ANY(), Undefined()); 2199 Label next(env); 2200 GateRef hclass = LoadHClass(srcTypedArray); 2201 GateRef obj = NewJSObject(glue, hclass); 2202 result = obj; 2203 GateRef ctorName = Load(VariableType::JS_POINTER(), srcTypedArray, 2204 IntPtr(JSTypedArray::TYPED_ARRAY_NAME_OFFSET)); 2205 GateRef elementSize = GetElementSizeFromType(glue, srcType); 2206 GateRef newByteLength = Int32Mul(elementSize, length); 2207 GateRef contentType = Load(VariableType::INT32(), srcTypedArray, IntPtr(JSTypedArray::CONTENT_TYPE_OFFSET)); 2208 BRANCH(Int32LessThanOrEqual(newByteLength, Int32(RangeInfo::TYPED_ARRAY_ONHEAP_MAX)), &next, &slowPath); 2209 Bind(&next); 2210 { 2211 Label sameObjectSize(env); 2212 Label newByteArrayExit(env); 2213 GateRef onHeapHClass = GetOnHeapHClassFromType(glue, srcType); 2214 GateRef originalHClassObjectSize = GetObjectSizeFromHClass(hclass); 2215 GateRef onHeapHClassObjectSize = GetObjectSizeFromHClass(onHeapHClass); 2216 BRANCH(Equal(originalHClassObjectSize, onHeapHClassObjectSize), &sameObjectSize, &slowPath); 2217 Bind(&sameObjectSize); 2218 NewByteArray(&buffer, &newByteArrayExit, elementSize, length); 2219 Bind(&newByteArrayExit); 2220 StoreHClass(glue, obj, onHeapHClass); 2221 Store(VariableType::JS_POINTER(), glue, obj, IntPtr(JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET), *buffer); 2222 Store(VariableType::JS_POINTER(), glue, obj, IntPtr(JSTypedArray::TYPED_ARRAY_NAME_OFFSET), ctorName); 2223 Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::BYTE_LENGTH_OFFSET), newByteLength); 2224 Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::BYTE_OFFSET_OFFSET), Int32(0)); 2225 Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::ARRAY_LENGTH_OFFSET), length); 2226 Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::CONTENT_TYPE_OFFSET), contentType); 2227 Jump(&exit); 2228 } 2229 } 2230 2231 Bind(&slowPath); 2232 { 2233 result = CallRuntime(glue, RTSTUB_ID(TypedArraySpeciesCreate), 2234 { srcTypedArray, IntToTaggedInt(Int32(1)), IntToTaggedInt(length) }); 2235 Jump(&exit); 2236 } 2237 2238 Bind(&exit); 2239 auto ret = *result; 2240 env->SubCfgExit(); 2241 return ret; 2242} 2243 2244// use NewJSObjectByConstructor need to InitializeJSObject by type 2245GateRef NewObjectStubBuilder::NewJSObjectByConstructor(GateRef glue, GateRef constructor, GateRef newTarget) 2246{ 2247 auto env = GetEnvironment(); 2248 Label entry(env); 2249 env->SubCfgEntry(&entry); 2250 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined()); 2251 DEFVARIABLE(jshclass, VariableType::JS_ANY(), Undefined()); 2252 Label exit(env); 2253 Label slowPath(env); 2254 Label newObj(env); 2255 Label isValid(env); 2256 Label checkIsJSShared(env); 2257 Label constructorIsShared(env); 2258 SetGlue(glue); 2259 BRANCH(IntPtrEqual(constructor, newTarget), &isValid, &checkIsJSShared); 2260 Bind(&checkIsJSShared); 2261 BRANCH(IsJSShared(constructor), &constructorIsShared, &isValid); 2262 Bind(&constructorIsShared); 2263 { 2264 BRANCH(IsJSShared(newTarget), &isValid, &slowPath); 2265 } 2266 Bind(&isValid); 2267 { 2268 Label hasFunctionPrototype(env); 2269 Label notHasFunctionPrototype(env); 2270 BRANCH(HasFunctionPrototype(constructor), &hasFunctionPrototype, ¬HasFunctionPrototype); 2271 Bind(&hasFunctionPrototype); 2272 { 2273 GateRef proto = GetCtorPrototype(constructor); 2274 BRANCH(IsEcmaObject(proto), ¬HasFunctionPrototype, &slowPath); 2275 } 2276 Bind(¬HasFunctionPrototype); 2277 { 2278 Label isEqual(env); 2279 Label isHClass(env); 2280 BRANCH(IntPtrEqual(constructor, newTarget), &isEqual, &slowPath); 2281 Bind(&isEqual); 2282 GateRef protoOrHClass = GetProtoOrHClass(constructor); 2283 BRANCH(IsJSHClass(protoOrHClass), &isHClass, &slowPath); 2284 Bind(&isHClass); 2285 jshclass = protoOrHClass; 2286 Jump(&newObj); 2287 } 2288 } 2289 Bind(&newObj); 2290 { 2291 Label notShared(env); 2292 BRANCH(IsJSShared(*jshclass), &slowPath, ¬Shared); 2293 Bind(¬Shared); 2294 { 2295 result = NewJSObject(glue, *jshclass); 2296 Jump(&exit); 2297 } 2298 } 2299 Bind(&slowPath); 2300 { 2301 result = CallRuntime(glue, RTSTUB_ID(NewJSObjectByConstructor), { constructor, newTarget }); 2302 Jump(&exit); 2303 } 2304 2305 Bind(&exit); 2306 auto ret = *result; 2307 env->SubCfgExit(); 2308 return ret; 2309} 2310 2311GateRef NewObjectStubBuilder::NewFloat32ArrayObj(GateRef glue, GateRef glueGlobalEnv) 2312{ 2313 GateRef arrayFunc = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, 2314 GlobalEnv::FLOAT32_ARRAY_FUNCTION_INDEX); 2315 GateRef hclass = Load(VariableType::JS_POINTER(), arrayFunc, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET)); 2316 GateRef obj = NewJSObject(glue, hclass); 2317 return obj; 2318} 2319 2320GateRef NewObjectStubBuilder::NewFloat32ArrayWithSize(GateRef glue, GateRef size) 2321{ 2322 auto env = GetEnvironment(); 2323 Label entry(env); 2324 env->SubCfgEntry(&entry); 2325 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined()); 2326 DEFVARIABLE(buffer, VariableType::JS_ANY(), Undefined()); 2327 Label exit(env); 2328 GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit())); 2329 GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset); 2330 GateRef obj = NewFloat32ArrayObj(glue, glueGlobalEnv); 2331 result = obj; 2332 GateRef ctorName = GetGlobalConstantValue(VariableType::JS_POINTER(), glue, 2333 ConstantIndex::FLOAT32_ARRAY_STRING_INDEX); 2334 GateRef elementSize = Int32(4); // 4: float32 primtype's byte length 2335 GateRef newByteLength = Int32Mul(size, elementSize); 2336 GateRef contentType = Int32(static_cast<int32_t>(ContentType::Number)); 2337 { 2338 Label newByteArrayExit(env); 2339 NewByteArray(&buffer, &newByteArrayExit, elementSize, size); 2340 Bind(&newByteArrayExit); 2341 GateRef onHeapHClass = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, 2342 GlobalEnv::FLOAT32_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX); 2343 StoreHClass(glue, obj, onHeapHClass); 2344 Store(VariableType::JS_POINTER(), glue, obj, IntPtr(JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET), *buffer); 2345 Store(VariableType::JS_POINTER(), glue, obj, IntPtr(JSTypedArray::TYPED_ARRAY_NAME_OFFSET), 2346 ctorName, MemoryAttribute::NoBarrier()); 2347 Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::BYTE_LENGTH_OFFSET), 2348 newByteLength, MemoryAttribute::NoBarrier()); 2349 Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::BYTE_OFFSET_OFFSET), 2350 Int32(0), MemoryAttribute::NoBarrier()); 2351 Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::ARRAY_LENGTH_OFFSET), 2352 size, MemoryAttribute::NoBarrier()); 2353 Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::CONTENT_TYPE_OFFSET), 2354 contentType, MemoryAttribute::NoBarrier()); 2355 Jump(&exit); 2356 } 2357 Bind(&exit); 2358 auto ret = *result; 2359 env->SubCfgExit(); 2360 return ret; 2361} 2362 2363GateRef NewObjectStubBuilder::NewTypedArrayFromCtor(GateRef glue, GateRef ctor, GateRef length, Label *slowPath) 2364{ 2365 auto env = GetEnvironment(); 2366 Label entry(env); 2367 env->SubCfgEntry(&entry); 2368 2369 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined()); 2370 Label thisObjIsECmaObject(env); 2371 Label thisObjIsFastTypedArray(env); 2372 Label defaultConstr(env); 2373 Label exit(env); 2374 2375 GateRef thisObj = FastNewThisObject(glue, ctor); 2376 result = thisObj; 2377 GateRef arrayType = GetObjectType(LoadHClass(thisObj)); 2378 2379 BRANCH(IsEcmaObject(thisObj), &thisObjIsECmaObject, slowPath); 2380 Bind(&thisObjIsECmaObject); 2381 BRANCH(IsFastTypeArray(arrayType), &thisObjIsFastTypedArray, slowPath); 2382 Bind(&thisObjIsFastTypedArray); 2383 BRANCH(HasConstructor(thisObj), slowPath, &defaultConstr); 2384 Bind(&defaultConstr); 2385 2386 DEFVARIABLE(buffer, VariableType::JS_ANY(), Undefined()); 2387 GateRef elementSize = GetElementSizeFromType(glue, arrayType); 2388 GateRef newByteLength = Int32Mul(elementSize, length); 2389 Label newByteArrayExit(env); 2390 NewByteArray(&buffer, &newByteArrayExit, elementSize, length); 2391 Bind(&newByteArrayExit); 2392 Store(VariableType::JS_POINTER(), glue, thisObj, IntPtr(JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET), *buffer); 2393 Store(VariableType::INT32(), glue, thisObj, IntPtr(JSTypedArray::BYTE_LENGTH_OFFSET), newByteLength); 2394 Store(VariableType::INT32(), glue, thisObj, IntPtr(JSTypedArray::ARRAY_LENGTH_OFFSET), length); 2395 Jump(&exit); 2396 2397 Bind(&exit); 2398 auto ret = *result; 2399 env->SubCfgExit(); 2400 return ret; 2401} 2402 2403void NewObjectStubBuilder::NewByteArray(Variable *result, Label *exit, GateRef elementSize, GateRef length) 2404{ 2405 auto env = GetEnvironment(); 2406 2407 Label noError(env); 2408 Label initializeExit(env); 2409 GateRef size = AlignUp(ComputeTaggedTypedArraySize(ZExtInt32ToPtr(elementSize), ZExtInt32ToPtr(length)), 2410 IntPtr(static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT))); 2411 size_ = size; 2412 auto hclass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_, ConstantIndex::BYTE_ARRAY_CLASS_INDEX); 2413 AllocateInYoung(result, exit, &noError, hclass); 2414 Bind(&noError); 2415 { 2416 StoreBuiltinHClass(glue_, result->ReadVariable(), hclass); 2417 auto startOffset = Int32(ByteArray::DATA_OFFSET); 2418 static_assert(static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT) == 8); 2419 InitializeWithSpeicalValue(&initializeExit, result->ReadVariable(), Int64(0), startOffset, 2420 TruncPtrToInt32(size)); 2421 Bind(&initializeExit); 2422 Store(VariableType::INT32(), glue_, result->ReadVariable(), IntPtr(ByteArray::ARRAY_LENGTH_OFFSET), length); 2423 Store(VariableType::INT32(), glue_, result->ReadVariable(), IntPtr(ByteArray::BYTE_LENGTH_OFFSET), elementSize); 2424 Jump(exit); 2425 } 2426} 2427 2428GateRef NewObjectStubBuilder::NewProfileTypeInfoCell(GateRef glue, GateRef value) 2429{ 2430 auto env = GetEnvironment(); 2431 Label entry(env); 2432 env->SubCfgEntry(&entry); 2433 2434 Label initialize(env); 2435 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined()); 2436 auto hclass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue, 2437 ConstantIndex::PROFILE_TYPE_INFO_CELL_0_CLASS_INDEX); 2438 GateRef size = GetObjectSizeFromHClass(hclass); 2439 SetParameters(glue, size); 2440 HeapAlloc(&result, &initialize, RegionSpaceFlag::IN_YOUNG_SPACE, hclass); 2441 Bind(&initialize); 2442 StoreHClassWithoutBarrier(glue, *result, hclass); 2443 SetValueToProfileTypeInfoCell(glue, *result, value); 2444 GateRef machineCodeOffset = IntPtr(ProfileTypeInfoCell::MACHINE_CODE_OFFSET); 2445 Store(VariableType::JS_POINTER(), glue, *result, machineCodeOffset, Hole()); 2446 GateRef handleOffset = IntPtr(ProfileTypeInfoCell::HANDLE_OFFSET); 2447 Store(VariableType::JS_POINTER(), glue, *result, handleOffset, Undefined()); 2448 2449 auto ret = *result; 2450 env->SubCfgExit(); 2451 return ret; 2452} 2453 2454GateRef NewObjectStubBuilder::GetElementSizeFromType(GateRef glue, GateRef type) 2455{ 2456 auto env = GetEnvironment(); 2457 Label entry(env); 2458 env->SubCfgEntry(&entry); 2459 2460 DEFVARIABLE(result, VariableType::INT32(), Int32(0)); 2461 Label defaultLabel(env); 2462 Label exit(env); 2463 Label labelBuffer[11] = { 2464 Label(env), Label(env), Label(env), Label(env), Label(env), Label(env), 2465 Label(env), Label(env), Label(env), Label(env), Label(env) }; 2466 int64_t valueBuffer[11] = { 2467 static_cast<int64_t>(JSType::JS_INT8_ARRAY), 2468 static_cast<int64_t>(JSType::JS_UINT8_ARRAY), 2469 static_cast<int64_t>(JSType::JS_UINT8_CLAMPED_ARRAY), 2470 static_cast<int64_t>(JSType::JS_INT16_ARRAY), 2471 static_cast<int64_t>(JSType::JS_UINT16_ARRAY), 2472 static_cast<int64_t>(JSType::JS_INT32_ARRAY), 2473 static_cast<int64_t>(JSType::JS_UINT32_ARRAY), 2474 static_cast<int64_t>(JSType::JS_FLOAT32_ARRAY), 2475 static_cast<int64_t>(JSType::JS_FLOAT64_ARRAY), 2476 static_cast<int64_t>(JSType::JS_BIGINT64_ARRAY), 2477 static_cast<int64_t>(JSType::JS_BIGUINT64_ARRAY) }; 2478 2479 // 11 : this switch has 11 case 2480 Switch(type, &defaultLabel, valueBuffer, labelBuffer, 11); 2481 // 0 : index of this buffer 2482 Bind(&labelBuffer[0]); 2483 { 2484 // 1 : the elementSize of this type is 1 2485 result = Int32(1); 2486 Jump(&exit); 2487 } 2488 // 1 : index of this buffer 2489 Bind(&labelBuffer[1]); 2490 { 2491 // 1 : the elementSize of this type is 1 2492 result = Int32(1); 2493 Jump(&exit); 2494 } 2495 // 2 : index of this buffer 2496 Bind(&labelBuffer[2]); 2497 { 2498 // 1 : the elementSize of this type is 1 2499 result = Int32(1); 2500 Jump(&exit); 2501 } 2502 // 3 : index of this buffer 2503 Bind(&labelBuffer[3]); 2504 { 2505 // 2 : the elementSize of this type is 2 2506 result = Int32(2); 2507 Jump(&exit); 2508 } 2509 // 4 : index of this buffer 2510 Bind(&labelBuffer[4]); 2511 { 2512 // 2 : the elementSize of this type is 2 2513 result = Int32(2); 2514 Jump(&exit); 2515 } 2516 // 5 : index of this buffer 2517 Bind(&labelBuffer[5]); 2518 { 2519 // 4 : the elementSize of this type is 4 2520 result = Int32(4); 2521 Jump(&exit); 2522 } 2523 // 6 : index of this buffer 2524 Bind(&labelBuffer[6]); 2525 { 2526 // 4 : the elementSize of this type is 4 2527 result = Int32(4); 2528 Jump(&exit); 2529 } 2530 // 7 : index of this buffer 2531 Bind(&labelBuffer[7]); 2532 { 2533 // 4 : the elementSize of this type is 4 2534 result = Int32(4); 2535 Jump(&exit); 2536 } 2537 // 8 : index of this buffer 2538 Bind(&labelBuffer[8]); 2539 { 2540 // 8 : the elementSize of this type is 8 2541 result = Int32(8); 2542 Jump(&exit); 2543 } 2544 // 9 : index of this buffer 2545 Bind(&labelBuffer[9]); 2546 { 2547 // 8 : the elementSize of this type is 8 2548 result = Int32(8); 2549 Jump(&exit); 2550 } 2551 // 10 : index of this buffer 2552 Bind(&labelBuffer[10]); 2553 { 2554 // 8 : the elementSize of this type is 8 2555 result = Int32(8); 2556 Jump(&exit); 2557 } 2558 Bind(&defaultLabel); 2559 { 2560 FatalPrint(glue, { Int32(GET_MESSAGE_STRING_ID(ThisBranchIsUnreachable)) }); 2561 Jump(&exit); 2562 } 2563 2564 Bind(&exit); 2565 auto ret = *result; 2566 env->SubCfgExit(); 2567 return ret; 2568} 2569 2570GateRef NewObjectStubBuilder::GetOnHeapHClassFromType(GateRef glue, GateRef type) 2571{ 2572 auto env = GetEnvironment(); 2573 Label entry(env); 2574 env->SubCfgEntry(&entry); 2575 2576 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined()); 2577 GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit())); 2578 GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset); 2579 Label defaultLabel(env); 2580 Label exit(env); 2581 Label labelBuffer[11] = { 2582 Label(env), Label(env), Label(env), Label(env), Label(env), Label(env), 2583 Label(env), Label(env), Label(env), Label(env), Label(env) }; 2584 int64_t valueBuffer[11] = { 2585 static_cast<int64_t>(JSType::JS_INT8_ARRAY), 2586 static_cast<int64_t>(JSType::JS_UINT8_ARRAY), 2587 static_cast<int64_t>(JSType::JS_UINT8_CLAMPED_ARRAY), 2588 static_cast<int64_t>(JSType::JS_INT16_ARRAY), 2589 static_cast<int64_t>(JSType::JS_UINT16_ARRAY), 2590 static_cast<int64_t>(JSType::JS_INT32_ARRAY), 2591 static_cast<int64_t>(JSType::JS_UINT32_ARRAY), 2592 static_cast<int64_t>(JSType::JS_FLOAT32_ARRAY), 2593 static_cast<int64_t>(JSType::JS_FLOAT64_ARRAY), 2594 static_cast<int64_t>(JSType::JS_BIGINT64_ARRAY), 2595 static_cast<int64_t>(JSType::JS_BIGUINT64_ARRAY) }; 2596 2597 // 11 : this switch has 11 case 2598 Switch(type, &defaultLabel, valueBuffer, labelBuffer, 11); 2599 // 0 : index of this buffer 2600 Bind(&labelBuffer[0]); 2601 { 2602 result = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, 2603 GlobalEnv::INT8_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX); 2604 Jump(&exit); 2605 } 2606 // 1 : index of this buffer 2607 Bind(&labelBuffer[1]); 2608 { 2609 result = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, 2610 GlobalEnv::UINT8_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX); 2611 Jump(&exit); 2612 } 2613 // 2 : index of this buffer 2614 Bind(&labelBuffer[2]); 2615 { 2616 result = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, 2617 GlobalEnv::UINT8_CLAMPED_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX); 2618 Jump(&exit); 2619 } 2620 // 3 : index of this buffer 2621 Bind(&labelBuffer[3]); 2622 { 2623 result = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, 2624 GlobalEnv::INT16_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX); 2625 Jump(&exit); 2626 } 2627 // 4 : index of this buffer 2628 Bind(&labelBuffer[4]); 2629 { 2630 result = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, 2631 GlobalEnv::UINT16_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX); 2632 Jump(&exit); 2633 } 2634 // 5 : index of this buffer 2635 Bind(&labelBuffer[5]); 2636 { 2637 result = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, 2638 GlobalEnv::INT32_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX); 2639 Jump(&exit); 2640 } 2641 // 6 : index of this buffer 2642 Bind(&labelBuffer[6]); 2643 { 2644 result = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, 2645 GlobalEnv::UINT32_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX); 2646 Jump(&exit); 2647 } 2648 // 7 : index of this buffer 2649 Bind(&labelBuffer[7]); 2650 { 2651 result = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, 2652 GlobalEnv::FLOAT32_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX); 2653 Jump(&exit); 2654 } 2655 // 8 : index of this buffer 2656 Bind(&labelBuffer[8]); 2657 { 2658 result = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, 2659 GlobalEnv::FLOAT64_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX); 2660 Jump(&exit); 2661 } 2662 // 9 : index of this buffer 2663 Bind(&labelBuffer[9]); 2664 { 2665 result = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, 2666 GlobalEnv::BIGINT64_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX); 2667 Jump(&exit); 2668 } 2669 // 10 : index of this buffer 2670 Bind(&labelBuffer[10]); 2671 { 2672 result = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, 2673 GlobalEnv::BIGUINT64_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX); 2674 Jump(&exit); 2675 } 2676 Bind(&defaultLabel); 2677 { 2678 FatalPrint(glue, { Int32(GET_MESSAGE_STRING_ID(ThisBranchIsUnreachable)) }); 2679 Jump(&exit); 2680 } 2681 2682 Bind(&exit); 2683 auto ret = *result; 2684 env->SubCfgExit(); 2685 return ret; 2686} 2687} // namespace panda::ecmascript::kungfu 2688