1/* 2 * Copyright (c) 2023 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/builtins/builtins_array_stub_builder.h" 17 18#include "ecmascript/builtins/builtins_string.h" 19#include "ecmascript/compiler/builtins/builtins_stubs.h" 20#include "ecmascript/compiler/call_stub_builder.h" 21#include "ecmascript/compiler/new_object_stub_builder.h" 22#include "ecmascript/compiler/profiler_operation.h" 23#include "ecmascript/compiler/rt_call_signature.h" 24#include "ecmascript/runtime_call_id.h" 25#include "ecmascript/js_iterator.h" 26#include "ecmascript/compiler/access_object_stub_builder.h" 27#include "ecmascript/base/array_helper.h" 28 29namespace panda::ecmascript::kungfu { 30 31void BuiltinsArrayStubBuilder::ElementsKindHclassCompare(GateRef glue, GateRef arrayCls, 32 Label *matchCls, Label *slowPath) 33{ 34 auto env = GetEnvironment(); 35 Label isGeneric(env); 36 GateRef elementsKind = GetElementsKindFromHClass(arrayCls); 37 GateRef notGeneric = NotEqual(elementsKind, Int32(static_cast<uint32_t>(ElementsKind::GENERIC))); 38 BRANCH(notGeneric, matchCls, &isGeneric); 39 Bind(&isGeneric); 40 { 41 GateRef intialHClass = GetGlobalConstantValue(VariableType::JS_ANY(), glue, 42 ConstantIndex::ELEMENT_HOLE_TAGGED_HCLASS_INDEX); 43 BRANCH(Equal(intialHClass, arrayCls), matchCls, slowPath); 44 } 45} 46 47void BuiltinsArrayStubBuilder::With(GateRef glue, GateRef thisValue, GateRef numArgs, 48 Variable *result, Label *exit, Label *slowPath) 49{ 50 auto env = GetEnvironment(); 51 DEFVARIABLE(relativeIndex, VariableType::INT64(), Int64(0)); 52 DEFVARIABLE(actualIndex, VariableType::INT64(), Int64(0)); 53 Label isHeapObject(env); 54 Label isJsArray(env); 55 Label isStableArray(env); 56 Label defaultConstr(env); 57 Label notCOWArray(env); 58 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath); 59 Bind(&isHeapObject); 60 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath); 61 Bind(&isJsArray); 62 BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr); 63 Bind(&defaultConstr); 64 BRANCH(IsStableJSArray(glue, thisValue), &isStableArray, slowPath); 65 Bind(&isStableArray); 66 BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray); 67 Bind(¬COWArray); 68 69 GateRef thisLen = ZExtInt32ToInt64(GetArrayLength(thisValue)); 70 GateRef index = GetCallArg0(numArgs); 71 Label taggedIsInt(env); 72 BRANCH(TaggedIsInt(index), &taggedIsInt, slowPath); 73 Bind(&taggedIsInt); 74 { 75 relativeIndex = GetInt64OfTInt(index); 76 DEFVARIABLE(value, VariableType::JS_ANY(), Hole()); 77 Label twoArg(env); 78 Label ifOneArg(env); 79 Label getIndex(env); 80 // 2 : means there are two args 81 BRANCH(Int64Equal(numArgs, IntPtr(2)), &twoArg, &ifOneArg); 82 Bind(&twoArg); 83 { 84 value = GetCallArg1(numArgs); 85 Jump(&getIndex); 86 } 87 Bind(&ifOneArg); 88 { 89 // 1 : means there are only one arg 90 BRANCH(Int64Equal(numArgs, IntPtr(1)), &getIndex, slowPath); 91 } 92 Bind(&getIndex); 93 { 94 Label indexGreaterOrEqualZero(env); 95 Label indexLessZero(env); 96 Label next(env); 97 Label notOutOfRange(env); 98 BRANCH(Int64GreaterThanOrEqual(*relativeIndex, Int64(0)), &indexGreaterOrEqualZero, &indexLessZero); 99 Bind(&indexGreaterOrEqualZero); 100 { 101 actualIndex = *relativeIndex; 102 Jump(&next); 103 } 104 Bind(&indexLessZero); 105 { 106 actualIndex = Int64Add(thisLen, *relativeIndex); 107 Jump(&next); 108 } 109 Bind(&next); 110 { 111 BRANCH(BitOr(Int64GreaterThanOrEqual(*actualIndex, thisLen), Int64LessThan(*actualIndex, Int64(0))), 112 slowPath, ¬OutOfRange); 113 Bind(¬OutOfRange); 114 { 115 GateRef newArray = NewArray(glue, Int32(0)); 116 GrowElementsCapacity(glue, newArray, TruncInt64ToInt32(thisLen)); 117 DEFVARIABLE(k, VariableType::INT64(), Int64(0)); 118 Label loopHead(env); 119 Label loopEnd(env); 120 Label loopExit(env); 121 Label loopNext(env); 122 Label replaceIndex(env); 123 Label notReplaceIndex(env); 124 Jump(&loopHead); 125 LoopBegin(&loopHead); 126 { 127 BRANCH(Int64LessThan(*k, thisLen), &loopNext, &loopExit); 128 Bind(&loopNext); 129 BRANCH(Int64Equal(*k, *actualIndex), &replaceIndex, ¬ReplaceIndex); 130 Bind(&replaceIndex); 131 { 132 SetValueWithElementsKind(glue, newArray, *value, *k, Boolean(true), 133 Int32(static_cast<uint32_t>(ElementsKind::NONE))); 134 Jump(&loopEnd); 135 } 136 Bind(¬ReplaceIndex); 137 { 138 GateRef ele = GetTaggedValueWithElementsKind(thisValue, *k); 139 Label eleIsHole(env); 140 Label eleNotHole(env); 141 BRANCH(TaggedIsHole(ele), &eleIsHole, &eleNotHole); 142 Bind(&eleIsHole); 143 { 144 SetValueWithElementsKind(glue, newArray, Undefined(), *k, Boolean(true), 145 Int32(static_cast<uint32_t>(ElementsKind::NONE))); 146 Jump(&loopEnd); 147 } 148 Bind(&eleNotHole); 149 { 150 SetValueWithElementsKind(glue, newArray, ele, *k, Boolean(true), 151 Int32(static_cast<uint32_t>(ElementsKind::NONE))); 152 Jump(&loopEnd); 153 } 154 } 155 } 156 Bind(&loopEnd); 157 k = Int64Add(*k, Int64(1)); 158 LoopEnd(&loopHead); 159 Bind(&loopExit); 160 SetArrayLength(glue, newArray, thisLen); 161 result->WriteVariable(newArray); 162 Jump(exit); 163 } 164 } 165 } 166 } 167} 168 169void BuiltinsArrayStubBuilder::Unshift(GateRef glue, GateRef thisValue, GateRef numArgs, 170 Variable *result, Label *exit, Label *slowPath) 171{ 172 auto env = GetEnvironment(); 173 Label isHeapObject(env); 174 Label isJsArray(env); 175 Label isStableJsArray(env); 176 Label notOverRange(env); 177 Label numNotEqualZero(env); 178 Label numLessThanOrEqualThree(env); 179 Label afterCopy(env); 180 Label grow(env); 181 Label setValue(env); 182 Label matchCls(env); 183 Label numEqual2(env); 184 Label numEqual3(env); 185 Label threeArgs(env); 186 Label final(env); 187 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath); 188 Bind(&isHeapObject); 189 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath); 190 Bind(&isJsArray); 191 BRANCH(IsStableJSArray(glue, thisValue), &isStableJsArray, slowPath); 192 Bind(&isStableJsArray); 193 GateRef arrayCls = LoadHClass(thisValue); 194 ElementsKindHclassCompare(glue, arrayCls, &matchCls, slowPath); 195 Bind(&matchCls); 196 BRANCH(Int64GreaterThan(numArgs, IntPtr(0)), &numNotEqualZero, slowPath); 197 Bind(&numNotEqualZero); 198 GateRef thisLen = ZExtInt32ToInt64(GetArrayLength(thisValue)); 199 GateRef argLen = ZExtInt32ToInt64(ChangeIntPtrToInt32(numArgs)); 200 GateRef newLen = Int64Add(thisLen, argLen); 201 BRANCH(Int64GreaterThan(newLen, Int64(base::MAX_SAFE_INTEGER)), slowPath, ¬OverRange); 202 Bind(¬OverRange); 203 // 3 : max param num 204 BRANCH(Int64LessThanOrEqual(numArgs, IntPtr(3)), &numLessThanOrEqualThree, slowPath); 205 Bind(&numLessThanOrEqualThree); 206 GateRef capacity = ZExtInt32ToInt64(GetLengthOfTaggedArray(GetElementsArray(thisValue))); 207 BRANCH(Int64GreaterThan(newLen, capacity), &grow, &setValue); 208 Bind(&grow); 209 { 210 GrowElementsCapacity(glue, thisValue, TruncInt64ToInt32(newLen)); 211 Jump(&setValue); 212 } 213 Bind(&setValue); 214 { 215 Label elementsKindEnabled(env); 216 GateRef elements = GetElementsArray(thisValue); 217 GateRef arrayStart = GetDataPtrInTaggedArray(elements); 218 GateRef moveTo = PtrAdd(arrayStart, PtrMul(numArgs, IntPtr(JSTaggedValue::TaggedTypeSize()))); 219 GateRef isElementsKindEnabled = IsEnableElementsKind(glue); 220 Label isIntOrNumber(env); 221 Label isTagged(env); 222 BRANCH_NO_WEIGHT(isElementsKindEnabled, &elementsKindEnabled, &isTagged); 223 Bind(&elementsKindEnabled); 224 { 225 GateRef kind = GetElementsKindFromHClass(LoadHClass(thisValue)); 226 GateRef isInt = LogicAndBuilder(env) 227 .And(Int32GreaterThanOrEqual(kind, Int32(static_cast<int32_t>(ElementsKind::INT)))) 228 .And(Int32LessThanOrEqual(kind, Int32(static_cast<int32_t>(ElementsKind::HOLE_INT)))) 229 .Done(); 230 GateRef isNumber = LogicAndBuilder(env) 231 .And(Int32GreaterThanOrEqual(kind, Int32(static_cast<int32_t>(ElementsKind::NUMBER)))) 232 .And(Int32LessThanOrEqual(kind, Int32(static_cast<int32_t>(ElementsKind::HOLE_NUMBER)))) 233 .Done(); 234 GateRef isIntOrNumberKind = LogicOrBuilder(env).Or(isInt).Or(isNumber).Done(); 235 BRANCH_NO_WEIGHT(isIntOrNumberKind, &isIntOrNumber, &isTagged); 236 Bind(&isIntOrNumber); 237 { 238 ArrayCopy<MustOverlap>(glue, arrayStart, moveTo, TruncInt64ToInt32(thisLen), 239 MemoryAttribute::NoBarrier()); 240 Jump(&afterCopy); 241 } 242 Bind(&isTagged); 243 { 244 ArrayCopy<MustOverlap>(glue, arrayStart, moveTo, TruncInt64ToInt32(thisLen)); 245 Jump(&afterCopy); 246 } 247 Bind(&afterCopy); 248 { 249 GateRef value0 = GetCallArg0(numArgs); 250 // 0 : the first Element position 251 SetValueWithElementsKind(glue, thisValue, value0, Int64(0), Boolean(false), 252 Int32(static_cast<uint32_t>(ElementsKind::NONE))); 253 // 2 : the second param 254 BRANCH(Int64GreaterThanOrEqual(numArgs, IntPtr(2)), &numEqual2, &numEqual3); 255 Bind(&numEqual2); 256 { 257 GateRef value1 = GetCallArg1(numArgs); 258 // 1 : the second Element position 259 SetValueWithElementsKind(glue, thisValue, value1, Int64(1), Boolean(false), 260 Int32(static_cast<uint32_t>(ElementsKind::NONE))); 261 Jump(&numEqual3); 262 } 263 Bind(&numEqual3); 264 { 265 // 3 : the third param 266 BRANCH(Int64Equal(numArgs, IntPtr(3)), &threeArgs, &final); 267 Bind(&threeArgs); 268 GateRef value2 = GetCallArg2(numArgs); 269 // 2 : the third Element position 270 SetValueWithElementsKind(glue, thisValue, value2, Int64(2), Boolean(false), 271 Int32(static_cast<uint32_t>(ElementsKind::NONE))); 272 Jump(&final); 273 } 274 Bind(&final); 275 { 276 SetArrayLength(glue, thisValue, newLen); 277 result->WriteVariable(IntToTaggedPtr(newLen)); 278 Jump(exit); 279 } 280 } 281 } 282 } 283} 284 285void BuiltinsArrayStubBuilder::Shift(GateRef glue, GateRef thisValue, 286 [[maybe_unused]] GateRef numArgs, Variable *result, Label *exit, Label *slowPath) 287{ 288 auto env = GetEnvironment(); 289 Label isHeapObject(env); 290 Label stableJSArray(env); 291 Label isDefaultConstructor(env); 292 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath); 293 Bind(&isHeapObject); 294 BRANCH(HasConstructor(thisValue), slowPath, &isDefaultConstructor); 295 Bind(&isDefaultConstructor); 296 BRANCH(IsStableJSArray(glue, thisValue), &stableJSArray, slowPath); 297 Bind(&stableJSArray); 298 { 299 Label isLengthWritable(env); 300 BRANCH(IsArrayLengthWritable(glue, thisValue), &isLengthWritable, slowPath); 301 Bind(&isLengthWritable); 302 { 303 GateRef thisLen = ZExtInt32ToInt64(GetArrayLength(thisValue)); 304 Label lengthNotZero(env); 305 BRANCH(Int64Equal(thisLen, Int64(0)), exit, &lengthNotZero); 306 Bind(&lengthNotZero); 307 { 308 Label isJsCOWArray(env); 309 Label getElements(env); 310 BRANCH(IsJsCOWArray(thisValue), &isJsCOWArray, &getElements); 311 Bind(&isJsCOWArray); 312 { 313 CallRuntime(glue, RTSTUB_ID(CheckAndCopyArray), { thisValue }); 314 Jump(&getElements); 315 } 316 Bind(&getElements); 317 { 318 GateRef elements = GetElementsArray(thisValue); 319 GateRef capacity = ZExtInt32ToInt64(GetLengthOfTaggedArray(elements)); 320 GateRef index = Int64Sub(thisLen, Int64(1)); 321 DEFVARIABLE(element, VariableType::JS_ANY(), Hole()); 322 element = GetTaggedValueWithElementsKind(thisValue, Int64(0)); 323 Label hasException0(env); 324 Label taggedHole(env); 325 Label copyArray(env); 326 BRANCH(TaggedIsHole(*element), &taggedHole, ©Array); 327 Bind(&taggedHole); 328 { 329 element = FastGetPropertyByIndex(glue, thisValue, Int32(0), ProfileOperation()); 330 BRANCH(HasPendingException(glue), &hasException0, ©Array); 331 Bind(&hasException0); 332 { 333 result->WriteVariable(Exception()); 334 Jump(exit); 335 } 336 } 337 Bind(©Array); 338 { 339 DEFVARIABLE(fromKey, VariableType::INT64(), Int64(1)); 340 DEFVARIABLE(toKey, VariableType::INT64(), Int64Sub(*fromKey, Int64(1))); 341 Label loopHead(env); 342 Label loopNext(env); 343 Label loopEnd(env); 344 Label loopExit(env); 345 Jump(&loopHead); 346 LoopBegin(&loopHead); 347 { 348 BRANCH(Int64LessThan(*fromKey, thisLen), &loopNext, &loopExit); 349 Bind(&loopNext); 350 { 351 GateRef ele = GetTaggedValueWithElementsKind(thisValue, *fromKey); 352 SetValueWithElementsKind(glue, thisValue, ele, *toKey, Boolean(false), 353 Int32(static_cast<uint32_t>(ElementsKind::NONE))); 354 Jump(&loopEnd); 355 } 356 } 357 Bind(&loopEnd); 358 fromKey = Int64Add(*fromKey, Int64(1)); 359 toKey = Int64Add(*toKey, Int64(1)); 360 LoopEnd(&loopHead); 361 Bind(&loopExit); 362 { 363 Label noTrim(env); 364 Label needTrim(env); 365 Label setNewLen(env); 366 GateRef unused = Int64Sub(capacity, index); 367 BRANCH(Int64GreaterThan(unused, Int64(TaggedArray::MAX_END_UNUSED)), &needTrim, &noTrim); 368 Bind(&needTrim); 369 { 370 CallNGCRuntime(glue, RTSTUB_ID(ArrayTrim), {glue, elements, index}); 371 Jump(&setNewLen); 372 } 373 Bind(&noTrim); 374 { 375 SetValueWithElementsKind(glue, thisValue, Hole(), index, Boolean(false), 376 Int32(static_cast<uint32_t>(ElementsKind::NONE))); 377 Jump(&setNewLen); 378 } 379 Bind(&setNewLen); 380 { 381 GateRef lengthOffset = IntPtr(JSArray::LENGTH_OFFSET); 382 Store(VariableType::INT32(), glue, thisValue, lengthOffset, index); 383 384 Label isNotHole(env); 385 BRANCH(TaggedIsHole(*element), exit, &isNotHole); 386 Bind(&isNotHole); 387 { 388 result->WriteVariable(*element); 389 Jump(exit); 390 } 391 } 392 } 393 } 394 } 395 } 396 } 397 } 398} 399 400void BuiltinsArrayStubBuilder::Concat(GateRef glue, GateRef thisValue, GateRef numArgs, 401 Variable *result, Label *exit, Label *slowPath) 402{ 403 auto env = GetEnvironment(); 404 Label isHeapObject(env); 405 Label isJsArray(env); 406 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath); 407 Bind(&isHeapObject); 408 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath); 409 Bind(&isJsArray); 410 { 411 Label isExtensible(env); 412 BRANCH(HasConstructor(thisValue), slowPath, &isExtensible); 413 Bind(&isExtensible); 414 { 415 Label numArgsOne(env); 416 BRANCH(Int64Equal(numArgs, IntPtr(1)), &numArgsOne, slowPath); 417 Bind(&numArgsOne); 418 { 419 GateRef arg0 = GetCallArg0(numArgs); 420 Label allStableJsArray(env); 421 GateRef isAllStableJsArray = LogicAndBuilder(env).And(IsStableJSArray(glue, thisValue)) 422 .And(IsStableJSArray(glue, arg0)).Done(); 423 BRANCH(isAllStableJsArray, &allStableJsArray, slowPath); 424 Bind(&allStableJsArray); 425 { 426 GateRef maxArrayIndex = Int64(TaggedArray::MAX_ARRAY_INDEX); 427 GateRef thisLen = ZExtInt32ToInt64(GetArrayLength(thisValue)); 428 GateRef argLen = ZExtInt32ToInt64(GetArrayLength(arg0)); 429 GateRef sumArrayLen = Int64Add(argLen, thisLen); 430 Label isEmptyArray(env); 431 Label notEmptyArray(env); 432 BRANCH(Int64Equal(sumArrayLen, Int64(0)), &isEmptyArray, ¬EmptyArray); 433 Bind(&isEmptyArray); 434 { 435 NewObjectStubBuilder newBuilder(this); 436 result->WriteVariable(newBuilder.CreateEmptyArray(glue)); 437 Jump(exit); 438 } 439 Bind(¬EmptyArray); 440 Label notOverFlow(env); 441 BRANCH(Int64GreaterThan(sumArrayLen, maxArrayIndex), slowPath, ¬OverFlow); 442 Bind(¬OverFlow); 443 { 444 Label spreadable(env); 445 GateRef isAllConcatSpreadable = LogicAndBuilder(env).And(IsConcatSpreadable(glue, thisValue)) 446 .And(IsConcatSpreadable(glue, arg0)).Done(); 447 BRANCH(isAllConcatSpreadable, &spreadable, slowPath); 448 Bind(&spreadable); 449 { 450 Label setProperties(env); 451 GateRef glueGlobalEnvOffset = 452 IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit())); 453 GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset); 454 auto arrayFunc = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, 455 GlobalEnv::ARRAY_FUNCTION_INDEX); 456 GateRef intialHClass = Load(VariableType::JS_ANY(), arrayFunc, 457 IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET)); 458 NewObjectStubBuilder newBuilder(this); 459 newBuilder.SetParameters(glue, 0); 460 GateRef newArray = newBuilder.NewJSArrayWithSize(intialHClass, sumArrayLen); 461 BRANCH(TaggedIsException(newArray), exit, &setProperties); 462 Bind(&setProperties); 463 { 464 GateRef lengthOffset = IntPtr(JSArray::LENGTH_OFFSET); 465 Store(VariableType::INT32(), glue, newArray, lengthOffset, 466 TruncInt64ToInt32(sumArrayLen)); 467 GateRef accessor = GetGlobalConstantValue(VariableType::JS_ANY(), glue, 468 ConstantIndex::ARRAY_LENGTH_ACCESSOR); 469 SetPropertyInlinedProps(glue, newArray, intialHClass, accessor, 470 Int32(JSArray::LENGTH_INLINE_PROPERTY_INDEX)); 471 SetExtensibleToBitfield(glue, newArray, true); 472 DEFVARIABLE(i, VariableType::INT64(), Int64(0)); 473 DEFVARIABLE(j, VariableType::INT64(), Int64(0)); 474 DEFVARIABLE(k, VariableType::INT64(), Int64(0)); 475 Label loopHead(env); 476 Label loopEnd(env); 477 Label next(env); 478 Label loopExit(env); 479 Jump(&loopHead); 480 LoopBegin(&loopHead); 481 { 482 BRANCH(Int64LessThan(*i, thisLen), &next, &loopExit); 483 Bind(&next); 484 GateRef ele = GetTaggedValueWithElementsKind(thisValue, *i); 485 #if ECMASCRIPT_ENABLE_ELEMENTSKIND_ALWAY_GENERIC 486 SetValueWithElementsKind(glue, newArray, ele, *j, Boolean(true), 487 Int32(static_cast<uint32_t>(ElementsKind::GENERIC))); 488 #else 489 SetValueWithElementsKind(glue, newArray, ele, *j, Boolean(true), 490 Int32(static_cast<uint32_t>(ElementsKind::NONE))); 491 #endif 492 Jump(&loopEnd); 493 } 494 Bind(&loopEnd); 495 i = Int64Add(*i, Int64(1)); 496 j = Int64Add(*j, Int64(1)); 497 LoopEnd(&loopHead, env, glue); 498 Bind(&loopExit); 499 Label loopHead1(env); 500 Label loopEnd1(env); 501 Label next1(env); 502 Label loopExit1(env); 503 Jump(&loopHead1); 504 LoopBegin(&loopHead1); 505 { 506 BRANCH(Int64LessThan(*k, argLen), &next1, &loopExit1); 507 Bind(&next1); 508 GateRef ele = GetTaggedValueWithElementsKind(arg0, *k); 509 #if ECMASCRIPT_ENABLE_ELEMENTSKIND_ALWAY_GENERIC 510 SetValueWithElementsKind(glue, newArray, ele, *j, Boolean(true), 511 Int32(static_cast<uint32_t>(ElementsKind::GENERIC))); 512 #else 513 SetValueWithElementsKind(glue, newArray, ele, *j, Boolean(true), 514 Int32(static_cast<uint32_t>(ElementsKind::NONE))); 515 #endif 516 Jump(&loopEnd1); 517 } 518 Bind(&loopEnd1); 519 k = Int64Add(*k, Int64(1)); 520 j = Int64Add(*j, Int64(1)); 521 LoopEnd(&loopHead1); 522 Bind(&loopExit1); 523 result->WriteVariable(newArray); 524 Jump(exit); 525 } 526 } 527 } 528 } 529 } 530 } 531 } 532} 533 534void BuiltinsArrayStubBuilder::Filter(GateRef glue, GateRef thisValue, GateRef numArgs, 535 Variable *result, Label *exit, Label *slowPath) 536{ 537 auto env = GetEnvironment(); 538 Label isHeapObject(env); 539 Label isJsArray(env); 540 Label defaultConstr(env); 541 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath); 542 Bind(&isHeapObject); 543 GateRef thisValueAndProtoIsJSArray = LogicAndBuilder(env).And(IsJsArray(thisValue)) 544 .And(IsJsArray(StubBuilder::GetPrototype(glue, thisValue))).Done(); 545 BRANCH(thisValueAndProtoIsJSArray, &isJsArray, slowPath); 546 Bind(&isJsArray); 547 BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr); 548 Bind(&defaultConstr); 549 550 GateRef callbackFnHandle = GetCallArg0(numArgs); 551 Label argOHeapObject(env); 552 Label callable(env); 553 Label notOverFlow(env); 554 BRANCH(TaggedIsHeapObject(callbackFnHandle), &argOHeapObject, slowPath); 555 Bind(&argOHeapObject); 556 BRANCH(IsCallable(callbackFnHandle), &callable, slowPath); 557 Bind(&callable); 558 GateRef len = ZExtInt32ToInt64(GetArrayLength(thisValue)); 559 Label isEmptyArray(env); 560 Label notEmptyArray(env); 561 BRANCH(Int64Equal(len, Int64(0)), &isEmptyArray, ¬EmptyArray); 562 Bind(&isEmptyArray); 563 { 564 NewObjectStubBuilder newBuilder(this); 565 result->WriteVariable(newBuilder.CreateEmptyArray(glue)); 566 Jump(exit); 567 } 568 Bind(¬EmptyArray); 569 BRANCH(Int64GreaterThan(len, Int64(JSObject::MAX_GAP)), slowPath, ¬OverFlow); 570 Bind(¬OverFlow); 571 572 GateRef argHandle = GetCallArg1(numArgs); 573 GateRef newArray = NewArray(glue, len); 574 GateRef lengthOffset = IntPtr(JSArray::LENGTH_OFFSET); 575 GateRef newArrayEles = GetElementsArray(newArray); 576 Label stableJSArray(env); 577 Label notStableJSArray(env); 578 DEFVARIABLE(i, VariableType::INT64(), Int64(0)); 579 DEFVARIABLE(toIndex, VariableType::INT64(), Int64(0)); 580 BRANCH(IsStableJSArray(glue, thisValue), &stableJSArray, slowPath); 581 Bind(&stableJSArray); 582 { 583 DEFVARIABLE(thisArrLenVar, VariableType::INT64(), len); 584 DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole()); 585 Label loopHead(env); 586 Label loopEnd(env); 587 Label next(env); 588 Label loopExit(env); 589 Jump(&loopHead); 590 LoopBegin(&loopHead); 591 { 592 BRANCH(Int64LessThan(*i, *thisArrLenVar), &next, &loopExit); 593 Bind(&next); 594 kValue = GetTaggedValueWithElementsKind(thisValue, *i); 595 Label kValueIsHole(env); 596 Label kValueNotHole(env); 597 Label arrayValueIsHole(env); 598 Label arrayValueNotHole(env); 599 Label hasProperty(env); 600 BRANCH(TaggedIsHole(*kValue), &arrayValueIsHole, &arrayValueNotHole); 601 Bind(&arrayValueIsHole); 602 { 603 GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*i) }); 604 BRANCH(TaggedIsTrue(hasProp), &hasProperty, &arrayValueNotHole); 605 Bind(&hasProperty); 606 Label hasException0(env); 607 Label notHasException0(env); 608 kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation()); 609 BRANCH(HasPendingException(glue), &hasException0, ¬HasException0); 610 Bind(&hasException0); 611 { 612 result->WriteVariable(Exception()); 613 Jump(exit); 614 } 615 Bind(¬HasException0); 616 { 617 Jump(&arrayValueNotHole); 618 } 619 } 620 Bind(&arrayValueNotHole); 621 BRANCH(TaggedIsHole(*kValue), &kValueIsHole, &kValueNotHole); 622 Bind(&kValueNotHole); 623 { 624 GateRef key = Int64ToTaggedInt(*i); 625 Label checkArray(env); 626 JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN); 627 callArgs.callThisArg3WithReturnArgs = { argHandle, *kValue, key, thisValue }; 628 CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr, 629 Circuit::NullGate(), callArgs); 630 GateRef retValue = callBuilder.JSCallDispatch(); 631 Label find(env); 632 Label hasException1(env); 633 Label notHasException1(env); 634 BRANCH(HasPendingException(glue), &hasException1, ¬HasException1); 635 Bind(&hasException1); 636 { 637 result->WriteVariable(Exception()); 638 Jump(exit); 639 } 640 Bind(¬HasException1); 641 BRANCH(TaggedIsTrue(FastToBoolean(retValue)), &find, &checkArray); 642 Bind(&find); 643 { 644 SetValueWithElementsKind(glue, newArray, *kValue, *toIndex, Boolean(true), 645 Int32(static_cast<uint32_t>(ElementsKind::NONE))); 646 toIndex = Int64Add(*toIndex, Int64(1)); 647 Jump(&checkArray); 648 } 649 Bind(&checkArray); 650 { 651 Label lenChange(env); 652 GateRef tmpArrLen = ZExtInt32ToInt64(GetArrayLength(thisValue)); 653 BRANCH(Int64LessThan(tmpArrLen, *thisArrLenVar), &lenChange, &kValueIsHole); 654 Bind(&lenChange); 655 { 656 thisArrLenVar = tmpArrLen; 657 Jump(&kValueIsHole); 658 } 659 } 660 } 661 Bind(&kValueIsHole); 662 i = Int64Add(*i, Int64(1)); 663 BRANCH(IsStableJSArray(glue, thisValue), &loopEnd, ¬StableJSArray); 664 } 665 Bind(&loopEnd); 666 LoopEnd(&loopHead, env, glue); 667 Bind(&loopExit); 668 Jump(¬StableJSArray); 669 } 670 Bind(¬StableJSArray); 671 { 672 Label finish(env); 673 Label callRT(env); 674 BRANCH(Int32LessThan(*i, len), &callRT, &finish); 675 Bind(&callRT); 676 { 677 CallNGCRuntime(glue, RTSTUB_ID(ArrayTrim), {glue, newArrayEles, *toIndex}); 678 Store(VariableType::INT32(), glue, newArray, lengthOffset, TruncInt64ToInt32(*toIndex)); 679 GateRef ret = CallRuntime(glue, RTSTUB_ID(JSArrayFilterUnStable), { argHandle, thisValue, 680 IntToTaggedInt(*i), IntToTaggedInt(len), IntToTaggedInt(*toIndex), newArray, callbackFnHandle }); 681 result->WriteVariable(ret); 682 Jump(exit); 683 } 684 Bind(&finish); 685 { 686 result->WriteVariable(newArray); 687 Label needTrim(env); 688 BRANCH(Int64LessThan(*toIndex, len), &needTrim, exit); 689 Bind(&needTrim); 690 CallNGCRuntime(glue, RTSTUB_ID(ArrayTrim), {glue, newArrayEles, *toIndex}); 691 Store(VariableType::INT32(), glue, newArray, lengthOffset, TruncInt64ToInt32(*toIndex)); 692 Jump(exit); 693 } 694 } 695} 696 697void BuiltinsArrayStubBuilder::Map(GateRef glue, GateRef thisValue, GateRef numArgs, 698 Variable *result, Label *exit, Label *slowPath) 699{ 700 auto env = GetEnvironment(); 701 Label isHeapObject(env); 702 Label isJsArray(env); 703 Label defaultConstr(env); 704 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath); 705 Bind(&isHeapObject); 706 GateRef thisValueAndProtoIsJSArray = LogicAndBuilder(env).And(IsJsArray(thisValue)) 707 .And(IsJsArray(StubBuilder::GetPrototype(glue, thisValue))).Done(); 708 BRANCH(thisValueAndProtoIsJSArray, &isJsArray, slowPath); 709 Bind(&isJsArray); 710 BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr); 711 Bind(&defaultConstr); 712 713 GateRef callbackFnHandle = GetCallArg0(numArgs); 714 Label argOHeapObject(env); 715 Label callable(env); 716 Label notOverFlow(env); 717 BRANCH(TaggedIsHeapObject(callbackFnHandle), &argOHeapObject, slowPath); 718 Bind(&argOHeapObject); 719 BRANCH(IsCallable(callbackFnHandle), &callable, slowPath); 720 Bind(&callable); 721 GateRef len = ZExtInt32ToInt64(GetArrayLength(thisValue)); 722 Label isEmptyArray(env); 723 Label notEmptyArray(env); 724 BRANCH(Int64Equal(len, Int64(0)), &isEmptyArray, ¬EmptyArray); 725 Bind(&isEmptyArray); 726 { 727 NewObjectStubBuilder newBuilder(this); 728 result->WriteVariable(newBuilder.CreateEmptyArray(glue)); 729 Jump(exit); 730 } 731 Bind(¬EmptyArray); 732 BRANCH(Int64GreaterThan(len, Int64(JSObject::MAX_GAP)), slowPath, ¬OverFlow); 733 Bind(¬OverFlow); 734 735 GateRef argHandle = GetCallArg1(numArgs); 736 GateRef newArray = NewArray(glue, len); 737 Label stableJSArray(env); 738 Label notStableJSArray(env); 739 DEFVARIABLE(i, VariableType::INT64(), Int64(0)); 740 BRANCH(IsStableJSArray(glue, thisValue), &stableJSArray, slowPath); 741 Bind(&stableJSArray); 742 { 743 DEFVARIABLE(thisArrLenVar, VariableType::INT64(), len); 744 DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole()); 745 Label loopHead(env); 746 Label loopEnd(env); 747 Label next(env); 748 Label loopExit(env); 749 Jump(&loopHead); 750 LoopBegin(&loopHead); 751 { 752 BRANCH(Int64LessThan(*i, *thisArrLenVar), &next, &loopExit); 753 Bind(&next); 754 kValue = GetTaggedValueWithElementsKind(thisValue, *i); 755 Label kValueIsHole(env); 756 Label kValueNotHole(env); 757 Label arrayValueIsHole(env); 758 Label arrayValueNotHole(env); 759 Label hasProperty(env); 760 BRANCH(TaggedIsHole(*kValue), &arrayValueIsHole, &arrayValueNotHole); 761 Bind(&arrayValueIsHole); 762 { 763 GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*i) }); 764 BRANCH(TaggedIsTrue(hasProp), &hasProperty, &arrayValueNotHole); 765 Bind(&hasProperty); 766 Label hasException0(env); 767 Label notHasException0(env); 768 kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation()); 769 BRANCH(HasPendingException(glue), &hasException0, ¬HasException0); 770 Bind(&hasException0); 771 { 772 result->WriteVariable(Exception()); 773 Jump(exit); 774 } 775 Bind(¬HasException0); 776 { 777 Jump(&arrayValueNotHole); 778 } 779 } 780 Bind(&arrayValueNotHole); 781 BRANCH(TaggedIsHole(*kValue), &kValueIsHole, &kValueNotHole); 782 Bind(&kValueNotHole); 783 { 784 GateRef key = Int64ToTaggedInt(*i); 785 Label checkArray(env); 786 JSCallArgs callArgs = (JSCallMode::CALL_THIS_ARG3_WITH_RETURN); 787 callArgs.callThisArg3WithReturnArgs = {argHandle, *kValue, key, thisValue}; 788 CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr, 789 Circuit::NullGate(), callArgs); 790 GateRef retValue = callBuilder.JSCallDispatch(); 791 Label hasException1(env); 792 Label notHasException1(env); 793 BRANCH(HasPendingException(glue), &hasException1, ¬HasException1); 794 Bind(&hasException1); 795 { 796 result->WriteVariable(Exception()); 797 Jump(exit); 798 } 799 Bind(¬HasException1); 800 SetValueWithElementsKind(glue, newArray, retValue, *i, Boolean(true), 801 Int32(static_cast<uint32_t>(ElementsKind::NONE))); 802 Label lenChange(env); 803 GateRef tmpArrLen = ZExtInt32ToInt64(GetArrayLength(thisValue)); 804 BRANCH(Int64LessThan(tmpArrLen, *thisArrLenVar), &lenChange, &kValueIsHole); 805 Bind(&lenChange); 806 { 807 thisArrLenVar = tmpArrLen; 808 Jump(&kValueIsHole); 809 } 810 } 811 Bind(&kValueIsHole); 812 i = Int64Add(*i, Int64(1)); 813 BRANCH(IsStableJSArray(glue, thisValue), &loopEnd, ¬StableJSArray); 814 } 815 Bind(&loopEnd); 816 LoopEnd(&loopHead); 817 Bind(&loopExit); 818 Jump(¬StableJSArray); 819 } 820 Bind(¬StableJSArray); 821 { 822 GateRef ret = CallRuntime(glue, RTSTUB_ID(JSArrayMapUnStable), { argHandle, thisValue, 823 IntToTaggedInt(*i), IntToTaggedInt(len), newArray, callbackFnHandle }); 824 result->WriteVariable(ret); 825 Jump(exit); 826 } 827} 828 829// Note: unused arguments are reserved for further development 830void BuiltinsArrayStubBuilder::ForEach([[maybe_unused]] GateRef glue, GateRef thisValue, GateRef numArgs, 831 [[maybe_unused]] Variable *result, Label *exit, Label *slowPath) 832{ 833 auto env = GetEnvironment(); 834 Label thisExists(env); 835 Label matchCls(env); 836 Label isHeapObject(env); 837 Label isGeneric(env); 838 Label isJsArray(env); 839 Label defaultConstr(env); 840 Label isStability(env); 841 Label notCOWArray(env); 842 Label equalCls(env); 843 BRANCH(TaggedIsUndefinedOrNull(thisValue), slowPath, &thisExists); 844 Bind(&thisExists); 845 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath); 846 Bind(&isHeapObject); 847 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath); 848 Bind(&isJsArray); 849 BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr); 850 Bind(&defaultConstr); 851 BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath); 852 Bind(&isStability); 853 BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray); 854 Bind(¬COWArray); 855 GateRef arrayCls = LoadHClass(thisValue); 856 ElementsKindHclassCompare(glue, arrayCls, &matchCls, slowPath); 857 Bind(&matchCls); 858 Label arg0HeapObject(env); 859 Label callable(env); 860 Label thisIsStable(env); 861 Label thisNotStable(env); 862 GateRef callbackFnHandle = GetCallArg0(numArgs); 863 BRANCH(TaggedIsHeapObject(callbackFnHandle), &arg0HeapObject, slowPath); 864 Bind(&arg0HeapObject); 865 BRANCH(IsCallable(callbackFnHandle), &callable, slowPath); 866 Bind(&callable); 867 GateRef argHandle = GetCallArg1(numArgs); 868 869 DEFVARIABLE(i, VariableType::INT64(), Int64(0)); 870 DEFVARIABLE(thisLen, VariableType::INT32(), Int32(0)); 871 thisLen = GetArrayLength(thisValue); 872 Jump(&thisIsStable); 873 874 Bind(&thisIsStable); 875 { 876 DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole()); 877 Label loopHead(env); 878 Label loopEnd(env); 879 Label next(env); 880 Label loopExit(env); 881 Jump(&loopHead); 882 LoopBegin(&loopHead); 883 { 884 Label nextStep(env); 885 Label kValueIsHole(env); 886 Label callDispatch(env); 887 Label hasProperty(env); 888 Label hasException0(env); 889 Label hasException1(env); 890 GateRef newLen = GetArrayLength(thisValue); 891 BRANCH(BitAnd(IsStableJSArray(glue, thisValue), Int32Equal(*thisLen, newLen)), 892 &nextStep, &thisNotStable); 893 Bind(&nextStep); 894 BRANCH(Int64GreaterThanOrEqual(*i, ZExtInt32ToInt64(*thisLen)), &loopExit, &next); 895 Bind(&next); 896 kValue = GetTaggedValueWithElementsKind(thisValue, *i); 897 BRANCH(TaggedIsHole(*kValue), &kValueIsHole, &callDispatch); 898 Bind(&kValueIsHole); 899 { 900 GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*i) }); 901 BRANCH(TaggedIsTrue(hasProp), &hasProperty, &loopEnd); 902 Bind(&hasProperty); 903 kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation()); 904 BRANCH(HasPendingException(glue), &hasException0, &callDispatch); 905 Bind(&hasException0); 906 { 907 result->WriteVariable(Exception()); 908 Jump(exit); 909 } 910 } 911 Bind(&callDispatch); 912 { 913 GateRef key = Int64ToTaggedInt(*i); 914 JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN); 915 callArgs.callThisArg3WithReturnArgs = { argHandle, *kValue, key, thisValue }; 916 CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr, 917 Circuit::NullGate(), callArgs); 918 callBuilder.JSCallDispatch(); 919 BRANCH(HasPendingException(glue), &hasException1, &loopEnd); 920 Bind(&hasException1); 921 { 922 result->WriteVariable(Exception()); 923 Jump(exit); 924 } 925 } 926 } 927 Bind(&loopEnd); 928 i = Int64Add(*i, Int64(1)); 929 LoopEnd(&loopHead); 930 Bind(&loopExit); 931 Jump(exit); 932 } 933 934 Bind(&thisNotStable); 935 { 936 DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole()); 937 Label loopHead(env); 938 Label loopEnd(env); 939 Label next(env); 940 Label loopExit(env); 941 Jump(&loopHead); 942 LoopBegin(&loopHead); 943 { 944 Label hasProperty(env); 945 Label hasException0(env); 946 Label notHasException0(env); 947 Label hasException1(env); 948 BRANCH(Int64GreaterThanOrEqual(*i, ZExtInt32ToInt64(*thisLen)), &loopExit, &next); 949 Bind(&next); 950 GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*i) }); 951 BRANCH(TaggedIsTrue(hasProp), &hasProperty, &loopEnd); 952 Bind(&hasProperty); 953 kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation()); 954 BRANCH(HasPendingException(glue), &hasException0, ¬HasException0); 955 Bind(&hasException0); 956 { 957 result->WriteVariable(Exception()); 958 Jump(exit); 959 } 960 Bind(¬HasException0); 961 { 962 GateRef key = Int64ToTaggedInt(*i); 963 JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN); 964 callArgs.callThisArg3WithReturnArgs = { argHandle, *kValue, key, thisValue }; 965 CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr, 966 Circuit::NullGate(), callArgs); 967 callBuilder.JSCallDispatch(); 968 BRANCH(HasPendingException(glue), &hasException1, &loopEnd); 969 Bind(&hasException1); 970 { 971 result->WriteVariable(Exception()); 972 Jump(exit); 973 } 974 } 975 } 976 Bind(&loopEnd); 977 i = Int64Add(*i, Int64(1)); 978 LoopEnd(&loopHead); 979 Bind(&loopExit); 980 Jump(exit); 981 } 982} 983 984// Note: unused arguments are reserved for further development 985void BuiltinsArrayStubBuilder::IndexOf([[maybe_unused]] GateRef glue, GateRef thisValue, GateRef numArgs, 986 Variable *result, Label *exit, Label *slowPath) 987{ 988 auto env = GetEnvironment(); 989 Label thisIsEmpty(env); 990 // Fast path if: (1) this is an empty array; (2) fromIndex is missing 991 JsArrayRequirements req; 992 BRANCH(IsJsArrayWithLengthLimit(glue, thisValue, MAX_LENGTH_ZERO, req), &thisIsEmpty, slowPath); 993 Bind(&thisIsEmpty); 994 { 995 Label atMostOneArg(env); 996 BRANCH(Int32LessThanOrEqual(TruncPtrToInt32(numArgs), Int32(1)), &atMostOneArg, slowPath); 997 // Returns -1 on fast path 998 Bind(&atMostOneArg); 999 result->WriteVariable(IntToTaggedPtr(Int32(-1))); 1000 Jump(exit); 1001 } 1002} 1003 1004// Note: unused arguments are reserved for further development 1005void BuiltinsArrayStubBuilder::LastIndexOf([[maybe_unused]] GateRef glue, GateRef thisValue, GateRef numArgs, 1006 Variable *result, Label *exit, Label *slowPath) 1007{ 1008 auto env = GetEnvironment(); 1009 Label thisIsEmpty(env); 1010 // Fast path if: (1) this is an empty array; (2) fromIndex is missing 1011 JsArrayRequirements req; 1012 BRANCH(IsJsArrayWithLengthLimit(glue, thisValue, MAX_LENGTH_ZERO, req), &thisIsEmpty, slowPath); 1013 Bind(&thisIsEmpty); 1014 { 1015 Label atMostOneArg(env); 1016 BRANCH(Int32LessThanOrEqual(TruncPtrToInt32(numArgs), Int32(1)), &atMostOneArg, slowPath); 1017 // Returns -1 on fast path 1018 Bind(&atMostOneArg); 1019 result->WriteVariable(IntToTaggedPtr(Int32(-1))); 1020 Jump(exit); 1021 } 1022} 1023 1024void BuiltinsArrayStubBuilder::Pop(GateRef glue, GateRef thisValue, 1025 [[maybe_unused]] GateRef numArgs, Variable *result, Label *exit, Label *slowPath) 1026{ 1027 auto env = GetEnvironment(); 1028 Label isHeapObject(env); 1029 Label stableJSArray(env); 1030 Label isDeufaltConstructor(env); 1031 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath); 1032 Bind(&isHeapObject); 1033 BRANCH(HasConstructor(thisValue), slowPath, &isDeufaltConstructor); 1034 Bind(&isDeufaltConstructor); 1035 BRANCH(IsStableJSArray(glue, thisValue), &stableJSArray, slowPath); 1036 Bind(&stableJSArray); 1037 1038 Label isLengthWritable(env); 1039 BRANCH(IsArrayLengthWritable(glue, thisValue), &isLengthWritable, slowPath); 1040 Bind(&isLengthWritable); 1041 GateRef thisLen = ZExtInt32ToInt64(GetArrayLength(thisValue)); 1042 1043 Label notZeroLen(env); 1044 BRANCH(Int64Equal(thisLen, Int64(0)), exit, ¬ZeroLen); 1045 Bind(¬ZeroLen); 1046 Label isJsCOWArray(env); 1047 Label getElements(env); 1048 BRANCH(IsJsCOWArray(thisValue), &isJsCOWArray, &getElements); 1049 Bind(&isJsCOWArray); 1050 { 1051 CallRuntime(glue, RTSTUB_ID(CheckAndCopyArray), { thisValue }); 1052 Jump(&getElements); 1053 } 1054 Bind(&getElements); 1055 GateRef elements = GetElementsArray(thisValue); 1056 GateRef capacity = ZExtInt32ToInt64(GetLengthOfTaggedArray(elements)); 1057 GateRef index = Int64Sub(thisLen, Int64(1)); 1058 1059 Label inRange(env); 1060 Label trimCheck(env); 1061 Label noTrimCheck(env); 1062 Label setNewLen(env); 1063 Label isHole(env); 1064 DEFVARIABLE(element, VariableType::JS_ANY(), Hole()); 1065 BRANCH(Int64LessThan(index, capacity), &inRange, &trimCheck); 1066 Bind(&inRange); 1067 { 1068 element = GetTaggedValueWithElementsKind(thisValue, index); 1069 Jump(&isHole); 1070 } 1071 Bind(&isHole); 1072 BRANCH(TaggedIsHole(*element), &noTrimCheck, &trimCheck); 1073 Bind(&noTrimCheck); 1074 { 1075 Label hasException0(env); 1076 Label notHasException0(env); 1077 element = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(index), ProfileOperation()); 1078 BRANCH(HasPendingException(glue), &hasException0, ¬HasException0); 1079 Bind(&hasException0); 1080 { 1081 result->WriteVariable(Exception()); 1082 Jump(exit); 1083 } 1084 Bind(¬HasException0); 1085 { 1086 Jump(&setNewLen); 1087 } 1088 } 1089 Bind(&trimCheck); 1090 // ShouldTrim check 1091 // (oldLength - newLength > MAX_END_UNUSED) 1092 Label noTrim(env); 1093 Label needTrim(env); 1094 GateRef unused = Int64Sub(capacity, index); 1095 BRANCH(Int64GreaterThan(unused, Int64(TaggedArray::MAX_END_UNUSED)), &needTrim, &noTrim); 1096 Bind(&needTrim); 1097 { 1098 CallNGCRuntime(glue, RTSTUB_ID(ArrayTrim), {glue, elements, index}); 1099 Jump(&setNewLen); 1100 } 1101 Bind(&noTrim); 1102 { 1103 SetValueWithElementsKind(glue, thisValue, Hole(), index, Boolean(false), 1104 Int32(static_cast<uint32_t>(ElementsKind::NONE))); 1105 Jump(&setNewLen); 1106 } 1107 Bind(&setNewLen); 1108 GateRef lengthOffset = IntPtr(JSArray::LENGTH_OFFSET); 1109 Store(VariableType::INT32(), glue, thisValue, lengthOffset, TruncInt64ToInt32(index)); 1110 1111 Label isNotHole(env); 1112 BRANCH(TaggedIsHole(*element), exit, &isNotHole); 1113 Bind(&isNotHole); 1114 { 1115 result->WriteVariable(*element); 1116 Jump(exit); 1117 } 1118} 1119 1120void BuiltinsArrayStubBuilder::Slice(GateRef glue, GateRef thisValue, GateRef numArgs, 1121 Variable *result, Label *exit, Label *slowPath) 1122{ 1123 auto env = GetEnvironment(); 1124 Label isHeapObject(env); 1125 Label isJsArray(env); 1126 Label noConstructor(env); 1127 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath); 1128 Bind(&isHeapObject); 1129 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath); 1130 Bind(&isJsArray); 1131 BRANCH(HasConstructor(thisValue), slowPath, &noConstructor); 1132 Bind(&noConstructor); 1133 1134 Label thisIsEmpty(env); 1135 Label thisNotEmpty(env); 1136 // Fast path if: 1137 // (1) this is an empty array with constructor not reset (see ArraySpeciesCreate for details); 1138 // (2) no arguments exist 1139 JsArrayRequirements req; 1140 req.defaultConstructor = true; 1141 BRANCH(IsJsArrayWithLengthLimit(glue, thisValue, MAX_LENGTH_ZERO, req), &thisIsEmpty, &thisNotEmpty); 1142 Bind(&thisIsEmpty); 1143 { 1144 Label noArgs(env); 1145 GateRef numArgsAsInt32 = TruncPtrToInt32(numArgs); 1146 BRANCH(Int32Equal(numArgsAsInt32, Int32(0)), &noArgs, slowPath); 1147 // Creates a new empty array on fast path 1148 Bind(&noArgs); 1149 NewObjectStubBuilder newBuilder(this); 1150 result->WriteVariable(newBuilder.CreateEmptyArray(glue)); 1151 Jump(exit); 1152 } 1153 Bind(&thisNotEmpty); 1154 { 1155 Label stableJSArray(env); 1156 Label arrayLenNotZero(env); 1157 1158 GateRef isThisStableJSArray = IsStableJSArray(glue, thisValue); 1159 BRANCH(isThisStableJSArray, &stableJSArray, slowPath); 1160 Bind(&stableJSArray); 1161 1162 GateRef msg0 = GetCallArg0(numArgs); 1163 GateRef msg1 = GetCallArg1(numArgs); 1164 GateRef thisArrLen = ZExtInt32ToInt64(GetArrayLength(thisValue)); 1165 Label msg0Int(env); 1166 BRANCH(TaggedIsInt(msg0), &msg0Int, slowPath); 1167 Bind(&msg0Int); 1168 DEFVARIABLE(start, VariableType::INT64(), Int64(0)); 1169 DEFVARIABLE(end, VariableType::INT64(), thisArrLen); 1170 1171 GateRef argStart = SExtInt32ToInt64(TaggedGetInt(msg0)); 1172 Label arg0LessZero(env); 1173 Label arg0NotLessZero(env); 1174 Label startDone(env); 1175 BRANCH(Int64LessThan(argStart, Int64(0)), &arg0LessZero, &arg0NotLessZero); 1176 Bind(&arg0LessZero); 1177 { 1178 Label tempGreaterZero(env); 1179 Label tempNotGreaterZero(env); 1180 GateRef tempStart = Int64Add(argStart, thisArrLen); 1181 BRANCH(Int64GreaterThan(tempStart, Int64(0)), &tempGreaterZero, &tempNotGreaterZero); 1182 Bind(&tempGreaterZero); 1183 { 1184 start = tempStart; 1185 Jump(&startDone); 1186 } 1187 Bind(&tempNotGreaterZero); 1188 { 1189 Jump(&startDone); 1190 } 1191 } 1192 Bind(&arg0NotLessZero); 1193 { 1194 Label argLessLen(env); 1195 Label argNotLessLen(env); 1196 BRANCH(Int64LessThan(argStart, thisArrLen), &argLessLen, &argNotLessLen); 1197 Bind(&argLessLen); 1198 { 1199 start = argStart; 1200 Jump(&startDone); 1201 } 1202 Bind(&argNotLessLen); 1203 { 1204 start = thisArrLen; 1205 Jump(&startDone); 1206 } 1207 } 1208 Bind(&startDone); 1209 { 1210 Label endDone(env); 1211 Label msg1Def(env); 1212 BRANCH(TaggedIsUndefined(msg1), &endDone, &msg1Def); 1213 Bind(&msg1Def); 1214 { 1215 Label msg1Int(env); 1216 BRANCH(TaggedIsInt(msg1), &msg1Int, slowPath); 1217 Bind(&msg1Int); 1218 { 1219 GateRef argEnd = SExtInt32ToInt64(TaggedGetInt(msg1)); 1220 Label arg1LessZero(env); 1221 Label arg1NotLessZero(env); 1222 BRANCH(Int64LessThan(argEnd, Int64(0)), &arg1LessZero, &arg1NotLessZero); 1223 Bind(&arg1LessZero); 1224 { 1225 Label tempGreaterZero(env); 1226 Label tempNotGreaterZero(env); 1227 GateRef tempEnd = Int64Add(argEnd, thisArrLen); 1228 BRANCH(Int64GreaterThan(tempEnd, Int64(0)), &tempGreaterZero, &tempNotGreaterZero); 1229 Bind(&tempGreaterZero); 1230 { 1231 end = tempEnd; 1232 Jump(&endDone); 1233 } 1234 Bind(&tempNotGreaterZero); 1235 { 1236 end = Int64(0); 1237 Jump(&endDone); 1238 } 1239 } 1240 Bind(&arg1NotLessZero); 1241 { 1242 Label argLessLen(env); 1243 Label argNotLessLen(env); 1244 BRANCH(Int64LessThan(argEnd, thisArrLen), &argLessLen, &argNotLessLen); 1245 Bind(&argLessLen); 1246 { 1247 end = argEnd; 1248 Jump(&endDone); 1249 } 1250 Bind(&argNotLessLen); 1251 { 1252 end = thisArrLen; 1253 Jump(&endDone); 1254 } 1255 } 1256 } 1257 } 1258 Bind(&endDone); 1259 { 1260 DEFVARIABLE(count, VariableType::INT64(), Int64(0)); 1261 GateRef tempCnt = Int64Sub(*end, *start); 1262 Label tempCntGreaterOrEqualZero(env); 1263 Label tempCntDone(env); 1264 BRANCH(Int64LessThan(tempCnt, Int64(0)), &tempCntDone, &tempCntGreaterOrEqualZero); 1265 Bind(&tempCntGreaterOrEqualZero); 1266 { 1267 count = tempCnt; 1268 Jump(&tempCntDone); 1269 } 1270 Bind(&tempCntDone); 1271 { 1272 Label notOverFlow(env); 1273 BRANCH(Int64GreaterThan(*count, Int64(JSObject::MAX_GAP)), slowPath, ¬OverFlow); 1274 Bind(¬OverFlow); 1275 { 1276 GateRef newArray = NewArray(glue, *count); 1277 GateRef thisEles = GetElementsArray(thisValue); 1278 GateRef thisElesLen = ZExtInt32ToInt64(GetLengthOfTaggedArray(thisEles)); 1279 1280 Label inThisEles(env); 1281 Label outThisEles(env); 1282 BRANCH(Int64GreaterThan(thisElesLen, Int64Add(*start, *count)), &inThisEles, &outThisEles); 1283 Bind(&inThisEles); 1284 { 1285 DEFVARIABLE(idx, VariableType::INT64(), Int64(0)); 1286 Label loopHead(env); 1287 Label loopEnd(env); 1288 Label next(env); 1289 Label loopExit(env); 1290 Jump(&loopHead); 1291 LoopBegin(&loopHead); 1292 { 1293 BRANCH(Int64LessThan(*idx, *count), &next, &loopExit); 1294 Bind(&next); 1295 1296 GateRef ele = GetTaggedValueWithElementsKind(thisValue, Int64Add(*idx, *start)); 1297 SetValueWithElementsKind(glue, newArray, ele, *idx, Boolean(true), 1298 Int32(static_cast<uint32_t>(ElementsKind::NONE))); 1299 Jump(&loopEnd); 1300 } 1301 Bind(&loopEnd); 1302 idx = Int64Add(*idx, Int64(1)); 1303 LoopEnd(&loopHead, env, glue); 1304 Bind(&loopExit); 1305 result->WriteVariable(newArray); 1306 Jump(exit); 1307 } 1308 Bind(&outThisEles); 1309 { 1310 DEFVARIABLE(idx, VariableType::INT64(), Int64(0)); 1311 Label loopHead(env); 1312 Label loopEnd(env); 1313 Label next(env); 1314 Label loopExit(env); 1315 Jump(&loopHead); 1316 LoopBegin(&loopHead); 1317 { 1318 BRANCH(Int64LessThan(*idx, *count), &next, &loopExit); 1319 Bind(&next); 1320 GateRef index = Int64Add(*idx, *start); 1321 DEFVARIABLE(ele, VariableType::JS_ANY(), Hole()); 1322 1323 Label indexOutRange(env); 1324 Label indexInRange(env); 1325 Label setEle(env); 1326 BRANCH(Int64GreaterThan(thisElesLen, index), &indexInRange, &indexOutRange); 1327 Bind(&indexInRange); 1328 { 1329 ele = GetTaggedValueWithElementsKind(thisValue, index); 1330 Jump(&setEle); 1331 } 1332 Bind(&indexOutRange); 1333 { 1334 ele = Hole(); 1335 Jump(&setEle); 1336 } 1337 Bind(&setEle); 1338 SetValueWithElementsKind(glue, newArray, *ele, *idx, Boolean(true), 1339 Int32(static_cast<uint32_t>(ElementsKind::NONE))); 1340 Jump(&loopEnd); 1341 } 1342 Bind(&loopEnd); 1343 idx = Int64Add(*idx, Int64(1)); 1344 LoopEnd(&loopHead, env, glue); 1345 Bind(&loopExit); 1346 result->WriteVariable(newArray); 1347 Jump(exit); 1348 } 1349 } 1350 } 1351 } 1352 } 1353 } 1354} 1355 1356void BuiltinsArrayStubBuilder::Sort(GateRef glue, GateRef thisValue, 1357 GateRef numArgs, Variable *result, Label *exit, Label *slowPath) 1358{ 1359 GateRef callbackFnHandle = GetCallArg0(numArgs); 1360 SortAfterArgs(glue, thisValue, callbackFnHandle, result, exit, slowPath); 1361} 1362 1363void BuiltinsArrayStubBuilder::SortAfterArgs(GateRef glue, GateRef thisValue, 1364 GateRef callbackFnHandle, Variable *result, Label *exit, Label *slowPath, GateRef hir) 1365{ 1366 auto env = GetEnvironment(); 1367 Label isHeapObject(env); 1368 Label isJsArray(env); 1369 Label defaultConstr(env); 1370 Label isStability(env); 1371 Label notCOWArray(env); 1372 Label argUndefined(env); 1373 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath); 1374 Bind(&isHeapObject); 1375 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath); 1376 Bind(&isJsArray); 1377 BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr); 1378 Bind(&defaultConstr); 1379 BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath); 1380 Bind(&isStability); 1381 BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray); 1382 Bind(¬COWArray); 1383 BRANCH(TaggedIsUndefined(callbackFnHandle), &argUndefined, slowPath); 1384 Bind(&argUndefined); 1385 result->WriteVariable(DoSort(glue, thisValue, Boolean(false), result, exit, slowPath, hir)); 1386 Jump(exit); 1387} 1388 1389void BuiltinsArrayStubBuilder::ToSorted(GateRef glue, GateRef thisValue, 1390 GateRef numArgs, Variable *result, Label *exit, Label *slowPath) 1391{ 1392 auto env = GetEnvironment(); 1393 Label isHeapObject(env); 1394 Label isJsArray(env); 1395 Label defaultConstr(env); 1396 Label isStability(env); 1397 Label notCOWArray(env); 1398 Label argUndefined(env); 1399 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath); 1400 Bind(&isHeapObject); 1401 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath); 1402 Bind(&isJsArray); 1403 BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr); 1404 Bind(&defaultConstr); 1405 BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath); 1406 Bind(&isStability); 1407 BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray); 1408 Bind(¬COWArray); 1409 GateRef callbackFnHandle = GetCallArg0(numArgs); 1410 BRANCH(TaggedIsUndefined(callbackFnHandle), &argUndefined, slowPath); 1411 Bind(&argUndefined); 1412 1413 GateRef thisArrLen = ZExtInt32ToInt64(GetArrayLength(thisValue)); 1414 GateRef receiver = NewArray(glue, thisArrLen); 1415 DEFVARIABLE(i, VariableType::INT64(), Int64(0)); 1416 Label loopHead(env); 1417 Label loopEnd(env); 1418 Label next(env); 1419 Label loopExit(env); 1420 Jump(&loopHead); 1421 LoopBegin(&loopHead); 1422 { 1423 BRANCH(Int64LessThan(*i, thisArrLen), &next, &loopExit); 1424 Bind(&next); 1425 { 1426 GateRef ele = GetTaggedValueWithElementsKind(thisValue, *i); 1427 SetValueWithElementsKind(glue, receiver, ele, *i, Boolean(true), 1428 Int32(static_cast<uint32_t>(ElementsKind::NONE))); 1429 Jump(&loopEnd); 1430 } 1431 } 1432 Bind(&loopEnd); 1433 i = Int64Add(*i, Int64(1)); 1434 LoopEnd(&loopHead); 1435 Bind(&loopExit); 1436 result->WriteVariable(DoSort(glue, receiver, Boolean(true), result, exit, slowPath)); 1437 Jump(exit); 1438} 1439 1440GateRef BuiltinsArrayStubBuilder::DoSort(GateRef glue, GateRef receiver, GateRef receiverState, 1441 Variable *result, Label *exit, Label *slowPath, GateRef hir) 1442{ 1443 auto env = GetEnvironment(); 1444 Label entry(env); 1445 env->SubCfgEntry(&entry); 1446 GateRef len = ZExtInt32ToInt64(GetArrayLength(receiver)); 1447 DEFVARIABLE(i, VariableType::INT64(), Int64(1)); 1448 DEFVARIABLE(presentValue, VariableType::JS_ANY(), Undefined()); 1449 DEFVARIABLE(middleValue, VariableType::JS_ANY(), Undefined()); 1450 DEFVARIABLE(previousValue, VariableType::JS_ANY(), Undefined()); 1451 Label loopHead(env); 1452 Label loopEnd(env); 1453 Label next(env); 1454 Label loopExit(env); 1455 Jump(&loopHead); 1456 LoopBegin(&loopHead); 1457 { 1458 BRANCH(Int64LessThan(*i, len), &next, &loopExit); 1459 Bind(&next); 1460 DEFVARIABLE(beginIndex, VariableType::INT64(), Int64(0)); 1461 DEFVARIABLE(endIndex, VariableType::INT64(), *i); 1462 Label presentValueIsHole(env); 1463 Label afterGettingpresentValue(env); 1464 Label presentValueHasProperty(env); 1465 Label presentValueHasException0(env); 1466 presentValue = GetTaggedValueWithElementsKind(receiver, *i); 1467 BRANCH(TaggedIsHole(*presentValue), &presentValueIsHole, &afterGettingpresentValue); 1468 Bind(&presentValueIsHole); 1469 { 1470 GateRef presentValueHasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { receiver, IntToTaggedInt(*i) }); 1471 BRANCH(TaggedIsTrue(presentValueHasProp), &presentValueHasProperty, &afterGettingpresentValue); 1472 Bind(&presentValueHasProperty); 1473 { 1474 presentValue = FastGetPropertyByIndex(glue, receiver, TruncInt64ToInt32(*i), ProfileOperation(), hir); 1475 BRANCH(HasPendingException(glue), &presentValueHasException0, &afterGettingpresentValue); 1476 Bind(&presentValueHasException0); 1477 { 1478 result->WriteVariable(Exception()); 1479 Jump(exit); 1480 } 1481 } 1482 } 1483 Bind(&afterGettingpresentValue); 1484 { 1485 Label loopHead1(env); 1486 Label loopEnd1(env); 1487 Label next1(env); 1488 Label loopExit1(env); 1489 Jump(&loopHead1); 1490 LoopBegin(&loopHead1); 1491 { 1492 Label middleValueIsHole(env); 1493 Label afterGettingmiddleValue(env); 1494 Label middleValueHasProperty(env); 1495 Label middleValueHasException0(env); 1496 BRANCH(Int64LessThan(*beginIndex, *endIndex), &next1, &loopExit1); 1497 Bind(&next1); 1498 GateRef sum = Int64Add(*beginIndex, *endIndex); 1499 GateRef middleIndex = Int64Div(sum, Int64(2)); // 2 : half 1500 middleValue = GetTaggedValueWithElementsKind(receiver, middleIndex); 1501 BRANCH(TaggedIsHole(*middleValue), &middleValueIsHole, &afterGettingmiddleValue); 1502 Bind(&middleValueIsHole); 1503 { 1504 GateRef middleValueHasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), 1505 { receiver, IntToTaggedInt(middleIndex) }); 1506 BRANCH(TaggedIsTrue(middleValueHasProp), &middleValueHasProperty, &afterGettingmiddleValue); 1507 Bind(&middleValueHasProperty); 1508 { 1509 middleValue = FastGetPropertyByIndex(glue, receiver, 1510 TruncInt64ToInt32(middleIndex), ProfileOperation(), hir); 1511 BRANCH(HasPendingException(glue), &middleValueHasException0, &afterGettingmiddleValue); 1512 Bind(&middleValueHasException0); 1513 { 1514 result->WriteVariable(Exception()); 1515 Jump(exit); 1516 } 1517 } 1518 } 1519 Bind(&afterGettingmiddleValue); 1520 { 1521 Label isInt(env); 1522 Label notInt(env); 1523 Label exchangeIndex(env); 1524 GateRef middleVal = *middleValue; 1525 GateRef presentVal = *presentValue; 1526 DEFVARIABLE(compareResult, VariableType::INT32(), Int32(0)); 1527 GateRef intBool = LogicAndBuilder(env) 1528 .And(TaggedIsInt(middleVal)) 1529 .And(TaggedIsInt(presentVal)) 1530 .Done(); 1531 BRANCH(intBool, &isInt, ¬Int); 1532 Bind(&isInt); 1533 { 1534 compareResult = 1535 CallNGCRuntime(glue, RTSTUB_ID(FastArraySort), {*middleValue, *presentValue}); 1536 Jump(&exchangeIndex); 1537 } 1538 Bind(¬Int); 1539 { 1540 Label isString(env); 1541 GateRef strBool = LogicAndBuilder(env) 1542 .And(TaggedIsString(middleVal)) 1543 .And(TaggedIsString(presentVal)) 1544 .Done(); 1545 BRANCH(strBool, &isString, slowPath); 1546 Bind(&isString); 1547 { 1548 compareResult = CallNGCRuntime(glue, 1549 RTSTUB_ID(FastArraySortString), {glue, *middleValue, *presentValue}); 1550 Jump(&exchangeIndex); 1551 } 1552 } 1553 Bind(&exchangeIndex); 1554 { 1555 Label less0(env); 1556 Label greater0(env); 1557 BRANCH(Int32LessThanOrEqual(*compareResult, Int32(0)), &less0, &greater0); 1558 Bind(&greater0); 1559 { 1560 endIndex = middleIndex; 1561 Jump(&loopEnd1); 1562 } 1563 Bind(&less0); 1564 { 1565 beginIndex = middleIndex; 1566 beginIndex = Int64Add(*beginIndex, Int64(1)); 1567 Jump(&loopEnd1); 1568 } 1569 } 1570 } 1571 } 1572 Bind(&loopEnd1); 1573 LoopEnd(&loopHead1); 1574 Bind(&loopExit1); 1575 1576 Label shouldCopy(env); 1577 GateRef isGreater0 = Int64GreaterThanOrEqual(*endIndex, Int64(0)); 1578 GateRef lessI = Int64LessThan(*endIndex, *i); 1579 BRANCH(BitAnd(isGreater0, lessI), &shouldCopy, &loopEnd); 1580 Bind(&shouldCopy); 1581 { 1582 DEFVARIABLE(j, VariableType::INT64(), *i); 1583 Label loopHead2(env); 1584 Label loopEnd2(env); 1585 Label next2(env); 1586 Label loopExit2(env); 1587 Label receiverIsNew(env); 1588 Label receiverIsOrigin(env); 1589 Label receiverIsNew2(env); 1590 Label receiverIsOrigin2(env); 1591 Jump(&loopHead2); 1592 LoopBegin(&loopHead2); 1593 { 1594 Label previousValueIsHole(env); 1595 Label afterGettingpreviousValue(env); 1596 Label previousValueHasProperty(env); 1597 Label previousValueHasException0(env); 1598 BRANCH(Int64GreaterThan(*j, *endIndex), &next2, &loopExit2); 1599 Bind(&next2); 1600 previousValue = GetTaggedValueWithElementsKind(receiver, Int64Sub(*j, Int64(1))); 1601 BRANCH(TaggedIsHole(*previousValue), &previousValueIsHole, &afterGettingpreviousValue); 1602 Bind(&previousValueIsHole); 1603 { 1604 GateRef previousValueHasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), 1605 { receiver, IntToTaggedInt(Int64Sub(*j, Int64(1))) }); 1606 BRANCH(TaggedIsTrue(previousValueHasProp), 1607 &previousValueHasProperty, &afterGettingpreviousValue); 1608 Bind(&previousValueHasProperty); 1609 { 1610 previousValue = FastGetPropertyByIndex(glue, receiver, 1611 TruncInt64ToInt32(Int64Sub(*j, Int64(1))), ProfileOperation(), hir); 1612 BRANCH(HasPendingException(glue), &previousValueHasException0, &afterGettingpreviousValue); 1613 Bind(&previousValueHasException0); 1614 { 1615 result->WriteVariable(Exception()); 1616 Jump(exit); 1617 } 1618 } 1619 } 1620 Bind(&afterGettingpreviousValue); 1621 { 1622 BRANCH(receiverState, &receiverIsNew, &receiverIsOrigin); 1623 Bind(&receiverIsNew); 1624 SetValueWithElementsKind(glue, receiver, *previousValue, *j, Boolean(true), 1625 Int32(static_cast<uint32_t>(ElementsKind::NONE))); 1626 Jump(&loopEnd2); 1627 Bind(&receiverIsOrigin); 1628 SetValueWithElementsKind(glue, receiver, *previousValue, *j, Boolean(false), 1629 Int32(static_cast<uint32_t>(ElementsKind::NONE))); 1630 Jump(&loopEnd2); 1631 } 1632 } 1633 Bind(&loopEnd2); 1634 j = Int64Sub(*j, Int64(1)); 1635 LoopEnd(&loopHead2); 1636 Bind(&loopExit2); 1637 BRANCH(receiverState, &receiverIsNew2, &receiverIsOrigin2); 1638 Bind(&receiverIsNew2); 1639 { 1640 SetValueWithElementsKind(glue, receiver, *presentValue, *endIndex, Boolean(true), 1641 Int32(static_cast<uint32_t>(ElementsKind::NONE))); 1642 Jump(&loopEnd); 1643 } 1644 Bind(&receiverIsOrigin2); 1645 { 1646 SetValueWithElementsKind(glue, receiver, *presentValue, *endIndex, Boolean(false), 1647 Int32(static_cast<uint32_t>(ElementsKind::NONE))); 1648 Jump(&loopEnd); 1649 } 1650 } 1651 } 1652 } 1653 Bind(&loopEnd); 1654 i = Int64Add(*i, Int64(1)); 1655 LoopEnd(&loopHead); 1656 Bind(&loopExit); 1657 env->SubCfgExit(); 1658 return receiver; 1659} 1660 1661void BuiltinsArrayStubBuilder::Reduce(GateRef glue, GateRef thisValue, GateRef numArgs, 1662 Variable *result, Label *exit, Label *slowPath) 1663{ 1664 auto env = GetEnvironment(); 1665 DEFVARIABLE(thisLen, VariableType::INT32(), Int32(0)); 1666 Label isHeapObject(env); 1667 Label isJsArray(env); 1668 Label defaultConstr(env); 1669 Label atLeastOneArg(env); 1670 Label callbackFnHandleHeapObject(env); 1671 Label callbackFnHandleCallable(env); 1672 Label noTypeError(env); 1673 1674 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath); 1675 Bind(&isHeapObject); 1676 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath); 1677 Bind(&isJsArray); 1678 BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr); 1679 Bind(&defaultConstr); 1680 thisLen = GetArrayLength(thisValue); 1681 BRANCH(Int64GreaterThanOrEqual(numArgs, IntPtr(1)), &atLeastOneArg, slowPath); 1682 Bind(&atLeastOneArg); 1683 GateRef callbackFnHandle = GetCallArg0(numArgs); 1684 BRANCH(TaggedIsHeapObject(callbackFnHandle), &callbackFnHandleHeapObject, slowPath); 1685 Bind(&callbackFnHandleHeapObject); 1686 BRANCH(IsCallable(callbackFnHandle), &callbackFnHandleCallable, slowPath); 1687 Bind(&callbackFnHandleCallable); 1688 GateRef thisLenIsZero = Int32Equal(*thisLen, Int32(0)); 1689 GateRef numArgsLessThanTwo = Int64LessThan(numArgs, IntPtr(2)); 1690 BRANCH(BitAnd(thisLenIsZero, numArgsLessThanTwo), slowPath, &noTypeError); 1691 Bind(&noTypeError); 1692 { 1693 DEFVARIABLE(accumulator, VariableType::JS_ANY(), Undefined()); 1694 DEFVARIABLE(k, VariableType::INT32(), Int32(0)); 1695 1696 Label updateAccumulator(env); 1697 Label checkForStableJSArray(env); 1698 1699 BRANCH(Int64Equal(numArgs, IntPtr(2)), &updateAccumulator, slowPath); // 2: provide initialValue param 1700 Bind(&updateAccumulator); 1701 { 1702 accumulator = GetCallArg1(numArgs); 1703 Jump(&checkForStableJSArray); 1704 } 1705 Bind(&checkForStableJSArray); 1706 { 1707 Label isStableJSArray(env); 1708 Label notStableJSArray(env); 1709 BRANCH(IsStableJSArray(glue, thisValue), &isStableJSArray, ¬StableJSArray); 1710 Bind(&isStableJSArray); 1711 { 1712 GateRef argsLength = Int32(4); // 4: «accumulator, kValue, k, thisValue» 1713 NewObjectStubBuilder newBuilder(this); 1714 GateRef argList = newBuilder.NewTaggedArray(glue, argsLength); 1715 Label loopHead(env); 1716 Label next(env); 1717 Label loopEnd(env); 1718 Label loopExit(env); 1719 Jump(&loopHead); 1720 LoopBegin(&loopHead); 1721 { 1722 BRANCH(Int32LessThan(*k, *thisLen), &next, &loopExit); 1723 Bind(&next); 1724 { 1725 Label updateK(env); 1726 Label notHole(env); 1727 Label changeThisLen(env); 1728 Label updateCallResult(env); 1729 GateRef elements = GetElementsArray(thisValue); 1730 GateRef kValue = GetTaggedValueWithElementsKind(thisValue, *k); 1731 BRANCH(TaggedIsHole(kValue), &loopEnd, ¬Hole); 1732 Bind(¬Hole); 1733 { 1734 SetValueToTaggedArray(VariableType::JS_ANY(), glue, argList, Int32(0), *accumulator); 1735 SetValueToTaggedArray(VariableType::JS_ANY(), glue, argList, Int32(1), kValue); 1736 // 2 : parameter location 1737 SetValueToTaggedArray(VariableType::INT32(), glue, argList, Int32(2), IntToTaggedInt(*k)); 1738 // 3 : parameter location 1739 SetValueToTaggedArray(VariableType::JS_ANY(), glue, argList, Int32(3), thisValue); 1740 GateRef argv = PtrAdd(argList, IntPtr(TaggedArray::DATA_OFFSET)); 1741 JSCallArgs callArgs(JSCallMode::CALL_THIS_ARGV_WITH_RETURN); 1742 callArgs.callThisArgvWithReturnArgs = { argsLength, argv, Undefined() }; 1743 CallStubBuilder callBuilder(this, glue, callbackFnHandle, argsLength, 0, nullptr, 1744 Circuit::NullGate(), callArgs); 1745 GateRef callResult = callBuilder.JSCallDispatch(); 1746 Label hasException1(env); 1747 Label notHasException1(env); 1748 BRANCH(HasPendingException(glue), &hasException1, ¬HasException1); 1749 Bind(&hasException1); 1750 { 1751 result->WriteVariable(Exception()); 1752 Jump(exit); 1753 } 1754 Bind(¬HasException1); 1755 GateRef newLen = GetLengthOfTaggedArray(elements); 1756 BRANCH(Int32LessThan(newLen, *thisLen), &changeThisLen, &updateCallResult); 1757 Bind(&changeThisLen); 1758 { 1759 thisLen = newLen; 1760 Jump(&updateCallResult); 1761 } 1762 Bind(&updateCallResult); 1763 { 1764 accumulator = callResult; 1765 Jump(&loopEnd); 1766 } 1767 } 1768 } 1769 } 1770 Bind(&loopEnd); 1771 { 1772 k = Int32Add(*k, Int32(1)); 1773 1774 Label isStableJSArray1(env); 1775 Label notStableJSArray1(env); 1776 BRANCH(IsStableJSArray(glue, thisValue), &isStableJSArray1, ¬StableJSArray1); 1777 Bind(¬StableJSArray1); 1778 { 1779 Jump(&loopExit); 1780 } 1781 Bind(&isStableJSArray1); 1782 LoopEnd(&loopHead, env, glue); 1783 } 1784 Bind(&loopExit); 1785 Jump(¬StableJSArray); 1786 } 1787 Bind(¬StableJSArray); 1788 { 1789 Label finish(env); 1790 Label callRT(env); 1791 BRANCH(Int32LessThan(*k, *thisLen), &callRT, &finish); 1792 Bind(&callRT); 1793 { 1794 accumulator = CallRuntime(glue, RTSTUB_ID(JSArrayReduceUnStable), { thisValue, thisValue, 1795 IntToTaggedInt(*k), IntToTaggedInt(*thisLen), *accumulator, callbackFnHandle }); 1796 Jump(&finish); 1797 } 1798 Bind(&finish); 1799 { 1800 result->WriteVariable(*accumulator); 1801 Jump(exit); 1802 } 1803 } 1804 } 1805 } 1806} 1807 1808void BuiltinsArrayStubBuilder::Reverse(GateRef glue, GateRef thisValue, [[maybe_unused]] GateRef numArgs, 1809 Variable *result, Label *exit, Label *slowPath) 1810{ 1811 auto env = GetEnvironment(); 1812 Label isHeapObject(env); 1813 Label isJsArray(env); 1814 Label isStability(env); 1815 Label defaultConstr(env); 1816 Label notCOWArray(env); 1817 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath); 1818 Bind(&isHeapObject); 1819 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath); 1820 Bind(&isJsArray); 1821 BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr); 1822 Bind(&defaultConstr); 1823 BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath); 1824 Bind(&isStability); 1825 BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray); 1826 Bind(¬COWArray); 1827 1828 GateRef thisArrLen = ZExtInt32ToInt64(GetArrayLength(thisValue)); 1829 DEFVARIABLE(i, VariableType::INT64(), Int64(0)); 1830 DEFVARIABLE(j, VariableType::INT64(), Int64Sub(thisArrLen, Int64(1))); 1831 1832 GateRef hclass = LoadHClass(thisValue); 1833 GateRef kind = GetElementsKindFromHClass(hclass); 1834 Label isInt(env); 1835 Label isNotInt(env); 1836 Label notFastKind(env); 1837 GateRef isElementsKindEnabled = IsEnableElementsKind(glue); 1838 GateRef checkIntKind = LogicAndBuilder(env) 1839 .And(isElementsKindEnabled) 1840 .And(Int32GreaterThanOrEqual(kind, Int32(static_cast<int32_t>(ElementsKind::INT)))) 1841 .And(Int32LessThanOrEqual(kind, Int32(static_cast<int32_t>(ElementsKind::HOLE_INT)))) 1842 .Done(); 1843 BRANCH(checkIntKind, &isInt, &isNotInt); 1844 Bind(&isInt); 1845 { 1846 FastReverse(glue, thisValue, thisArrLen, ElementsKind::INT, result, exit); 1847 } 1848 Bind(&isNotInt); 1849 { 1850 Label isNumber(env); 1851 Label isNotNumber(env); 1852 GateRef checkNumberKind = LogicAndBuilder(env) 1853 .And(isElementsKindEnabled) 1854 .And(Int32GreaterThanOrEqual(kind, Int32(static_cast<int32_t>(ElementsKind::NUMBER)))) 1855 .And(Int32LessThanOrEqual(kind, Int32(static_cast<int32_t>(ElementsKind::HOLE_NUMBER)))) 1856 .Done(); 1857 BRANCH(checkNumberKind, &isNumber, &isNotNumber); 1858 Bind(&isNumber); 1859 { 1860 FastReverse(glue, thisValue, thisArrLen, ElementsKind::NUMBER, result, exit); 1861 } 1862 Bind(&isNotNumber); 1863 { 1864 FastReverse(glue, thisValue, thisArrLen, ElementsKind::TAGGED, result, exit); 1865 } 1866 } 1867} 1868 1869void BuiltinsArrayStubBuilder::FastReverse(GateRef glue, GateRef thisValue, GateRef len, 1870 ElementsKind kind, Variable *result, Label *exit) 1871{ 1872 auto env = GetEnvironment(); 1873 DEFVARIABLE(i, VariableType::INT64(), Int64(0)); 1874 DEFVARIABLE(j, VariableType::INT64(), Int64Sub(len, Int64(1))); 1875 GateRef elements = GetElementsArray(thisValue); 1876 Label loopHead(env); 1877 Label loopEnd(env); 1878 Label next(env); 1879 Label loopExit(env); 1880 Jump(&loopHead); 1881 LoopBegin(&loopHead); 1882 { 1883 Label arrayValue(env); 1884 Label valueEqual(env); 1885 BRANCH(Int64LessThan(*i, *j), &next, &loopExit); 1886 Bind(&next); 1887 { 1888 if (kind == ElementsKind::INT || kind == ElementsKind::NUMBER) { 1889 GateRef lower = GetValueFromMutantTaggedArray(elements, *i); 1890 GateRef upper = GetValueFromMutantTaggedArray(elements, *j); 1891 FastSetValueWithElementsKind(glue, elements, upper, *i, kind); 1892 FastSetValueWithElementsKind(glue, elements, lower, *j, kind); 1893 Jump(&loopEnd); 1894 } else { 1895 GateRef lower = GetValueFromTaggedArray(elements, *i); 1896 GateRef upper = GetValueFromTaggedArray(elements, *j); 1897 FastSetValueWithElementsKind(glue, elements, upper, *i, kind); 1898 FastSetValueWithElementsKind(glue, elements, lower, *j, kind); 1899 Jump(&loopEnd); 1900 } 1901 } 1902 } 1903 Bind(&loopEnd); 1904 i = Int64Add(*i, Int64(1)); 1905 j = Int64Sub(*j, Int64(1)); 1906 LoopEnd(&loopHead, env, glue); 1907 Bind(&loopExit); 1908 result->WriteVariable(thisValue); 1909 Jump(exit); 1910} 1911 1912void BuiltinsArrayStubBuilder::ToReversed(GateRef glue, GateRef thisValue, [[maybe_unused]] GateRef numArgs, 1913 Variable* result, Label* exit, Label* slowPath) 1914{ 1915 auto env = GetEnvironment(); 1916 Label isHeapObject(env); 1917 Label isJsArray(env); 1918 Label defaultConstr(env); 1919 Label isStability(env); 1920 Label notCOWArray(env); 1921 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath); 1922 Bind(&isHeapObject); 1923 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath); 1924 Bind(&isJsArray); 1925 BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr); 1926 Bind(&defaultConstr); 1927 BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath); 1928 Bind(&isStability); 1929 BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray); 1930 Bind(¬COWArray); 1931 Label newArrayIsTagged(env); 1932 Label notChange(env); 1933 GateRef isElementsKindEnabled = IsEnableElementsKind(glue); 1934 DEFVARIABLE(newHClass, VariableType::JS_ANY(), LoadHClass(thisValue)); 1935 GateRef kind = GetElementsKindFromHClass(LoadHClass(thisValue)); 1936 BRANCH_NO_WEIGHT(LogicAndBuilder(env).And(isElementsKindEnabled).And(ElementsKindHasHole(kind)).Done(), 1937 &newArrayIsTagged, ¬Change); 1938 Bind(&newArrayIsTagged); 1939 { 1940 // If the kind has hole, we know it must be transited to TAGGED kind; 1941 // There will be no hole in the new array because hole will be converted to undefined. 1942 newHClass = GetGlobalConstantValue(VariableType::JS_ANY(), glue, ConstantIndex::ELEMENT_TAGGED_HCLASS_INDEX); 1943 Jump(¬Change); 1944 } 1945 1946 Bind(¬Change); 1947 GateRef thisArrLen = GetArrayLength(thisValue); 1948 GateRef receiver = NewArrayWithHClass(glue, *newHClass); 1949 GrowElementsCapacity(glue, receiver, thisArrLen); 1950 SetArrayLength(glue, receiver, thisArrLen); 1951 1952 Label afterReverse(env); 1953 Label isIntOrNumber(env); 1954 Label notIntOrNumber(env); 1955 Label isTagged(env); 1956 Label isHoleOrIntOrNumber(env); 1957 Label elementsKindEnabled(env); 1958 BRANCH_NO_WEIGHT(isElementsKindEnabled, &elementsKindEnabled, &isTagged); 1959 Bind(&elementsKindEnabled); 1960 { 1961 GateRef intOrNumber = LogicOrBuilder(env) 1962 .Or(Int32Equal(kind, Int32(static_cast<int32_t>(ElementsKind::INT)))) 1963 .Or(Int32Equal(kind, Int32(static_cast<int32_t>(ElementsKind::NUMBER)))) 1964 .Done(); 1965 BRANCH_NO_WEIGHT(intOrNumber, &isIntOrNumber, ¬IntOrNumber); 1966 Bind(¬IntOrNumber); 1967 { 1968 GateRef holeOrIntOrNumber = LogicOrBuilder(env) 1969 .Or(Int32Equal(kind, Int32(static_cast<int32_t>(ElementsKind::HOLE_INT)))) 1970 .Or(Int32Equal(kind, Int32(static_cast<int32_t>(ElementsKind::HOLE_NUMBER)))) 1971 .Done(); 1972 BRANCH_NO_WEIGHT(holeOrIntOrNumber, &isHoleOrIntOrNumber, &isTagged); 1973 } 1974 } 1975 Bind(&isTagged); 1976 { 1977 // The old array and new array are both TaggedArray, so load and store the element directly. 1978 // And barrier is needed. 1979 DoReverse(glue, thisValue, receiver, true, false, MemoryAttribute::Default()); 1980 Jump(&afterReverse); 1981 } 1982 Bind(&isIntOrNumber); 1983 { 1984 // The old array and new array are both MutantTaggedArray, so load and store the element directly. 1985 // And barrier is not needed. 1986 DoReverse(glue, thisValue, receiver, false, false, MemoryAttribute::NoBarrier()); 1987 Jump(&afterReverse); 1988 } 1989 Bind(&isHoleOrIntOrNumber); 1990 { 1991 // The old array is mutant, but new array is TaggedArray, so load the value from old array with 1992 // elements kind. And set it to new array directly, And barrier is not needed. 1993 DoReverse(glue, thisValue, receiver, true, true, MemoryAttribute::NoBarrier()); 1994 Jump(&afterReverse); 1995 } 1996 Bind(&afterReverse); 1997 result->WriteVariable(receiver); 1998 Jump(exit); 1999} 2000 2001void BuiltinsArrayStubBuilder::DoReverse(GateRef glue, GateRef fromArray, GateRef toArray, bool holeToUndefined, 2002 bool getWithKind, MemoryAttribute mAttr) 2003{ 2004 auto env = GetEnvironment(); 2005 Label entry(env); 2006 env->SubCfgEntry(&entry); 2007 Label loopExit(env); 2008 Label begin(env); 2009 Label body(env); 2010 Label endLoop(env); 2011 2012 GateRef fromElements = GetElementsArray(fromArray); 2013 GateRef toElements = GetElementsArray(toArray); 2014 GateRef thisArrLen = GetArrayLength(fromArray); 2015 DEFVARIABLE(index, VariableType::INT32(), Int32(0)); 2016 GateRef endIndex = Int32Sub(thisArrLen, Int32(1)); 2017 Jump(&begin); 2018 LoopBegin(&begin); 2019 { 2020 BRANCH_LIKELY(Int32UnsignedLessThan(*index, thisArrLen), &body, &loopExit); 2021 Bind(&body); 2022 { 2023 GateRef toIndex = Int32Sub(endIndex, *index); 2024 // The old array and new array are both TaggedArray, so load and store the element directly. 2025 // And barrier is needed. 2026 GateRef value = getWithKind ? GetTaggedValueWithElementsKind(fromArray, *index) 2027 : GetValueFromTaggedArray(fromElements, *index); 2028 if (holeToUndefined) { 2029 Label isHole(env); 2030 Label isNotHole(env); 2031 BRANCH_UNLIKELY(TaggedIsHole(value), &isHole, &isNotHole); 2032 Bind(&isHole); 2033 { 2034 // The return value of toReversed() is never sparse. 2035 // Empty slots become undefined in the returned array. 2036 SetValueToTaggedArray(VariableType::JS_ANY(), glue, toElements, toIndex, Undefined(), 2037 MemoryAttribute::NoBarrier()); 2038 Jump(&endLoop); 2039 } 2040 Bind(&isNotHole); 2041 } 2042 SetValueToTaggedArray(VariableType::JS_ANY(), glue, toElements, toIndex, value, mAttr); 2043 Jump(&endLoop); 2044 } 2045 } 2046 Bind(&endLoop); 2047 index = Int32Add(*index, Int32(1)); 2048 LoopEnd(&begin); 2049 Bind(&loopExit); 2050 env->SubCfgExit(); 2051} 2052 2053GateRef BuiltinsArrayStubBuilder::IsJsArrayWithLengthLimit(GateRef glue, GateRef object, 2054 uint32_t maxLength, JsArrayRequirements requirements) 2055{ 2056 auto env = GetEnvironment(); 2057 Label entry(env); 2058 env->SubCfgEntry(&entry); 2059 Label isHeapObject(env); 2060 Label isJsArray(env); 2061 Label stabilityCheckPassed(env); 2062 Label defaultConstructorCheckPassed(env); 2063 Label exit(env); 2064 DEFVARIABLE(result, VariableType::BOOL(), False()); 2065 2066 BRANCH(TaggedIsHeapObject(object), &isHeapObject, &exit); 2067 Bind(&isHeapObject); 2068 BRANCH(IsJsArray(object), &isJsArray, &exit); 2069 Bind(&isJsArray); 2070 if (requirements.stable) { 2071 BRANCH(IsStableJSArray(glue, object), &stabilityCheckPassed, &exit); 2072 } else { 2073 Jump(&stabilityCheckPassed); 2074 } 2075 Bind(&stabilityCheckPassed); 2076 if (requirements.defaultConstructor) { 2077 // If HasConstructor bit is set to 1, then the constructor has been modified. 2078 BRANCH(HasConstructor(object), &exit, &defaultConstructorCheckPassed); 2079 } else { 2080 Jump(&defaultConstructorCheckPassed); 2081 } 2082 Bind(&defaultConstructorCheckPassed); 2083 result.WriteVariable(Int32UnsignedLessThanOrEqual(GetArrayLength(object), Int32(maxLength))); 2084 Jump(&exit); 2085 Bind(&exit); 2086 GateRef ret = *result; 2087 env->SubCfgExit(); 2088 return ret; 2089} 2090 2091void BuiltinsArrayStubBuilder::Values(GateRef glue, GateRef thisValue, 2092 [[maybe_unused]] GateRef numArgs, Variable *result, Label *exit, Label *slowPath) 2093{ 2094 auto env = GetEnvironment(); 2095 Label isHeapObject(env); 2096 Label isJsArray(env); 2097 Label defaultConstr(env); 2098 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath); 2099 Bind(&isHeapObject); 2100 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath); 2101 Bind(&isJsArray); 2102 BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr); 2103 Bind(&defaultConstr); 2104 ConstantIndex iterClassIdx = ConstantIndex::JS_ARRAY_ITERATOR_CLASS_INDEX; 2105 GateRef iteratorHClass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue, iterClassIdx); 2106 NewObjectStubBuilder newBuilder(this); 2107 newBuilder.SetParameters(glue, 0); 2108 GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit())); 2109 GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset); 2110 GateRef prototype = GetGlobalEnvValue(VariableType::JS_POINTER(), glueGlobalEnv, 2111 GlobalEnv::ARRAY_ITERATOR_PROTOTYPE_INDEX); 2112 SetPrototypeToHClass(VariableType::JS_POINTER(), glue, iteratorHClass, prototype); 2113 GateRef iter = newBuilder.NewJSObject(glue, iteratorHClass); 2114 SetIteratedArrayOfArrayIterator(glue, iter, thisValue); 2115 SetNextIndexOfArrayIterator(glue, iter, Int32(0)); 2116 GateRef kind = Int32(static_cast<int32_t>(IterationKind::VALUE)); 2117 SetBitFieldOfArrayIterator(glue, iter, kind); 2118 result->WriteVariable(iter); 2119 Jump(exit); 2120} 2121 2122void BuiltinsArrayStubBuilder::Find(GateRef glue, GateRef thisValue, GateRef numArgs, 2123 Variable *result, Label *exit, Label *slowPath) 2124{ 2125 auto env = GetEnvironment(); 2126 Label isHeapObject(env); 2127 Label isJsArray(env); 2128 Label isStability(env); 2129 Label defaultConstr(env); 2130 Label notCOWArray(env); 2131 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath); 2132 Bind(&isHeapObject); 2133 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath); 2134 Bind(&isJsArray); 2135 BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr); 2136 Bind(&defaultConstr); 2137 BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath); 2138 Bind(&isStability); 2139 BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray); 2140 Bind(¬COWArray); 2141 2142 GateRef callbackFnHandle = GetCallArg0(numArgs); 2143 Label arg0HeapObject(env); 2144 BRANCH(TaggedIsHeapObject(callbackFnHandle), &arg0HeapObject, slowPath); 2145 Bind(&arg0HeapObject); 2146 Label callable(env); 2147 BRANCH(IsCallable(callbackFnHandle), &callable, slowPath); 2148 Bind(&callable); 2149 GateRef argHandle = GetCallArg1(numArgs); 2150 DEFVARIABLE(thisArrLen, VariableType::INT64(), ZExtInt32ToInt64(GetArrayLength(thisValue))); 2151 DEFVARIABLE(i, VariableType::INT64(), Int64(0)); 2152 Label loopHead(env); 2153 Label loopEnd(env); 2154 Label next(env); 2155 Label loopExit(env); 2156 Jump(&loopHead); 2157 LoopBegin(&loopHead); 2158 { 2159 Label hasException0(env); 2160 Label notHasException0(env); 2161 BRANCH(Int64LessThan(*i, *thisArrLen), &next, &loopExit); 2162 Bind(&next); 2163 GateRef kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation()); 2164 BRANCH(HasPendingException(glue), &hasException0, ¬HasException0); 2165 Bind(&hasException0); 2166 { 2167 result->WriteVariable(Exception()); 2168 Jump(exit); 2169 } 2170 Bind(¬HasException0); 2171 { 2172 GateRef key = Int64ToTaggedInt(*i); 2173 Label hasException(env); 2174 Label notHasException(env); 2175 JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN); 2176 callArgs.callThisArg3WithReturnArgs = { argHandle, kValue, key, thisValue }; 2177 CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr, 2178 Circuit::NullGate(), callArgs); 2179 GateRef retValue = callBuilder.JSCallDispatch(); 2180 BRANCH(HasPendingException(glue), &hasException, ¬HasException); 2181 Bind(&hasException); 2182 { 2183 result->WriteVariable(retValue); 2184 Jump(exit); 2185 } 2186 Bind(¬HasException); 2187 { 2188 Label find(env); 2189 BRANCH(TaggedIsTrue(FastToBoolean(retValue)), &find, &loopEnd); 2190 Bind(&find); 2191 { 2192 result->WriteVariable(kValue); 2193 Jump(exit); 2194 } 2195 } 2196 } 2197 } 2198 Bind(&loopEnd); 2199 thisArrLen = ZExtInt32ToInt64(GetArrayLength(thisValue)); 2200 i = Int64Add(*i, Int64(1)); 2201 LoopEnd(&loopHead, env, glue); 2202 Bind(&loopExit); 2203 Jump(exit); 2204} 2205 2206void BuiltinsArrayStubBuilder::FindIndex(GateRef glue, GateRef thisValue, GateRef numArgs, 2207 Variable *result, Label *exit, Label *slowPath) 2208{ 2209 auto env = GetEnvironment(); 2210 Label isHeapObject(env); 2211 Label isJsArray(env); 2212 Label defaultConstr(env); 2213 Label notCOWArray(env); 2214 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath); 2215 Bind(&isHeapObject); 2216 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath); 2217 Bind(&isJsArray); 2218 BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr); 2219 Bind(&defaultConstr); 2220 BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray); 2221 Bind(¬COWArray); 2222 2223 Label arg0HeapObject(env); 2224 Label callable(env); 2225 Label stableJSArray(env); 2226 Label notStableJSArray(env); 2227 GateRef callbackFnHandle = GetCallArg0(numArgs); 2228 BRANCH(TaggedIsHeapObject(callbackFnHandle), &arg0HeapObject, slowPath); 2229 Bind(&arg0HeapObject); 2230 BRANCH(IsCallable(callbackFnHandle), &callable, slowPath); 2231 Bind(&callable); 2232 result->WriteVariable(IntToTaggedPtr(Int32(-1))); 2233 GateRef argHandle = GetCallArg1(numArgs); 2234 DEFVARIABLE(thisArrLen, VariableType::INT64(), ZExtInt32ToInt64(GetArrayLength(thisValue))); 2235 BRANCH(IsStableJSArray(glue, thisValue), &stableJSArray, ¬StableJSArray); 2236 Bind(&stableJSArray); 2237 { 2238 DEFVARIABLE(i, VariableType::INT64(), Int64(0)); 2239 DEFVARIABLE(kValue, VariableType::JS_ANY(), Undefined()); 2240 Label loopHead(env); 2241 Label loopEnd(env); 2242 Label next(env); 2243 Label loopExit(env); 2244 Jump(&loopHead); 2245 LoopBegin(&loopHead); 2246 { 2247 BRANCH(Int64LessThan(*i, *thisArrLen), &next, &loopExit); 2248 Bind(&next); 2249 kValue = GetTaggedValueWithElementsKind(thisValue, *i); 2250 Label isHole(env); 2251 Label notHole(env); 2252 BRANCH(TaggedIsHole(*kValue), &isHole, ¬Hole); 2253 Bind(&isHole); 2254 { 2255 Label hasException0(env); 2256 Label notHasException0(env); 2257 GateRef res = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation()); 2258 BRANCH(HasPendingException(glue), &hasException0, ¬HasException0); 2259 Bind(&hasException0); 2260 { 2261 result->WriteVariable(Exception()); 2262 Jump(exit); 2263 } 2264 Bind(¬HasException0); 2265 { 2266 Label resIsHole(env); 2267 Label resNotHole(env); 2268 BRANCH(TaggedIsHole(res), &resIsHole, &resNotHole); 2269 Bind(&resIsHole); 2270 { 2271 kValue = Undefined(); 2272 Jump(¬Hole); 2273 } 2274 Bind(&resNotHole);{ 2275 kValue = res; 2276 Jump(¬Hole); 2277 } 2278 } 2279 } 2280 Bind(¬Hole); 2281 { 2282 GateRef key = IntToTaggedPtr(*i); 2283 Label hasException(env); 2284 Label notHasException(env); 2285 Label checkStable(env); 2286 JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN); 2287 callArgs.callThisArg3WithReturnArgs = { argHandle, *kValue, key, thisValue }; 2288 CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr, 2289 Circuit::NullGate(), callArgs); 2290 GateRef retValue = callBuilder.JSCallDispatch(); 2291 BRANCH(HasPendingException(glue), &hasException, ¬HasException); 2292 Bind(&hasException); 2293 { 2294 result->WriteVariable(retValue); 2295 Jump(exit); 2296 } 2297 Bind(¬HasException); 2298 { 2299 Label find(env); 2300 BRANCH(TaggedIsTrue(FastToBoolean(retValue)), &find, &checkStable); 2301 Bind(&find); 2302 { 2303 result->WriteVariable(key); 2304 Jump(exit); 2305 } 2306 } 2307 Bind(&checkStable); 2308 i = Int64Add(*i, Int64(1)); 2309 BRANCH(IsStableJSArray(glue, thisValue), &loopEnd, ¬StableJSArray); 2310 } 2311 } 2312 Bind(&loopEnd); 2313 thisArrLen = ZExtInt32ToInt64(GetArrayLength(thisValue)); 2314 LoopEnd(&loopHead, env, glue); 2315 Bind(&loopExit); 2316 Jump(exit); 2317 } 2318 Bind(¬StableJSArray); 2319 { 2320 DEFVARIABLE(j, VariableType::INT64(), Int64(0)); 2321 Label loopHead(env); 2322 Label loopEnd(env); 2323 Label next(env); 2324 Label loopExit(env); 2325 Jump(&loopHead); 2326 LoopBegin(&loopHead); 2327 { 2328 thisArrLen = ZExtInt32ToInt64(GetArrayLength(thisValue)); 2329 BRANCH(Int64LessThan(*j, *thisArrLen), &next, &loopExit); 2330 Bind(&next); 2331 { 2332 Label hasException0(env); 2333 Label notHasException0(env); 2334 GateRef kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*j), ProfileOperation()); 2335 BRANCH(HasPendingException(glue), &hasException0, ¬HasException0); 2336 Bind(&hasException0); 2337 { 2338 result->WriteVariable(Exception()); 2339 Jump(exit); 2340 } 2341 Bind(¬HasException0); 2342 { 2343 GateRef key = IntToTaggedPtr(*j); 2344 Label hasException(env); 2345 Label notHasException(env); 2346 JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN); 2347 callArgs.callThisArg3WithReturnArgs = { argHandle, kValue, key, thisValue }; 2348 CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, 2349 nullptr, Circuit::NullGate(), callArgs); 2350 GateRef retValue = callBuilder.JSCallDispatch(); 2351 BRANCH(TaggedIsException(retValue), &hasException, ¬HasException); 2352 Bind(&hasException); 2353 { 2354 result->WriteVariable(retValue); 2355 Jump(exit); 2356 } 2357 Bind(¬HasException); 2358 { 2359 Label find(env); 2360 BRANCH(TaggedIsTrue(FastToBoolean(retValue)), &find, &loopEnd); 2361 Bind(&find); 2362 { 2363 result->WriteVariable(key); 2364 Jump(exit); 2365 } 2366 } 2367 } 2368 } 2369 } 2370 Bind(&loopEnd); 2371 thisArrLen = ZExtInt32ToInt64(GetArrayLength(thisValue)); 2372 j = Int64Add(*j, Int64(1)); 2373 LoopEnd(&loopHead, env, glue); 2374 Bind(&loopExit); 2375 Jump(exit); 2376 } 2377} 2378 2379void BuiltinsArrayStubBuilder::Push(GateRef glue, GateRef thisValue, 2380 GateRef numArgs, Variable *result, Label *exit, Label *slowPath) 2381{ 2382 auto env = GetEnvironment(); 2383 Label isHeapObject(env); 2384 Label isJsArray(env); 2385 Label isStability(env); 2386 Label setLength(env); 2387 Label smallArgs(env); 2388 Label checkSmallArgs(env); 2389 2390 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath); 2391 Bind(&isHeapObject); 2392 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath); 2393 Bind(&isJsArray); 2394 Label isLengthWritable(env); 2395 BRANCH(IsArrayLengthWritable(glue, thisValue), &isLengthWritable, slowPath); 2396 Bind(&isLengthWritable); 2397 2398 BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath); 2399 Bind(&isStability); 2400 2401 GateRef oldLength = GetArrayLength(thisValue); 2402 *result = IntToTaggedPtr(oldLength); 2403 2404 BRANCH(Int32Equal(ChangeIntPtrToInt32(numArgs), Int32(0)), exit, &checkSmallArgs); 2405 Bind(&checkSmallArgs); 2406 // now unsupport more than 2 args 2407 BRANCH(Int32LessThanOrEqual(ChangeIntPtrToInt32(numArgs), Int32(2)), &smallArgs, slowPath); 2408 Bind(&smallArgs); 2409 GateRef newLength = Int32Add(oldLength, ChangeIntPtrToInt32(numArgs)); 2410 2411 DEFVARIABLE(elements, VariableType::JS_ANY(), GetElementsArray(thisValue)); 2412 GateRef capacity = GetLengthOfTaggedArray(*elements); 2413 Label grow(env); 2414 Label setValue(env); 2415 BRANCH(Int32GreaterThan(newLength, capacity), &grow, &setValue); 2416 Bind(&grow); 2417 { 2418 elements = GrowElementsCapacity(glue, thisValue, newLength); 2419 Jump(&setValue); 2420 } 2421 Bind(&setValue); 2422 { 2423 Label oneArg(env); 2424 Label twoArg(env); 2425 DEFVARIABLE(index, VariableType::INT32(), Int32(0)); 2426 DEFVARIABLE(value, VariableType::JS_ANY(), Undefined()); 2427 BRANCH(Int64Equal(numArgs, IntPtr(1)), &oneArg, &twoArg); // 1 one arg 2428 Bind(&oneArg); 2429 { 2430 value = GetCallArg0(numArgs); 2431 index = Int32Add(oldLength, Int32(0)); // 0 slot index 2432 SetValueWithElementsKind(glue, thisValue, *value, *index, Boolean(true), 2433 Int32(static_cast<uint32_t>(ElementsKind::NONE))); 2434 Jump(&setLength); 2435 } 2436 Bind(&twoArg); 2437 { 2438 value = GetCallArg0(numArgs); 2439 index = Int32Add(oldLength, Int32(0)); // 0 slot index 2440 SetValueWithElementsKind(glue, thisValue, *value, *index, Boolean(true), 2441 Int32(static_cast<uint32_t>(ElementsKind::NONE))); 2442 value = GetCallArg1(numArgs); 2443 index = Int32Add(oldLength, Int32(1)); // 1 slot index 2444 SetValueWithElementsKind(glue, thisValue, *value, *index, Boolean(true), 2445 Int32(static_cast<uint32_t>(ElementsKind::NONE))); 2446 Jump(&setLength); 2447 } 2448 } 2449 Bind(&setLength); 2450 SetArrayLength(glue, thisValue, newLength); 2451 result->WriteVariable(IntToTaggedPtr(newLength)); 2452 Jump(exit); 2453} 2454 2455GateRef BuiltinsArrayStubBuilder::IsConcatSpreadable(GateRef glue, GateRef obj) 2456{ 2457 auto env = GetEnvironment(); 2458 Label entry(env); 2459 env->SubCfgEntry(&entry); 2460 DEFVARIABLE(result, VariableType::BOOL(), False()); 2461 Label exit(env); 2462 Label isEcmaObj(env); 2463 BRANCH(IsEcmaObject(obj), &isEcmaObj, &exit); 2464 Bind(&isEcmaObj); 2465 { 2466 GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit())); 2467 GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset); 2468 GateRef isConcatsprKey = 2469 GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::ISCONCAT_SYMBOL_INDEX); 2470 AccessObjectStubBuilder builder(this); 2471 GateRef spreadable = 2472 builder.LoadObjByValue(glue, obj, isConcatsprKey, Undefined(), Int32(0), ProfileOperation()); 2473 Label isDefined(env); 2474 Label isUnDefined(env); 2475 BRANCH(TaggedIsUndefined(spreadable), &isUnDefined, &isDefined); 2476 Bind(&isUnDefined); 2477 { 2478 Label IsArray(env); 2479 BRANCH(IsJsArray(obj), &IsArray, &exit); 2480 Bind(&IsArray); 2481 result = True(); 2482 Jump(&exit); 2483 } 2484 Bind(&isDefined); 2485 { 2486 result = TaggedIsTrue(spreadable); 2487 Jump(&exit); 2488 } 2489 } 2490 Bind(&exit); 2491 auto res = *result; 2492 env->SubCfgExit(); 2493 return res; 2494} 2495 2496void BuiltinsArrayStubBuilder::InitializeArray(GateRef glue, GateRef count, Variable* result, GateRef intialHClass) 2497{ 2498 GateRef lengthOffset = IntPtr(JSArray::LENGTH_OFFSET); 2499 Store(VariableType::INT32(), glue, result->ReadVariable(), lengthOffset, TruncInt64ToInt32(count)); 2500 GateRef accessor = GetGlobalConstantValue(VariableType::JS_ANY(), glue, ConstantIndex::ARRAY_LENGTH_ACCESSOR); 2501 SetPropertyInlinedProps(glue, result->ReadVariable(), intialHClass, accessor, 2502 Int32(JSArray::LENGTH_INLINE_PROPERTY_INDEX)); 2503 SetExtensibleToBitfield(glue, result->ReadVariable(), true); 2504} 2505 2506GateRef BuiltinsArrayStubBuilder::NewArray(GateRef glue, GateRef count) 2507{ 2508 auto env = GetEnvironment(); 2509 Label entry(env); 2510 env->SubCfgEntry(&entry); 2511 DEFVARIABLE(result, VariableType::JS_POINTER(), Undefined()); 2512 Label exit(env); 2513 Label setProperties(env); 2514 GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit())); 2515 GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset); 2516 auto arrayFunc = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::ARRAY_FUNCTION_INDEX); 2517 GateRef intialHClass = Load(VariableType::JS_ANY(), arrayFunc, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET)); 2518 NewObjectStubBuilder newBuilder(this); 2519 newBuilder.SetParameters(glue, 0); 2520 result = newBuilder.NewJSArrayWithSize(intialHClass, count); 2521 BRANCH(TaggedIsException(*result), &exit, &setProperties); 2522 Bind(&setProperties); 2523 { 2524 InitializeArray(glue, count, &result, intialHClass); 2525 Jump(&exit); 2526 } 2527 Bind(&exit); 2528 auto res = *result; 2529 env->SubCfgExit(); 2530 return res; 2531} 2532 2533GateRef BuiltinsArrayStubBuilder::NewArrayWithHClass(GateRef glue, GateRef hclass) 2534{ 2535 // New an array with zero length. 2536 auto env = GetEnvironment(); 2537 Label entry(env); 2538 env->SubCfgEntry(&entry); 2539 DEFVARIABLE(result, VariableType::JS_POINTER(), Undefined()); 2540 Label exit(env); 2541 Label setProperties(env); 2542 NewObjectStubBuilder newBuilder(this); 2543 newBuilder.SetParameters(glue, Int32(0)); 2544 result = newBuilder.NewJSArrayWithSize(hclass, Int32(0)); 2545 BRANCH(TaggedIsException(*result), &exit, &setProperties); 2546 Bind(&setProperties); 2547 { 2548 InitializeArray(glue, Int32(0), &result, hclass); 2549 Jump(&exit); 2550 } 2551 Bind(&exit); 2552 auto res = *result; 2553 env->SubCfgExit(); 2554 return res; 2555} 2556 2557 2558void BuiltinsArrayStubBuilder::Includes(GateRef glue, GateRef thisValue, GateRef numArgs, 2559 Variable *result, Label *exit, Label *slowPath) 2560{ 2561 auto env = GetEnvironment(); 2562 Label isDictMode(env); 2563 Label isHeapObject(env); 2564 Label isJsArray(env); 2565 Label isStableJsArray(env); 2566 Label notFound(env); 2567 Label thisLenNotZero(env); 2568 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath); 2569 Bind(&isHeapObject); 2570 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath); 2571 Bind(&isJsArray); 2572 BRANCH(IsStableJSArray(glue, thisValue), &isStableJsArray, slowPath); 2573 Bind(&isStableJsArray); 2574 GateRef thisLen = GetArrayLength(thisValue); 2575 BRANCH(Int32Equal(thisLen, Int32(0)), ¬Found, &thisLenNotZero); 2576 Bind(&thisLenNotZero); 2577 { 2578 DEFVARIABLE(fromIndex, VariableType::INT32(), Int32(0)); 2579 Label getArgTwo(env); 2580 Label nextProcess(env); 2581 BRANCH(Int64Equal(numArgs, IntPtr(2)), &getArgTwo, &nextProcess); // 2: 2 parameters 2582 Bind(&getArgTwo); 2583 { 2584 Label secondArgIsInt(env); 2585 GateRef fromIndexTemp = GetCallArg1(numArgs); 2586 BRANCH(TaggedIsInt(fromIndexTemp), &secondArgIsInt, slowPath); 2587 Bind(&secondArgIsInt); 2588 fromIndex = GetInt32OfTInt(fromIndexTemp); 2589 Jump(&nextProcess); 2590 } 2591 Bind(&nextProcess); 2592 { 2593 Label atLeastOneArg(env); 2594 Label setBackZero(env); 2595 Label calculateFrom(env); 2596 Label nextCheck(env); 2597 BRANCH(Int64GreaterThanOrEqual(numArgs, IntPtr(1)), &atLeastOneArg, slowPath); 2598 Bind(&atLeastOneArg); 2599 BRANCH(Int32GreaterThanOrEqual(*fromIndex, thisLen), ¬Found, &nextCheck); 2600 Bind(&nextCheck); 2601 { 2602 GateRef negThisLen = Int32Sub(Int32(0), thisLen); 2603 BRANCH(Int32LessThan(*fromIndex, negThisLen), &setBackZero, &calculateFrom); 2604 Bind(&setBackZero); 2605 { 2606 fromIndex = Int32(0); 2607 Jump(&calculateFrom); 2608 } 2609 Bind(&calculateFrom); 2610 { 2611 DEFVARIABLE(from, VariableType::INT32(), Int32(0)); 2612 Label fromIndexGreaterOrEqualZero(env); 2613 Label fromIndexLessThanZero(env); 2614 Label startLoop(env); 2615 BRANCH(Int32GreaterThanOrEqual(*fromIndex, Int32(0)), 2616 &fromIndexGreaterOrEqualZero, &fromIndexLessThanZero); 2617 Bind(&fromIndexGreaterOrEqualZero); 2618 { 2619 from = *fromIndex; 2620 Jump(&startLoop); 2621 } 2622 Bind(&fromIndexLessThanZero); 2623 { 2624 Label isLenFromIndex(env); 2625 GateRef lenFromIndexSum = Int32Add(thisLen, *fromIndex); 2626 BRANCH(Int32GreaterThanOrEqual(lenFromIndexSum, Int32(0)), &isLenFromIndex, &startLoop); 2627 Bind(&isLenFromIndex); 2628 { 2629 from = lenFromIndexSum; 2630 Jump(&startLoop); 2631 } 2632 } 2633 Bind(&startLoop); 2634 { 2635 GateRef searchElement = GetCallArg0(numArgs); 2636 Label loopHead(env); 2637 Label loopEnd(env); 2638 Label next(env); 2639 Label loopExit(env); 2640 Jump(&loopHead); 2641 LoopBegin(&loopHead); 2642 { 2643 BRANCH(Int32LessThan(*from, thisLen), &next, &loopExit); 2644 Bind(&next); 2645 { 2646 Label notHoleOrUndefValue(env); 2647 Label valueFound(env); 2648 GateRef value = GetTaggedValueWithElementsKind(thisValue, *from); 2649 GateRef isHole = TaggedIsHole(value); 2650 GateRef isUndef = TaggedIsUndefined(value); 2651 BRANCH(BitOr(isHole, isUndef), slowPath, ¬HoleOrUndefValue); 2652 Bind(¬HoleOrUndefValue); 2653 GateRef valueEqual = StubBuilder::SameValueZero(glue, searchElement, value); 2654 BRANCH(valueEqual, &valueFound, &loopEnd); 2655 Bind(&valueFound); 2656 { 2657 result->WriteVariable(TaggedTrue()); 2658 Jump(exit); 2659 } 2660 } 2661 } 2662 Bind(&loopEnd); 2663 from = Int32Add(*from, Int32(1)); 2664 LoopEnd(&loopHead, env, glue); 2665 Bind(&loopExit); 2666 Jump(¬Found); 2667 } 2668 } 2669 } 2670 } 2671 } 2672 Bind(¬Found); 2673 { 2674 result->WriteVariable(TaggedFalse()); 2675 Jump(exit); 2676 } 2677} 2678 2679void BuiltinsArrayStubBuilder::From(GateRef glue, [[maybe_unused]] GateRef thisValue, GateRef numArgs, 2680 Variable *result, Label *exit, Label *slowPath) 2681{ 2682 auto env = GetEnvironment(); 2683 GateRef item = GetCallArg0(numArgs); 2684 Label stringItem(env); 2685 BRANCH(TaggedIsString(item), &stringItem, slowPath); 2686 Bind(&stringItem); 2687 Label undefFn(env); 2688 GateRef fn = GetCallArg1(numArgs); 2689 BRANCH(TaggedIsUndefined(fn), &undefFn, slowPath); 2690 Bind(&undefFn); 2691 GateRef strLen = GetLengthFromString(item); 2692 Label lessStrLen(env); 2693 BRANCH(Int32LessThan(strLen, Int32(builtins::StringToListResultCache::MAX_STRING_LENGTH)), &lessStrLen, slowPath); 2694 Bind(&lessStrLen); 2695 GateRef cacheArray = CallNGCRuntime(glue, RTSTUB_ID(GetStringToListCacheArray), { glue }); 2696 2697 Label cacheDef(env); 2698 BRANCH(TaggedIsUndefined(cacheArray), slowPath, &cacheDef); 2699 Bind(&cacheDef); 2700 { 2701 GateRef hash = GetHashcodeFromString(glue, item); 2702 GateRef entry = Int32And(hash, Int32Sub(Int32(builtins::StringToListResultCache::CACHE_SIZE), Int32(1))); 2703 GateRef index = Int32Mul(entry, Int32(builtins::StringToListResultCache::ENTRY_SIZE)); 2704 GateRef cacheStr = GetValueFromTaggedArray(cacheArray, 2705 Int32Add(index, Int32(builtins::StringToListResultCache::STRING_INDEX))); 2706 Label cacheStrDef(env); 2707 BRANCH(TaggedIsUndefined(cacheStr), slowPath, &cacheStrDef); 2708 Bind(&cacheStrDef); 2709 Label strEqual(env); 2710 Label strSlowEqual(env); 2711 // cache str is intern 2712 BRANCH(Equal(cacheStr, item), &strEqual, &strSlowEqual); 2713 Bind(&strSlowEqual); 2714 BRANCH(FastStringEqual(glue, cacheStr, item), &strEqual, slowPath); 2715 Bind(&strEqual); 2716 2717 GateRef cacheResArray = GetValueFromTaggedArray(cacheArray, 2718 Int32Add(index, Int32(builtins::StringToListResultCache::ARRAY_INDEX))); 2719 GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit())); 2720 GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset); 2721 auto arrayFunc = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::ARRAY_FUNCTION_INDEX); 2722 GateRef intialHClass = Load(VariableType::JS_ANY(), arrayFunc, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET)); 2723 NewObjectStubBuilder newBuilder(this); 2724 newBuilder.SetParameters(glue, 0); 2725 GateRef newArray = newBuilder.NewJSObject(glue, intialHClass); 2726 Store(VariableType::INT32(), glue, newArray, IntPtr(JSArray::LENGTH_OFFSET), strLen); 2727 GateRef accessor = GetGlobalConstantValue(VariableType::JS_ANY(), glue, ConstantIndex::ARRAY_LENGTH_ACCESSOR); 2728 SetPropertyInlinedProps(glue, newArray, intialHClass, accessor, Int32(JSArray::LENGTH_INLINE_PROPERTY_INDEX)); 2729 SetExtensibleToBitfield(glue, newArray, true); 2730 2731 SetElementsArray(VariableType::JS_ANY(), glue, newArray, cacheResArray); 2732 *result = newArray; 2733 Jump(exit); 2734 } 2735} 2736 2737GateRef BuiltinsArrayStubBuilder::CreateSpliceDeletedArray(GateRef glue, GateRef thisValue, GateRef actualDeleteCount, 2738 GateRef arrayCls, GateRef start) 2739{ 2740 auto env = GetEnvironment(); 2741 Label subentry(env); 2742 Label exit(env); 2743 env->SubCfgEntry(&subentry); 2744 DEFVARIABLE(result, VariableType::BOOL(), False()); 2745 2746 // new delete array 2747 DEFVARIABLE(srcElements, VariableType::JS_ANY(), GetElementsArray(thisValue)); 2748 NewObjectStubBuilder newBuilder(this); 2749 newBuilder.SetParameters(glue, 0); 2750 GateRef newArray = newBuilder.NewJSArrayWithSize(arrayCls, actualDeleteCount); 2751 GateRef lengthOffset = IntPtr(JSArray::LENGTH_OFFSET); 2752 Store(VariableType::INT32(), glue, newArray, lengthOffset, TruncInt64ToInt32(actualDeleteCount)); 2753 GateRef accessor = GetGlobalConstantValue(VariableType::JS_ANY(), glue, ConstantIndex::ARRAY_LENGTH_ACCESSOR); 2754 SetPropertyInlinedProps(glue, newArray, arrayCls, accessor, Int32(JSArray::LENGTH_INLINE_PROPERTY_INDEX)); 2755 SetExtensibleToBitfield(glue, newArray, true); 2756 result = newArray; 2757 2758 DEFVARIABLE(i, VariableType::INT32(), Int32(0)); 2759 Label loopHead(env); 2760 Label loopEnd(env); 2761 Label next(env); 2762 Label loopExit(env); 2763 Jump(&loopHead); 2764 LoopBegin(&loopHead); 2765 { 2766 BRANCH(Int32LessThan(*i, actualDeleteCount), &next, &loopExit); 2767 Bind(&next); 2768 Label setHole(env); 2769 Label setSrc(env); 2770 BRANCH(Int32GreaterThanOrEqual(Int32Add(*i, start), 2771 GetLengthOfTaggedArray(*srcElements)), &setHole, &setSrc); 2772 Bind(&setHole); 2773 { 2774 SetValueWithElementsKind(glue, newArray, Hole(), *i, Boolean(true), 2775 Int32(static_cast<uint32_t>(ElementsKind::NONE))); 2776 Jump(&loopEnd); 2777 } 2778 Bind(&setSrc); 2779 { 2780 GateRef val = GetTaggedValueWithElementsKind(thisValue, Int32Add(start, *i)); 2781 SetValueWithElementsKind(glue, newArray, val, *i, Boolean(true), 2782 Int32(static_cast<uint32_t>(ElementsKind::NONE))); 2783 Jump(&loopEnd); 2784 } 2785 } 2786 Bind(&loopEnd); 2787 i = Int32Add(*i, Int32(1)); 2788 LoopEnd(&loopHead, env, glue); 2789 Bind(&loopExit); 2790 Jump(&exit); 2791 2792 Bind(&exit); 2793 auto res = *result; 2794 env->SubCfgExit(); 2795 return res; 2796} 2797 2798void BuiltinsArrayStubBuilder::Fill(GateRef glue, GateRef thisValue, GateRef numArgs, 2799 Variable *result, Label *exit, Label *slowPath) 2800{ 2801 auto env = GetEnvironment(); 2802 Label isHeapObject(env); 2803 Label isJsArray(env); 2804 Label isStability(env); 2805 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath); 2806 Bind(&isHeapObject); 2807 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath); 2808 Bind(&isJsArray); 2809 BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath); 2810 Bind(&isStability); 2811 Label notCOWArray(env); 2812 BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray); 2813 Bind(¬COWArray); 2814 GateRef arrayCls = LoadHClass(thisValue); 2815 // 1. Let O be ToObject(this value). 2816 // 2 ReturnIfAbrupt(O). 2817 Label hasException(env); 2818 Label proNotCOWArray(env); 2819 GateRef prop = GetPropertiesFromJSObject(thisValue); 2820 BRANCH(IsCOWArray(prop), slowPath, &proNotCOWArray); 2821 Bind(&proNotCOWArray); 2822 // 3. Let len be ToLength(Get(O,"length")). 2823 GateRef value = GetCallArg0(numArgs); 2824 GateRef thisArrLen = GetLengthOfJSArray(thisValue); 2825 Label isDict(env); 2826 Label notDict(env); 2827 BRANCH(IsDictionaryElement(arrayCls), &isDict, ¬Dict); 2828 Bind(&isDict); 2829 { 2830 GateRef size = GetNumberOfElements(thisValue); 2831 BRANCH(Int32GreaterThan(Int32Sub(thisArrLen, size), 2832 TruncInt64ToInt32(IntPtr(JSObject::MAX_GAP))), slowPath, ¬Dict); 2833 } 2834 Bind(¬Dict); 2835 // 5. let relativeStart be ToInteger(start). 2836 GateRef startArg = GetCallArg1(numArgs); 2837 // 6 ReturnIfAbrupt(relativeStart). 2838 GateRef argStart = NumberGetInt(glue, ToNumber(glue, startArg)); 2839 Label notHasException3(env); 2840 BRANCH(HasPendingException(glue), &hasException, ¬HasException3); 2841 Bind(¬HasException3); 2842 // 7. If relativeStart < 0, let k be max((len + relativeStart),0); else let k be min(relativeStart, len). 2843 DEFVARIABLE(start, VariableType::INT32(), Int32(0)); 2844 Label maxStart(env); 2845 Label minStart(env); 2846 Label startExit(env); 2847 BRANCH(Int32LessThan(argStart, Int32(0)), &maxStart, &minStart); 2848 Bind(&maxStart); 2849 { 2850 GateRef tempStart = Int32Add(argStart, thisArrLen); 2851 Label bind1(env); 2852 BRANCH(Int32GreaterThan(tempStart, Int32(0)), &bind1, &startExit); 2853 Bind(&bind1); 2854 { 2855 start = tempStart; 2856 Jump(&startExit); 2857 } 2858 } 2859 Bind(&minStart); 2860 { 2861 Label bind1(env); 2862 Label bind2(env); 2863 BRANCH(Int32LessThan(argStart, thisArrLen), &bind1, &bind2); 2864 Bind(&bind1); 2865 { 2866 start = argStart; 2867 Jump(&startExit); 2868 } 2869 Bind(&bind2); 2870 { 2871 start = thisArrLen; 2872 Jump(&startExit); 2873 } 2874 } 2875 Bind(&startExit); 2876 // 8. If end is undefined, let relativeEnd be len; else let relativeEnd be ToInteger(end). 2877 GateRef endArg = GetCallArg2(numArgs); 2878 DEFVARIABLE(argEnd, VariableType::INT32(), Int32(0)); 2879 Label endArgIsUndefined(env); 2880 Label endArgNotUndefined(env); 2881 Label next1(env); 2882 BRANCH(TaggedIsUndefined(endArg), &endArgIsUndefined, &endArgNotUndefined); 2883 Bind(&endArgIsUndefined); 2884 { 2885 argEnd = thisArrLen; 2886 Jump(&next1); 2887 } 2888 Bind(&endArgNotUndefined); 2889 { 2890 argEnd = NumberGetInt(glue, ToNumber(glue, endArg)); 2891 // 9. ReturnIfAbrupt(relativeEnd). 2892 BRANCH(HasPendingException(glue), &hasException, &next1); 2893 } 2894 Bind(&next1); 2895 2896 // 10. If relativeEnd < 0, let final be max((len + relativeEnd),0); else let final be min(relativeEnd, len). 2897 DEFVARIABLE(end, VariableType::INT32(), Int32(0)); 2898 Label maxEnd(env); 2899 Label minEnd(env); 2900 Label endExit(env); 2901 BRANCH(Int32LessThan(*argEnd, Int32(0)), &maxEnd, &minEnd); 2902 Bind(&maxEnd); 2903 { 2904 GateRef tempEnd = Int32Add(*argEnd, thisArrLen); 2905 Label bind1(env); 2906 Label bind2(env); 2907 BRANCH(Int32GreaterThan(tempEnd, Int32(0)), &bind1, &endExit); 2908 Bind(&bind1); 2909 { 2910 end = tempEnd; 2911 Jump(&endExit); 2912 } 2913 } 2914 Bind(&minEnd); 2915 { 2916 Label bind1(env); 2917 Label bind2(env); 2918 BRANCH(Int32LessThan(*argEnd, thisArrLen), &bind1, &bind2); 2919 Bind(&bind1); 2920 { 2921 end = *argEnd; 2922 Jump(&endExit); 2923 } 2924 Bind(&bind2); 2925 { 2926 end = thisArrLen; 2927 Jump(&endExit); 2928 } 2929 } 2930 Bind(&endExit); 2931 // 11. Repeat, while k < final 2932 // a. Let Pk be ToString(k). 2933 // b. Let setStatus be Set(O, Pk, value, true). 2934 // c. ReturnIfAbrupt(setStatus). 2935 // d. Increase k by 1. 2936 Label argNotJsObj(env); 2937 GateRef check = LogicOrBuilder(env) 2938 .Or(TaggedIsObject(startArg)) 2939 .Or(TaggedIsObject(endArg)).Done(); 2940 BRANCH(check, slowPath, &argNotJsObj); 2941 Bind(&argNotJsObj); 2942 { 2943 Label newElements(env); 2944 Label defaultElements(env); 2945 Label startFill(env); 2946 GateRef elementKind = GetElementsKindFromHClass(arrayCls); 2947 TransitToElementsKind(glue, thisValue, value, elementKind); 2948 DEFVARIABLE(migratedValue, VariableType::JS_ANY(), value); 2949 DEFVARIABLE(elements, VariableType::JS_ANY(), GetElementsArray(thisValue)); 2950 GateRef mutant = IsMutantTaggedArray(*elements); 2951 GateRef elementLen = GetLengthOfTaggedArray(*elements); 2952 BRANCH(Int32GreaterThanOrEqual(elementLen, *end), &defaultElements, &newElements); 2953 Bind(&defaultElements); 2954 { 2955 Label isMutant(env); 2956 BRANCH(mutant, &isMutant, &startFill); 2957 Bind(&isMutant); 2958 { 2959 migratedValue = ConvertTaggedValueWithElementsKind(glue, value, elementKind); 2960 Jump(&startFill); 2961 } 2962 } 2963 Bind(&newElements); 2964 { 2965 Label isMutant(env); 2966 Label notMutant(env); 2967 NewObjectStubBuilder newBuilder(this); 2968 BRANCH(mutant, &isMutant, ¬Mutant); 2969 Bind(&isMutant); 2970 { 2971 elements = newBuilder.NewMutantTaggedArray(glue, elementLen); 2972 migratedValue = ConvertTaggedValueWithElementsKind(glue, value, elementKind); 2973 Jump(&startFill); 2974 } 2975 Bind(¬Mutant); 2976 { 2977 elements = newBuilder.NewTaggedArray(glue, elementLen); 2978 Jump(&startFill); 2979 } 2980 } 2981 Bind(&startFill); 2982 Label noBarrier(env); 2983 Label needBarrier(env); 2984 Label barrierExit(env); 2985 BRANCH(mutant, &noBarrier, &needBarrier); 2986 Bind(&noBarrier); 2987 { 2988 DEFVARIABLE(idx, VariableType::INT32(), *start); 2989 Label loopHead(env); 2990 Label loopEnd(env); 2991 Label next(env); 2992 Label loopExit(env); 2993 Jump(&loopHead); 2994 LoopBegin(&loopHead); 2995 { 2996 BRANCH(Int32LessThan(*idx, *end), &next, &loopExit); 2997 Bind(&next); 2998 SetValueToTaggedArray(VariableType::JS_ANY(), glue, 2999 *elements, *idx, *migratedValue, MemoryAttribute::NoBarrier()); 3000 Jump(&loopEnd); 3001 } 3002 Bind(&loopEnd); 3003 idx = Int32Add(*idx, Int32(1)); 3004 LoopEnd(&loopHead); 3005 Bind(&loopExit); 3006 Jump(&barrierExit); 3007 } 3008 Bind(&needBarrier); 3009 { 3010 DEFVARIABLE(idx, VariableType::INT32(), *start); 3011 Label loopHead(env); 3012 Label loopEnd(env); 3013 Label next(env); 3014 Label loopExit(env); 3015 Jump(&loopHead); 3016 LoopBegin(&loopHead); 3017 { 3018 BRANCH(Int32LessThan(*idx, *end), &next, &loopExit); 3019 Bind(&next); 3020 SetValueToTaggedArray(VariableType::JS_ANY(), glue, *elements, *idx, *migratedValue); 3021 Jump(&loopEnd); 3022 } 3023 Bind(&loopEnd); 3024 idx = Int32Add(*idx, Int32(1)); 3025 LoopEnd(&loopHead); 3026 Bind(&loopExit); 3027 Jump(&barrierExit); 3028 } 3029 Bind(&barrierExit); 3030 SetElementsArray(VariableType::JS_POINTER(), glue, thisValue, *elements); 3031 result->WriteVariable(thisValue); 3032 Jump(exit); 3033 } 3034 Bind(&hasException); 3035 { 3036 result->WriteVariable(Exception()); 3037 Jump(exit); 3038 } 3039} 3040 3041void BuiltinsArrayStubBuilder::Splice(GateRef glue, GateRef thisValue, GateRef numArgs, 3042 Variable *result, Label *exit, Label *slowPath) 3043{ 3044 auto env = GetEnvironment(); 3045 Label isHeapObject(env); 3046 Label isJsArray(env); 3047 Label isStability(env); 3048 Label defaultConstr(env); 3049 Label matchCls(env); 3050 Label isGeneric(env); 3051 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath); 3052 Bind(&isHeapObject); 3053 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath); 3054 Bind(&isJsArray); 3055 BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr); 3056 Bind(&defaultConstr); 3057 BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath); 3058 Bind(&isStability); 3059 Label notCOWArray(env); 3060 BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray); 3061 Bind(¬COWArray); 3062 GateRef arrayCls = LoadHClass(thisValue); 3063 ElementsKindHclassCompare(glue, arrayCls, &matchCls, slowPath); 3064 Bind(&matchCls); 3065 GateRef arrayLen = GetArrayLength(thisValue); 3066 Label lessThreeArg(env); 3067 3068 DEFVARIABLE(start, VariableType::INT32(), Int32(0)); 3069 DEFVARIABLE(insertCount, VariableType::INT32(), Int32(0)); 3070 DEFVARIABLE(actualDeleteCount, VariableType::INT32(), Int32(0)); 3071 GateRef argc = ChangeIntPtrToInt32(numArgs); 3072 BRANCH(Int32LessThanOrEqual(argc, Int32(3)), &lessThreeArg, slowPath); // 3 : three arg 3073 Bind(&lessThreeArg); 3074 { 3075 Label checkOverflow(env); 3076 Label greaterZero(env); 3077 Label greaterOne(env); 3078 Label checkGreaterOne(env); 3079 Label notOverflow(env); 3080 BRANCH(Int32GreaterThan(argc, Int32(0)), &greaterZero, &checkGreaterOne); 3081 Bind(&greaterZero); 3082 GateRef taggedStart = GetCallArg0(numArgs); 3083 Label taggedStartInt(env); 3084 BRANCH(TaggedIsInt(taggedStart), &taggedStartInt, slowPath); 3085 Bind(&taggedStartInt); 3086 { 3087 GateRef intStart = GetInt32OfTInt(taggedStart); 3088 start = CalArrayRelativePos(intStart, arrayLen); 3089 } 3090 actualDeleteCount = Int32Sub(arrayLen, *start); 3091 Jump(&checkGreaterOne); 3092 Bind(&checkGreaterOne); 3093 BRANCH(Int32GreaterThan(argc, Int32(1)), &greaterOne, &checkOverflow); 3094 Bind(&greaterOne); 3095 insertCount = Int32Sub(argc, Int32(2)); // 2 : two args 3096 GateRef argDeleteCount = GetCallArg1(numArgs); 3097 Label argDeleteCountInt(env); 3098 BRANCH(TaggedIsInt(argDeleteCount), &argDeleteCountInt, slowPath); 3099 Bind(&argDeleteCountInt); 3100 DEFVARIABLE(deleteCount, VariableType::INT32(), TaggedGetInt(argDeleteCount)); 3101 Label deleteCountLessZero(env); 3102 Label calActualDeleteCount(env); 3103 BRANCH(Int32LessThan(*deleteCount, Int32(0)), &deleteCountLessZero, &calActualDeleteCount); 3104 Bind(&deleteCountLessZero); 3105 deleteCount = Int32(0); 3106 Jump(&calActualDeleteCount); 3107 Bind(&calActualDeleteCount); 3108 actualDeleteCount = *deleteCount; 3109 Label lessArrayLen(env); 3110 BRANCH(Int32LessThan(Int32Sub(arrayLen, *start), *deleteCount), &lessArrayLen, &checkOverflow); 3111 Bind(&lessArrayLen); 3112 actualDeleteCount = Int32Sub(arrayLen, *start); 3113 Jump(&checkOverflow); 3114 Bind(&checkOverflow); 3115 BRANCH(Int64GreaterThan(Int64Sub(Int64Add(ZExtInt32ToInt64(arrayLen), ZExtInt32ToInt64(*insertCount)), 3116 ZExtInt32ToInt64(*actualDeleteCount)), Int64(base::MAX_SAFE_INTEGER)), slowPath, ¬Overflow); 3117 Bind(¬Overflow); 3118 *result = CreateSpliceDeletedArray(glue, thisValue, *actualDeleteCount, arrayCls, *start); 3119 // insert Val 3120 DEFVARIABLE(srcElements, VariableType::JS_ANY(), GetElementsArray(thisValue)); 3121 GateRef oldCapacity = GetLengthOfTaggedArray(*srcElements); 3122 GateRef newCapacity = Int32Add(Int32Sub(arrayLen, *actualDeleteCount), *insertCount); 3123 Label grow(env); 3124 Label copy(env); 3125 BRANCH(Int32GreaterThan(newCapacity, oldCapacity), &grow, ©); 3126 Bind(&grow); 3127 { 3128 srcElements = GrowElementsCapacity(glue, thisValue, newCapacity); 3129 Jump(©); 3130 } 3131 Bind(©); 3132 GateRef srcElementsLen = GetLengthOfTaggedArray(*srcElements); 3133 Label insertLessDelete(env); 3134 Label insertGreaterDelete(env); 3135 Label insertCountVal(env); 3136 Label setArrayLen(env); 3137 Label trimCheck(env); 3138 BRANCH(Int32LessThan(*insertCount, *actualDeleteCount), &insertLessDelete, &insertGreaterDelete); 3139 Bind(&insertLessDelete); 3140 { 3141 { 3142 DEFVARIABLE(i, VariableType::INT32(), *start); 3143 DEFVARIABLE(ele, VariableType::JS_ANY(), Hole()); 3144 3145 Label loopHead(env); 3146 Label loopEnd(env); 3147 Label next(env); 3148 Label loopExit(env); 3149 Jump(&loopHead); 3150 LoopBegin(&loopHead); 3151 { 3152 BRANCH(Int32LessThan(*i, Int32Sub(arrayLen, *actualDeleteCount)), &next, &loopExit); 3153 Bind(&next); 3154 ele = Hole(); 3155 Label getSrcEle(env); 3156 Label setEle(env); 3157 BRANCH(Int32LessThan(Int32Add(*i, *actualDeleteCount), srcElementsLen), &getSrcEle, &setEle); 3158 Bind(&getSrcEle); 3159 { 3160 ele = GetTaggedValueWithElementsKind(thisValue, Int32Add(*i, *actualDeleteCount)); 3161 Jump(&setEle); 3162 } 3163 Bind(&setEle); 3164 { 3165 Label setIndexLessLen(env); 3166 BRANCH(Int32LessThan(Int32Add(*i, *insertCount), srcElementsLen), &setIndexLessLen, &loopEnd); 3167 Bind(&setIndexLessLen); 3168 { 3169 SetValueWithElementsKind(glue, thisValue, *ele, Int32Add(*i, *insertCount), Boolean(true), 3170 Int32(static_cast<uint32_t>(ElementsKind::NONE))); 3171 Jump(&loopEnd); 3172 } 3173 } 3174 } 3175 Bind(&loopEnd); 3176 i = Int32Add(*i, Int32(1)); 3177 LoopEnd(&loopHead, env, glue); 3178 Bind(&loopExit); 3179 Jump(&trimCheck); 3180 } 3181 3182 Label trim(env); 3183 Label noTrim(env); 3184 Bind(&trimCheck); 3185 GateRef needTrim = LogicAndBuilder(env) 3186 .And(Int32GreaterThan(oldCapacity, newCapacity)) 3187 .And(Int32GreaterThan(Int32Sub(newCapacity, oldCapacity), Int32(TaggedArray::MAX_END_UNUSED))) 3188 .Done(); 3189 BRANCH(needTrim, &trim, &noTrim); 3190 Bind(&trim); 3191 { 3192 CallNGCRuntime(glue, RTSTUB_ID(ArrayTrim), {glue, *srcElements, ZExtInt32ToInt64(newCapacity)}); 3193 Jump(&insertCountVal); 3194 } 3195 Bind(&noTrim); 3196 { 3197 DEFVARIABLE(idx, VariableType::INT32(), newCapacity); 3198 Label loopHead1(env); 3199 Label loopEnd1(env); 3200 Label next1(env); 3201 Label loopExit1(env); 3202 Jump(&loopHead1); 3203 LoopBegin(&loopHead1); 3204 { 3205 BRANCH(Int32LessThan(*idx, arrayLen), &next1, &loopExit1); 3206 Bind(&next1); 3207 3208 Label setHole(env); 3209 BRANCH(Int32LessThan(*idx, srcElementsLen), &setHole, &loopEnd1); 3210 Bind(&setHole); 3211 { 3212 SetValueWithElementsKind(glue, thisValue, Hole(), *idx, Boolean(true), 3213 Int32(static_cast<uint32_t>(ElementsKind::NONE))); 3214 Jump(&loopEnd1); 3215 } 3216 } 3217 Bind(&loopEnd1); 3218 idx = Int32Add(*idx, Int32(1)); 3219 LoopEnd(&loopHead1); 3220 Bind(&loopExit1); 3221 Jump(&insertCountVal); 3222 } 3223 Bind(&insertGreaterDelete); 3224 { 3225 DEFVARIABLE(j, VariableType::INT32(), Int32Sub(arrayLen, *actualDeleteCount)); 3226 DEFVARIABLE(ele, VariableType::JS_ANY(), Hole()); 3227 Label loopHead(env); 3228 Label loopEnd(env); 3229 Label next(env); 3230 Label loopExit(env); 3231 Jump(&loopHead); 3232 LoopBegin(&loopHead); 3233 { 3234 BRANCH(Int32GreaterThan(*j, *start), &next, &loopExit); 3235 Bind(&next); 3236 ele = GetTaggedValueWithElementsKind(thisValue, Int32Sub(Int32Add(*j, *actualDeleteCount), 3237 Int32(1))); 3238 SetValueWithElementsKind(glue, thisValue, *ele, Int32Sub(Int32Add(*j, *insertCount), Int32(1)), 3239 Boolean(true), Int32(static_cast<uint32_t>(ElementsKind::NONE))); 3240 Jump(&loopEnd); 3241 } 3242 Bind(&loopEnd); 3243 j = Int32Sub(*j, Int32(1)); 3244 LoopEnd(&loopHead, env, glue); 3245 Bind(&loopExit); 3246 Jump(&insertCountVal); 3247 } 3248 Bind(&insertCountVal); 3249 { 3250 Label threeArgs(env); 3251 BRANCH(Int32Equal(ChangeIntPtrToInt32(numArgs), Int32(3)), &threeArgs, &setArrayLen); // 3 : three arg 3252 Bind(&threeArgs); 3253 { 3254 GateRef e = GetCallArg2(numArgs); 3255 SetValueWithElementsKind(glue, thisValue, e, *start, Boolean(true), 3256 Int32(static_cast<uint32_t>(ElementsKind::NONE))); 3257 Jump(&setArrayLen); 3258 } 3259 } 3260 Bind(&setArrayLen); 3261 SetArrayLength(glue, thisValue, newCapacity); 3262 Jump(exit); 3263 } 3264 } 3265} 3266 3267void BuiltinsArrayStubBuilder::ToSpliced(GateRef glue, GateRef thisValue, GateRef numArgs, 3268 Variable *result, Label *exit, Label *slowPath) 3269{ 3270 auto env = GetEnvironment(); 3271 Label isHeapObject(env); 3272 Label isJsArray(env); 3273 Label isStability(env); 3274 Label defaultConstr(env); 3275 Label matchCls(env); 3276 Label isGeneric(env); 3277 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath); 3278 Bind(&isHeapObject); 3279 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath); 3280 Bind(&isJsArray); 3281 BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr); 3282 Bind(&defaultConstr); 3283 BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath); 3284 Bind(&isStability); 3285 Label notCOWArray(env); 3286 BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray); 3287 Bind(¬COWArray); 3288 GateRef arrayCls = LoadHClass(thisValue); 3289 ElementsKindHclassCompare(glue, arrayCls, &matchCls, slowPath); 3290 Bind(&matchCls); 3291 GateRef thisLen = GetArrayLength(thisValue); 3292 Label lessThreeArg(env); 3293 DEFVARIABLE(actualStart, VariableType::INT32(), Int32(0)); 3294 DEFVARIABLE(actualDeleteCount, VariableType::INT32(), Int32(0)); 3295 DEFVARIABLE(newLen, VariableType::INT32(), Int32(0)); 3296 DEFVARIABLE(insertCount, VariableType::INT32(), Int32(0)); 3297 GateRef argc = ChangeIntPtrToInt32(numArgs); 3298 // 3: max arg count 3299 BRANCH(Int32LessThanOrEqual(argc, Int32(3)), &lessThreeArg, slowPath); 3300 Bind(&lessThreeArg); 3301 { 3302 Label checkOverFlow(env); 3303 Label greaterZero(env); 3304 Label greaterOne(env); 3305 Label checkGreaterOne(env); 3306 Label notOverFlow(env); 3307 Label copyAfter(env); 3308 // 0: judge the first arg exists 3309 BRANCH(Int32GreaterThan(argc, Int32(0)), &greaterZero, &checkGreaterOne); 3310 Bind(&greaterZero); 3311 { 3312 GateRef taggedStart = GetCallArg0(numArgs); 3313 Label taggedStartInt(env); 3314 BRANCH(TaggedIsInt(taggedStart), &taggedStartInt, slowPath); 3315 Bind(&taggedStartInt); 3316 { 3317 GateRef intStart = GetInt32OfTInt(taggedStart); 3318 actualStart = CalArrayRelativePos(intStart, thisLen); 3319 actualDeleteCount = Int32Sub(thisLen, *actualStart); 3320 Jump(&checkGreaterOne); 3321 } 3322 } 3323 Bind(&checkGreaterOne); 3324 { 3325 // 1: judge the second arg exists 3326 BRANCH(Int32GreaterThan(argc, Int32(1)), &greaterOne, &checkOverFlow); 3327 Bind(&greaterOne); 3328 { 3329 // 2: arg count which is not an item 3330 insertCount = Int32Sub(argc, Int32(2)); 3331 GateRef argDeleteCount = GetCallArg1(numArgs); 3332 Label argDeleteCountInt(env); 3333 BRANCH(TaggedIsInt(argDeleteCount), &argDeleteCountInt, slowPath); 3334 Bind(&argDeleteCountInt); 3335 { 3336 DEFVARIABLE(deleteCount, VariableType::INT32(), TaggedGetInt(argDeleteCount)); 3337 Label deleteCountLessZero(env); 3338 Label calActualDeleteCount(env); 3339 BRANCH(Int32LessThan(*deleteCount, Int32(0)), &deleteCountLessZero, &calActualDeleteCount); 3340 Bind(&deleteCountLessZero); 3341 { 3342 deleteCount = Int32(0); 3343 Jump(&calActualDeleteCount); 3344 } 3345 Bind(&calActualDeleteCount); 3346 { 3347 actualDeleteCount = *deleteCount; 3348 Label lessArrayLen(env); 3349 BRANCH(Int32LessThan(Int32Sub(thisLen, *actualStart), *deleteCount), 3350 &lessArrayLen, &checkOverFlow); 3351 Bind(&lessArrayLen); 3352 { 3353 actualDeleteCount = Int32Sub(thisLen, *actualStart); 3354 Jump(&checkOverFlow); 3355 } 3356 } 3357 } 3358 } 3359 Bind(&checkOverFlow); 3360 { 3361 newLen = Int32Add(Int32Sub(thisLen, *actualDeleteCount), *insertCount); 3362 BRANCH(Int64GreaterThan(ZExtInt32ToInt64(*newLen), Int64(base::MAX_SAFE_INTEGER)), 3363 slowPath, ¬OverFlow); 3364 Bind(¬OverFlow); 3365 Label newLenEmpty(env); 3366 Label newLenNotEmpty(env); 3367 BRANCH(Int32Equal(*newLen, Int32(0)), &newLenEmpty, &newLenNotEmpty); 3368 Bind(&newLenEmpty); 3369 { 3370 NewObjectStubBuilder newBuilder(this); 3371 result->WriteVariable(newBuilder.CreateEmptyArray(glue)); 3372 Jump(exit); 3373 } 3374 Bind(&newLenNotEmpty); 3375 { 3376 Label copyBefore(env); 3377 Label insertArg(env); 3378 GateRef newArray = NewArray(glue, Int32(0)); 3379 GrowElementsCapacity(glue, newArray, *newLen); 3380 DEFVARIABLE(oldIndex, VariableType::INT32(), Int32(0)); 3381 DEFVARIABLE(newIndex, VariableType::INT32(), Int32(0)); 3382 BRANCH(Int32GreaterThan(*actualStart, Int32(0)), ©Before, &insertArg); 3383 Bind(©Before); 3384 { 3385 Label loopHead(env); 3386 Label loopEnd(env); 3387 Label loopNext(env); 3388 Label loopExit(env); 3389 Label eleIsHole(env); 3390 Label eleNotHole(env); 3391 Jump(&loopHead); 3392 LoopBegin(&loopHead); 3393 { 3394 BRANCH(Int32LessThan(*oldIndex, *actualStart), &loopNext, &loopExit); 3395 Bind(&loopNext); 3396 GateRef ele = GetTaggedValueWithElementsKind(thisValue, *oldIndex); 3397 BRANCH(TaggedIsHole(ele), &eleIsHole, &eleNotHole); 3398 Bind(&eleIsHole); 3399 { 3400 SetValueWithElementsKind(glue, newArray, Undefined(), *newIndex, Boolean(true), 3401 Int32(static_cast<uint32_t>(ElementsKind::NONE))); 3402 Jump(&loopEnd); 3403 } 3404 Bind(&eleNotHole); 3405 { 3406 SetValueWithElementsKind(glue, newArray, ele, *newIndex, Boolean(true), 3407 Int32(static_cast<uint32_t>(ElementsKind::NONE))); 3408 Jump(&loopEnd); 3409 } 3410 } 3411 Bind(&loopEnd); 3412 oldIndex = Int32Add(*oldIndex, Int32(1)); 3413 newIndex = Int32Add(*newIndex, Int32(1)); 3414 LoopEnd(&loopHead); 3415 Bind(&loopExit); 3416 Jump(&insertArg); 3417 } 3418 Bind(&insertArg); 3419 { 3420 Label insert(env); 3421 BRANCH(Int32GreaterThan(*insertCount, Int32(0)), &insert, ©After); 3422 Bind(&insert); 3423 { 3424 GateRef insertNum = GetCallArg2(numArgs); 3425 SetValueWithElementsKind(glue, newArray, insertNum, *newIndex, Boolean(true), 3426 Int32(static_cast<uint32_t>(ElementsKind::NONE))); 3427 newIndex = Int32Add(*newIndex, Int32(1)); 3428 Jump(©After); 3429 } 3430 } 3431 Bind(©After); 3432 { 3433 Label canCopyAfter(env); 3434 Label setLength(env); 3435 oldIndex = Int32Add(*actualStart, *actualDeleteCount); 3436 BRANCH(Int32LessThan(*oldIndex, thisLen), &canCopyAfter, &setLength); 3437 Bind(&canCopyAfter); 3438 { 3439 Label loopHead1(env); 3440 Label loopNext1(env); 3441 Label loopEnd1(env); 3442 Label loopExit1(env); 3443 Label ele1IsHole(env); 3444 Label ele1NotHole(env); 3445 Jump(&loopHead1); 3446 LoopBegin(&loopHead1); 3447 { 3448 BRANCH(Int32LessThan(*oldIndex, thisLen), &loopNext1, &loopExit1); 3449 Bind(&loopNext1); 3450 GateRef ele1 = GetTaggedValueWithElementsKind(thisValue, *oldIndex); 3451 BRANCH(TaggedIsHole(ele1), &ele1IsHole, &ele1NotHole); 3452 Bind(&ele1IsHole); 3453 { 3454 SetValueWithElementsKind(glue, newArray, Undefined(), *newIndex, Boolean(true), 3455 Int32(static_cast<uint32_t>(ElementsKind::NONE))); 3456 Jump(&loopEnd1); 3457 } 3458 Bind(&ele1NotHole); 3459 { 3460 SetValueWithElementsKind(glue, newArray, ele1, *newIndex, Boolean(true), 3461 Int32(static_cast<uint32_t>(ElementsKind::NONE))); 3462 Jump(&loopEnd1); 3463 } 3464 } 3465 Bind(&loopEnd1); 3466 oldIndex = Int32Add(*oldIndex, Int32(1)); 3467 newIndex = Int32Add(*newIndex, Int32(1)); 3468 LoopEnd(&loopHead1); 3469 Bind(&loopExit1); 3470 Jump(&setLength); 3471 } 3472 Bind(&setLength); 3473 { 3474 SetArrayLength(glue, newArray, *newLen); 3475 result->WriteVariable(newArray); 3476 Jump(exit); 3477 } 3478 } 3479 } 3480 } 3481 } 3482 } 3483} 3484 3485void BuiltinsArrayStubBuilder::CopyWithin(GateRef glue, GateRef thisValue, GateRef numArgs, 3486 Variable *result, Label *exit, Label *slowPath) 3487{ 3488 auto env = GetEnvironment(); 3489 Label thisExists(env); 3490 Label isHeapObject(env); 3491 Label isJsArray(env); 3492 Label defaultConstr(env); 3493 Label isStability(env); 3494 Label isGeneric(env); 3495 Label notCOWArray(env); 3496 Label matchCls(env); 3497 BRANCH(TaggedIsUndefinedOrNull(thisValue), slowPath, &thisExists); 3498 Bind(&thisExists); 3499 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath); 3500 Bind(&isHeapObject); 3501 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath); 3502 Bind(&isJsArray); 3503 BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr); 3504 Bind(&defaultConstr); 3505 BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath); 3506 Bind(&isStability); 3507 BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray); 3508 Bind(¬COWArray); 3509 GateRef arrayCls = LoadHClass(thisValue); 3510 ElementsKindHclassCompare(glue, arrayCls, &matchCls, slowPath); 3511 Bind(&matchCls); 3512 DEFVARIABLE(startPos, VariableType::INT64(), Int64(0)); 3513 DEFVARIABLE(endPos, VariableType::INT64(), Int64(0)); 3514 Label targetTagExists(env); 3515 Label targetTagIsInt(env); 3516 Label startTagExists(env); 3517 Label startTagIsInt(env); 3518 Label afterCallArg1(env); 3519 Label endTagExists(env); 3520 Label endTagIsInt(env); 3521 Label afterCallArg2(env); 3522 GateRef thisLen = ZExtInt32ToInt64(GetArrayLength(thisValue)); 3523 BRANCH(Int64GreaterThanOrEqual(IntPtr(0), numArgs), slowPath, &targetTagExists); 3524 Bind(&targetTagExists); 3525 GateRef targetTag = GetCallArg0(numArgs); 3526 BRANCH(TaggedIsInt(targetTag), &targetTagIsInt, slowPath); 3527 Bind(&targetTagIsInt); 3528 GateRef argTarget = SExtInt32ToInt64(TaggedGetInt(targetTag)); 3529 BRANCH(Int64GreaterThanOrEqual(IntPtr(1), numArgs), &afterCallArg1, &startTagExists); 3530 Bind(&startTagExists); 3531 { 3532 GateRef startTag = GetCallArg1(numArgs); 3533 BRANCH(TaggedIsInt(startTag), &startTagIsInt, slowPath); 3534 Bind(&startTagIsInt); 3535 startPos = SExtInt32ToInt64(TaggedGetInt(startTag)); 3536 Jump(&afterCallArg1); 3537 } 3538 Bind(&afterCallArg1); 3539 { 3540 endPos = thisLen; 3541 BRANCH(Int64GreaterThanOrEqual(IntPtr(2), numArgs), &afterCallArg2, &endTagExists); 3542 Bind(&endTagExists); 3543 { 3544 GateRef endTag = GetCallArg2(numArgs); 3545 BRANCH(TaggedIsInt(endTag), &endTagIsInt, slowPath); 3546 Bind(&endTagIsInt); 3547 { 3548 endPos = SExtInt32ToInt64(TaggedGetInt(endTag)); 3549 Jump(&afterCallArg2); 3550 } 3551 } 3552 } 3553 Bind(&afterCallArg2); 3554 { 3555 DEFVARIABLE(copyTo, VariableType::INT64(), Int64(0)); 3556 DEFVARIABLE(copyFrom, VariableType::INT64(), Int64(0)); 3557 DEFVARIABLE(copyEnd, VariableType::INT64(), Int64(0)); 3558 DEFVARIABLE(count, VariableType::INT64(), Int64(0)); 3559 DEFVARIABLE(direction, VariableType::INT64(), Int64(0)); 3560 Label calculateCountBranch1(env); 3561 Label calculateCountBranch2(env); 3562 Label afterCalculateCount(env); 3563 Label needToAdjustParam(env); 3564 Label afterAdjustParam(env); 3565 copyTo = CalculatePositionWithLength(argTarget, thisLen); 3566 copyFrom = CalculatePositionWithLength(*startPos, thisLen); 3567 copyEnd = CalculatePositionWithLength(*endPos, thisLen); 3568 BRANCH(Int64LessThan(Int64Sub(*copyEnd, *copyFrom), Int64Sub(thisLen, *copyTo)), 3569 &calculateCountBranch1, &calculateCountBranch2); 3570 Bind(&calculateCountBranch1); 3571 { 3572 count = Int64Sub(*copyEnd, *copyFrom); 3573 Jump(&afterCalculateCount); 3574 } 3575 Bind(&calculateCountBranch2); 3576 { 3577 count = Int64Sub(thisLen, *copyTo); 3578 Jump(&afterCalculateCount); 3579 } 3580 3581 Bind(&afterCalculateCount); 3582 { 3583 direction = Int64(1); 3584 GateRef copyFromVal = *copyFrom; 3585 GateRef copyToVal = *copyTo; 3586 GateRef countVal = *count; 3587 BRANCH(LogicAndBuilder(env).And(Int64LessThan(copyFromVal, copyToVal)) 3588 .And(Int64LessThan(copyToVal, Int64Add(copyFromVal, countVal))).Done(), 3589 &needToAdjustParam, &afterAdjustParam); 3590 Bind(&needToAdjustParam); 3591 { 3592 direction = Int64(-1); 3593 copyFrom = Int64Sub(Int64Add(*copyFrom, *count), Int64(1)); 3594 copyTo = Int64Sub(Int64Add(*copyTo, *count), Int64(1)); 3595 Jump(&afterAdjustParam); 3596 } 3597 3598 Bind(&afterAdjustParam); 3599 { 3600 DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole()); 3601 Label loopHead(env); 3602 Label loopEnd(env); 3603 Label next(env); 3604 Label loopExit(env); 3605 Jump(&loopHead); 3606 LoopBegin(&loopHead); 3607 { 3608 Label kValueIsHole(env); 3609 Label setValue(env); 3610 Label hasProperty(env); 3611 Label setHole(env); 3612 Label hasException0(env); 3613 Label notHasException0(env); 3614 BRANCH(Int64GreaterThan(*count, Int64(0)), &next, &loopExit); 3615 Bind(&next); 3616 kValue = GetTaggedValueWithElementsKind(thisValue, *copyFrom); 3617 BRANCH(TaggedIsHole(*kValue), &kValueIsHole, &setValue); 3618 Bind(&kValueIsHole); 3619 GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), 3620 { thisValue, IntToTaggedInt(*copyFrom) }); 3621 BRANCH(TaggedIsTrue(hasProp), &hasProperty, &setHole); 3622 3623 Bind(&hasProperty); 3624 kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*copyFrom), ProfileOperation()); 3625 BRANCH(HasPendingException(glue), &hasException0, ¬HasException0); 3626 Bind(&hasException0); 3627 { 3628 result->WriteVariable(Exception()); 3629 Jump(exit); 3630 } 3631 Bind(¬HasException0); 3632 BRANCH(TaggedIsHole(*kValue), &setHole, &setValue); 3633 Bind(&setHole); 3634 { 3635 SetValueWithElementsKind(glue, thisValue, Hole(), *copyTo, 3636 Boolean(true), Int32(static_cast<uint32_t>(ElementsKind::DICTIONARY))); 3637 Jump(&loopEnd); 3638 } 3639 Bind(&setValue); 3640 { 3641 SetValueWithElementsKind(glue, thisValue, *kValue, *copyTo, 3642 Boolean(true), Int32(static_cast<uint32_t>(ElementsKind::NONE))); 3643 Jump(&loopEnd); 3644 } 3645 } 3646 Bind(&loopEnd); 3647 copyFrom = Int64Add(*copyFrom, *direction); 3648 copyTo = Int64Add(*copyTo, *direction); 3649 count = Int64Sub(*count, Int64(1)); 3650 LoopEnd(&loopHead); 3651 Bind(&loopExit); 3652 result->WriteVariable(thisValue); 3653 Jump(exit); 3654 } 3655 } 3656 } 3657} 3658 3659GateRef BuiltinsArrayStubBuilder::CalculatePositionWithLength(GateRef position, GateRef length) 3660{ 3661 auto env = GetEnvironment(); 3662 Label entry(env); 3663 env->SubCfgEntry(&entry); 3664 DEFVARIABLE(result, VariableType::INT64(), Int64(0)); 3665 Label positionLessThanZero(env); 3666 Label positionNotLessThanZero(env); 3667 Label resultNotGreaterThanZero(env); 3668 Label positionLessThanLength(env); 3669 Label positionNotLessThanLength(env); 3670 Label afterCalculatePosition(env); 3671 3672 BRANCH(Int64LessThan(position, Int64(0)), &positionLessThanZero, &positionNotLessThanZero); 3673 Bind(&positionLessThanZero); 3674 { 3675 result = Int64Add(position, length); 3676 BRANCH(Int64GreaterThan(*result, Int64(0)), &afterCalculatePosition, &resultNotGreaterThanZero); 3677 Bind(&resultNotGreaterThanZero); 3678 result = Int64(0); 3679 Jump(&afterCalculatePosition); 3680 } 3681 Bind(&positionNotLessThanZero); 3682 { 3683 BRANCH(Int64LessThan(position, length), &positionLessThanLength, &positionNotLessThanLength); 3684 Bind(&positionLessThanLength); 3685 { 3686 result = position; 3687 Jump(&afterCalculatePosition); 3688 } 3689 Bind(&positionNotLessThanLength); 3690 { 3691 result = length; 3692 Jump(&afterCalculatePosition); 3693 } 3694 } 3695 Bind(&afterCalculatePosition); 3696 auto ret = *result; 3697 env->SubCfgExit(); 3698 return ret; 3699} 3700 3701void BuiltinsArrayStubBuilder::Some(GateRef glue, GateRef thisValue, GateRef numArgs, 3702 Variable *result, Label *exit, Label *slowPath) 3703{ 3704 auto env = GetEnvironment(); 3705 Label thisExists(env); 3706 Label isHeapObject(env); 3707 Label isJsArray(env); 3708 Label defaultConstr(env); 3709 Label isStability(env); 3710 Label notCOWArray(env); 3711 Label equalCls(env); 3712 Label matchCls(env); 3713 Label isGeneric(env); 3714 BRANCH(TaggedIsUndefinedOrNull(thisValue), slowPath, &thisExists); 3715 Bind(&thisExists); 3716 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath); 3717 Bind(&isHeapObject); 3718 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath); 3719 Bind(&isJsArray); 3720 BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr); 3721 Bind(&defaultConstr); 3722 BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath); 3723 Bind(&isStability); 3724 BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray); 3725 Bind(¬COWArray); 3726 GateRef arrayCls = LoadHClass(thisValue); 3727 ElementsKindHclassCompare(glue, arrayCls, &matchCls, slowPath); 3728 Bind(&matchCls); 3729 Label arg0HeapObject(env); 3730 Label callable(env); 3731 Label thisIsStable(env); 3732 Label thisNotStable(env); 3733 GateRef callbackFnHandle = GetCallArg0(numArgs); 3734 BRANCH(TaggedIsHeapObject(callbackFnHandle), &arg0HeapObject, slowPath); 3735 Bind(&arg0HeapObject); 3736 BRANCH(IsCallable(callbackFnHandle), &callable, slowPath); 3737 Bind(&callable); 3738 GateRef argHandle = GetCallArg1(numArgs); 3739 3740 DEFVARIABLE(i, VariableType::INT64(), Int64(0)); 3741 DEFVARIABLE(thisArrLen, VariableType::INT64(), ZExtInt32ToInt64(GetArrayLength(thisValue))); 3742 Jump(&thisIsStable); 3743 3744 Bind(&thisIsStable); 3745 { 3746 DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole()); 3747 Label loopHead(env); 3748 Label loopEnd(env); 3749 Label next(env); 3750 Label loopExit(env); 3751 Jump(&loopHead); 3752 LoopBegin(&loopHead); 3753 { 3754 Label nextStep(env); 3755 Label kValueIsHole(env); 3756 Label callDispatch(env); 3757 Label hasProperty(env); 3758 Label hasException0(env); 3759 Label notHasException0(env); 3760 Label hasException1(env); 3761 Label notHasException1(env); 3762 BRANCH(IsStableJSArray(glue, thisValue), &nextStep, &thisNotStable); 3763 Bind(&nextStep); 3764 BRANCH(Int64LessThan(*i, *thisArrLen), &next, &loopExit); 3765 Bind(&next); 3766 kValue = GetTaggedValueWithElementsKind(thisValue, *i); 3767 BRANCH(TaggedIsHole(*kValue), &kValueIsHole, &callDispatch); 3768 Bind(&kValueIsHole); 3769 { 3770 GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*i) }); 3771 BRANCH(TaggedIsTrue(hasProp), &hasProperty, &loopEnd); 3772 Bind(&hasProperty); 3773 { 3774 kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation()); 3775 BRANCH(HasPendingException(glue), &hasException0, ¬HasException0); 3776 Bind(&hasException0); 3777 { 3778 result->WriteVariable(Exception()); 3779 Jump(exit); 3780 } 3781 Bind(¬HasException0); 3782 { 3783 BRANCH(TaggedIsHole(*kValue), &loopEnd, &callDispatch); 3784 } 3785 } 3786 } 3787 Bind(&callDispatch); 3788 { 3789 GateRef key = Int64ToTaggedInt(*i); 3790 JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN); 3791 callArgs.callThisArg3WithReturnArgs = { argHandle, *kValue, key, thisValue }; 3792 CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr, 3793 Circuit::NullGate(), callArgs); 3794 GateRef retValue = callBuilder.JSCallDispatch(); 3795 BRANCH(HasPendingException(glue), &hasException1, ¬HasException1); 3796 Bind(&hasException1); 3797 { 3798 result->WriteVariable(Exception()); 3799 Jump(exit); 3800 } 3801 Bind(¬HasException1); 3802 { 3803 DEFVARIABLE(newLen, VariableType::INT64(), ZExtInt32ToInt64(GetArrayLength(thisValue))); 3804 Label changeThisLen(env); 3805 Label afterChangeLen(env); 3806 Label retValueIsTrue(env); 3807 BRANCH(Int64LessThan(*newLen, *thisArrLen), &changeThisLen, &afterChangeLen); 3808 Bind(&changeThisLen); 3809 { 3810 thisArrLen = *newLen; 3811 Jump(&afterChangeLen); 3812 } 3813 Bind(&afterChangeLen); 3814 { 3815 BRANCH(TaggedIsTrue(FastToBoolean(retValue)), &retValueIsTrue, &loopEnd); 3816 Bind(&retValueIsTrue); 3817 { 3818 result->WriteVariable(TaggedTrue()); 3819 Jump(exit); 3820 } 3821 } 3822 } 3823 } 3824 } 3825 Bind(&loopEnd); 3826 i = Int64Add(*i, Int64(1)); 3827 LoopEnd(&loopHead); 3828 Bind(&loopExit); 3829 result->WriteVariable(TaggedFalse()); 3830 Jump(exit); 3831 } 3832 3833 Bind(&thisNotStable); 3834 { 3835 DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole()); 3836 Label loopHead(env); 3837 Label loopEnd(env); 3838 Label next(env); 3839 Label loopExit(env); 3840 Jump(&loopHead); 3841 LoopBegin(&loopHead); 3842 { 3843 Label hasProperty(env); 3844 Label hasException0(env); 3845 Label notHasException0(env); 3846 Label callDispatch(env); 3847 Label hasException1(env); 3848 Label notHasException1(env); 3849 BRANCH(Int64LessThan(*i, *thisArrLen), &next, &loopExit); 3850 Bind(&next); 3851 GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*i) }); 3852 BRANCH(TaggedIsTrue(hasProp), &hasProperty, &loopEnd); 3853 Bind(&hasProperty); 3854 { 3855 kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation()); 3856 BRANCH(HasPendingException(glue), &hasException0, ¬HasException0); 3857 Bind(&hasException0); 3858 { 3859 result->WriteVariable(Exception()); 3860 Jump(exit); 3861 } 3862 Bind(¬HasException0); 3863 { 3864 BRANCH(TaggedIsHole(*kValue), &loopEnd, &callDispatch); 3865 Bind(&callDispatch); 3866 { 3867 GateRef key = Int64ToTaggedInt(*i); 3868 JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN); 3869 callArgs.callThisArg3WithReturnArgs = { argHandle, *kValue, key, thisValue }; 3870 CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, 3871 nullptr, Circuit::NullGate(), callArgs); 3872 GateRef retValue = callBuilder.JSCallDispatch(); 3873 BRANCH(HasPendingException(glue), &hasException1, ¬HasException1); 3874 Bind(&hasException1); 3875 { 3876 result->WriteVariable(Exception()); 3877 Jump(exit); 3878 } 3879 Bind(¬HasException1); 3880 { 3881 Label retValueIsTrue(env); 3882 BRANCH(TaggedIsTrue(FastToBoolean(retValue)), &retValueIsTrue, &loopEnd); 3883 Bind(&retValueIsTrue); 3884 { 3885 result->WriteVariable(TaggedTrue()); 3886 Jump(exit); 3887 } 3888 } 3889 } 3890 } 3891 } 3892 } 3893 Bind(&loopEnd); 3894 i = Int64Add(*i, Int64(1)); 3895 LoopEnd(&loopHead); 3896 Bind(&loopExit); 3897 result->WriteVariable(TaggedFalse()); 3898 Jump(exit); 3899 } 3900} 3901 3902void BuiltinsArrayStubBuilder::Every(GateRef glue, GateRef thisValue, GateRef numArgs, 3903 Variable *result, Label *exit, Label *slowPath) 3904{ 3905 auto env = GetEnvironment(); 3906 Label thisExists(env); 3907 Label isHeapObject(env); 3908 Label isJsArray(env); 3909 Label defaultConstr(env); 3910 Label isStability(env); 3911 Label notCOWArray(env); 3912 Label equalCls(env); 3913 Label arg0HeapObject(env); 3914 Label callable(env); 3915 Label matchCls(env); 3916 Label isGeneric(env); 3917 BRANCH(TaggedIsUndefinedOrNull(thisValue), slowPath, &thisExists); 3918 Bind(&thisExists); 3919 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath); 3920 Bind(&isHeapObject); 3921 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath); 3922 Bind(&isJsArray); 3923 BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr); 3924 Bind(&defaultConstr); 3925 BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath); 3926 Bind(&isStability); 3927 BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray); 3928 Bind(¬COWArray); 3929 GateRef arrayCls = LoadHClass(thisValue); 3930 ElementsKindHclassCompare(glue, arrayCls, &matchCls, slowPath); 3931 Bind(&matchCls); 3932 GateRef callbackFnHandle = GetCallArg0(numArgs); 3933 BRANCH(TaggedIsHeapObject(callbackFnHandle), &arg0HeapObject, slowPath); 3934 Bind(&arg0HeapObject); 3935 BRANCH(IsCallable(callbackFnHandle), &callable, slowPath); 3936 Bind(&callable); 3937 3938 Label thisIsStable(env); 3939 Label thisNotStable(env); 3940 GateRef argHandle = GetCallArg1(numArgs); 3941 DEFVARIABLE(i, VariableType::INT64(), Int64(0)); 3942 DEFVARIABLE(thisArrLen, VariableType::INT64(), ZExtInt32ToInt64(GetArrayLength(thisValue))); 3943 Jump(&thisIsStable); 3944 3945 Bind(&thisIsStable); 3946 { 3947 DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole()); 3948 Label loopHead(env); 3949 Label loopEnd(env); 3950 Label next(env); 3951 Label loopExit(env); 3952 Jump(&loopHead); 3953 LoopBegin(&loopHead); 3954 { 3955 Label nextStep(env); 3956 Label kValueIsHole(env); 3957 Label callDispatch(env); 3958 Label hasProperty(env); 3959 Label hasException0(env); 3960 Label notHasException0(env); 3961 Label hasException1(env); 3962 Label notHasException1(env); 3963 BRANCH(IsStableJSArray(glue, thisValue), &nextStep, &thisNotStable); 3964 Bind(&nextStep); 3965 BRANCH(Int64LessThan(*i, *thisArrLen), &next, &loopExit); 3966 Bind(&next); 3967 kValue = GetTaggedValueWithElementsKind(thisValue, *i); 3968 BRANCH(TaggedIsHole(*kValue), &kValueIsHole, &callDispatch); 3969 Bind(&kValueIsHole); 3970 { 3971 GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*i) }); 3972 BRANCH(TaggedIsTrue(hasProp), &hasProperty, &loopEnd); 3973 Bind(&hasProperty); 3974 kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation()); 3975 BRANCH(HasPendingException(glue), &hasException0, ¬HasException0); 3976 Bind(&hasException0); 3977 { 3978 result->WriteVariable(Exception()); 3979 Jump(exit); 3980 } 3981 Bind(¬HasException0); 3982 BRANCH(TaggedIsHole(*kValue), &loopEnd, &callDispatch); 3983 } 3984 Bind(&callDispatch); 3985 { 3986 GateRef key = Int64ToTaggedInt(*i); 3987 JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN); 3988 callArgs.callThisArg3WithReturnArgs = { argHandle, *kValue, key, thisValue }; 3989 CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr, 3990 Circuit::NullGate(), callArgs); 3991 GateRef retValue = callBuilder.JSCallDispatch(); 3992 BRANCH(HasPendingException(glue), &hasException1, ¬HasException1); 3993 Bind(&hasException1); 3994 { 3995 result->WriteVariable(Exception()); 3996 Jump(exit); 3997 } 3998 Bind(¬HasException1); 3999 { 4000 DEFVARIABLE(newLen, VariableType::INT64(), ZExtInt32ToInt64(GetArrayLength(thisValue))); 4001 Label changeThisLen(env); 4002 Label afterChangeLen(env); 4003 Label retValueIsFalse(env); 4004 BRANCH(Int64LessThan(*newLen, *thisArrLen), &changeThisLen, &afterChangeLen); 4005 Bind(&changeThisLen); 4006 { 4007 thisArrLen = *newLen; 4008 Jump(&afterChangeLen); 4009 } 4010 Bind(&afterChangeLen); 4011 { 4012 BRANCH(TaggedIsFalse(FastToBoolean(retValue)), &retValueIsFalse, &loopEnd); 4013 Bind(&retValueIsFalse); 4014 result->WriteVariable(TaggedFalse()); 4015 Jump(exit); 4016 } 4017 } 4018 } 4019 } 4020 Bind(&loopEnd); 4021 i = Int64Add(*i, Int64(1)); 4022 LoopEnd(&loopHead); 4023 Bind(&loopExit); 4024 result->WriteVariable(TaggedTrue()); 4025 Jump(exit); 4026 } 4027 4028 Bind(&thisNotStable); 4029 { 4030 DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole()); 4031 Label loopHead(env); 4032 Label loopEnd(env); 4033 Label next(env); 4034 Label loopExit(env); 4035 Jump(&loopHead); 4036 LoopBegin(&loopHead); 4037 { 4038 Label hasProperty(env); 4039 Label hasException0(env); 4040 Label notHasException0(env); 4041 Label callDispatch(env); 4042 Label hasException1(env); 4043 Label notHasException1(env); 4044 BRANCH(Int64LessThan(*i, *thisArrLen), &next, &loopExit); 4045 Bind(&next); 4046 GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*i) }); 4047 BRANCH(TaggedIsTrue(hasProp), &hasProperty, &loopEnd); 4048 Bind(&hasProperty); 4049 kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation()); 4050 BRANCH(HasPendingException(glue), &hasException0, ¬HasException0); 4051 Bind(&hasException0); 4052 { 4053 result->WriteVariable(Exception()); 4054 Jump(exit); 4055 } 4056 Bind(¬HasException0); 4057 { 4058 BRANCH(TaggedIsHole(*kValue), &loopEnd, &callDispatch); 4059 Bind(&callDispatch); 4060 GateRef key = Int64ToTaggedInt(*i); 4061 JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN); 4062 callArgs.callThisArg3WithReturnArgs = { argHandle, *kValue, key, thisValue }; 4063 CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr, 4064 Circuit::NullGate(), callArgs); 4065 GateRef retValue = callBuilder.JSCallDispatch(); 4066 BRANCH(HasPendingException(glue), &hasException1, ¬HasException1); 4067 Bind(&hasException1); 4068 { 4069 result->WriteVariable(Exception()); 4070 Jump(exit); 4071 } 4072 Bind(¬HasException1); 4073 { 4074 Label retValueIsFalse(env); 4075 BRANCH(TaggedIsFalse(FastToBoolean(retValue)), &retValueIsFalse, &loopEnd); 4076 Bind(&retValueIsFalse); 4077 result->WriteVariable(TaggedFalse()); 4078 Jump(exit); 4079 } 4080 } 4081 } 4082 Bind(&loopEnd); 4083 i = Int64Add(*i, Int64(1)); 4084 LoopEnd(&loopHead); 4085 Bind(&loopExit); 4086 result->WriteVariable(TaggedTrue()); 4087 Jump(exit); 4088 } 4089} 4090 4091void BuiltinsArrayStubBuilder::ReduceRight(GateRef glue, GateRef thisValue, GateRef numArgs, 4092 Variable *result, Label *exit, Label *slowPath) 4093{ 4094 auto env = GetEnvironment(); 4095 Label thisExists(env); 4096 Label isHeapObject(env); 4097 Label isJsArray(env); 4098 Label defaultConstr(env); 4099 Label isStability(env); 4100 Label notCOWArray(env); 4101 Label equalCls(env); 4102 Label matchCls(env); 4103 Label isGeneric(env); 4104 BRANCH(TaggedIsUndefinedOrNull(thisValue), slowPath, &thisExists); 4105 Bind(&thisExists); 4106 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath); 4107 Bind(&isHeapObject); 4108 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath); 4109 Bind(&isJsArray); 4110 BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr); 4111 Bind(&defaultConstr); 4112 BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath); 4113 Bind(&isStability); 4114 BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray); 4115 Bind(¬COWArray); 4116 GateRef arrayCls = LoadHClass(thisValue); 4117 ElementsKindHclassCompare(glue, arrayCls, &matchCls, slowPath); 4118 Bind(&matchCls); 4119 DEFVARIABLE(thisLen, VariableType::INT32(), Int32(0)); 4120 DEFVARIABLE(accumulator, VariableType::JS_ANY(), Undefined()); 4121 DEFVARIABLE(k, VariableType::INT32(), Int32(0)); 4122 Label atLeastOneArg(env); 4123 Label callbackFnHandleHeapObject(env); 4124 Label callbackFnHandleCallable(env); 4125 Label updateAccumulator(env); 4126 Label thisIsStable(env); 4127 Label thisNotStable(env); 4128 thisLen = GetArrayLength(thisValue); 4129 BRANCH(Int64GreaterThanOrEqual(numArgs, IntPtr(1)), &atLeastOneArg, slowPath); 4130 Bind(&atLeastOneArg); 4131 GateRef callbackFnHandle = GetCallArg0(numArgs); 4132 BRANCH(TaggedIsHeapObject(callbackFnHandle), &callbackFnHandleHeapObject, slowPath); 4133 Bind(&callbackFnHandleHeapObject); 4134 BRANCH(IsCallable(callbackFnHandle), &callbackFnHandleCallable, slowPath); 4135 Bind(&callbackFnHandleCallable); 4136 GateRef numArgsLessThanTwo = Int64LessThan(numArgs, IntPtr(2)); // 2: callbackFn initialValue 4137 k = Int32Sub(*thisLen, Int32(1)); 4138 BRANCH(numArgsLessThanTwo, slowPath, &updateAccumulator); // 2: callbackFn initialValue 4139 Bind(&updateAccumulator); 4140 accumulator = GetCallArg1(numArgs); 4141 Jump(&thisIsStable); 4142 4143 Bind(&thisIsStable); 4144 { 4145 DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole()); 4146 GateRef argsLength = Int32(4); 4147 NewObjectStubBuilder newBuilder(this); 4148 GateRef argList = newBuilder.NewTaggedArray(glue, argsLength); 4149 Label loopHead(env); 4150 Label next(env); 4151 Label loopEnd(env); 4152 Label loopExit(env); 4153 Jump(&loopHead); 4154 LoopBegin(&loopHead); 4155 { 4156 Label nextStep(env); 4157 Label kValueIsHole(env); 4158 Label callDispatch(env); 4159 Label hasProperty(env); 4160 Label hasException0(env); 4161 Label notHasException0(env); 4162 Label hasException1(env); 4163 Label notHasException1(env); 4164 GateRef thisLenVal = *thisLen; 4165 BRANCH(LogicAndBuilder(env).And(IsStableJSArray(glue, thisValue)) 4166 .And(Int32Equal(thisLenVal, GetArrayLength(thisValue))).Done(), 4167 &nextStep, &thisNotStable); 4168 Bind(&nextStep); 4169 BRANCH(Int32GreaterThanOrEqual(*k, Int32(0)), &next, &loopExit); 4170 Bind(&next); 4171 kValue = GetTaggedValueWithElementsKind(thisValue, *k); 4172 BRANCH(TaggedIsHole(*kValue), &kValueIsHole, &callDispatch); 4173 Bind(&kValueIsHole); 4174 { 4175 GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*k) }); 4176 BRANCH(TaggedIsTrue(hasProp), &hasProperty, &loopEnd); 4177 Bind(&hasProperty); 4178 kValue = FastGetPropertyByIndex(glue, thisValue, *k, ProfileOperation()); 4179 BRANCH(HasPendingException(glue), &hasException0, ¬HasException0); 4180 Bind(&hasException0); 4181 result->WriteVariable(Exception()); 4182 Jump(exit); 4183 Bind(¬HasException0); 4184 BRANCH(TaggedIsHole(*kValue), &loopEnd, &callDispatch); 4185 } 4186 Bind(&callDispatch); 4187 { 4188 // callback param 0: accumulator 4189 SetValueToTaggedArray(VariableType::JS_ANY(), glue, argList, Int32(0), *accumulator); 4190 // callback param 1: currentValue 4191 SetValueToTaggedArray(VariableType::JS_ANY(), glue, argList, Int32(1), *kValue); 4192 // callback param 2: index 4193 SetValueToTaggedArray(VariableType::INT32(), glue, argList, Int32(2), IntToTaggedInt(*k)); 4194 // callback param 3: array 4195 SetValueToTaggedArray(VariableType::JS_ANY(), glue, argList, Int32(3), thisValue); 4196 GateRef argv = PtrAdd(argList, IntPtr(TaggedArray::DATA_OFFSET)); 4197 JSCallArgs callArgs(JSCallMode::CALL_THIS_ARGV_WITH_RETURN); 4198 callArgs.callThisArgvWithReturnArgs = { argsLength, argv, Undefined() }; 4199 CallStubBuilder callBuilder(this, glue, callbackFnHandle, argsLength, 0, nullptr, Circuit::NullGate(), 4200 callArgs); 4201 GateRef callResult = callBuilder.JSCallDispatch(); 4202 BRANCH(HasPendingException(glue), &hasException1, ¬HasException1); 4203 Bind(&hasException1); 4204 { 4205 result->WriteVariable(Exception()); 4206 Jump(exit); 4207 } 4208 4209 Bind(¬HasException1); 4210 { 4211 accumulator = callResult; 4212 Jump(&loopEnd); 4213 } 4214 } 4215 } 4216 Bind(&loopEnd); 4217 k = Int32Sub(*k, Int32(1)); 4218 LoopEnd(&loopHead); 4219 Bind(&loopExit); 4220 result->WriteVariable(*accumulator); 4221 Jump(exit); 4222 } 4223 4224 Bind(&thisNotStable); 4225 { 4226 DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole()); 4227 GateRef argsLength = Int32(4); 4228 NewObjectStubBuilder newBuilder(this); 4229 GateRef argList = newBuilder.NewTaggedArray(glue, argsLength); 4230 Label loopHead(env); 4231 Label next(env); 4232 Label loopEnd(env); 4233 Label loopExit(env); 4234 Jump(&loopHead); 4235 LoopBegin(&loopHead); 4236 { 4237 Label hasProperty(env); 4238 Label hasException0(env); 4239 Label notHasException0(env); 4240 Label callDispatch(env); 4241 Label hasException1(env); 4242 Label notHasException1(env); 4243 BRANCH(Int32GreaterThanOrEqual(*k, Int32(0)), &next, &loopExit); 4244 Bind(&next); 4245 GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*k) }); 4246 BRANCH(TaggedIsTrue(hasProp), &hasProperty, &loopEnd); 4247 Bind(&hasProperty); 4248 kValue = FastGetPropertyByIndex(glue, thisValue, *k, ProfileOperation()); 4249 BRANCH(HasPendingException(glue), &hasException0, ¬HasException0); 4250 Bind(&hasException0); 4251 result->WriteVariable(Exception()); 4252 Jump(exit); 4253 Bind(¬HasException0); 4254 BRANCH(TaggedIsHole(*kValue), &loopEnd, &callDispatch); 4255 Bind(&callDispatch); 4256 { 4257 // callback param 0: accumulator 4258 SetValueToTaggedArray(VariableType::JS_ANY(), glue, argList, Int32(0), *accumulator); 4259 // callback param 1: currentValue 4260 SetValueToTaggedArray(VariableType::JS_ANY(), glue, argList, Int32(1), *kValue); 4261 // callback param 2: index 4262 SetValueToTaggedArray(VariableType::INT32(), glue, argList, Int32(2), IntToTaggedInt(*k)); 4263 // callback param 3: array 4264 SetValueToTaggedArray(VariableType::JS_ANY(), glue, argList, Int32(3), thisValue); 4265 GateRef argv = PtrAdd(argList, IntPtr(TaggedArray::DATA_OFFSET)); 4266 JSCallArgs callArgs(JSCallMode::CALL_THIS_ARGV_WITH_RETURN); 4267 callArgs.callThisArgvWithReturnArgs = { argsLength, argv, Undefined() }; 4268 CallStubBuilder callBuilder(this, glue, callbackFnHandle, argsLength, 0, nullptr, Circuit::NullGate(), 4269 callArgs); 4270 GateRef callResult = callBuilder.JSCallDispatch(); 4271 BRANCH(HasPendingException(glue), &hasException1, ¬HasException1); 4272 Bind(&hasException1); 4273 { 4274 result->WriteVariable(Exception()); 4275 Jump(exit); 4276 } 4277 4278 Bind(¬HasException1); 4279 { 4280 accumulator = callResult; 4281 Jump(&loopEnd); 4282 } 4283 } 4284 } 4285 Bind(&loopEnd); 4286 k = Int32Sub(*k, Int32(1)); 4287 LoopEnd(&loopHead); 4288 Bind(&loopExit); 4289 result->WriteVariable(*accumulator); 4290 Jump(exit); 4291 } 4292} 4293 4294void BuiltinsArrayStubBuilder::FindLastIndex(GateRef glue, GateRef thisValue, GateRef numArgs, 4295 Variable *result, Label *exit, Label *slowPath) 4296{ 4297 auto env = GetEnvironment(); 4298 Label thisExists(env); 4299 Label isHeapObject(env); 4300 Label isJsArray(env); 4301 Label defaultConstr(env); 4302 Label isStability(env); 4303 Label notCOWArray(env); 4304 Label equalCls(env); 4305 Label isGeneric(env); 4306 Label matchCls(env); 4307 BRANCH(TaggedIsUndefinedOrNull(thisValue), slowPath, &thisExists); 4308 Bind(&thisExists); 4309 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath); 4310 Bind(&isHeapObject); 4311 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath); 4312 Bind(&isJsArray); 4313 BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr); 4314 Bind(&defaultConstr); 4315 BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath); 4316 Bind(&isStability); 4317 BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray); 4318 Bind(¬COWArray); 4319 GateRef arrayCls = LoadHClass(thisValue); 4320 ElementsKindHclassCompare(glue, arrayCls, &matchCls, slowPath); 4321 Bind(&matchCls); 4322 Label arg0HeapObject(env); 4323 Label callable(env); 4324 Label thisIsStable(env); 4325 Label thisNotStable(env); 4326 GateRef callbackFnHandle = GetCallArg0(numArgs); 4327 BRANCH(TaggedIsHeapObject(callbackFnHandle), &arg0HeapObject, slowPath); 4328 Bind(&arg0HeapObject); 4329 BRANCH(IsCallable(callbackFnHandle), &callable, slowPath); 4330 Bind(&callable); 4331 GateRef argHandle = GetCallArg1(numArgs); 4332 4333 DEFVARIABLE(i, VariableType::INT64(), Int64Sub(ZExtInt32ToInt64(GetArrayLength(thisValue)), Int64(1))); 4334 Jump(&thisIsStable); 4335 4336 Bind(&thisIsStable); 4337 { 4338 DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole()); 4339 Label loopHead(env); 4340 Label loopEnd(env); 4341 Label next(env); 4342 Label loopExit(env); 4343 Jump(&loopHead); 4344 LoopBegin(&loopHead); 4345 { 4346 Label nextStep(env); 4347 Label kValueIsHole(env); 4348 Label callDispatch(env); 4349 Label hasProperty(env); 4350 Label hasException0(env); 4351 Label notHasException0(env); 4352 Label useUndefined(env); 4353 Label hasException1(env); 4354 Label notHasException1(env); 4355 BRANCH(IsStableJSArray(glue, thisValue), &nextStep, &thisNotStable); 4356 Bind(&nextStep); 4357 BRANCH(Int64LessThan(*i, Int64(0)), &loopExit, &next); 4358 Bind(&next); 4359 kValue = GetTaggedValueWithElementsKind(thisValue, *i); 4360 BRANCH(TaggedIsHole(*kValue), &kValueIsHole, &callDispatch); 4361 Bind(&kValueIsHole); 4362 { 4363 GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*i) }); 4364 BRANCH(TaggedIsTrue(hasProp), &hasProperty, &useUndefined); 4365 Bind(&hasProperty); 4366 kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation()); 4367 BRANCH(HasPendingException(glue), &hasException0, ¬HasException0); 4368 Bind(&hasException0); 4369 { 4370 result->WriteVariable(Exception()); 4371 Jump(exit); 4372 } 4373 Bind(¬HasException0); 4374 { 4375 BRANCH(TaggedIsHole(*kValue), &useUndefined, &callDispatch); 4376 Bind(&useUndefined); 4377 kValue = Undefined(); 4378 Jump(&callDispatch); 4379 } 4380 } 4381 Bind(&callDispatch); 4382 { 4383 GateRef key = Int64ToTaggedInt(*i); 4384 JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN); 4385 callArgs.callThisArg3WithReturnArgs = { argHandle, *kValue, key, thisValue }; 4386 CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr, 4387 Circuit::NullGate(), callArgs); 4388 GateRef retValue = callBuilder.JSCallDispatch(); 4389 BRANCH(HasPendingException(glue), &hasException1, ¬HasException1); 4390 Bind(&hasException1); 4391 { 4392 result->WriteVariable(Exception()); 4393 Jump(exit); 4394 } 4395 4396 Bind(¬HasException1); 4397 { 4398 DEFVARIABLE(newLen, VariableType::INT64(), ZExtInt32ToInt64(GetArrayLength(thisValue))); 4399 Label checkRetValue(env); 4400 Label find(env); 4401 BRANCH(Int64LessThan(*newLen, Int64Add(*i, Int64(1))), &thisNotStable, &checkRetValue); 4402 Bind(&checkRetValue); 4403 BRANCH(TaggedIsTrue(FastToBoolean(retValue)), &find, &loopEnd); 4404 Bind(&find); 4405 result->WriteVariable(IntToTaggedPtr(*i)); 4406 Jump(exit); 4407 } 4408 } 4409 } 4410 Bind(&loopEnd); 4411 i = Int64Sub(*i, Int64(1)); 4412 LoopEnd(&loopHead); 4413 Bind(&loopExit); 4414 result->WriteVariable(IntToTaggedPtr(Int32(-1))); 4415 Jump(exit); 4416 } 4417 4418 Bind(&thisNotStable); 4419 { 4420 DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole()); 4421 Label loopHead(env); 4422 Label loopEnd(env); 4423 Label next(env); 4424 Label loopExit(env); 4425 Jump(&loopHead); 4426 LoopBegin(&loopHead); 4427 { 4428 Label hasProperty(env); 4429 Label hasException0(env); 4430 Label notHasException0(env); 4431 Label useUndefined(env); 4432 Label callDispatch(env); 4433 Label hasException1(env); 4434 Label notHasException1(env); 4435 BRANCH(Int64LessThan(*i, Int64(0)), &loopExit, &next); 4436 Bind(&next); 4437 GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*i) }); 4438 BRANCH(TaggedIsTrue(hasProp), &hasProperty, &useUndefined); 4439 Bind(&hasProperty); 4440 kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation()); 4441 BRANCH(HasPendingException(glue), &hasException0, ¬HasException0); 4442 Bind(&hasException0); 4443 { 4444 result->WriteVariable(Exception()); 4445 Jump(exit); 4446 } 4447 Bind(¬HasException0); 4448 { 4449 BRANCH(TaggedIsHole(*kValue), &useUndefined, &callDispatch); 4450 Bind(&useUndefined); 4451 kValue = Undefined(); 4452 Jump(&callDispatch); 4453 Bind(&callDispatch); 4454 GateRef key = Int64ToTaggedInt(*i); 4455 JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN); 4456 callArgs.callThisArg3WithReturnArgs = { argHandle, *kValue, key, thisValue }; 4457 CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr, 4458 Circuit::NullGate(), callArgs); 4459 GateRef retValue = callBuilder.JSCallDispatch(); 4460 BRANCH(HasPendingException(glue), &hasException1, ¬HasException1); 4461 Bind(&hasException1); 4462 { 4463 result->WriteVariable(Exception()); 4464 Jump(exit); 4465 } 4466 4467 Bind(¬HasException1); 4468 { 4469 Label find(env); 4470 BRANCH(TaggedIsTrue(FastToBoolean(retValue)), &find, &loopEnd); 4471 Bind(&find); 4472 result->WriteVariable(IntToTaggedPtr(*i)); 4473 Jump(exit); 4474 } 4475 } 4476 } 4477 Bind(&loopEnd); 4478 i = Int64Sub(*i, Int64(1)); 4479 LoopEnd(&loopHead); 4480 Bind(&loopExit); 4481 result->WriteVariable(IntToTaggedPtr(Int32(-1))); 4482 Jump(exit); 4483 } 4484} 4485 4486void BuiltinsArrayStubBuilder::FindLast(GateRef glue, GateRef thisValue, GateRef numArgs, 4487 Variable *result, Label *exit, Label *slowPath) 4488{ 4489 auto env = GetEnvironment(); 4490 Label thisExists(env); 4491 Label isHeapObject(env); 4492 Label isJsArray(env); 4493 Label defaultConstr(env); 4494 Label isStability(env); 4495 Label notCOWArray(env); 4496 Label equalCls(env); 4497 Label matchCls(env); 4498 Label isGeneric(env); 4499 BRANCH(TaggedIsUndefinedOrNull(thisValue), slowPath, &thisExists); 4500 Bind(&thisExists); 4501 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath); 4502 Bind(&isHeapObject); 4503 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath); 4504 Bind(&isJsArray); 4505 BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr); 4506 Bind(&defaultConstr); 4507 BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath); 4508 Bind(&isStability); 4509 BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray); 4510 Bind(¬COWArray); 4511 GateRef arrayCls = LoadHClass(thisValue); 4512 ElementsKindHclassCompare(glue, arrayCls, &matchCls, slowPath); 4513 Bind(&matchCls); 4514 Label arg0HeapObject(env); 4515 Label callable(env); 4516 Label thisIsStable(env); 4517 Label thisNotStable(env); 4518 GateRef callbackFnHandle = GetCallArg0(numArgs); 4519 BRANCH(TaggedIsHeapObject(callbackFnHandle), &arg0HeapObject, slowPath); 4520 Bind(&arg0HeapObject); 4521 BRANCH(IsCallable(callbackFnHandle), &callable, slowPath); 4522 Bind(&callable); 4523 GateRef argHandle = GetCallArg1(numArgs); 4524 4525 DEFVARIABLE(i, VariableType::INT64(), Int64Sub(ZExtInt32ToInt64(GetArrayLength(thisValue)), Int64(1))); 4526 Jump(&thisIsStable); 4527 4528 Bind(&thisIsStable); 4529 { 4530 DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole()); 4531 Label loopHead(env); 4532 Label loopEnd(env); 4533 Label next(env); 4534 Label loopExit(env); 4535 Jump(&loopHead); 4536 LoopBegin(&loopHead); 4537 { 4538 Label nextStep(env); 4539 Label kValueIsHole(env); 4540 Label callDispatch(env); 4541 Label hasProperty(env); 4542 Label hasException0(env); 4543 Label notHasException0(env); 4544 Label useUndefined(env); 4545 Label hasException1(env); 4546 Label notHasException1(env); 4547 BRANCH(IsStableJSArray(glue, thisValue), &nextStep, &thisNotStable); 4548 Bind(&nextStep); 4549 BRANCH(Int64LessThan(*i, Int64(0)), &loopExit, &next); 4550 Bind(&next); 4551 kValue = GetTaggedValueWithElementsKind(thisValue, *i); 4552 BRANCH(TaggedIsHole(*kValue), &kValueIsHole, &callDispatch); 4553 Bind(&kValueIsHole); 4554 { 4555 GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*i) }); 4556 BRANCH(TaggedIsTrue(hasProp), &hasProperty, &useUndefined); 4557 Bind(&hasProperty); 4558 kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation()); 4559 BRANCH(HasPendingException(glue), &hasException0, ¬HasException0); 4560 Bind(&hasException0); 4561 { 4562 result->WriteVariable(Exception()); 4563 Jump(exit); 4564 } 4565 Bind(¬HasException0); 4566 { 4567 BRANCH(TaggedIsHole(*kValue), &useUndefined, &callDispatch); 4568 Bind(&useUndefined); 4569 kValue = Undefined(); 4570 Jump(&callDispatch); 4571 } 4572 } 4573 Bind(&callDispatch); 4574 { 4575 GateRef key = Int64ToTaggedInt(*i); 4576 JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN); 4577 callArgs.callThisArg3WithReturnArgs = { argHandle, *kValue, key, thisValue }; 4578 CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr, 4579 Circuit::NullGate(), callArgs); 4580 GateRef retValue = callBuilder.JSCallDispatch(); 4581 BRANCH(HasPendingException(glue), &hasException1, ¬HasException1); 4582 Bind(&hasException1); 4583 { 4584 result->WriteVariable(Exception()); 4585 Jump(exit); 4586 } 4587 4588 Bind(¬HasException1); 4589 { 4590 DEFVARIABLE(newLen, VariableType::INT64(), ZExtInt32ToInt64(GetArrayLength(thisValue))); 4591 Label checkRetValue(env); 4592 Label find(env); 4593 BRANCH(Int64LessThan(*newLen, Int64Add(*i, Int64(1))), &thisNotStable, &checkRetValue); 4594 Bind(&checkRetValue); 4595 BRANCH(TaggedIsTrue(FastToBoolean(retValue)), &find, &loopEnd); 4596 Bind(&find); 4597 result->WriteVariable(*kValue); 4598 Jump(exit); 4599 } 4600 } 4601 } 4602 Bind(&loopEnd); 4603 i = Int64Sub(*i, Int64(1)); 4604 LoopEnd(&loopHead); 4605 Bind(&loopExit); 4606 Jump(exit); 4607 } 4608 4609 Bind(&thisNotStable); 4610 { 4611 DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole()); 4612 Label loopHead(env); 4613 Label loopEnd(env); 4614 Label next(env); 4615 Label loopExit(env); 4616 Jump(&loopHead); 4617 LoopBegin(&loopHead); 4618 { 4619 Label hasProperty(env); 4620 Label hasException0(env); 4621 Label notHasException0(env); 4622 Label useUndefined(env); 4623 Label callDispatch(env); 4624 Label hasException1(env); 4625 Label notHasException1(env); 4626 BRANCH(Int64LessThan(*i, Int64(0)), &loopExit, &next); 4627 Bind(&next); 4628 GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*i) }); 4629 BRANCH(TaggedIsTrue(hasProp), &hasProperty, &useUndefined); 4630 Bind(&hasProperty); 4631 kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation()); 4632 BRANCH(HasPendingException(glue), &hasException0, ¬HasException0); 4633 Bind(&hasException0); 4634 { 4635 result->WriteVariable(Exception()); 4636 Jump(exit); 4637 } 4638 Bind(¬HasException0); 4639 { 4640 BRANCH(TaggedIsHole(*kValue), &useUndefined, &callDispatch); 4641 Bind(&useUndefined); 4642 { 4643 kValue = Undefined(); 4644 Jump(&callDispatch); 4645 } 4646 Bind(&callDispatch); 4647 { 4648 GateRef key = Int64ToTaggedInt(*i); 4649 JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN); 4650 callArgs.callThisArg3WithReturnArgs = { argHandle, *kValue, key, thisValue }; 4651 CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, 4652 nullptr, Circuit::NullGate(), callArgs); 4653 GateRef retValue = callBuilder.JSCallDispatch(); 4654 BRANCH(HasPendingException(glue), &hasException1, ¬HasException1); 4655 Bind(&hasException1); 4656 { 4657 result->WriteVariable(Exception()); 4658 Jump(exit); 4659 } 4660 4661 Bind(¬HasException1); 4662 { 4663 Label find(env); 4664 BRANCH(TaggedIsTrue(FastToBoolean(retValue)), &find, &loopEnd); 4665 Bind(&find); 4666 result->WriteVariable(*kValue); 4667 Jump(exit); 4668 } 4669 } 4670 } 4671 } 4672 Bind(&loopEnd); 4673 i = Int64Sub(*i, Int64(1)); 4674 LoopEnd(&loopHead); 4675 Bind(&loopExit); 4676 Jump(exit); 4677 } 4678} 4679 4680void BuiltinsArrayStubBuilder::FastCreateArrayWithArgv(GateRef glue, Variable *res, GateRef argc, 4681 GateRef hclass, Label *exit) 4682{ 4683 auto env = GetEnvironment(); 4684 NewObjectStubBuilder newBuilder(this); 4685 newBuilder.SetParameters(glue, 0); 4686 4687 // create elements from argv 4688 GateRef len = TruncInt64ToInt32(argc); 4689 GateRef elements = newBuilder.NewTaggedArray(glue, len); 4690 4691 // set value 4692 DEFVARIABLE(i, VariableType::INT64(), Int64(0)); 4693 DEFVARIABLE(value, VariableType::JS_ANY(), Undefined()); 4694#if ECMASCRIPT_ENABLE_ELEMENTSKIND_ALWAY_GENERIC 4695 DEFVARIABLE(elementKind, VariableType::INT32(), Int32(static_cast<int32_t>(ElementsKind::GENERIC))); 4696#else 4697 DEFVARIABLE(elementKind, VariableType::INT32(), Int32(static_cast<int32_t>(ElementsKind::HOLE))); 4698#endif 4699 Label loopHead(env); 4700 Label loopEnd(env); 4701 Label setValue(env); 4702 Label loopExit(env); 4703 Jump(&loopHead); 4704 LoopBegin(&loopHead); 4705 { 4706 BRANCH(Int64LessThan(*i, argc), &setValue, &loopExit); 4707 Bind(&setValue); 4708 Label isHole(env); 4709 Label notHole(env); 4710 value = GetArgFromArgv(*i); 4711 elementKind = Int32Or(TaggedToElementKind(*value), *elementKind); 4712 BRANCH(TaggedIsHole(*value), &isHole, ¬Hole); 4713 Bind(&isHole); 4714 value = TaggedUndefined(); 4715 Jump(¬Hole); 4716 Bind(¬Hole); 4717 SetValueToTaggedArray(VariableType::JS_ANY(), glue, elements, *i, *value); 4718 i = Int64Add(*i, Int64(1)); 4719 Jump(&loopEnd); 4720 } 4721 Bind(&loopEnd); 4722 LoopEnd(&loopHead); 4723 Bind(&loopExit); 4724 4725 // create array object 4726 GateRef arr = newBuilder.NewJSObject(glue, hclass); 4727 res->WriteVariable(arr); 4728 GateRef lengthOffset = IntPtr(JSArray::LENGTH_OFFSET); 4729 Store(VariableType::INT32(), glue, arr, lengthOffset, len); 4730 GateRef accessor = GetGlobalConstantValue(VariableType::JS_ANY(), glue, ConstantIndex::ARRAY_LENGTH_ACCESSOR); 4731 SetPropertyInlinedProps(glue, arr, hclass, accessor, Int32(JSArray::LENGTH_INLINE_PROPERTY_INDEX)); 4732 SetExtensibleToBitfield(glue, arr, true); 4733 SetElementsArray(VariableType::JS_POINTER(), glue, arr, elements); 4734 4735 // set elementkind if needed 4736 Label enabledElementsKind(env); 4737 BRANCH(IsEnableElementsKind(glue), &enabledElementsKind, exit); 4738 Bind(&enabledElementsKind); 4739 CallRuntime(glue, RTSTUB_ID(UpdateHClassForElementsKind), { arr, *elementKind }); 4740 Jump(exit); 4741} 4742 4743void BuiltinsArrayStubBuilder::GenArrayConstructor(GateRef glue, GateRef nativeCode, 4744 GateRef func, GateRef newTarget, GateRef thisValue, GateRef numArgs) 4745{ 4746 auto env = GetEnvironment(); 4747 DEFVARIABLE(res, VariableType::JS_ANY(), Undefined()); 4748 4749 Label newTargetIsHeapObject(env); 4750 Label newTargetIsJSFunction(env); 4751 Label slowPath(env); 4752 Label slowPath1(env); 4753 Label exit(env); 4754 4755 BRANCH(TaggedIsHeapObject(newTarget), &newTargetIsHeapObject, &slowPath); 4756 Bind(&newTargetIsHeapObject); 4757 BRANCH(IsJSFunction(newTarget), &newTargetIsJSFunction, &slowPath); 4758 Bind(&newTargetIsJSFunction); 4759 { 4760 Label fastGetHclass(env); 4761 Label intialHClassIsHClass(env); 4762 GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit())); 4763 GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset); 4764 auto arrayFunc = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::ARRAY_FUNCTION_INDEX); 4765 BRANCH(Equal(arrayFunc, newTarget), &fastGetHclass, &slowPath1); 4766 Bind(&fastGetHclass); 4767 GateRef intialHClass = Load(VariableType::JS_ANY(), newTarget, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET)); 4768 DEFVARIABLE(arrayLength, VariableType::INT64(), Int64(0)); 4769 BRANCH(IsJSHClass(intialHClass), &intialHClassIsHClass, &slowPath1); 4770 Bind(&intialHClassIsHClass); 4771 { 4772 Label noArg(env); 4773 Label hasArg(env); 4774 Label arrayCreate(env); 4775 BRANCH(Int64Equal(numArgs, IntPtr(0)), &noArg, &hasArg); 4776 Bind(&noArg); 4777 { 4778 Jump(&arrayCreate); 4779 } 4780 Bind(&hasArg); 4781 { 4782 Label hasOneArg(env); 4783 Label multiArg(env); 4784 BRANCH(Int64Equal(numArgs, IntPtr(1)), &hasOneArg, &multiArg); 4785 Bind(&hasOneArg); 4786 { 4787 Label argIsNumber(env); 4788 GateRef arg0 = GetArgFromArgv(IntPtr(0), numArgs, true); 4789 BRANCH(TaggedIsNumber(arg0), &argIsNumber, &slowPath); 4790 Bind(&argIsNumber); 4791 { 4792 Label argIsInt(env); 4793 Label argIsDouble(env); 4794 BRANCH(TaggedIsInt(arg0), &argIsInt, &argIsDouble); 4795 Bind(&argIsInt); 4796 { 4797 Label validIntLength(env); 4798 GateRef intLen = GetInt64OfTInt(arg0); 4799 GateRef isGEZero = Int64GreaterThanOrEqual(intLen, Int64(0)); 4800 GateRef isLEMaxLen = Int64LessThanOrEqual(intLen, Int64(JSArray::MAX_ARRAY_INDEX)); 4801 BRANCH(BitAnd(isGEZero, isLEMaxLen), &validIntLength, &slowPath); 4802 Bind(&validIntLength); 4803 { 4804 arrayLength = intLen; 4805 Jump(&arrayCreate); 4806 } 4807 } 4808 Bind(&argIsDouble); 4809 { 4810 Label validDoubleLength(env); 4811 GateRef doubleLength = GetDoubleOfTDouble(arg0); 4812 GateRef doubleToInt = DoubleToInt(glue, doubleLength); 4813 GateRef intToDouble = CastInt64ToFloat64(SExtInt32ToInt64(doubleToInt)); 4814 GateRef doubleEqual = DoubleEqual(doubleLength, intToDouble); 4815 GateRef doubleLEMaxLen = 4816 DoubleLessThanOrEqual(doubleLength, Double(JSArray::MAX_ARRAY_INDEX)); 4817 BRANCH(BitAnd(doubleEqual, doubleLEMaxLen), &validDoubleLength, &slowPath); 4818 Bind(&validDoubleLength); 4819 { 4820 arrayLength = SExtInt32ToInt64(doubleToInt); 4821 Jump(&arrayCreate); 4822 } 4823 } 4824 } 4825 } 4826 Bind(&multiArg); 4827 { 4828 Label lengthValid(env); 4829 BRANCH(Int64LessThan(numArgs, IntPtr(JSObject::MAX_GAP)), &lengthValid, &slowPath); 4830 Bind(&lengthValid); 4831 { 4832 FastCreateArrayWithArgv(glue, &res, numArgs, intialHClass, &exit); 4833 } 4834 } 4835 } 4836 Bind(&arrayCreate); 4837 { 4838 Label lengthValid(env); 4839 BRANCH(Int64GreaterThan(*arrayLength, Int64(JSObject::MAX_GAP)), &slowPath, &lengthValid); 4840 Bind(&lengthValid); 4841 { 4842 NewObjectStubBuilder newBuilder(this); 4843 newBuilder.SetParameters(glue, 0); 4844 res = newBuilder.NewJSArrayWithSize(intialHClass, *arrayLength); 4845 GateRef lengthOffset = IntPtr(JSArray::LENGTH_OFFSET); 4846 Store(VariableType::INT32(), glue, *res, lengthOffset, TruncInt64ToInt32(*arrayLength)); 4847 GateRef accessor = GetGlobalConstantValue(VariableType::JS_ANY(), glue, 4848 ConstantIndex::ARRAY_LENGTH_ACCESSOR); 4849 SetPropertyInlinedProps(glue, *res, intialHClass, accessor, 4850 Int32(JSArray::LENGTH_INLINE_PROPERTY_INDEX)); 4851 SetExtensibleToBitfield(glue, *res, true); 4852 Jump(&exit); 4853 } 4854 } 4855 } 4856 Bind(&slowPath1); 4857 { 4858 GateRef argv = GetArgv(); 4859 res = CallBuiltinRuntimeWithNewTarget(glue, 4860 { glue, nativeCode, func, thisValue, numArgs, argv, newTarget }); 4861 Jump(&exit); 4862 } 4863 } 4864 Bind(&slowPath); 4865 { 4866 GateRef argv = GetArgv(); 4867 res = CallBuiltinRuntime(glue, { glue, nativeCode, func, thisValue, numArgs, argv }, true); 4868 Jump(&exit); 4869 } 4870 4871 Bind(&exit); 4872 Return(*res); 4873} 4874 4875void BuiltinsArrayStubBuilder::FlatMap(GateRef glue, GateRef thisValue, GateRef numArgs, 4876 Variable *result, Label *exit, Label *slowPath) 4877{ 4878 auto env = GetEnvironment(); 4879 Label thisExists(env); 4880 Label isHeapObject(env); 4881 Label isJsArray(env); 4882 Label defaultConstr(env); 4883 Label isStability(env); 4884 Label notCOWArray(env); 4885 Label equalCls(env); 4886 Label matchCls(env); 4887 Label isGeneric(env); 4888 BRANCH(TaggedIsUndefinedOrNull(thisValue), slowPath, &thisExists); 4889 Bind(&thisExists); 4890 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath); 4891 Bind(&isHeapObject); 4892 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath); 4893 Bind(&isJsArray); 4894 BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr); 4895 Bind(&defaultConstr); 4896 BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath); 4897 Bind(&isStability); 4898 BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray); 4899 Bind(¬COWArray); 4900 GateRef arrayCls = LoadHClass(thisValue); 4901 ElementsKindHclassCompare(glue, arrayCls, &matchCls, slowPath); 4902 Bind(&matchCls); 4903 Label arg0HeapObject(env); 4904 Label callable(env); 4905 Label thisIsStable(env); 4906 Label thisNotStable(env); 4907 Label doFlat(env); 4908 GateRef callbackFnHandle = GetCallArg0(numArgs); 4909 BRANCH(TaggedIsHeapObject(callbackFnHandle), &arg0HeapObject, slowPath); 4910 Bind(&arg0HeapObject); 4911 BRANCH(IsCallable(callbackFnHandle), &callable, slowPath); 4912 Bind(&callable); 4913 GateRef argHandle = GetCallArg1(numArgs); 4914 4915 DEFVARIABLE(i, VariableType::INT64(), Int64(0)); 4916 DEFVARIABLE(thisArrLen, VariableType::INT64(), ZExtInt32ToInt64(GetArrayLength(thisValue))); 4917 DEFVARIABLE(newArrLen, VariableType::INT64(), ZExtInt32ToInt64(GetArrayLength(thisValue))); 4918 GateRef mappedArray = NewArray(glue, *thisArrLen); 4919 BRANCH(IsStableJSArray(glue, thisValue), &thisIsStable, &thisNotStable); 4920 4921 Bind(&thisIsStable); 4922 { 4923 DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole()); 4924 Label loopHead(env); 4925 Label loopEnd(env); 4926 Label next(env); 4927 Label loopExit(env); 4928 Jump(&loopHead); 4929 LoopBegin(&loopHead); 4930 { 4931 Label nextStep(env); 4932 Label kValueIsHole(env); 4933 Label callDispatch(env); 4934 Label hasProperty(env); 4935 Label changeNewArrLen(env); 4936 Label hasException0(env); 4937 Label notHasException0(env); 4938 Label hasException1(env); 4939 Label notHasException1(env); 4940 BRANCH(IsStableJSArray(glue, thisValue), &nextStep, &thisNotStable); 4941 Bind(&nextStep); 4942 BRANCH(Int64LessThan(*i, *thisArrLen), &next, &loopExit); 4943 Bind(&next); 4944 kValue = GetTaggedValueWithElementsKind(thisValue, *i); 4945 BRANCH(TaggedIsHole(*kValue), &kValueIsHole, &callDispatch); 4946 Bind(&kValueIsHole); 4947 { 4948 GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*i) }); 4949 BRANCH(TaggedIsTrue(hasProp), &hasProperty, &changeNewArrLen); 4950 Bind(&hasProperty); 4951 { 4952 kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation()); 4953 BRANCH(HasPendingException(glue), &hasException0, ¬HasException0); 4954 Bind(&hasException0); 4955 { 4956 result->WriteVariable(Exception()); 4957 Jump(exit); 4958 } 4959 Bind(¬HasException0); 4960 { 4961 BRANCH(TaggedIsHole(*kValue), &changeNewArrLen, &callDispatch); 4962 } 4963 } 4964 Bind(&changeNewArrLen); 4965 { 4966 newArrLen = Int64Sub(*newArrLen, Int64(1)); 4967 Jump(&loopEnd); 4968 } 4969 } 4970 Bind(&callDispatch); 4971 { 4972 GateRef key = Int64ToTaggedInt(*i); 4973 JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN); 4974 callArgs.callThisArg3WithReturnArgs = { argHandle, *kValue, key, thisValue }; 4975 CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr, 4976 Circuit::NullGate(), callArgs); 4977 GateRef retValue = callBuilder.JSCallDispatch(); 4978 BRANCH(HasPendingException(glue), &hasException1, ¬HasException1); 4979 Bind(&hasException1); 4980 { 4981 result->WriteVariable(Exception()); 4982 Jump(exit); 4983 } 4984 Bind(¬HasException1); 4985 { 4986 DEFVARIABLE(newLen, VariableType::INT64(), ZExtInt32ToInt64(GetArrayLength(thisValue))); 4987 Label changeThisLen(env); 4988 Label afterChangeLen(env); 4989 Label retValueIsHeapObject(env); 4990 Label retValueIsJsArray(env); 4991 BRANCH(Int64LessThan(*newLen, *thisArrLen), &changeThisLen, &afterChangeLen); 4992 Bind(&changeThisLen); 4993 { 4994 newArrLen = Int64Sub(*newArrLen, Int64Sub(*thisArrLen, *newLen)); 4995 thisArrLen = *newLen; 4996 Jump(&afterChangeLen); 4997 } 4998 Bind(&afterChangeLen); 4999 { 5000 SetValueWithElementsKind(glue, mappedArray, retValue, *i, Boolean(true), 5001 Int32(static_cast<uint32_t>(ElementsKind::NONE))); 5002 BRANCH(TaggedIsHeapObject(retValue), &retValueIsHeapObject, &loopEnd); 5003 Bind(&retValueIsHeapObject); 5004 { 5005 BRANCH(IsJsArray(retValue), &retValueIsJsArray, &loopEnd); 5006 } 5007 Bind(&retValueIsJsArray); 5008 { 5009 GateRef elementsNum = 5010 ZExtInt32ToInt64(GetNumberOfElements(retValue)); // newArray only contains non-hole elements 5011 newArrLen = Int64Sub(Int64Add(*newArrLen, elementsNum), Int64(1)); 5012 Jump(&loopEnd); 5013 } 5014 } 5015 } 5016 } 5017 } 5018 Bind(&loopEnd); 5019 i = Int64Add(*i, Int64(1)); 5020 LoopEnd(&loopHead); 5021 Bind(&loopExit); 5022 Jump(&doFlat); 5023 } 5024 5025 Bind(&thisNotStable); 5026 { 5027 DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole()); 5028 Label loopHead(env); 5029 Label loopEnd(env); 5030 Label next(env); 5031 Label loopExit(env); 5032 Jump(&loopHead); 5033 LoopBegin(&loopHead); 5034 { 5035 Label hasProperty(env); 5036 Label changeNewArrLen(env); 5037 Label hasException0(env); 5038 Label notHasException0(env); 5039 Label callDispatch(env); 5040 Label hasException1(env); 5041 Label notHasException1(env); 5042 BRANCH(Int64LessThan(*i, *thisArrLen), &next, &loopExit); 5043 Bind(&next); 5044 GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*i) }); 5045 BRANCH(TaggedIsTrue(hasProp), &hasProperty, &changeNewArrLen); 5046 Bind(&hasProperty); 5047 { 5048 kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation()); 5049 BRANCH(HasPendingException(glue), &hasException0, ¬HasException0); 5050 Bind(&hasException0); 5051 { 5052 result->WriteVariable(Exception()); 5053 Jump(exit); 5054 } 5055 Bind(¬HasException0); 5056 { 5057 BRANCH(TaggedIsHole(*kValue), &changeNewArrLen, &callDispatch); 5058 } 5059 } 5060 Bind(&changeNewArrLen); 5061 { 5062 newArrLen = Int64Sub(*newArrLen, Int64(1)); 5063 Jump(&loopEnd); 5064 } 5065 Bind(&callDispatch); 5066 { 5067 GateRef key = Int64ToTaggedInt(*i); 5068 JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN); 5069 callArgs.callThisArg3WithReturnArgs = { argHandle, *kValue, key, thisValue }; 5070 CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr, 5071 Circuit::NullGate(), callArgs); 5072 GateRef retValue = callBuilder.JSCallDispatch(); 5073 BRANCH(HasPendingException(glue), &hasException1, ¬HasException1); 5074 Bind(&hasException1); 5075 { 5076 result->WriteVariable(Exception()); 5077 Jump(exit); 5078 } 5079 Bind(¬HasException1); 5080 { 5081 Label retValueIsHeapObject(env); 5082 Label retValueIsJsArray(env); 5083 SetValueWithElementsKind(glue, mappedArray, retValue, *i, Boolean(true), 5084 Int32(static_cast<uint32_t>(ElementsKind::NONE))); 5085 BRANCH(TaggedIsHeapObject(retValue), &retValueIsHeapObject, &loopEnd); 5086 Bind(&retValueIsHeapObject); 5087 { 5088 BRANCH(IsJsArray(retValue), &retValueIsJsArray, &loopEnd); 5089 } 5090 Bind(&retValueIsJsArray); 5091 { 5092 GateRef elementsNum = 5093 ZExtInt32ToInt64(GetNumberOfElements(retValue)); // newArray only contains non-hole elements 5094 newArrLen = Int64Sub(Int64Add(*newArrLen, elementsNum), Int64(1)); 5095 Jump(&loopEnd); 5096 } 5097 } 5098 } 5099 } 5100 Bind(&loopEnd); 5101 i = Int64Add(*i, Int64(1)); 5102 LoopEnd(&loopHead); 5103 Bind(&loopExit); 5104 Jump(&doFlat); 5105 } 5106 5107 Bind(&doFlat); 5108 { 5109 i = Int64(0); 5110 DEFVARIABLE(j, VariableType::INT64(), Int64(0)); 5111 DEFVARIABLE(retValueItem, VariableType::JS_ANY(), Hole()); 5112 GateRef newArray = NewArray(glue, *newArrLen); 5113 Label loopHead2(env); 5114 Label loopEnd2(env); 5115 Label next2(env); 5116 Label loopExit2(env); 5117 Jump(&loopHead2); 5118 LoopBegin(&loopHead2); 5119 { 5120 Label nextStep(env); 5121 Label retValueIsHeapObject(env); 5122 Label retValueIsJsArray(env); 5123 Label retValueIsNotJsArray(env); 5124 BRANCH(Int64LessThan(*i, *thisArrLen), &next2, &loopExit2); 5125 Bind(&next2); 5126 GateRef retValue = GetTaggedValueWithElementsKind(mappedArray, *i); 5127 BRANCH(TaggedIsHole(retValue), &loopEnd2, &nextStep); 5128 Bind(&nextStep); 5129 BRANCH(TaggedIsHeapObject(retValue), &retValueIsHeapObject, &retValueIsNotJsArray); 5130 Bind(&retValueIsHeapObject); 5131 { 5132 BRANCH(IsJsArray(retValue), &retValueIsJsArray, &retValueIsNotJsArray); 5133 Bind(&retValueIsJsArray); 5134 { 5135 Label retValueIsStableArray(env); 5136 Label retValueNotStableArray(env); 5137 GateRef retValueIsStable = IsStableJSArray(glue, retValue); 5138 GateRef arrLen = ZExtInt32ToInt64(GetArrayLength(retValue)); 5139 DEFVARIABLE(k, VariableType::INT64(), Int64(0)); 5140 Label loopHead3(env); 5141 Label loopEnd3(env); 5142 Label next3(env); 5143 Label loopExit3(env); 5144 Label setValue(env); 5145 Label itemExist(env); 5146 Jump(&loopHead3); 5147 LoopBegin(&loopHead3); 5148 { 5149 BRANCH(Int64LessThan(*k, arrLen), &next3, &loopExit3); 5150 Bind(&next3); 5151 BRANCH(retValueIsStable, &retValueIsStableArray, &retValueNotStableArray); 5152 Bind(&retValueIsStableArray); 5153 retValueItem = GetTaggedValueWithElementsKind(retValue, *k); 5154 BRANCH(TaggedIsHole(*retValueItem), &loopEnd3, &setValue); 5155 Bind(&retValueNotStableArray); 5156 GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { retValue, IntToTaggedInt(*k) }); 5157 BRANCH(TaggedIsTrue(hasProp), &itemExist, &loopEnd3); 5158 Bind(&itemExist); 5159 retValueItem = 5160 FastGetPropertyByIndex(glue, retValue, TruncInt64ToInt32(*k), ProfileOperation()); 5161 Jump(&setValue); 5162 Bind(&setValue); 5163 SetValueWithElementsKind(glue, newArray, *retValueItem, *j, Boolean(true), 5164 Int32(static_cast<uint32_t>(ElementsKind::NONE))); 5165 j = Int64Add(*j, Int64(1)); 5166 Jump(&loopEnd3); 5167 } 5168 Bind(&loopEnd3); 5169 k = Int64Add(*k, Int64(1)); 5170 LoopEnd(&loopHead3); 5171 Bind(&loopExit3); 5172 Jump(&loopEnd2); 5173 } 5174 } 5175 Bind(&retValueIsNotJsArray); 5176 { 5177 SetValueWithElementsKind(glue, newArray, retValue, *j, Boolean(true), 5178 Int32(static_cast<uint32_t>(ElementsKind::NONE))); 5179 j = Int64Add(*j, Int64(1)); 5180 Jump(&loopEnd2); 5181 } 5182 } 5183 Bind(&loopEnd2); 5184 i = Int64Add(*i, Int64(1)); 5185 LoopEnd(&loopHead2); 5186 Bind(&loopExit2); 5187 result->WriteVariable(newArray); 5188 Jump(exit); 5189 } 5190} 5191 5192void BuiltinsArrayStubBuilder::IsArray([[maybe_unused]] GateRef glue, [[maybe_unused]] GateRef thisValue, 5193 GateRef numArgs, Variable *result, Label *exit, Label *slowPath) 5194{ 5195 auto env = GetEnvironment(); 5196 GateRef obj = GetCallArg0(numArgs); 5197 Label isHeapObj(env); 5198 Label notHeapObj(env); 5199 BRANCH(TaggedIsHeapObject(obj), &isHeapObj, ¬HeapObj); 5200 Bind(&isHeapObj); 5201 { 5202 Label isJSArray(env); 5203 Label notJSArray(env); 5204 GateRef objectType = GetObjectType(LoadHClass(obj)); 5205 BRANCH(Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_ARRAY))), &isJSArray, ¬JSArray); 5206 Bind(&isJSArray); 5207 { 5208 result->WriteVariable(TaggedTrue()); 5209 Jump(exit); 5210 } 5211 Bind(¬JSArray); 5212 BRANCH(Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_PROXY))), slowPath, ¬HeapObj); 5213 } 5214 Bind(¬HeapObj); 5215 { 5216 result->WriteVariable(TaggedFalse()); 5217 Jump(exit); 5218 } 5219} 5220} // namespace panda::ecmascript::kungfu 5221