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#ifndef ECMASCRIPT_COMPILER_MCR_CIRCUIT_BUILDER_H 17#define ECMASCRIPT_COMPILER_MCR_CIRCUIT_BUILDER_H 18 19#include "ecmascript/compiler/circuit_builder.h" 20#include "ecmascript/compiler/circuit_builder_helper.h" 21#include "ecmascript/mem/region.h" 22#include "ecmascript/method.h" 23#include "ecmascript/js_function.h" 24 25namespace panda::ecmascript::kungfu { 26 27// bit operation 28 29GateRef CircuitBuilder::TaggedIsInt(GateRef x) 30{ 31 x = ChangeTaggedPointerToInt64(x); 32 return Equal(Int64And(x, Int64(JSTaggedValue::TAG_MARK)), 33 Int64(JSTaggedValue::TAG_INT)); 34} 35 36GateRef CircuitBuilder::TaggedIsDouble(GateRef x) 37{ 38 x = ChangeTaggedPointerToInt64(x); 39 x = Int64And(x, Int64(JSTaggedValue::TAG_MARK)); 40 auto left = NotEqual(x, Int64(JSTaggedValue::TAG_INT)); 41 auto right = NotEqual(x, Int64(JSTaggedValue::TAG_OBJECT)); 42 return BitAnd(left, right); 43} 44 45GateRef CircuitBuilder::TaggedIsObject(GateRef x) 46{ 47 x = ChangeTaggedPointerToInt64(x); 48 return Equal(Int64And(x, Int64(JSTaggedValue::TAG_MARK)), 49 Int64(JSTaggedValue::TAG_OBJECT)); 50} 51 52GateRef CircuitBuilder::TaggedIsNumber(GateRef x) 53{ 54 return BoolNot(TaggedIsObject(x)); 55} 56 57GateRef CircuitBuilder::TaggedIsNumeric(GateRef x) 58{ 59 return LogicOrBuilder(env_).Or(TaggedIsNumber(x)).Or(TaggedIsBigInt(x)).Done(); 60} 61 62GateRef CircuitBuilder::TaggedObjectIsString(GateRef obj) 63{ 64 GateRef objectType = GetObjectType(LoadHClass(obj)); 65 return BitAnd( 66 Int32LessThanOrEqual(objectType, Int32(static_cast<int32_t>(JSType::STRING_LAST))), 67 Int32GreaterThanOrEqual(objectType, Int32(static_cast<int32_t>(JSType::STRING_FIRST)))); 68} 69 70GateRef CircuitBuilder::TaggedObjectIsShared(GateRef obj) 71{ 72 GateRef bitfield = Load(VariableType::INT32(), LoadHClass(obj), IntPtr(JSHClass::BIT_FIELD_OFFSET)); 73 return Int32NotEqual( 74 Int32And(Int32LSR(bitfield, Int32(JSHClass::IsJSSharedBit::START_BIT)), 75 Int32((1LU << JSHClass::IsJSSharedBit::SIZE) - 1)), 76 Int32(0)); 77} 78 79GateRef CircuitBuilder::TaggedObjectIsEcmaObject(GateRef obj) 80{ 81 GateRef objectType = GetObjectType(LoadHClass(obj)); 82 return BitAnd( 83 Int32LessThanOrEqual(objectType, Int32(static_cast<int32_t>(JSType::ECMA_OBJECT_LAST))), 84 Int32GreaterThanOrEqual(objectType, Int32(static_cast<int32_t>(JSType::ECMA_OBJECT_FIRST)))); 85} 86 87GateRef CircuitBuilder::TaggedObjectIsByteArray(GateRef obj) 88{ 89 GateRef objectType = GetObjectType(LoadHClass(obj)); 90 return Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::BYTE_ARRAY))); 91} 92 93GateRef CircuitBuilder::TaggedObjectIsMap(GateRef obj) 94{ 95 GateRef objectType = GetObjectType(LoadHClass(obj)); 96 return Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_MAP))); 97} 98 99GateRef CircuitBuilder::TaggedObjectIsDataView(GateRef obj) 100{ 101 GateRef objectType = GetObjectType(LoadHClass(obj)); 102 return Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_DATA_VIEW))); 103} 104 105GateRef CircuitBuilder::IsSpecialSlicedString(GateRef obj) 106{ 107 GateRef objectType = GetObjectType(LoadHClass(obj)); 108 GateRef isSlicedString = Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::SLICED_STRING))); 109 Label entry(env_); 110 SubCfgEntry(&entry); 111 Label exit(env_); 112 DEFVALUE(result, env_, VariableType::BOOL(), False()); 113 Label isSlicedStr(env_); 114 BRANCH_CIR2(isSlicedString, &isSlicedStr, &exit); 115 Bind(&isSlicedStr); 116 { 117 GateRef hasBackingStore = LoadConstOffset(VariableType::INT32(), obj, SlicedString::BACKING_STORE_FLAG); 118 result = Int32Equal(hasBackingStore, Int32(EcmaString::HAS_BACKING_STORE)); 119 Jump(&exit); 120 } 121 Bind(&exit); 122 auto ret = *result; 123 SubCfgExit(); 124 return ret; 125} 126 127GateRef CircuitBuilder::TaggedIsBigInt(GateRef obj) 128{ 129 Label entry(env_); 130 SubCfgEntry(&entry); 131 Label exit(env_); 132 DEFVALUE(result, env_, VariableType::BOOL(), False()); 133 Label isHeapObject(env_); 134 BRANCH_CIR2(TaggedIsHeapObject(obj), &isHeapObject, &exit); 135 Bind(&isHeapObject); 136 { 137 result = Int32Equal(GetObjectType(LoadHClass(obj)), 138 Int32(static_cast<int32_t>(JSType::BIGINT))); 139 Jump(&exit); 140 } 141 Bind(&exit); 142 auto ret = *result; 143 SubCfgExit(); 144 return ret; 145} 146 147GateRef CircuitBuilder::TaggedIsString(GateRef obj) 148{ 149 Label entry(env_); 150 SubCfgEntry(&entry); 151 Label exit(env_); 152 DEFVALUE(result, env_, VariableType::BOOL(), False()); 153 Label isHeapObject(env_); 154 BRANCH_CIR2(TaggedIsHeapObject(obj), &isHeapObject, &exit); 155 Bind(&isHeapObject); 156 { 157 result = TaggedObjectIsString(obj); 158 Jump(&exit); 159 } 160 Bind(&exit); 161 auto ret = *result; 162 SubCfgExit(); 163 return ret; 164} 165 166GateRef CircuitBuilder::TaggedIsStringIterator(GateRef obj) 167{ 168 Label entry(env_); 169 SubCfgEntry(&entry); 170 Label exit(env_); 171 DEFVALUE(result, env_, VariableType::BOOL(), False()); 172 Label isHeapObject(env_); 173 Branch(TaggedIsHeapObject(obj), &isHeapObject, &exit); 174 Bind(&isHeapObject); 175 { 176 result = Int32Equal(GetObjectType(LoadHClass(obj)), 177 Int32(static_cast<int32_t>(JSType::JS_STRING_ITERATOR))); 178 Jump(&exit); 179 } 180 Bind(&exit); 181 auto ret = *result; 182 SubCfgExit(); 183 return ret; 184} 185 186GateRef CircuitBuilder::TaggedIsSharedObj(GateRef obj) 187{ 188 Label entry(env_); 189 SubCfgEntry(&entry); 190 Label exit(env_); 191 DEFVALUE(result, env_, VariableType::BOOL(), False()); 192 Label isHeapObject(env_); 193 BRANCH_CIR2(TaggedIsHeapObject(obj), &isHeapObject, &exit); 194 Bind(&isHeapObject); 195 { 196 result = TaggedObjectIsShared(obj); 197 Jump(&exit); 198 } 199 Bind(&exit); 200 auto ret = *result; 201 SubCfgExit(); 202 return ret; 203} 204 205GateRef CircuitBuilder::TaggedIsSymbol(GateRef obj) 206{ 207 Label entry(env_); 208 SubCfgEntry(&entry); 209 Label exit(env_); 210 DEFVALUE(result, env_, VariableType::BOOL(), False()); 211 Label isHeapObject(env_); 212 BRANCH_CIR2(TaggedIsHeapObject(obj), &isHeapObject, &exit); 213 Bind(&isHeapObject); 214 { 215 GateRef objType = GetObjectType(LoadHClass(obj)); 216 result = Equal(objType, Int32(static_cast<int32_t>(JSType::SYMBOL))); 217 Jump(&exit); 218 } 219 Bind(&exit); 220 auto ret = *result; 221 SubCfgExit(); 222 return ret; 223} 224 225GateRef CircuitBuilder::TaggedIsStringOrSymbol(GateRef obj) 226{ 227 Label entry(env_); 228 SubCfgEntry(&entry); 229 Label exit(env_); 230 DEFVALUE(result, env_, VariableType::BOOL(), False()); 231 Label isHeapObject(env_); 232 BRANCH_CIR2(TaggedIsHeapObject(obj), &isHeapObject, &exit); 233 Bind(&isHeapObject); 234 { 235 result = TaggedObjectIsString(obj); 236 Label isString(env_); 237 Label notString(env_); 238 BRANCH_CIR2(*result, &exit, ¬String); 239 Bind(¬String); 240 { 241 GateRef objType = GetObjectType(LoadHClass(obj)); 242 result = Equal(objType, Int32(static_cast<int32_t>(JSType::SYMBOL))); 243 Jump(&exit); 244 } 245 } 246 Bind(&exit); 247 auto ret = *result; 248 SubCfgExit(); 249 return ret; 250} 251 252GateRef CircuitBuilder::TaggedIsProtoChangeMarker(GateRef obj) 253{ 254 Label entry(env_); 255 SubCfgEntry(&entry); 256 Label exit(env_); 257 DEFVALUE(result, env_, VariableType::BOOL(), False()); 258 Label isHeapObject(env_); 259 BRANCH_CIR2(TaggedIsHeapObject(obj), &isHeapObject, &exit); 260 Bind(&isHeapObject); 261 { 262 GateRef objType = GetObjectType(LoadHClass(obj)); 263 result = Equal(objType, Int32(static_cast<int32_t>(JSType::PROTO_CHANGE_MARKER))); 264 Jump(&exit); 265 } 266 Bind(&exit); 267 auto ret = *result; 268 SubCfgExit(); 269 return ret; 270} 271 272GateRef CircuitBuilder::TaggedObjectIsJSMap(GateRef obj) 273{ 274 GateRef objType = GetObjectType(LoadHClass(obj)); 275 return Equal(objType, Int32(static_cast<int32_t>(JSType::JS_MAP))); 276} 277 278GateRef CircuitBuilder::TaggedObjectIsJSSet(GateRef obj) 279{ 280 GateRef objType = GetObjectType(LoadHClass(obj)); 281 return Equal(objType, Int32(static_cast<int32_t>(JSType::JS_SET))); 282} 283 284GateRef CircuitBuilder::TaggedObjectIsJSDate(GateRef obj) 285{ 286 GateRef objType = GetObjectType(LoadHClass(obj)); 287 return Equal(objType, Int32(static_cast<int32_t>(JSType::JS_DATE))); 288} 289 290GateRef CircuitBuilder::TaggedObjectIsTypedArray(GateRef obj) 291{ 292 GateRef jsType = GetObjectType(LoadHClass(obj)); 293 return BitAnd(Int32GreaterThan(jsType, Int32(static_cast<int32_t>(JSType::JS_TYPED_ARRAY_FIRST))), 294 Int32GreaterThanOrEqual(Int32(static_cast<int32_t>(JSType::JS_TYPED_ARRAY_LAST)), jsType)); 295} 296 297GateRef CircuitBuilder::TaggedObjectIsJSArray(GateRef obj) 298{ 299 GateRef objType = GetObjectType(LoadHClass(obj)); 300 return Equal(objType, Int32(static_cast<int32_t>(JSType::JS_ARRAY))); 301} 302 303GateRef CircuitBuilder::TaggedIsBoundFunction(GateRef obj) 304{ 305 GateRef objType = GetObjectType(LoadHClass(obj)); 306 return Equal(objType, Int32(static_cast<int32_t>(JSType::JS_BOUND_FUNCTION))); 307} 308 309inline GateRef CircuitBuilder::JudgeAotAndFastCall(GateRef jsFunc, JudgeMethodType type) 310{ 311 GateRef bitFieldOffset = IntPtr(JSFunctionBase::BIT_FIELD_OFFSET); 312 GateRef bitField = Load(VariableType::INT32(), jsFunc, bitFieldOffset); 313 switch (type) { 314 case JudgeMethodType::HAS_AOT: { 315 return Int32NotEqual( 316 Int32And( 317 Int32LSR(bitField, Int32(JSFunctionBase::IsCompiledCodeBit::START_BIT)), 318 Int32((1U << JSFunctionBase::IsCompiledCodeBit::SIZE) - 1)), 319 Int32(0)); 320 } 321 case JudgeMethodType::HAS_AOT_FASTCALL: { 322 return Int32Equal( 323 Int32And( 324 bitField, 325 Int32(JSFunctionBase::COMPILED_CODE_FASTCALL_BITS << JSFunctionBase::IsCompiledCodeBit::START_BIT)), 326 Int32(JSFunctionBase::COMPILED_CODE_FASTCALL_BITS << JSFunctionBase::IsCompiledCodeBit::START_BIT)); 327 } 328 case JudgeMethodType::HAS_AOT_NOTFASTCALL: { 329 GateRef fastCallField = 330 Int32And(bitField, 331 Int32(JSFunctionBase::COMPILED_CODE_FASTCALL_BITS << JSFunctionBase::IsCompiledCodeBit::START_BIT)); 332 GateRef hasAot = Int32(1U << JSFunctionBase::IsCompiledCodeBit::START_BIT); 333 return Int32Equal(fastCallField, hasAot); 334 } 335 default: 336 UNREACHABLE(); 337 } 338} 339 340GateRef CircuitBuilder::BothAreString(GateRef x, GateRef y) 341{ 342 return LogicAndBuilder(env_).And(TaggedIsHeapObject(x)).And(TaggedIsHeapObject(y)) 343 .And(TaggedObjectIsString(x)).And(TaggedObjectIsString(y)).Done(); 344} 345 346GateRef CircuitBuilder::TaggedIsHole(GateRef x) 347{ 348 return Equal(x, HoleConstant()); 349} 350 351GateRef CircuitBuilder::TaggedIsNullPtr(GateRef x) 352{ 353 return Equal(x, NullPtrConstant()); 354} 355 356GateRef CircuitBuilder::IsSpecialHole(GateRef x) 357{ 358 return Equal(x, SpecialHoleConstant()); 359} 360 361GateRef CircuitBuilder::IsNotSpecialHole(GateRef x) 362{ 363 return NotEqual(x, SpecialHoleConstant()); 364} 365 366GateRef CircuitBuilder::TaggedIsNotHole(GateRef x) 367{ 368 return NotEqual(x, HoleConstant()); 369} 370 371GateRef CircuitBuilder::TaggedIsUndefined(GateRef x) 372{ 373 return Equal(x, UndefineConstant()); 374} 375 376GateRef CircuitBuilder::TaggedIsException(GateRef x) 377{ 378 return Equal(x, ExceptionConstant()); 379} 380 381GateRef CircuitBuilder::TaggedIsSpecial(GateRef x) 382{ 383 return LogicOrBuilder(env_) 384 .Or(TaggedIsHole(x)) 385 .Or(Equal(Int64And(ChangeTaggedPointerToInt64(x), Int64(JSTaggedValue::TAG_SPECIAL_MASK)), 386 Int64(JSTaggedValue::TAG_SPECIAL))) 387 .Done(); 388} 389 390GateRef CircuitBuilder::TaggedIsHeapObject(GateRef x) 391{ 392 x = ChangeTaggedPointerToInt64(x); 393 auto t = Int64And(x, Int64(JSTaggedValue::TAG_HEAPOBJECT_MASK), GateType::Empty(), "checkHeapObject"); 394 return Equal(t, Int64(0), "checkHeapObject"); 395} 396 397GateRef CircuitBuilder::TaggedIsAsyncGeneratorObject(GateRef x) 398{ 399 return LogicAndBuilder(env_).And(TaggedIsHeapObject(x)).And(IsJsType(x, JSType::JS_ASYNC_GENERATOR_OBJECT)).Done(); 400} 401 402GateRef CircuitBuilder::TaggedIsJSGlobalObject(GateRef x) 403{ 404 return LogicAndBuilder(env_).And(TaggedIsHeapObject(x)).And(IsJsType(x, JSType::JS_GLOBAL_OBJECT)).Done(); 405} 406 407GateRef CircuitBuilder::TaggedIsGeneratorObject(GateRef x) 408{ 409 return LogicAndBuilder(env_).And(TaggedIsHeapObject(x)).And(IsJsType(x, JSType::JS_GENERATOR_OBJECT)).Done(); 410} 411 412GateRef CircuitBuilder::TaggedIsJSArray(GateRef x) 413{ 414 return LogicAndBuilder(env_).And(TaggedIsHeapObject(x)).And(IsJsType(x, JSType::JS_ARRAY)).Done(); 415} 416 417GateRef CircuitBuilder::TaggedIsPropertyBox(GateRef x) 418{ 419 return LogicAndBuilder(env_).And(TaggedIsHeapObject(x)).And(IsJsType(x, JSType::PROPERTY_BOX)).Done(); 420} 421 422GateRef CircuitBuilder::TaggedIsWeak(GateRef x) 423{ 424 return LogicAndBuilder(env_) 425 .And(TaggedIsHeapObject(x)) 426 .And(Equal(Int64And(ChangeTaggedPointerToInt64(x), Int64(JSTaggedValue::TAG_WEAK)), Int64(1))) 427 .Done(); 428} 429 430GateRef CircuitBuilder::TaggedIsPrototypeHandler(GateRef x) 431{ 432 return LogicAndBuilder(env_).And(TaggedIsHeapObject(x)).And(IsJsType(x, JSType::PROTOTYPE_HANDLER)).Done(); 433} 434 435GateRef CircuitBuilder::TaggedIsTransitionHandler(GateRef x) 436{ 437 return LogicAndBuilder(env_).And(TaggedIsHeapObject(x)).And(IsJsType(x, JSType::TRANSITION_HANDLER)).Done(); 438} 439 440GateRef CircuitBuilder::TaggedIsStoreTSHandler(GateRef x) 441{ 442 return LogicAndBuilder(env_).And(TaggedIsHeapObject(x)).And(IsJsType(x, JSType::STORE_TS_HANDLER)).Done(); 443} 444 445GateRef CircuitBuilder::TaggedIsTransWithProtoHandler(GateRef x) 446{ 447 return LogicAndBuilder(env_).And(TaggedIsHeapObject(x)).And(IsJsType(x, JSType::TRANS_WITH_PROTO_HANDLER)).Done(); 448} 449 450GateRef CircuitBuilder::TaggedIsUndefinedOrNull(GateRef x) 451{ 452 x = ChangeTaggedPointerToInt64(x); 453 GateRef heapObjMask = Int64(JSTaggedValue::TAG_HEAPOBJECT_MASK); 454 GateRef tagSpecial = Int64(JSTaggedValue::TAG_SPECIAL); 455 GateRef andGate = Int64And(x, heapObjMask); 456 GateRef result = Equal(andGate, tagSpecial); 457 return result; 458} 459 460GateRef CircuitBuilder::TaggedIsUndefinedOrNullOrHole(GateRef x) 461{ 462 return BitOr(TaggedIsHole(x), TaggedIsUndefinedOrNull(x)); 463} 464 465GateRef CircuitBuilder::TaggedIsNotUndefinedAndNull(GateRef x) 466{ 467 x = ChangeTaggedPointerToInt64(x); 468 GateRef heapObjMask = Int64(JSTaggedValue::TAG_HEAPOBJECT_MASK); 469 GateRef tagSpecial = Int64(JSTaggedValue::TAG_SPECIAL); 470 GateRef andGate = Int64And(x, heapObjMask); 471 GateRef result = NotEqual(andGate, tagSpecial); 472 return result; 473} 474 475GateRef CircuitBuilder::TaggedIsNotUndefinedAndNullAndHole(GateRef x) 476{ 477 return BitAnd(TaggedIsNotHole(x), TaggedIsNotUndefinedAndNull(x)); 478} 479 480GateRef CircuitBuilder::TaggedIsUndefinedOrHole(GateRef x) 481{ 482 GateRef isUndefined = TaggedIsUndefined(x); 483 GateRef isHole = TaggedIsHole(x); 484 GateRef result = BitOr(isHole, isUndefined); 485 return result; 486} 487 488GateRef CircuitBuilder::TaggedTrue() 489{ 490 return GetCircuit()->GetConstantGate(MachineType::I64, JSTaggedValue::VALUE_TRUE, GateType::TaggedValue()); 491} 492 493GateRef CircuitBuilder::TaggedFalse() 494{ 495 return GetCircuit()->GetConstantGate(MachineType::I64, JSTaggedValue::VALUE_FALSE, GateType::TaggedValue()); 496} 497 498GateRef CircuitBuilder::TaggedIsTrue(GateRef x) 499{ 500 return Equal(x, TaggedTrue()); 501} 502 503GateRef CircuitBuilder::TaggedIsFalse(GateRef x) 504{ 505 return Equal(x, TaggedFalse()); 506} 507 508GateRef CircuitBuilder::TaggedIsNull(GateRef x) 509{ 510 return Equal(x, NullConstant()); 511} 512 513GateRef CircuitBuilder::TaggedIsNotNull(GateRef x) 514{ 515 return NotEqual(x, NullConstant()); 516} 517 518GateRef CircuitBuilder::TaggedIsBoolean(GateRef x) 519{ 520 return BitOr(TaggedIsFalse(x), TaggedIsTrue(x)); 521} 522 523GateRef CircuitBuilder::TaggedGetInt(GateRef x) 524{ 525 x = ChangeTaggedPointerToInt64(x); 526 return TruncInt64ToInt32(Int64And(x, Int64(~JSTaggedValue::TAG_MARK))); 527} 528 529inline GateRef CircuitBuilder::TypedCallBuiltin(GateRef hirGate, const std::vector<GateRef> &args, 530 BuiltinsStubCSigns::ID id, bool isSideEffect) 531{ 532 auto currentLabel = env_->GetCurrentLabel(); 533 auto currentControl = currentLabel->GetControl(); 534 auto currentDepend = currentLabel->GetDepend(); 535 536 std::vector<GateRef> inList { currentControl, currentDepend }; 537 inList.insert(inList.end(), args.begin(), args.end()); 538 inList.push_back(Int16(static_cast<int16_t>(id))); 539 AppendFrameArgs(inList, hirGate); 540 541 auto builtinOp = TypedCallOperator(hirGate, MachineType::I64, inList, isSideEffect); 542 currentLabel->SetControl(builtinOp); 543 currentLabel->SetDepend(builtinOp); 544 return builtinOp; 545} 546 547template<TypedBinOp Op> 548GateRef CircuitBuilder::TypedBinaryOp(GateRef x, GateRef y, ParamType paramType) 549{ 550 auto currentLabel = env_->GetCurrentLabel(); 551 auto currentControl = currentLabel->GetControl(); 552 auto currentDepend = currentLabel->GetDepend(); 553 uint64_t value = TypedBinaryAccessor::ToValue(paramType, Op); 554 auto numberBinaryOp = GetCircuit()->NewGate(circuit_->TypedBinaryOp(value), 555 MachineType::I64, {currentControl, currentDepend, x, y}, GateType::AnyType()); 556 currentLabel->SetControl(numberBinaryOp); 557 currentLabel->SetDepend(numberBinaryOp); 558 return numberBinaryOp; 559} 560 561template<TypedCallTargetCheckOp Op> 562GateRef CircuitBuilder::JSNoGCCallThisTargetTypeCheck(GateRef func, GateRef methodId, GateRef gate) 563{ 564 auto currentLabel = env_->GetCurrentLabel(); 565 auto currentControl = currentLabel->GetControl(); 566 auto currentDepend = currentLabel->GetDepend(); 567 auto frameState = acc_.GetFrameState(gate); 568 uint64_t value = TypedCallTargetCheckAccessor::ToValue(Op); 569 GateRef ret = GetCircuit()->NewGate(circuit_->TypedCallTargetCheckOp(value), MachineType::I1, 570 {currentControl, currentDepend, func, methodId, frameState}, GateType::NJSValue()); 571 currentLabel->SetControl(ret); 572 currentLabel->SetDepend(ret); 573 return ret; 574} 575 576template<TypedCallTargetCheckOp Op> 577GateRef CircuitBuilder::JSCallTargetTypeCheck(GateRef func, GateRef methodIndex, GateRef gate) 578{ 579 auto currentLabel = env_->GetCurrentLabel(); 580 auto currentControl = currentLabel->GetControl(); 581 auto currentDepend = currentLabel->GetDepend(); 582 auto frameState = acc_.GetFrameState(gate); 583 uint64_t value = TypedCallTargetCheckAccessor::ToValue(Op); 584 GateRef ret = GetCircuit()->NewGate(circuit_->TypedCallTargetCheckOp(value), MachineType::I1, 585 {currentControl, currentDepend, func, methodIndex, frameState}, GateType::NJSValue()); 586 currentLabel->SetControl(ret); 587 currentLabel->SetDepend(ret); 588 return ret; 589} 590 591template<TypedUnOp Op> 592GateRef CircuitBuilder::TypedUnaryOp(GateRef x, ParamType paramType) 593{ 594 auto currentLabel = env_->GetCurrentLabel(); 595 auto currentControl = currentLabel->GetControl(); 596 auto currentDepend = currentLabel->GetDepend(); 597 uint64_t value = TypedUnaryAccessor::ToValue(paramType, Op); 598 auto numberUnaryOp = GetCircuit()->NewGate(circuit_->TypedUnaryOp(value), 599 MachineType::I64, {currentControl, currentDepend, x}, GateType::AnyType()); 600 currentLabel->SetControl(numberUnaryOp); 601 currentLabel->SetDepend(numberUnaryOp); 602 return numberUnaryOp; 603} 604 605template<TypedJumpOp Op> 606GateRef CircuitBuilder::TypedConditionJump(GateRef x, ParamType paramType, uint32_t weight) 607{ 608 auto currentLabel = env_->GetCurrentLabel(); 609 auto currentControl = currentLabel->GetControl(); 610 auto currentDepend = currentLabel->GetDepend(); 611 auto machineType = MachineType::NOVALUE; 612 auto jumpOp = TypedConditionJump(machineType, Op, weight, paramType, {currentControl, currentDepend, x}); 613 currentLabel->SetControl(jumpOp); 614 currentLabel->SetDepend(jumpOp); 615 return jumpOp; 616} 617 618template <TypedLoadOp Op> 619GateRef CircuitBuilder::LoadElement(GateRef receiver, GateRef index, OnHeapMode onHeap) 620{ 621 auto currentLabel = env_->GetCurrentLabel(); 622 auto currentControl = currentLabel->GetControl(); 623 auto currentDepend = currentLabel->GetDepend(); 624 LoadElementAccessor accessor(Op, onHeap); 625 auto ret = GetCircuit()->NewGate(GetCircuit()->LoadElement(accessor.ToValue()), MachineType::I64, 626 {currentControl, currentDepend, receiver, index}, GateType::AnyType()); 627 currentLabel->SetControl(ret); 628 currentLabel->SetDepend(ret); 629 return ret; 630} 631 632template <TypedStoreOp Op> 633GateRef CircuitBuilder::StoreElement(GateRef receiver, GateRef index, GateRef value, OnHeapMode onHeap) 634{ 635 auto currentLabel = env_->GetCurrentLabel(); 636 auto currentControl = currentLabel->GetControl(); 637 auto currentDepend = currentLabel->GetDepend(); 638 StoreElementAccessor accessor(Op, onHeap); 639 auto ret = GetCircuit()->NewGate(GetCircuit()->StoreElement(accessor.ToValue()), MachineType::NOVALUE, 640 {currentControl, currentDepend, receiver, index, value}, GateType::AnyType()); 641 currentLabel->SetControl(ret); 642 currentLabel->SetDepend(ret); 643 return ret; 644} 645 646GateRef CircuitBuilder::PrimitiveToNumber(GateRef x, ParamType paramType) 647{ 648 auto currentLabel = env_->GetCurrentLabel(); 649 auto currentControl = currentLabel->GetControl(); 650 auto currentDepend = currentLabel->GetDepend(); 651 652 auto numberconvert = TypeConvert(MachineType::I64, paramType, GateType::NumberType(), 653 {currentControl, currentDepend, x}); 654 currentLabel->SetControl(numberconvert); 655 currentLabel->SetDepend(numberconvert); 656 return numberconvert; 657} 658 659GateRef CircuitBuilder::LoadFromTaggedArray(GateRef array, size_t index) 660{ 661 auto dataOffset = TaggedArray::DATA_OFFSET + index * JSTaggedValue::TaggedTypeSize(); 662 return LoadConstOffset(VariableType::JS_ANY(), array, dataOffset); 663} 664 665GateRef CircuitBuilder::StoreToTaggedArray(GateRef array, size_t index, GateRef value) 666{ 667 auto dataOffset = TaggedArray::DATA_OFFSET + index * JSTaggedValue::TaggedTypeSize(); 668 return StoreConstOffset(VariableType::JS_ANY(), array, dataOffset, value); 669} 670 671GateRef CircuitBuilder::TreeStringIsFlat(GateRef string) 672{ 673 GateRef second = GetSecondFromTreeString(string); 674 GateRef len = GetLengthFromString(second); 675 return Int32Equal(len, Int32(0)); 676} 677 678GateRef CircuitBuilder::GetFirstFromTreeString(GateRef string) 679{ 680 GateRef offset = IntPtr(TreeEcmaString::FIRST_OFFSET); 681 return Load(VariableType::JS_POINTER(), string, offset); 682} 683 684GateRef CircuitBuilder::GetSecondFromTreeString(GateRef string) 685{ 686 GateRef offset = IntPtr(TreeEcmaString::SECOND_OFFSET); 687 return Load(VariableType::JS_POINTER(), string, offset); 688} 689 690GateRef CircuitBuilder::GetValueFromTaggedArray(GateRef array, GateRef index) 691{ 692 GateRef offset = PtrMul(ZExtInt32ToPtr(index), IntPtr(JSTaggedValue::TaggedTypeSize())); 693 GateRef dataOffset = PtrAdd(offset, IntPtr(TaggedArray::DATA_OFFSET)); 694 return Load(VariableType::JS_ANY(), array, dataOffset); 695} 696 697GateRef CircuitBuilder::GetValueFromTaggedArray(VariableType valType, GateRef array, GateRef index) 698{ 699 GateRef offset = PtrMul(ZExtInt32ToPtr(index), IntPtr(JSTaggedValue::TaggedTypeSize())); 700 GateRef dataOffset = PtrAdd(offset, IntPtr(TaggedArray::DATA_OFFSET)); 701 return Load(valType, array, dataOffset); 702} 703 704GateRef CircuitBuilder::GetValueFromJSArrayWithElementsKind(VariableType type, GateRef array, GateRef index) 705{ 706 GateRef offset = PtrMul(ZExtInt32ToPtr(index), IntPtr(JSTaggedValue::TaggedTypeSize())); 707 GateRef dataOffset = PtrAdd(offset, IntPtr(TaggedArray::DATA_OFFSET)); 708 return Load(type, array, dataOffset); 709} 710 711void CircuitBuilder::SetValueToTaggedArray(VariableType valType, GateRef glue, 712 GateRef array, GateRef index, GateRef val) 713{ 714 GateRef offset = PtrMul(ZExtInt32ToPtr(index), IntPtr(JSTaggedValue::TaggedTypeSize())); 715 GateRef dataOffset = PtrAdd(offset, IntPtr(TaggedArray::DATA_OFFSET)); 716 Store(valType, glue, array, dataOffset, val); 717} 718} 719 720#endif // ECMASCRIPT_COMPILER_MCR_CIRCUIT_BUILDER_H 721