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#include "ecmascript/compiler/native_inline_lowering.h" 16#include "ecmascript/builtins/builtins_number.h" 17#include "ecmascript/builtins/builtins_string.h" 18#include "ecmascript/base/number_helper.h" 19#include "ecmascript/compiler/circuit.h" 20#include "ecmascript/compiler/circuit_builder-inl.h" 21#include "ecmascript/compiler/circuit_builder_helper.h" 22#include "ecmascript/compiler/share_gate_meta_data.h" 23#include "ecmascript/js_dataview.h" 24#include "ecmascript/compiler/circuit.h" 25#include "ecmascript/compiler/new_object_stub_builder.h" 26#include "ecmascript/global_env.h" 27#include "ecmascript/js_iterator.h" 28#include "ecmascript/js_thread.h" 29#include "ecmascript/message_string.h" 30 31namespace panda::ecmascript::kungfu { 32 33std::optional<std::pair<size_t, bool>> NativeInlineLowering::GetCallInfo(GateRef gate) 34{ 35 EcmaOpcode ecmaOpcode = acc_.GetByteCodeOpcode(gate); 36 switch (ecmaOpcode) { 37 case EcmaOpcode::CALLARG0_IMM8: 38 return {{0U, false}}; 39 case EcmaOpcode::CALLTHIS0_IMM8_V8: 40 return {{0U, true}}; 41 case EcmaOpcode::CALLARG1_IMM8_V8: 42 return {{1U, false}}; 43 case EcmaOpcode::CALLTHIS1_IMM8_V8_V8: 44 return {{1U, true}}; 45 case EcmaOpcode::CALLARGS2_IMM8_V8_V8: 46 return {{2U, false}}; 47 case EcmaOpcode::CALLTHIS2_IMM8_V8_V8_V8: 48 return {{2U, true}}; 49 case EcmaOpcode::CALLARGS3_IMM8_V8_V8_V8: 50 return {{3U, false}}; 51 case EcmaOpcode::CALLTHIS3_IMM8_V8_V8_V8_V8: 52 return {{3U, true}}; 53 case EcmaOpcode::CALLRANGE_IMM8_IMM8_V8: { 54 CallRangeTypeInfoAccessor tia(compilationEnv_, circuit_, gate); 55 return {{tia.GetArgc(), false}}; 56 } 57 case EcmaOpcode::CALLTHISRANGE_IMM8_IMM8_V8: { 58 CallThisRangeTypeInfoAccessor tia(compilationEnv_, circuit_, gate); 59 return {{tia.GetArgc(), true}}; 60 } 61 default: 62 return std::nullopt; 63 } 64} 65 66void NativeInlineLowering::RunNativeInlineLowering() 67{ 68 std::vector<GateRef> gateList; 69 circuit_->GetAllGates(gateList); 70 for (const auto &gate : gateList) { 71 auto op = acc_.GetOpCode(gate); 72 if (op != OpCode::JS_BYTECODE) { 73 continue; 74 } 75 auto optCallInfo = GetCallInfo(gate); 76 if (!optCallInfo) { 77 continue; 78 } 79 auto [argc, skipThis] = optCallInfo.value(); 80 CallTypeInfoAccessor ctia(compilationEnv_, circuit_, gate); 81 BuiltinsStubCSigns::ID id = ctia.TryGetPGOBuiltinMethodId(); 82 if (IS_INVALID_ID(id) && id != BuiltinsStubCSigns::ID::BigIntConstructor) { 83 continue; 84 } 85 switch (id) { 86 case BuiltinsStubCSigns::ID::StringFromCharCode: 87 TryInlineStringFromCharCode(gate, argc, skipThis); 88 break; 89 case BuiltinsStubCSigns::ID::StringCharCodeAt: 90 TryInlineStringCharCodeAt(gate, argc, skipThis); 91 break; 92 case BuiltinsStubCSigns::ID::StringSubstring: 93 TryInlineStringSubstring(gate, argc, skipThis); 94 break; 95 case BuiltinsStubCSigns::ID::StringSubStr: 96 TryInlineStringSubStr(gate, argc, skipThis); 97 break; 98 case BuiltinsStubCSigns::ID::StringSlice: 99 TryInlineStringSlice(gate, argc, skipThis); 100 break; 101 case BuiltinsStubCSigns::ID::NumberIsFinite: 102 TryInlineNumberIsFinite(gate, argc, skipThis); 103 break; 104 case BuiltinsStubCSigns::ID::NumberIsInteger: 105 TryInlineNumberIsInteger(gate, argc, skipThis); 106 break; 107 case BuiltinsStubCSigns::ID::NumberIsNaN: 108 TryInlineNumberIsNaN(gate, argc, skipThis); 109 break; 110 case BuiltinsStubCSigns::ID::NumberParseFloat: 111 TryInlineNumberParseFloat(gate, argc, skipThis); 112 break; 113 case BuiltinsStubCSigns::ID::NumberParseInt: 114 TryInlineNumberParseInt(gate, argc, skipThis); 115 break; 116 case BuiltinsStubCSigns::ID::NumberIsSafeInteger: 117 TryInlineNumberIsSafeInteger(gate, argc, skipThis); 118 break; 119 case BuiltinsStubCSigns::ID::TypedArrayEntries: 120 TryInlineTypedArrayIteratorBuiltin(gate, id, circuit_->TypedArrayEntries(), skipThis); 121 break; 122 case BuiltinsStubCSigns::ID::TypedArrayKeys: 123 TryInlineTypedArrayIteratorBuiltin(gate, id, circuit_->TypedArrayKeys(), skipThis); 124 break; 125 case BuiltinsStubCSigns::ID::TypedArrayValues: 126 TryInlineTypedArrayIteratorBuiltin(gate, id, circuit_->TypedArrayValues(), skipThis); 127 break; 128 case BuiltinsStubCSigns::ID::ArrayValues: 129 TryInlineArrayIterator(gate, id, skipThis); 130 break; 131 case BuiltinsStubCSigns::ID::ArrayKeys: 132 TryInlineArrayIterator(gate, id, skipThis); 133 break; 134 case BuiltinsStubCSigns::ID::ArrayEntries: 135 TryInlineArrayIterator(gate, id, skipThis); 136 break; 137 case BuiltinsStubCSigns::ID::MathAcos: 138 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathAcos(), skipThis); 139 break; 140 case BuiltinsStubCSigns::ID::MathAcosh: 141 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathAcosh(), skipThis); 142 break; 143 case BuiltinsStubCSigns::ID::MathAsin: 144 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathAsin(), skipThis); 145 break; 146 case BuiltinsStubCSigns::ID::MathAsinh: 147 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathAsinh(), skipThis); 148 break; 149 case BuiltinsStubCSigns::ID::MathAtan: 150 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathAtan(), skipThis); 151 break; 152 case BuiltinsStubCSigns::ID::MathAtan2: 153 TryInlineMathBinaryBuiltin(gate, argc, id, circuit_->MathAtan2(), skipThis); 154 break; 155 case BuiltinsStubCSigns::ID::MathAtanh: 156 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathAtanh(), skipThis); 157 break; 158 case BuiltinsStubCSigns::ID::MathCos: 159 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathCos(), skipThis); 160 break; 161 case BuiltinsStubCSigns::ID::MathCosh: 162 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathCosh(), skipThis); 163 break; 164 case BuiltinsStubCSigns::ID::MathSign: 165 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathSign(), skipThis); 166 break; 167 case BuiltinsStubCSigns::ID::MathSin: 168 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathSin(), skipThis); 169 break; 170 case BuiltinsStubCSigns::ID::MathSinh: 171 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathSinh(), skipThis); 172 break; 173 case BuiltinsStubCSigns::ID::MathSqrt: 174 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathSqrt(), skipThis); 175 break; 176 case BuiltinsStubCSigns::ID::MathTan: 177 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathTan(), skipThis); 178 break; 179 case BuiltinsStubCSigns::ID::MathTanh: 180 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathTanh(), skipThis); 181 break; 182 case BuiltinsStubCSigns::ID::MathTrunc: 183 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathTrunc(), skipThis); 184 break; 185 case BuiltinsStubCSigns::ID::MathAbs: 186 TryInlineMathAbsBuiltin(gate, argc, skipThis); 187 break; 188 case BuiltinsStubCSigns::ID::MathLog: 189 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathLog(), skipThis); 190 break; 191 case BuiltinsStubCSigns::ID::MathLog2: 192 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathLog2(), skipThis); 193 break; 194 case BuiltinsStubCSigns::ID::MathLog10: 195 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathLog10(), skipThis); 196 break; 197 case BuiltinsStubCSigns::ID::MathLog1p: 198 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathLog1p(), skipThis); 199 break; 200 case BuiltinsStubCSigns::ID::MathExp: 201 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathExp(), skipThis); 202 break; 203 case BuiltinsStubCSigns::ID::MathExpm1: 204 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathExpm1(), skipThis); 205 break; 206 case BuiltinsStubCSigns::ID::MathClz32: 207 TryInlineMathClz32Builtin(gate, argc, skipThis); 208 break; 209 case BuiltinsStubCSigns::ID::MathPow: 210 TryInlineMathBinaryBuiltin(gate, argc, id, circuit_->MathPow(), skipThis); 211 break; 212 case BuiltinsStubCSigns::ID::MathCbrt: 213 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathCbrt(), skipThis); 214 break; 215 case BuiltinsStubCSigns::ID::MathImul: 216 TryInlineMathImulBuiltin(gate, argc, id, circuit_->MathImul(), skipThis); 217 break; 218 case BuiltinsStubCSigns::ID::GlobalIsFinite: 219 TryInlineGlobalFiniteBuiltin(gate, argc, id, circuit_->GlobalIsFinite(), skipThis); 220 break; 221 case BuiltinsStubCSigns::ID::GlobalIsNan: 222 TryInlineGlobalNanBuiltin(gate, argc, id, circuit_->GlobalIsNan(), skipThis); 223 break; 224 case BuiltinsStubCSigns::ID::DateGetTime: 225 TryInlineDateGetTime(gate, argc, skipThis); 226 break; 227 case BuiltinsStubCSigns::ID::MathMin: 228 TryInlineMathMinMaxBuiltin(gate, argc, id, circuit_->MathMin(), base::POSITIVE_INFINITY, skipThis); 229 break; 230 case BuiltinsStubCSigns::ID::MathMax: 231 TryInlineMathMinMaxBuiltin(gate, argc, id, circuit_->MathMax(), -base::POSITIVE_INFINITY, skipThis); 232 break; 233 case BuiltinsStubCSigns::ID::MathRound: 234 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathRound(), skipThis); 235 break; 236 case BuiltinsStubCSigns::ID::MathFRound: 237 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathFRound(), skipThis); 238 break; 239 case BuiltinsStubCSigns::ID::MathCeil: 240 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathCeil(), skipThis); 241 break; 242 case BuiltinsStubCSigns::ID::MathFloor: 243 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathFloor(), skipThis); 244 break; 245 case BuiltinsStubCSigns::ID::ArrayBufferIsView: 246 TryInlineArrayBufferIsView(gate, argc, id, skipThis); 247 break; 248 case BuiltinsStubCSigns::ID::DataViewGetFloat32: 249 case BuiltinsStubCSigns::ID::DataViewGetFloat64: 250 case BuiltinsStubCSigns::ID::DataViewGetInt8: 251 case BuiltinsStubCSigns::ID::DataViewGetInt16: 252 case BuiltinsStubCSigns::ID::DataViewGetInt32: 253 case BuiltinsStubCSigns::ID::DataViewGetUint16: 254 case BuiltinsStubCSigns::ID::DataViewGetUint32: 255 case BuiltinsStubCSigns::ID::DataViewGetUint8: 256 TryInlineDataViewGet(gate, argc, id, skipThis); 257 break; 258 case BuiltinsStubCSigns::ID::DataViewSetFloat32: 259 case BuiltinsStubCSigns::ID::DataViewSetFloat64: 260 case BuiltinsStubCSigns::ID::DataViewSetInt8: 261 case BuiltinsStubCSigns::ID::DataViewSetInt16: 262 case BuiltinsStubCSigns::ID::DataViewSetInt32: 263 case BuiltinsStubCSigns::ID::DataViewSetUint8: 264 case BuiltinsStubCSigns::ID::DataViewSetUint16: 265 case BuiltinsStubCSigns::ID::DataViewSetUint32: 266 TryInlineDataViewSet(gate, argc, id, skipThis); 267 break; 268 case BuiltinsStubCSigns::ID::BigIntAsIntN: 269 case BuiltinsStubCSigns::ID::BigIntAsUintN: 270 TryInlineBigIntAsIntN(gate, argc, id, skipThis); 271 break; 272 case BuiltinsStubCSigns::ID::MapGet: 273 InlineStubBuiltin(gate, 1U, argc, id, circuit_->MapGet(), skipThis); 274 break; 275 case BuiltinsStubCSigns::ID::MapHas: 276 InlineStubBuiltin(gate, 1U, argc, id, circuit_->MapHas(), skipThis); 277 break; 278 case BuiltinsStubCSigns::ID::MapKeys: 279 InlineStubBuiltin(gate, 0U, argc, id, circuit_->MapKeys(), skipThis); 280 break; 281 case BuiltinsStubCSigns::ID::MapValues: 282 InlineStubBuiltin(gate, 0U, argc, id, circuit_->MapValues(), skipThis); 283 break; 284 case BuiltinsStubCSigns::ID::MapEntries: 285 InlineStubBuiltin(gate, 0U, argc, id, circuit_->MapEntries(), skipThis); 286 break; 287 case BuiltinsStubCSigns::ID::SetHas: 288 InlineStubBuiltin(gate, 1U, argc, id, circuit_->SetHas(), skipThis); 289 break; 290 case BuiltinsStubCSigns::ID::SetAdd: 291 InlineStubBuiltin(gate, 1U, argc, id, circuit_->SetAdd(), skipThis); 292 break; 293 case BuiltinsStubCSigns::ID::DateNow: 294 TryInlineWhitoutParamBuiltin(gate, argc, id, circuit_->DateNow(), skipThis); 295 break; 296 case BuiltinsStubCSigns::ID::MapDelete: 297 InlineStubBuiltin(gate, 1U, argc, id, circuit_->MapDelete(), skipThis); 298 break; 299 case BuiltinsStubCSigns::ID::SetDelete: 300 InlineStubBuiltin(gate, 1U, argc, id, circuit_->SetDelete(), skipThis); 301 break; 302 case BuiltinsStubCSigns::ID::SetValues: 303 InlineStubBuiltin(gate, 0U, argc, id, circuit_->SetValues(), skipThis); 304 break; 305 case BuiltinsStubCSigns::ID::SetEntries: 306 InlineStubBuiltin(gate, 0U, argc, id, circuit_->SetEntries(), skipThis); 307 break; 308 case BuiltinsStubCSigns::ID::BigIntConstructor: 309 TryInlineBigIntConstructor(gate, argc, skipThis); 310 break; 311 case BuiltinsStubCSigns::ID::MapClear: 312 InlineStubBuiltin(gate, 0U, argc, id, circuit_->MapClear(), skipThis); 313 break; 314 case BuiltinsStubCSigns::ID::SetClear: 315 InlineStubBuiltin(gate, 0U, argc, id, circuit_->SetClear(), skipThis); 316 break; 317 case BuiltinsStubCSigns::ID::ArraySort: 318 TryInlineArraySort(gate, argc, id, skipThis); 319 break; 320 case BuiltinsStubCSigns::ID::ObjectIs: 321 TryInlineObjectIs(gate, argc, id, skipThis); 322 break; 323 case BuiltinsStubCSigns::ID::ObjectGetPrototypeOf: 324 TryInlineObjectGetPrototypeOf(gate, argc, id, skipThis); 325 break; 326 case BuiltinsStubCSigns::ID::ObjectGetProto: 327 TryInlineObjectGetProto(gate, argc, id, skipThis); 328 break; 329 case BuiltinsStubCSigns::ID::ObjectCreate: 330 TryInlineObjectCreate(gate, argc, id, skipThis); 331 break; 332 case BuiltinsStubCSigns::ID::ObjectIsPrototypeOf: 333 TryInlineObjectIsPrototypeOf(gate, argc, id, skipThis); 334 break; 335 case BuiltinsStubCSigns::ID::ObjectHasOwnProperty: 336 TryInlineObjectHasOwnProperty(gate, argc, id, skipThis); 337 break; 338 case BuiltinsStubCSigns::ID::ReflectGetPrototypeOf: 339 TryInlineReflectGetPrototypeOf(gate, argc, id, skipThis); 340 break; 341 case BuiltinsStubCSigns::ID::ReflectGet: 342 TryInlineReflectGet(gate, argc, id, skipThis); 343 break; 344 case BuiltinsStubCSigns::ID::ReflectHas: 345 TryInlineReflectHas(gate, argc, id, skipThis); 346 break; 347 case BuiltinsStubCSigns::ID::ReflectConstruct: 348 TryInlineReflectConstruct(gate, argc, id, skipThis); 349 break; 350 case BuiltinsStubCSigns::ID::ReflectApply: 351 TryInlineReflectApply(gate, argc, id, skipThis); 352 break; 353 case BuiltinsStubCSigns::ID::FunctionPrototypeHasInstance: 354 TryInlineFunctionPrototypeHasInstance(gate, argc, id, skipThis); 355 break; 356 case BuiltinsStubCSigns::ID::ArrayIndexOf: 357 TryInlineIndexOfIncludes(gate, argc, id, skipThis); 358 break; 359 case BuiltinsStubCSigns::ID::ArrayIncludes: 360 TryInlineIndexOfIncludes(gate, argc, id, skipThis); 361 break; 362 case BuiltinsStubCSigns::ID::ArrayForEach: 363 TryInlineArrayForEach(gate, argc, id, skipThis); 364 break; 365 case BuiltinsStubCSigns::ID::ArrayFind: 366 TryInlineArrayFindOrFindIndex(gate, argc, id, skipThis); 367 break; 368 case BuiltinsStubCSigns::ID::ArrayFindIndex: 369 TryInlineArrayFindOrFindIndex(gate, argc, id, skipThis); 370 break; 371 case BuiltinsStubCSigns::ID::ArrayFilter: 372 TryInlineArrayFilter(gate, argc, id, skipThis); 373 break; 374 case BuiltinsStubCSigns::ID::ArrayMap: 375 TryInlineArrayMap(gate, argc, id, skipThis); 376 break; 377 case BuiltinsStubCSigns::ID::ArraySome: 378 TryInlineArraySome(gate, argc, id, skipThis); 379 break; 380 case BuiltinsStubCSigns::ID::ArrayEvery: 381 TryInlineArrayEvery(gate, argc, id, skipThis); 382 break; 383 case BuiltinsStubCSigns::ID::ArrayPop: 384 TryInlineArrayPop(gate, argc, id, skipThis); 385 break; 386 case BuiltinsStubCSigns::ID::ArraySlice: 387 TryInlineArraySlice(gate, argc, id, skipThis); 388 break; 389 default: 390 break; 391 } 392 } 393 394 if (EnableLog()) { 395 LOG_COMPILER(INFO) << " "; 396 LOG_COMPILER(INFO) << "\033[34m" << "=================" 397 << " After Native Inline Lowering " 398 << "[" << GetMethodName() << "] " 399 << "=================" << "\033[0m"; 400 circuit_->PrintAllGatesWithBytecode(); 401 LOG_COMPILER(INFO) << "\033[34m" << "=========================== End ===========================" << "\033[0m"; 402 } 403} 404 405void NativeInlineLowering::AddTraceLogs(GateRef gate, BuiltinsStubCSigns::ID id) 406{ 407 size_t index = RTSTUB_ID(AotInlineBuiltinTrace); 408 409 GateRef frameState = acc_.GetFrameState(gate); 410 GateRef frameArgs = acc_.GetValueIn(frameState); 411 GateRef callerFunc = acc_.GetValueIn(frameArgs, 0); 412 std::vector<GateRef> args{callerFunc, builder_.Int32(id)}; 413 414 builder_.CallRuntime(glue_, index, Gate::InvalidGateRef, args, gate); 415} 416 417void NativeInlineLowering::TryInlineStringFromCharCode(GateRef gate, size_t argc, bool skipThis) 418{ 419 if (!skipThis) { 420 return; 421 } 422 if (argc != 1) { 423 return; 424 } 425 CallThis1TypeInfoAccessor tacc(compilationEnv_, circuit_, gate); 426 Environment env(gate, circuit_, &builder_); 427 if (!Uncheck()) { 428 builder_.CallTargetCheck(gate, tacc.GetFunc(), 429 builder_.IntPtr(static_cast<int64_t>(BuiltinsStubCSigns::ID::StringFromCharCode)), 430 {tacc.GetArg0()}); 431 } 432 433 if (EnableTrace()) { 434 AddTraceLogs(gate, BuiltinsStubCSigns::ID::StringFromCharCode); 435 } 436 437 GateRef ret = builder_.StringFromSingleCharCode(tacc.GetArg0()); 438 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), ret); 439} 440 441void NativeInlineLowering::TryInlineStringCharCodeAt(GateRef gate, size_t argc, bool skipThis) 442{ 443 // only inline number input, string input will be deoptimized 444 if (!skipThis) { 445 return; 446 } 447 448 GateRef thisValue = acc_.GetValueIn(gate, 0); 449 GateRef posTag = (argc == 0) ? (builder_.Int32(0)) : (acc_.GetValueIn(gate, 1)); 450 GateRef func = acc_.GetValueIn(gate, argc + 1); 451 Environment env(gate, circuit_, &builder_); 452 if (!Uncheck()) { 453 builder_.CallTargetCheck(gate, func, 454 builder_.IntPtr(static_cast<int64_t>(BuiltinsStubCSigns::ID::StringCharCodeAt)), 455 {thisValue}); 456 builder_.EcmaStringCheck(thisValue); 457 } 458 459 if (EnableTrace()) { 460 AddTraceLogs(gate, BuiltinsStubCSigns::ID::StringCharCodeAt); 461 } 462 463 GateRef ret = builder_.StringCharCodeAt(thisValue, posTag); 464 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret); 465} 466 467void NativeInlineLowering::TryInlineStringSubstring(GateRef gate, size_t argc, bool skipThis) 468{ 469 if (!skipThis) { 470 return; 471 } 472 if (argc != 1 && argc != 2) { // only optimize one or two parameters scene 473 return; 474 } 475 Environment env(gate, circuit_, &builder_); 476 GateRef ret = Circuit::NullGate(); 477 if (argc == 1) { 478 CallThis1TypeInfoAccessor tacc(compilationEnv_, circuit_, gate); 479 GateRef thisValue = acc_.GetValueIn(gate, 0); 480 GateRef startTag = tacc.GetArg0(); 481 GateRef endTag = builder_.GetLengthFromString(thisValue); 482 if (!Uncheck()) { 483 builder_.CallTargetCheck(gate, tacc.GetFunc(), 484 builder_.IntPtr(static_cast<int64_t>(BuiltinsStubCSigns::ID::StringSubstring)), 485 {tacc.GetArg0()}); 486 builder_.EcmaStringCheck(thisValue); 487 auto param_check = builder_.TaggedIsNumber(startTag); 488 builder_.DeoptCheck(param_check, acc_.GetFrameState(gate), DeoptType::BUILTIN_INLINING_TYPE_GUARD); 489 } 490 ret = builder_.StringSubstring(thisValue, startTag, endTag); 491 } else { 492 GateRef thisValue = acc_.GetValueIn(gate, 0); 493 GateRef startTag = acc_.GetValueIn(gate, 1); 494 GateRef endTag = acc_.GetValueIn(gate, 2); 495 GateRef func = acc_.GetValueIn(gate, 3); 496 if (!Uncheck()) { 497 builder_.CallTargetCheck(gate, func, 498 builder_.IntPtr(static_cast<int64_t>(BuiltinsStubCSigns::ID::StringSubstring))); 499 builder_.EcmaStringCheck(thisValue); 500 auto param_check = LogicAndBuilder(&env).And(builder_.TaggedIsNumber(startTag)) 501 .And(builder_.TaggedIsNumber(endTag)).Done(); 502 builder_.DeoptCheck(param_check, acc_.GetFrameState(gate), DeoptType::BUILTIN_INLINING_TYPE_GUARD); 503 } 504 ret = builder_.StringSubstring(thisValue, startTag, endTag); 505 } 506 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret); 507} 508 509void NativeInlineLowering::TryInlineStringSubStr(GateRef gate, size_t argc, bool skipThis) 510{ 511 if (!skipThis) { 512 return; 513 } 514 if (argc != 1 && argc != 2) { // only optimize one or two parameters scene 515 return; 516 } 517 Environment env(gate, circuit_, &builder_); 518 GateRef ret = Circuit::NullGate(); 519 if (argc == 1) { 520 CallThis1TypeInfoAccessor tacc(compilationEnv_, circuit_, gate); 521 GateRef thisValue = acc_.GetValueIn(gate, 0); 522 GateRef intStart = tacc.GetArg0(); 523 GateRef lengthTag = builder_.Int32(INT_MAX); 524 if (!Uncheck()) { 525 builder_.CallTargetCheck(gate, tacc.GetFunc(), 526 builder_.IntPtr(static_cast<int64_t>(BuiltinsStubCSigns::ID::StringSubStr)), 527 {tacc.GetArg0()}); 528 builder_.EcmaStringCheck(thisValue); 529 auto param_check = builder_.TaggedIsNumber(intStart); 530 builder_.DeoptCheck(param_check, acc_.GetFrameState(gate), DeoptType::BUILTIN_INLINING_TYPE_GUARD); 531 } 532 ret = builder_.StringSubStr(thisValue, intStart, lengthTag); 533 } else { 534 GateRef thisValue = acc_.GetValueIn(gate, 0); 535 GateRef intStart = acc_.GetValueIn(gate, 1); 536 GateRef lengthTag = acc_.GetValueIn(gate, 2); 537 GateRef func = acc_.GetValueIn(gate, 3); //acc 538 if (!Uncheck()) { 539 builder_.CallTargetCheck(gate, func, 540 builder_.IntPtr(static_cast<int64_t>(BuiltinsStubCSigns::ID::StringSubStr))); 541 builder_.EcmaStringCheck(thisValue); 542 auto param_check = LogicAndBuilder(&env).And(builder_.TaggedIsNumber(intStart)) 543 .And(builder_.TaggedIsNumber(lengthTag)).Done(); 544 builder_.DeoptCheck(param_check, acc_.GetFrameState(gate), DeoptType::BUILTIN_INLINING_TYPE_GUARD); 545 } 546 ret = builder_.StringSubStr(thisValue, intStart, lengthTag); 547 } 548 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret); 549} 550 551void NativeInlineLowering::TryInlineStringSlice(GateRef gate, size_t argc, bool skipThis) 552{ 553 if (!skipThis) { 554 return; 555 } 556 if (argc != 1 && argc != 2) { // only optimize one or two parameters scene 557 return; 558 } 559 Environment env(gate, circuit_, &builder_); 560 GateRef ret = Circuit::NullGate(); 561 if (argc == 1) { 562 CallThis1TypeInfoAccessor tacc(compilationEnv_, circuit_, gate); 563 GateRef thisValue = acc_.GetValueIn(gate, 0); 564 GateRef startTag = tacc.GetArg0(); 565 GateRef endTag = builder_.GetLengthFromString(thisValue); 566 if (!Uncheck()) { 567 builder_.CallTargetCheck(gate, tacc.GetFunc(), 568 builder_.IntPtr(static_cast<int64_t>(BuiltinsStubCSigns::ID::StringSlice)), 569 {tacc.GetArg0()}); 570 builder_.EcmaStringCheck(thisValue); 571 auto param_check = builder_.TaggedIsNumber(startTag); 572 builder_.DeoptCheck(param_check, acc_.GetFrameState(gate), DeoptType::BUILTIN_INLINING_TYPE_GUARD); 573 } 574 ret = builder_.StringSlice(thisValue, startTag, endTag); 575 } else { 576 GateRef thisValue = acc_.GetValueIn(gate, 0); 577 GateRef startTag = acc_.GetValueIn(gate, 1); 578 GateRef endTag = acc_.GetValueIn(gate, 2); 579 GateRef func = acc_.GetValueIn(gate, 3); 580 if (!Uncheck()) { 581 builder_.CallTargetCheck(gate, func, 582 builder_.IntPtr(static_cast<int64_t>(BuiltinsStubCSigns::ID::StringSlice))); 583 builder_.EcmaStringCheck(thisValue); 584 auto param_check = LogicAndBuilder(&env).And(builder_.TaggedIsNumber(startTag)) 585 .And(builder_.TaggedIsNumber(endTag)).Done(); 586 builder_.DeoptCheck(param_check, acc_.GetFrameState(gate), DeoptType::BUILTIN_INLINING_TYPE_GUARD); 587 } 588 ret = builder_.StringSlice(thisValue, startTag, endTag); 589 } 590 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret); 591} 592 593void NativeInlineLowering::TryInlineNumberIsFinite(GateRef gate, size_t argc, bool skipThis) 594{ 595 if (!skipThis) { 596 return; 597 } 598 if (argc != 1) { 599 return; 600 } 601 CallThis1TypeInfoAccessor tacc(compilationEnv_, circuit_, gate); 602 Environment env(gate, circuit_, &builder_); 603 if (!Uncheck()) { 604 builder_.CallTargetCheck(gate, tacc.GetFunc(), 605 builder_.IntPtr(static_cast<int64_t>(BuiltinsStubCSigns::ID::NumberIsFinite))); 606 } 607 GateRef ret = builder_.NumberIsFinite(tacc.GetArg0()); 608 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret); 609} 610 611void NativeInlineLowering::TryInlineNumberIsInteger(GateRef gate, size_t argc, bool skipThis) 612{ 613 if (!skipThis) { 614 return; 615 } 616 if (argc != 1) { 617 return; 618 } 619 CallThis1TypeInfoAccessor tacc(compilationEnv_, circuit_, gate); 620 Environment env(gate, circuit_, &builder_); 621 auto id = BuiltinsStubCSigns::ID::NumberIsInteger; 622 if (!Uncheck()) { 623 builder_.CallTargetCheck(gate, tacc.GetFunc(), 624 builder_.IntPtr(static_cast<int64_t>(id))); 625 } 626 if (EnableTrace()) { 627 AddTraceLogs(gate, id); 628 } 629 GateRef ret = builder_.NumberIsInteger(tacc.GetArg0()); 630 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret); 631} 632 633void NativeInlineLowering::TryInlineNumberIsNaN(GateRef gate, size_t argc, bool skipThis) 634{ 635 if (!skipThis) { 636 return; 637 } 638 if (argc != 1) { 639 return; 640 } 641 CallThis1TypeInfoAccessor tacc(compilationEnv_, circuit_, gate); 642 Environment env(gate, circuit_, &builder_); 643 if (!Uncheck()) { 644 builder_.CallTargetCheck(gate, tacc.GetFunc(), 645 builder_.IntPtr(static_cast<int64_t>(BuiltinsStubCSigns::ID::NumberIsNaN))); 646 } 647 GateRef ret = builder_.NumberIsNaN(tacc.GetArg0()); 648 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret); 649} 650 651void NativeInlineLowering::TryInlineNumberParseFloat(GateRef gate, size_t argc, bool skipThis) 652{ 653 auto firstParam = skipThis ? 1 : 0; 654 auto func = acc_.GetValueIn(gate, argc + firstParam); 655 auto arg = acc_.GetValueIn(gate, firstParam); 656 657 Environment env(gate, circuit_, &builder_); 658 auto id = BuiltinsStubCSigns::ID::NumberParseFloat; 659 if (!Uncheck()) { 660 builder_.CallTargetCheck(gate, func, builder_.IntPtr(static_cast<int64_t>(id))); 661 } 662 if (EnableTrace()) { 663 AddTraceLogs(gate, id); 664 } 665 GateRef ret = builder_.NumberParseFloat(arg, acc_.GetFrameState(gate)); 666 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret); 667} 668 669void NativeInlineLowering::TryInlineNumberParseInt(GateRef gate, size_t argc, bool skipThis) 670{ 671 auto firstParam = skipThis ? 1 : 0; 672 auto func = acc_.GetValueIn(gate, argc + firstParam); 673 auto arg = acc_.GetValueIn(gate, firstParam); 674 auto radix = builder_.Undefined(); 675 if (argc > 1) { 676 radix = acc_.GetValueIn(gate, firstParam + 1); 677 } 678 679 Environment env(gate, circuit_, &builder_); 680 auto id = BuiltinsStubCSigns::ID::NumberParseInt; 681 if (!Uncheck()) { 682 builder_.CallTargetCheck(gate, func, builder_.IntPtr(static_cast<int64_t>(id))); 683 } 684 if (EnableTrace()) { 685 AddTraceLogs(gate, id); 686 } 687 GateRef ret = builder_.NumberParseInt(arg, radix); 688 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret); 689} 690 691void NativeInlineLowering::TryInlineNumberIsSafeInteger(GateRef gate, size_t argc, bool skipThis) 692{ 693 if (!skipThis) { 694 return; 695 } 696 if (argc != 1) { 697 return; 698 } 699 CallThis1TypeInfoAccessor tacc(compilationEnv_, circuit_, gate); 700 Environment env(gate, circuit_, &builder_); 701 auto id = BuiltinsStubCSigns::ID::NumberIsSafeInteger; 702 if (!Uncheck()) { 703 builder_.CallTargetCheck(gate, tacc.GetFunc(), 704 builder_.IntPtr(static_cast<int64_t>(id))); 705 } 706 if (EnableTrace()) { 707 AddTraceLogs(gate, id); 708 } 709 GateRef ret = builder_.NumberIsSafeInteger(tacc.GetArg0()); 710 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret); 711} 712 713void NativeInlineLowering::TryInlineBigIntAsIntN(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, 714 bool skipThis) 715{ 716 Environment env(gate, circuit_, &builder_); 717 bool firstParam = skipThis ? 1 : 0; 718 if (argc < 2U) { 719 return; 720 } 721 if (!Uncheck()) { 722 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam), 723 builder_.IntPtr(static_cast<int64_t>(id))); 724 } 725 if (EnableTrace()) { 726 AddTraceLogs(gate, id); 727 } 728 GateRef bits = acc_.GetValueIn(gate, firstParam); 729 GateRef bigint = acc_.GetValueIn(gate, firstParam + 1); 730 GateRef frameState = acc_.GetFrameState(gate); 731 bool isUnsigned = (id == BuiltinsStubCSigns::ID::BigIntAsUintN); 732 const auto* op = isUnsigned ? circuit_->BigIntAsUintN() : circuit_->BigIntAsIntN(); 733 GateRef ret = builder_.BuildBigIntAsIntN(op, {bits, bigint, frameState}); 734 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret); 735} 736 737void NativeInlineLowering::TryInlineTypedArrayIteratorBuiltin(GateRef gate, 738 BuiltinsStubCSigns::ID id, 739 const GateMetaData* op, bool skipThis) 740{ 741 if (!skipThis) { 742 return; 743 } 744 745 CallThis0TypeInfoAccessor tacc(compilationEnv_, circuit_, gate); 746 Environment env(gate, circuit_, &builder_); 747 748 if (!Uncheck()) { 749 builder_.CallTargetCheck(gate, tacc.GetFunc(), builder_.IntPtr(static_cast<int64_t>(id)), {tacc.GetThisObj()}); 750 } 751 752 if (EnableTrace()) { 753 AddTraceLogs(gate, id); 754 } 755 756 GateRef ret = builder_.BuildTypedArrayIterator(acc_.GetValueIn(gate, 0), op); 757 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret); 758} 759 760void NativeInlineLowering::TryInlineMathUnaryBuiltin(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, 761 const GateMetaData* op, bool skipThis) 762{ 763 Environment env(gate, circuit_, &builder_); 764 bool firstParam = skipThis ? 1 : 0; 765 if (!Uncheck()) { 766 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam), 767 builder_.IntPtr(static_cast<int64_t>(id))); 768 } 769 770 if (EnableTrace()) { 771 AddTraceLogs(gate, id); 772 } 773 774 if (argc == 0) { 775 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), builder_.NanValue()); 776 return; 777 } 778 GateRef ret = builder_.BuildControlDependOp(op, {acc_.GetValueIn(gate, firstParam)}); 779 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret); 780} 781 782void NativeInlineLowering::TryInlineWhitoutParamBuiltin(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, 783 const GateMetaData* op, bool skipThis) 784{ 785 Environment env(gate, circuit_, &builder_); 786 bool firstParam = skipThis ? 1 : 0; 787 if (!Uncheck()) { 788 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam), 789 builder_.IntPtr(static_cast<int64_t>(id))); 790 } 791 792 if (EnableTrace()) { 793 AddTraceLogs(gate, id); 794 } 795 796 GateRef ret = builder_.BuildControlDependOp(op, {}); 797 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret); 798} 799 800void NativeInlineLowering::TryInlineMathAbsBuiltin(GateRef gate, size_t argc, bool skipThis) 801{ 802 Environment env(gate, circuit_, &builder_); 803 bool firstParam = skipThis ? 1 : 0; 804 if (!Uncheck()) { 805 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam), 806 builder_.IntPtr(static_cast<int64_t>(BuiltinsStubCSigns::ID::MathAbs))); 807 } 808 809 if (EnableTrace()) { 810 AddTraceLogs(gate, BuiltinsStubCSigns::ID::MathAbs); 811 } 812 813 if (argc == 0) { 814 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), builder_.NanValue()); 815 return; 816 } 817 GateRef ret = builder_.BuildControlDependOp(circuit_->MathAbs(), {acc_.GetValueIn(gate, firstParam)}, 818 {acc_.GetFrameState(gate)}); 819 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret); 820} 821 822void NativeInlineLowering::TryInlineMathClz32Builtin(GateRef gate, size_t argc, bool skipThis) 823{ 824 Environment env(gate, circuit_, &builder_); 825 bool firstParam = skipThis ? 1 : 0; 826 if (!Uncheck()) { 827 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam), 828 builder_.IntPtr(static_cast<int64_t>(BuiltinsStubCSigns::ID::MathClz32))); 829 } 830 if (EnableTrace()) { 831 AddTraceLogs(gate, BuiltinsStubCSigns::ID::MathClz32); 832 } 833 if (argc == 0) { 834 const int32_t defaultValue = 32; 835 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), builder_.Int32(defaultValue)); 836 return; 837 } 838 GateRef ret = builder_.BuildControlDependOp(circuit_->MathClz32(), {acc_.GetValueIn(gate, firstParam)}); 839 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret); 840} 841 842void NativeInlineLowering::TryInlineGlobalFiniteBuiltin(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, 843 const GateMetaData* op, bool skipThis) 844{ 845 Environment env(gate, circuit_, &builder_); 846 bool firstParam = skipThis ? 1 : 0; 847 if (!Uncheck()) { 848 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam), 849 builder_.IntPtr(static_cast<int64_t>(id))); 850 } 851 if (EnableTrace()) { 852 AddTraceLogs(gate, id); 853 } 854 if (argc == 0) { 855 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), builder_.Boolean(false)); 856 return; 857 } 858 GateRef ret = builder_.BuildControlDependOp(op, {acc_.GetValueIn(gate, firstParam)}); 859 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret); 860} 861 862void NativeInlineLowering::TryInlineGlobalNanBuiltin(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, 863 const GateMetaData* op, bool skipThis) 864{ 865 Environment env(gate, circuit_, &builder_); 866 bool firstParam = skipThis ? 1 : 0; 867 if (!Uncheck()) { 868 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam), 869 builder_.IntPtr(static_cast<int64_t>(id))); 870 } 871 if (EnableTrace()) { 872 AddTraceLogs(gate, id); 873 } 874 if (argc == 0) { 875 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), builder_.Boolean(true)); 876 return; 877 } 878 GateRef ret = builder_.BuildControlDependOp(op, {acc_.GetValueIn(gate, firstParam)}); 879 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret); 880} 881 882void NativeInlineLowering::TryInlineMathImulBuiltin(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, 883 const GateMetaData* op, bool skipThis) 884{ 885 Environment env(gate, circuit_, &builder_); 886 bool firstParam = skipThis ? 1 : 0; 887 if (!Uncheck()) { 888 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam), 889 builder_.IntPtr(static_cast<int64_t>(id))); 890 } 891 if (EnableTrace()) { 892 AddTraceLogs(gate, id); 893 } 894 if (argc < 2U) { 895 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), builder_.Int32(0)); 896 return; 897 } 898 GateRef ret = builder_.BuildControlDependOp(op, {acc_.GetValueIn(gate, firstParam), 899 acc_.GetValueIn(gate, firstParam + 1)}); 900 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret); 901 return; 902} 903 904void NativeInlineLowering::TryInlineMathBinaryBuiltin(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, 905 const GateMetaData* op, bool skipThis) 906{ 907 Environment env(gate, circuit_, &builder_); 908 bool firstParam = skipThis ? 1 : 0; 909 if (!Uncheck()) { 910 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam), 911 builder_.IntPtr(static_cast<int64_t>(id))); 912 } 913 if (EnableTrace()) { 914 AddTraceLogs(gate, id); 915 } 916 if (argc < 2U) { 917 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), builder_.NanValue()); 918 return; 919 } 920 GateRef ret = builder_.BuildControlDependOp(op, {acc_.GetValueIn(gate, firstParam), 921 acc_.GetValueIn(gate, firstParam + 1)}); 922 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret); 923 return; 924} 925 926void NativeInlineLowering::TryInlineMathMinMaxBuiltin(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, 927 const GateMetaData* op, double defaultValue, bool skipThis) 928{ 929 Environment env(gate, circuit_, &builder_); 930 bool firstParam = skipThis ? 1 : 0; 931 if (!Uncheck()) { 932 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam), 933 builder_.IntPtr(static_cast<int64_t>(id))); 934 } 935 if (EnableTrace()) { 936 AddTraceLogs(gate, id); 937 } 938 if (argc == 0) { 939 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), builder_.Double(defaultValue)); 940 return; 941 } 942 GateRef ret = acc_.GetValueIn(gate, firstParam); 943 if (argc == 1) { 944 builder_.TypeOfCheck(ret, ParamType::NumberType()); 945 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret); 946 return; 947 } 948 for (size_t i = 1; i < argc; i++) { 949 auto param = acc_.GetValueIn(gate, i + firstParam); 950 ret = builder_.BuildControlDependOp(op, {ret, param}); 951 } 952 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret); 953} 954 955void NativeInlineLowering::TryInlineArrayBufferIsView(GateRef gate, 956 size_t argc, 957 BuiltinsStubCSigns::ID id, 958 bool skipThis) 959{ 960 if (!skipThis) { 961 return; 962 } 963 if (argc != 1) { 964 return; 965 } 966 CallThis1TypeInfoAccessor tacc(compilationEnv_, circuit_, gate); 967 Environment env(gate, circuit_, &builder_); 968 if (!Uncheck()) { 969 builder_.CallTargetCheck(gate, tacc.GetFunc(), builder_.IntPtr(static_cast<int64_t>(id)), {tacc.GetArg0()}); 970 } 971 GateRef arg0 = tacc.GetArg0(); 972 GateRef ret = builder_.ArrayBufferIsView(arg0); 973 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret); 974} 975 976void NativeInlineLowering::TryInlineDataViewGet(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis) 977{ 978 if (!skipThis) { 979 return; 980 } 981 if (argc != 1 && argc != 2) { // number of args must be 1/2 982 return; 983 } 984 Environment env(gate, circuit_, &builder_); 985 if (!Uncheck()) { 986 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id))); 987 } 988 GateRef thisObj = acc_.GetValueIn(gate, 0); // 0: this 989 builder_.EcmaObjectCheck(thisObj); 990 builder_.IsDataViewCheck(thisObj); 991 GateRef dataViewCallID = builder_.Int32(id); 992 GateRef index = acc_.GetValueIn(gate, 1); // 1: index of dataView 993 GateRef ret = Circuit::NullGate(); 994 GateRef frameState = acc_.GetFrameState(gate); 995 builder_.DeoptCheck(builder_.TaggedIsInt(index), frameState, DeoptType::INDEXNOTINT); 996 GateRef indexInt = builder_.TaggedGetInt(index); 997 if (argc == 1) { // if not provide isLittleEndian, default use big endian 998 ret = builder_.DataViewGet(thisObj, indexInt, dataViewCallID, builder_.False(), frameState); 999 } else if (argc == 2) { // 2: provide isLittleEndian 1000 GateRef isLittleEndian = acc_.GetValueIn(gate, 2); // 2: is little endian mode 1001 ret = builder_.DataViewGet(thisObj, indexInt, dataViewCallID, isLittleEndian, frameState); 1002 } 1003 if (EnableTrace()) { 1004 AddTraceLogs(gate, id); 1005 } 1006 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret); 1007} 1008 1009void NativeInlineLowering::TryInlineDataViewSet(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis) 1010{ 1011 if (!skipThis) { 1012 return; 1013 } 1014 if (argc != 1 && argc != 2 && argc != 3) { // number of args must be 1/2/3 1015 return; 1016 } 1017 Environment env(gate, circuit_, &builder_); 1018 if (!Uncheck()) { 1019 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id))); 1020 } 1021 GateRef thisObj = acc_.GetValueIn(gate, 0); // 0: this 1022 builder_.EcmaObjectCheck(thisObj); 1023 builder_.IsDataViewCheck(thisObj); 1024 GateRef dataViewCallID = builder_.Int32(id); 1025 GateRef index = acc_.GetValueIn(gate, 1); // 1: index 1026 GateRef frameState = acc_.GetFrameState(gate); 1027 builder_.DeoptCheck(builder_.TaggedIsInt(index), frameState, DeoptType::INDEXNOTINT); 1028 GateRef indexInt = builder_.TaggedGetInt(index); 1029 GateRef ret = Circuit::NullGate(); 1030 if (argc == 1) { // arg counts is 1 1031 ret = builder_.DataViewSet( 1032 thisObj, indexInt, builder_.Double(base::NAN_VALUE), dataViewCallID, builder_.False(), frameState); 1033 } else if (argc == 2) { // arg counts is 2 1034 GateRef value = acc_.GetValueIn(gate, 2); // 2: value 1035 ret = builder_.DataViewSet(thisObj, indexInt, value, dataViewCallID, builder_.False(), frameState); 1036 } else if (argc == 3) { // arg counts is 3 1037 GateRef value = acc_.GetValueIn(gate, 2); // 2: value 1038 GateRef isLittleEndian = acc_.GetValueIn(gate, 3); // 3: is little endian mode 1039 ret = builder_.DataViewSet(thisObj, indexInt, value, dataViewCallID, isLittleEndian, frameState); 1040 } 1041 if (EnableTrace()) { 1042 AddTraceLogs(gate, id); 1043 } 1044 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret); 1045} 1046 1047void NativeInlineLowering::InlineStubBuiltin(GateRef gate, size_t builtinArgc, size_t realArgc, 1048 BuiltinsStubCSigns::ID id, const GateMetaData* op, bool skipThis) 1049{ 1050 if (!skipThis) { 1051 return; 1052 } 1053 Environment env(gate, circuit_, &builder_); 1054 if (!Uncheck()) { 1055 GateRef obj = acc_.GetValueIn(gate, 0); 1056 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, realArgc + 1U), 1057 builder_.IntPtr(static_cast<int64_t>(id)), {obj}); 1058 } 1059 if (EnableTrace()) { 1060 AddTraceLogs(gate, id); 1061 } 1062 1063 std::vector<GateRef> args {}; 1064 for (size_t i = 0; i <= builtinArgc; i++) { 1065 args.push_back(i <= realArgc ? acc_.GetValueIn(gate, i) : builder_.Undefined()); 1066 } 1067 GateRef ret = builder_.BuildControlDependOp(op, args); 1068 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret); 1069} 1070 1071void NativeInlineLowering::ReplaceGateWithPendingException(GateRef hirGate, GateRef value) 1072{ 1073 GateRef state = builder_.GetState(); 1074 // copy depend-wire of hirGate to value 1075 GateRef depend = builder_.GetDepend(); 1076 // exception condition 1077 GateRef condition = builder_.HasPendingException(glue_); 1078 auto ifBranch = builder_.Branch(state, condition, 1, BranchWeight::DEOPT_WEIGHT, "checkException"); 1079 1080 GateRef ifTrue = builder_.IfTrue(ifBranch); 1081 GateRef ifFalse = builder_.IfFalse(ifBranch); 1082 GateRef eDepend = builder_.DependRelay(ifTrue, depend); 1083 GateRef sDepend = builder_.DependRelay(ifFalse, depend); 1084 StateDepend success(ifFalse, sDepend); 1085 StateDepend exception(ifTrue, eDepend); 1086 acc_.ReplaceHirWithIfBranch(hirGate, success, exception, value); 1087} 1088 1089void NativeInlineLowering::TryInlineBigIntConstructor(GateRef gate, size_t argc, bool skipThis) 1090{ 1091 Environment env(gate, circuit_, &builder_); 1092 bool firstParam = skipThis ? 1 : 0; 1093 auto id = BuiltinsStubCSigns::ID::BigIntConstructor; 1094 if (!Uncheck()) { 1095 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam), 1096 builder_.IntPtr(static_cast<int64_t>(id))); 1097 } 1098 if (EnableTrace()) { 1099 AddTraceLogs(gate, id); 1100 } 1101 1102 auto param = builder_.Undefined(); 1103 if (argc > 0) { 1104 param = acc_.GetValueIn(gate, firstParam); 1105 } 1106 1107 GateRef ret = builder_.BuildControlDependOp(circuit_->BigIntConstructor(), {param}); 1108 ReplaceGateWithPendingException(gate, ret); 1109 return; 1110} 1111 1112void NativeInlineLowering::TryInlineDateGetTime(GateRef gate, size_t argc, bool skipThis) 1113{ 1114 // Always shout be "this", we can't inline this function without instance of object 1115 if (!skipThis) { 1116 return; 1117 } 1118 Environment env(gate, circuit_, &builder_); 1119 // We are sure, that "this" is passed to this function, so always need to do +1 1120 bool firstParam = 1; 1121 if (!Uncheck()) { 1122 GateRef obj = acc_.GetValueIn(gate, 0); 1123 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam), 1124 builder_.IntPtr(static_cast<int64_t>(BuiltinsStubCSigns::ID::DateGetTime)), {obj}); 1125 } 1126 if (EnableTrace()) { 1127 AddTraceLogs(gate, BuiltinsStubCSigns::ID::DateGetTime); 1128 } 1129 // Take object using "this" 1130 GateRef obj = acc_.GetValueIn(gate, 0); 1131 GateRef ret = builder_.BuildControlDependOp(circuit_->DateGetTime(), {obj}); 1132 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret); 1133} 1134 1135void NativeInlineLowering::TryInlineObjectIs(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis) 1136{ 1137 Environment env(gate, circuit_, &builder_); 1138 if (argc != 2) { // 2: left and right 1139 return; 1140 } 1141 1142 size_t firstParam = skipThis ? 1 : 0; 1143 if (!Uncheck()) { 1144 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam), 1145 builder_.IntPtr(static_cast<int64_t>(id))); 1146 } 1147 1148 if (EnableTrace()) { 1149 AddTraceLogs(gate, id); 1150 } 1151 1152 GateRef left = acc_.GetValueIn(gate, firstParam); 1153 GateRef right = acc_.GetValueIn(gate, firstParam + 1); 1154 GateRef ret = builder_.BuildControlDependOp(circuit_->ObjectIs(), { left, right }); 1155 ReplaceGateWithPendingException(gate, ret); 1156} 1157 1158void NativeInlineLowering::TryInlineObjectGetPrototypeOf(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, 1159 bool skipThis) 1160{ 1161 Environment env(gate, circuit_, &builder_); 1162 if (argc != 1) { 1163 return; 1164 } 1165 1166 size_t firstParam = skipThis ? 1 : 0; 1167 if (!Uncheck()) { 1168 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam), 1169 builder_.IntPtr(static_cast<int64_t>(id))); 1170 } 1171 1172 if (EnableTrace()) { 1173 AddTraceLogs(gate, id); 1174 } 1175 1176 GateRef value = acc_.GetValueIn(gate, firstParam); 1177 GateRef ret = builder_.BuildControlDependOp(circuit_->ObjectGetPrototypeOf(), { value }); 1178 ReplaceGateWithPendingException(gate, ret); 1179} 1180 1181void NativeInlineLowering::TryInlineObjectGetProto(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis) 1182{ 1183 if (!skipThis || argc != 0) { 1184 return; 1185 } 1186 1187 Environment env(gate, circuit_, &builder_); 1188 if (!Uncheck()) { 1189 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, 1), builder_.IntPtr(static_cast<int64_t>(id))); // 1: func 1190 } 1191 1192 if (EnableTrace()) { 1193 AddTraceLogs(gate, id); 1194 } 1195 1196 GateRef thisValue = acc_.GetValueIn(gate, 0); 1197 GateRef ret = builder_.BuildControlDependOp(circuit_->ObjectGetPrototypeOf(), { thisValue }); 1198 ReplaceGateWithPendingException(gate, ret); 1199} 1200 1201void NativeInlineLowering::TryInlineObjectCreate(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis) 1202{ 1203 Environment env(gate, circuit_, &builder_); 1204 if (argc != 1) { 1205 return; 1206 } 1207 1208 size_t firstParam = skipThis ? 1 : 0; 1209 if (!Uncheck()) { 1210 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam), 1211 builder_.IntPtr(static_cast<int64_t>(id))); 1212 } 1213 1214 if (EnableTrace()) { 1215 AddTraceLogs(gate, id); 1216 } 1217 1218 GateRef proto = acc_.GetValueIn(gate, firstParam); 1219 GateRef ret = builder_.BuildControlDependOp(circuit_->ObjectCreate(), { proto }); 1220 ReplaceGateWithPendingException(gate, ret); 1221} 1222 1223void NativeInlineLowering::TryInlineObjectIsPrototypeOf(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, 1224 bool skipThis) 1225{ 1226 if (!skipThis || argc != 1) { 1227 return; 1228 } 1229 1230 Environment env(gate, circuit_, &builder_); 1231 if (!Uncheck()) { 1232 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, 2), builder_.IntPtr(static_cast<int64_t>(id))); // 2: func 1233 } 1234 1235 if (EnableTrace()) { 1236 AddTraceLogs(gate, id); 1237 } 1238 1239 GateRef thisValue = acc_.GetValueIn(gate, 0); 1240 GateRef value = acc_.GetValueIn(gate, 1); 1241 GateRef ret = builder_.BuildControlDependOp(circuit_->ObjectIsPrototypeOf(), {thisValue, value}); 1242 ReplaceGateWithPendingException(gate, ret); 1243} 1244 1245void NativeInlineLowering::TryInlineObjectHasOwnProperty(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, 1246 bool skipThis) 1247{ 1248 if (!skipThis || argc != 1) { 1249 return; 1250 } 1251 1252 Environment env(gate, circuit_, &builder_); 1253 if (!Uncheck()) { 1254 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, 2), builder_.IntPtr(static_cast<int64_t>(id))); // 2: func 1255 } 1256 1257 if (EnableTrace()) { 1258 AddTraceLogs(gate, id); 1259 } 1260 1261 GateRef thisValue = acc_.GetValueIn(gate, 0); 1262 GateRef key = acc_.GetValueIn(gate, 1); 1263 GateRef ret = builder_.BuildControlDependOp(circuit_->ObjectHasOwnProperty(), { thisValue, key }); 1264 ReplaceGateWithPendingException(gate, ret); 1265} 1266 1267void NativeInlineLowering::TryInlineReflectGetPrototypeOf(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, 1268 bool skipThis) 1269{ 1270 Environment env(gate, circuit_, &builder_); 1271 if (argc != 1) { 1272 return; 1273 } 1274 1275 size_t firstParam = skipThis ? 1 : 0; 1276 if (!Uncheck()) { 1277 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam), 1278 builder_.IntPtr(static_cast<int64_t>(id))); 1279 } 1280 1281 if (EnableTrace()) { 1282 AddTraceLogs(gate, id); 1283 } 1284 1285 GateRef value = acc_.GetValueIn(gate, firstParam); 1286 GateRef ret = builder_.BuildControlDependOp(circuit_->ReflectGetPrototypeOf(), { value }); 1287 ReplaceGateWithPendingException(gate, ret); 1288} 1289 1290void NativeInlineLowering::TryInlineReflectGet(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis) 1291{ 1292 Environment env(gate, circuit_, &builder_); 1293 if (argc != 2) { // 2: target and key, do not handle receiver argument scene 1294 return; 1295 } 1296 1297 size_t firstParam = skipThis ? 1 : 0; 1298 GateRef key = acc_.GetValueIn(gate, firstParam + 1); 1299 if (!TypeInfoAccessor::IsTrustedStringType(compilationEnv_, circuit_, chunk_, acc_, key)) { 1300 return; 1301 } 1302 1303 if (!Uncheck()) { 1304 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam), 1305 builder_.IntPtr(static_cast<int64_t>(id))); 1306 } 1307 1308 if (EnableTrace()) { 1309 AddTraceLogs(gate, id); 1310 } 1311 1312 GateRef target = acc_.GetValueIn(gate, firstParam); 1313 GateRef ret = builder_.BuildControlDependOp(circuit_->ReflectGet(), { target, key }); 1314 ReplaceGateWithPendingException(gate, ret); 1315} 1316 1317void NativeInlineLowering::TryInlineReflectHas(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis) 1318{ 1319 Environment env(gate, circuit_, &builder_); 1320 if (argc != 2) { // 2: target and key 1321 return; 1322 } 1323 1324 size_t firstParam = skipThis ? 1 : 0; 1325 if (!Uncheck()) { 1326 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam), 1327 builder_.IntPtr(static_cast<int64_t>(id))); 1328 } 1329 1330 if (EnableTrace()) { 1331 AddTraceLogs(gate, id); 1332 } 1333 1334 GateRef target = acc_.GetValueIn(gate, firstParam); 1335 GateRef key = acc_.GetValueIn(gate, firstParam + 1); 1336 GateRef ret = builder_.BuildControlDependOp(circuit_->ReflectHas(), { target, key }); 1337 ReplaceGateWithPendingException(gate, ret); 1338} 1339 1340void NativeInlineLowering::TryInlineReflectConstruct(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, 1341 bool skipThis) 1342{ 1343 Environment env(gate, circuit_, &builder_); 1344 if (argc != 2) { // 2: optimize newtarget equal target 1345 return; 1346 } 1347 1348 size_t firstParam = skipThis ? 1 : 0; 1349 GateRef target = acc_.GetValueIn(gate, firstParam); 1350 GateRef argumentsList = acc_.GetValueIn(gate, firstParam + 1); 1351 1352 OpCode op = acc_.GetOpCode(argumentsList); 1353 if (op != OpCode::JS_BYTECODE) { 1354 return; 1355 } 1356 1357 EcmaOpcode ecmaOpcode = acc_.GetByteCodeOpcode(argumentsList); 1358 // optimize empty array literal argumentsList 1359 if ((ecmaOpcode != EcmaOpcode::CREATEEMPTYARRAY_IMM8) && (ecmaOpcode != EcmaOpcode::CREATEEMPTYARRAY_IMM16)) { 1360 return; 1361 } 1362 1363 if (!Uncheck()) { 1364 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam), 1365 builder_.IntPtr(static_cast<int64_t>(id))); 1366 } 1367 1368 if (EnableTrace()) { 1369 AddTraceLogs(gate, id); 1370 } 1371 1372 GateRef ret = builder_.BuildControlDependOp(circuit_->ReflectConstruct(), { target }); 1373 ReplaceGateWithPendingException(gate, ret); 1374} 1375 1376void NativeInlineLowering::TryInlineReflectApply(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, 1377 bool skipThis) 1378{ 1379 Environment env(gate, circuit_, &builder_); 1380 if (argc != 3) { // 3: target key and argumentsList 1381 return; 1382 } 1383 1384 size_t firstParam = skipThis ? 1 : 0; 1385 GateRef target = acc_.GetValueIn(gate, firstParam); 1386 GateRef thisValue = acc_.GetValueIn(gate, firstParam + 1); 1387 GateRef argumentsList = acc_.GetValueIn(gate, firstParam + 2); 1388 1389 if (!Uncheck()) { 1390 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam), 1391 builder_.IntPtr(static_cast<int64_t>(id))); 1392 } 1393 1394 if (EnableTrace()) { 1395 AddTraceLogs(gate, id); 1396 } 1397 1398 GateRef ret = builder_.BuildControlDependOp(circuit_->ReflectApply(), { target, thisValue, argumentsList }); 1399 ReplaceGateWithPendingException(gate, ret); 1400} 1401 1402void NativeInlineLowering::TryInlineFunctionPrototypeApply(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, 1403 bool skipThis) 1404{ 1405 Environment env(gate, circuit_, &builder_); 1406 if (!skipThis || argc == 0) { 1407 return; 1408 } 1409 1410 if (!Uncheck()) { 1411 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id))); 1412 } 1413 1414 if (EnableTrace()) { 1415 AddTraceLogs(gate, id); 1416 } 1417 1418 GateRef thisFunc = acc_.GetValueIn(gate, 0); 1419 GateRef thisArg = acc_.GetValueIn(gate, 1); 1420 GateRef argArray = (argc == 2) ? (acc_.GetValueIn(gate, 2)) : (builder_.UndefineConstant()); 1421 GateRef ret = builder_.BuildControlDependOp(circuit_->FunctionPrototypeApply(), { thisFunc, thisArg, argArray }); 1422 ReplaceGateWithPendingException(gate, ret); 1423} 1424 1425void NativeInlineLowering::TryInlineFunctionPrototypeBind(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, 1426 bool skipThis) 1427{ 1428 Environment env(gate, circuit_, &builder_); 1429 if (!skipThis || argc != 1) { 1430 return; 1431 } 1432 1433 if (!Uncheck()) { 1434 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, 2), builder_.IntPtr(static_cast<int64_t>(id))); // 2: func 1435 } 1436 1437 if (EnableTrace()) { 1438 AddTraceLogs(gate, id); 1439 } 1440 1441 GateRef target = acc_.GetValueIn(gate, 0); 1442 GateRef thisArg = acc_.GetValueIn(gate, 1); 1443 GateRef ret = builder_.BuildControlDependOp(circuit_->FunctionPrototypeBind(), { target, thisArg }); 1444 ReplaceGateWithPendingException(gate, ret); 1445} 1446 1447void NativeInlineLowering::TryInlineFunctionPrototypeCall(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, 1448 bool skipThis) 1449{ 1450 Environment env(gate, circuit_, &builder_); 1451 if (!skipThis || argc == 0) { 1452 return; 1453 } 1454 1455 if (!Uncheck()) { 1456 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id))); 1457 } 1458 1459 if (EnableTrace()) { 1460 AddTraceLogs(gate, id); 1461 } 1462 1463 std::vector<GateRef> args(argc + 1); // 1: thisFunc 1464 for (size_t i = 0; i <= argc; ++i) { 1465 args[i] = acc_.GetValueIn(gate, i); 1466 } 1467 GateRef ret = builder_.BuildControlDependOp(circuit_->FunctionPrototypeCall(argc + 1), args); 1468 ReplaceGateWithPendingException(gate, ret); 1469} 1470 1471void NativeInlineLowering::TryInlineFunctionPrototypeHasInstance(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, 1472 bool skipThis) 1473{ 1474 Environment env(gate, circuit_, &builder_); 1475 if (!skipThis || argc != 1) { 1476 return; 1477 } 1478 1479 if (!Uncheck()) { 1480 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, 2), builder_.IntPtr(static_cast<int64_t>(id))); // 2: func 1481 } 1482 1483 if (EnableTrace()) { 1484 AddTraceLogs(gate, id); 1485 } 1486 1487 GateRef function = acc_.GetValueIn(gate, 0); 1488 GateRef value = acc_.GetValueIn(gate, 1); 1489 GateRef ret = builder_.OrdinaryHasInstance(value, function); 1490 ReplaceGateWithPendingException(gate, ret); 1491} 1492 1493void NativeInlineLowering::TryInlineIndexOfIncludes(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis) 1494{ 1495 if (!skipThis) { 1496 return; 1497 } 1498 if (argc == 0) { 1499 return; 1500 } 1501 Environment env(gate, circuit_, &builder_); 1502 GateRef thisArray = acc_.GetValueIn(gate, 0); 1503 GateRef targetElement = acc_.GetValueIn(gate, 1); 1504 ElementsKind kind = acc_.TryGetArrayElementsKind(thisArray); 1505 if (!Uncheck()) { 1506 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id))); 1507 } 1508 builder_.BuiltinPrototypeHClassCheck(thisArray, BuiltinTypeId::ARRAY, kind, false); 1509 builder_.StableArrayCheck(thisArray, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD); 1510 builder_.ElementsKindCheck(thisArray, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD); 1511 GateRef ret = Circuit::NullGate(); 1512 GateRef callID = builder_.Int32(static_cast<int32_t>(id)); 1513 GateRef arrayKind = builder_.Int32(static_cast<int32_t>(kind)); 1514 if (argc == 1) { 1515 ret = builder_.ArrayIncludesIndexOf(thisArray, builder_.Int32(0), targetElement, callID, arrayKind); 1516 } else { 1517 GateRef fromIndexHandler = acc_.GetValueIn(gate, 2); 1518 builder_.DeoptCheck(builder_.TaggedIsInt(fromIndexHandler), acc_.GetFrameState(gate), DeoptType::INDEXNOTINT); 1519 GateRef fromIndex = builder_.TaggedGetInt(fromIndexHandler); 1520 ret = builder_.ArrayIncludesIndexOf(thisArray, fromIndex, targetElement, callID, arrayKind); 1521 } 1522 if (EnableTrace()) { 1523 AddTraceLogs(gate, id); 1524 } 1525 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret); 1526} 1527 1528void NativeInlineLowering::TryInlineArrayIterator(GateRef gate, BuiltinsStubCSigns::ID id, bool skipThis) 1529{ 1530 if (!skipThis) { 1531 return; 1532 } 1533 CallThis0TypeInfoAccessor tacc(compilationEnv_, circuit_, gate); 1534 Environment env(gate, circuit_, &builder_); 1535 1536 if (!Uncheck()) { 1537 builder_.CallTargetCheck(gate, tacc.GetFunc(), builder_.IntPtr(static_cast<int64_t>(id)), {tacc.GetThisObj()}); 1538 } 1539 if (EnableTrace()) { 1540 AddTraceLogs(gate, id); 1541 } 1542 GateRef thisObj = acc_.GetValueIn(gate, 0); 1543 builder_.EcmaObjectCheck(thisObj); 1544 GateRef CallIDRef = builder_.Int32(static_cast<int32_t>(id)); 1545 GateRef ret = builder_.ArrayIteratorBuiltin(thisObj, CallIDRef); 1546 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret); 1547} 1548 1549void NativeInlineLowering::TryInlineArrayForEach(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis) 1550{ 1551 if (argc == 0) { // 0: Must have a callBackFn 1552 return; 1553 } 1554 if (!skipThis) { 1555 return; 1556 } 1557 Environment env(gate, circuit_, &builder_); 1558 auto pcOffset = acc_.TryGetPcOffset(gate); 1559 GateRef ret = Circuit::NullGate(); 1560 GateRef thisValue = acc_.GetValueIn(gate, 0); 1561 ElementsKind kind = acc_.TryGetArrayElementsKind(thisValue); 1562 if (Elements::IsHole(kind)) { 1563 return; 1564 } 1565 if (!Uncheck()) { 1566 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id))); 1567 } 1568 builder_.BuiltinPrototypeHClassCheck(thisValue, BuiltinTypeId::ARRAY, kind, false); 1569 builder_.StableArrayCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD); 1570 builder_.ElementsKindCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD); 1571 GateRef callBackFn = acc_.GetValueIn(gate, 1); 1572 builder_.IsCallableCheck(callBackFn); 1573 if (EnableTrace()) { 1574 AddTraceLogs(gate, id); 1575 } 1576 if (argc == 1) { 1577 ret = builder_.ArrayForEach(thisValue, callBackFn, builder_.UndefineConstant(), pcOffset); 1578 } else { 1579 ret = builder_.ArrayForEach(thisValue, callBackFn, acc_.GetValueIn(gate, 2), pcOffset); // 2:provide using This 1580 } 1581 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), ret); 1582} 1583 1584void NativeInlineLowering::TryInlineArrayFindOrFindIndex(GateRef gate, 1585 size_t argc, 1586 BuiltinsStubCSigns::ID id, 1587 bool skipThis) 1588{ 1589 if (argc == 0) { // 0: Must have a callBackFn 1590 return; 1591 } 1592 if (!skipThis) { 1593 return; 1594 } 1595 Environment env(gate, circuit_, &builder_); 1596 GateRef thisValue = acc_.GetValueIn(gate, 0); 1597 ElementsKind kind = acc_.TryGetArrayElementsKind(thisValue); 1598 if (Elements::IsHole(kind)) { 1599 return; 1600 } 1601 if (!Uncheck()) { 1602 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id))); 1603 } 1604 uint32_t pcOffset = acc_.TryGetPcOffset(gate); 1605 GateRef ret = Circuit::NullGate(); 1606 1607 builder_.BuiltinPrototypeHClassCheck(thisValue, BuiltinTypeId::ARRAY, kind, false); 1608 builder_.StableArrayCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD); 1609 builder_.ElementsKindCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD); 1610 GateRef callBackFn = acc_.GetValueIn(gate, 1); 1611 builder_.IsCallableCheck(callBackFn); 1612 if (EnableTrace()) { 1613 AddTraceLogs(gate, id); 1614 } 1615 GateRef callIDRef = builder_.Int32(static_cast<int32_t>(id)); 1616 1617 if (argc == 1) { 1618 ret = builder_.ArrayFindOrFindIndex(thisValue, callBackFn, builder_.UndefineConstant(), callIDRef, pcOffset); 1619 } else { 1620 ret = builder_.ArrayFindOrFindIndex( 1621 thisValue, callBackFn, acc_.GetValueIn(gate, 2), callIDRef, pcOffset); // 2:provide using This 1622 } 1623 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), ret); 1624} 1625 1626void NativeInlineLowering::TryInlineArrayFilter(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis) 1627{ 1628 if (argc == 0) { 1629 return; 1630 } 1631 if (!skipThis) { 1632 return; 1633 } 1634 Environment env(gate, circuit_, &builder_); 1635 GateRef thisValue = acc_.GetValueIn(gate, 0); 1636 ElementsKind kind = acc_.TryGetArrayElementsKind(thisValue); 1637 if (Elements::IsHole(kind)) { 1638 return; 1639 } 1640 if (!Uncheck()) { 1641 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id))); 1642 } 1643 builder_.BuiltinPrototypeHClassCheck(thisValue, BuiltinTypeId::ARRAY, kind, false); 1644 builder_.StableArrayCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD); 1645 builder_.ElementsKindCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD); 1646 GateRef callBackFn = acc_.GetValueIn(gate, 1); 1647 builder_.IsCallableCheck(callBackFn); 1648 if (EnableTrace()) { 1649 AddTraceLogs(gate, id); 1650 } 1651 uint32_t pcOffset = acc_.TryGetPcOffset(gate); 1652 GateRef frameState = acc_.GetFrameState(gate); 1653 GateRef ret = Circuit::NullGate(); 1654 if (argc == 1) { 1655 ret = builder_.ArrayFilter(thisValue, callBackFn, builder_.UndefineConstant(), frameState, pcOffset); 1656 } else { 1657 ret = builder_.ArrayFilter( 1658 thisValue, callBackFn, acc_.GetValueIn(gate, 2), frameState, pcOffset); //2: provide usingThis 1659 } 1660 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), ret); 1661} 1662 1663void NativeInlineLowering::TryInlineArrayMap(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis) 1664{ 1665 if (argc == 0) { 1666 return; 1667 } 1668 if (!skipThis) { 1669 return; 1670 } 1671 Environment env(gate, circuit_, &builder_); 1672 GateRef thisValue = acc_.GetValueIn(gate, 0); 1673 ElementsKind kind = acc_.TryGetArrayElementsKind(thisValue); 1674 if (Elements::IsHole(kind)) { 1675 return; 1676 } 1677 if (!Uncheck()) { 1678 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id))); 1679 } 1680 builder_.BuiltinPrototypeHClassCheck(thisValue, BuiltinTypeId::ARRAY, kind, false); 1681 builder_.StableArrayCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD); 1682 builder_.ElementsKindCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD); 1683 GateRef callBackFn = acc_.GetValueIn(gate, 1); 1684 builder_.IsCallableCheck(callBackFn); 1685 if (EnableTrace()) { 1686 AddTraceLogs(gate, id); 1687 } 1688 uint32_t pcOffset = acc_.TryGetPcOffset(gate); 1689 GateRef frameState = acc_.GetFrameState(gate); 1690 GateRef ret = Circuit::NullGate(); 1691 if (argc == 1) { 1692 ret = builder_.ArrayMap(thisValue, callBackFn, builder_.UndefineConstant(), frameState, pcOffset); 1693 } else { 1694 ret = builder_.ArrayMap( 1695 thisValue, callBackFn, acc_.GetValueIn(gate, 2), frameState, pcOffset); //2: provide usingThis 1696 } 1697 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), ret); 1698} 1699 1700void NativeInlineLowering::TryInlineArraySome(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis) 1701{ 1702 if (argc == 0) { 1703 return; 1704 } 1705 if (!skipThis) { 1706 return; 1707 } 1708 Environment env(gate, circuit_, &builder_); 1709 GateRef thisValue = acc_.GetValueIn(gate, 0); 1710 ElementsKind kind = acc_.TryGetArrayElementsKind(thisValue); 1711 if (Elements::IsHole(kind)) { 1712 return; 1713 } 1714 if (!Uncheck()) { 1715 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id))); 1716 } 1717 builder_.BuiltinPrototypeHClassCheck(thisValue, BuiltinTypeId::ARRAY, kind, false); 1718 builder_.StableArrayCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD); 1719 builder_.ElementsKindCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD); 1720 GateRef callBackFn = acc_.GetValueIn(gate, 1); 1721 builder_.IsCallableCheck(callBackFn); 1722 if (EnableTrace()) { 1723 AddTraceLogs(gate, id); 1724 } 1725 uint32_t pcOffset = acc_.TryGetPcOffset(gate); 1726 GateRef ret = Circuit::NullGate(); 1727 if (argc == 1) { 1728 ret = builder_.ArraySome(thisValue, callBackFn, builder_.UndefineConstant(), pcOffset); 1729 } else { 1730 ret = builder_.ArraySome(thisValue, callBackFn, acc_.GetValueIn(gate, 2), pcOffset); //2: provide usingThis 1731 } 1732 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), ret); 1733} 1734 1735void NativeInlineLowering::TryInlineArrayEvery(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis) 1736{ 1737 if (argc == 0) { 1738 return; 1739 } 1740 if (!skipThis) { 1741 return; 1742 } 1743 Environment env(gate, circuit_, &builder_); 1744 GateRef thisValue = acc_.GetValueIn(gate, 0); 1745 ElementsKind kind = acc_.TryGetArrayElementsKind(thisValue); 1746 if (Elements::IsHole(kind)) { 1747 return; 1748 } 1749 if (!Uncheck()) { 1750 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id))); 1751 } 1752 builder_.BuiltinPrototypeHClassCheck(thisValue, BuiltinTypeId::ARRAY, kind, false); 1753 builder_.StableArrayCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD); 1754 builder_.ElementsKindCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD); 1755 GateRef callBackFn = acc_.GetValueIn(gate, 1); 1756 builder_.IsCallableCheck(callBackFn); 1757 if (EnableTrace()) { 1758 AddTraceLogs(gate, id); 1759 } 1760 uint32_t pcOffset = acc_.TryGetPcOffset(gate); 1761 GateRef ret = Circuit::NullGate(); 1762 if (argc == 1) { 1763 ret = builder_.ArrayEvery(thisValue, callBackFn, builder_.UndefineConstant(), pcOffset); 1764 } else { 1765 ret = builder_.ArrayEvery(thisValue, callBackFn, acc_.GetValueIn(gate, 2), pcOffset); //2: provide usingThis 1766 } 1767 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), ret); 1768} 1769 1770void NativeInlineLowering::TryInlineArrayPop(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis) 1771{ 1772 if (!skipThis) { 1773 return; 1774 } 1775 Environment env(gate, circuit_, &builder_); 1776 if (!Uncheck()) { 1777 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id))); 1778 } 1779 GateRef thisValue = acc_.GetValueIn(gate, 0); 1780 ElementsKind kind = acc_.TryGetArrayElementsKind(thisValue); 1781 builder_.BuiltinPrototypeHClassCheck(thisValue, BuiltinTypeId::ARRAY, kind, false); 1782 builder_.StableArrayCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD); 1783 builder_.ElementsKindCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD); 1784 if (EnableTrace()) { 1785 AddTraceLogs(gate, id); 1786 } 1787 GateRef ret = builder_.ArrayPop(thisValue, acc_.GetFrameState(gate)); 1788 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret); 1789} 1790 1791void NativeInlineLowering::TryInlineArraySlice(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis) 1792{ 1793 if (!skipThis) { 1794 return; 1795 } 1796 Environment env(gate, circuit_, &builder_); 1797 GateRef thisValue = acc_.GetValueIn(gate, 0); 1798 ElementsKind kind = acc_.TryGetArrayElementsKind(thisValue); 1799 builder_.BuiltinPrototypeHClassCheck(thisValue, BuiltinTypeId::ARRAY, kind, false); 1800 builder_.StableArrayCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD); 1801 builder_.ElementsKindCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD); 1802 GateRef frameState = acc_.GetFrameState(gate); 1803 if (!Uncheck()) { 1804 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id))); 1805 } 1806 GateRef ret = Circuit::NullGate(); 1807 if (argc == 0) { 1808 ret = builder_.ArraySlice(thisValue, builder_.UndefineConstant(), builder_.UndefineConstant(), frameState); 1809 } else if (argc == 1) { 1810 GateRef startIndex = acc_.GetValueIn(gate, 1); 1811 builder_.DeoptCheck(builder_.TaggedIsInt(startIndex), acc_.GetFrameState(gate), DeoptType::INDEXNOTINT); 1812 ret = builder_.ArraySlice(thisValue, startIndex, builder_.UndefineConstant(), frameState); 1813 } else { 1814 GateRef startIndex = acc_.GetValueIn(gate, 1); 1815 GateRef endIndex = acc_.GetValueIn(gate, 2); 1816 builder_.DeoptCheck(builder_.TaggedIsInt(startIndex), acc_.GetFrameState(gate), DeoptType::INDEXNOTINT); 1817 builder_.DeoptCheck(builder_.TaggedIsInt(endIndex), acc_.GetFrameState(gate), DeoptType::INDEXNOTINT); 1818 ret = builder_.ArraySlice(thisValue, startIndex, endIndex, frameState); 1819 } 1820 if (EnableTrace()) { 1821 AddTraceLogs(gate, id); 1822 } 1823 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret); 1824} 1825 1826void NativeInlineLowering::TryInlineArraySort(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis) 1827{ 1828 if (!skipThis) { 1829 return; 1830 } 1831 if (argc > 1) { 1832 return; 1833 } 1834 Environment env(gate, circuit_, &builder_); 1835 if (argc == 1) { 1836 GateRef callBackFn = acc_.GetValueIn(gate, 1); 1837 auto fnType = acc_.GetGateType(callBackFn); 1838 if (!fnType.IsUndefinedType()) { 1839 return; 1840 } 1841 } 1842 GateRef thisValue = acc_.GetValueIn(gate, 0); 1843 ElementsKind kind = acc_.TryGetArrayElementsKind(thisValue); 1844 if (Elements::IsHole(kind)) { 1845 return; 1846 } 1847 if (!Uncheck()) { 1848 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id))); 1849 } 1850 GateRef ret = Circuit::NullGate(); 1851 1852 builder_.BuiltinPrototypeHClassCheck(thisValue, BuiltinTypeId::ARRAY, kind, false); 1853 builder_.StableArrayCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD); 1854 builder_.ElementsKindCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD); 1855 ret = builder_.ArraySort(thisValue, builder_.UndefineConstant()); 1856 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret); 1857} 1858 1859} // namespace panda::ecmascript 1860