1/* 2 * Copyright (c) 2021 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_INTERPRETER_STUB_INL_H 17#define ECMASCRIPT_COMPILER_INTERPRETER_STUB_INL_H 18 19#include "ecmascript/compiler/interpreter_stub.h" 20#include "ecmascript/compiler/new_object_stub_builder.h" 21#include "ecmascript/compiler/share_gate_meta_data.h" 22#include "ecmascript/module/js_module_source_text.h" 23#include "ecmascript/global_env.h" 24#include "ecmascript/js_async_generator_object.h" 25#include "ecmascript/js_arguments.h" 26#include "ecmascript/js_function.h" 27#include "ecmascript/js_generator_object.h" 28 29namespace panda::ecmascript::kungfu { 30void InterpreterStubBuilder::SetVregValue(GateRef glue, GateRef sp, GateRef idx, GateRef val) 31{ 32 Store(VariableType::INT64(), glue, sp, PtrMul(IntPtr(sizeof(JSTaggedType)), idx), val); 33} 34 35inline GateRef InterpreterStubBuilder::GetVregValue(GateRef sp, GateRef idx) 36{ 37 return Load(VariableType::JS_ANY(), sp, PtrMul(IntPtr(sizeof(JSTaggedType)), idx)); 38} 39 40GateRef InterpreterStubBuilder::ReadInst8_0(GateRef pc) 41{ 42 return Load(VariableType::INT8(), pc, IntPtr(1)); // 1 : skip 1 byte of bytecode 43} 44 45GateRef InterpreterStubBuilder::ReadInst8_1(GateRef pc) 46{ 47 return Load(VariableType::INT8(), pc, IntPtr(2)); // 2 : skip 1 byte of bytecode 48} 49 50GateRef InterpreterStubBuilder::ReadInst8_2(GateRef pc) 51{ 52 return Load(VariableType::INT8(), pc, IntPtr(3)); // 3 : skip 1 byte of bytecode 53} 54 55GateRef InterpreterStubBuilder::ReadInst8_3(GateRef pc) 56{ 57 return Load(VariableType::INT8(), pc, IntPtr(4)); // 4 : skip 1 byte of bytecode 58} 59 60GateRef InterpreterStubBuilder::ReadInst8_4(GateRef pc) 61{ 62 return Load(VariableType::INT8(), pc, IntPtr(5)); // 5 : skip 1 byte of bytecode 63} 64 65GateRef InterpreterStubBuilder::ReadInst8_5(GateRef pc) 66{ 67 return Load(VariableType::INT8(), pc, IntPtr(6)); // 6 : skip 1 byte of bytecode 68} 69 70GateRef InterpreterStubBuilder::ReadInst8_6(GateRef pc) 71{ 72 return Load(VariableType::INT8(), pc, IntPtr(7)); // 7 : skip 1 byte of bytecode 73} 74 75GateRef InterpreterStubBuilder::ReadInst8_7(GateRef pc) 76{ 77 return Load(VariableType::INT8(), pc, IntPtr(8)); // 8 : skip 1 byte of bytecode 78} 79 80GateRef InterpreterStubBuilder::ReadInst8_8(GateRef pc) 81{ 82 return Load(VariableType::INT8(), pc, IntPtr(9)); // 9 : skip 1 byte of bytecode 83} 84 85GateRef InterpreterStubBuilder::ReadInst8_9(GateRef pc) 86{ 87 return Load(VariableType::INT8(), pc, IntPtr(10)); // 10 : skip 1 byte of bytecode 88} 89 90GateRef InterpreterStubBuilder::ReadInst4_0(GateRef pc) 91{ 92 return Int8And(Load(VariableType::INT8(), pc, IntPtr(1)), Int8(0xf)); 93} 94 95GateRef InterpreterStubBuilder::ReadInst4_1(GateRef pc) 96{ 97 // 1 : skip 1 byte of bytecode 98 return Int8And( 99 Int8LSR(Load(VariableType::INT8(), pc, IntPtr(1)), Int8(4)), Int8(0xf)); // 4: read 4 byte of bytecode 100} 101 102GateRef InterpreterStubBuilder::ReadInst4_2(GateRef pc) 103{ 104 // 2 : skip 1 byte of bytecode 105 return Int8And(Load(VariableType::INT8(), pc, IntPtr(2)), Int8(0xf)); 106} 107 108GateRef InterpreterStubBuilder::ReadInst4_3(GateRef pc) 109{ 110 // 2 : skip 1 byte of bytecode 111 return Int8And( 112 Int8LSR(Load(VariableType::INT8(), pc, IntPtr(2)), Int8(4)), Int8(0xf)); // 4 : read 4 byte of bytecode 113} 114 115GateRef InterpreterStubBuilder::ReadInstSigned8_0(GateRef pc) 116{ 117 GateRef x = Load(VariableType::INT8(), pc, IntPtr(1)); // 1 : skip 1 byte of bytecode 118 return GetEnvironment()->GetBuilder()->SExtInt1ToInt32(x); 119} 120 121GateRef InterpreterStubBuilder::ReadInstSigned16_0(GateRef pc) 122{ 123 if (GetEnvironment()->IsAArch64() || GetEnvironment()->IsAmd64()) { 124 GateRef currentInst = Load(VariableType::INT16(), pc, IntPtr(1)); // 1 : skip 1 byte of bytecode 125 return GetEnvironment()->GetBuilder()->SExtInt16ToInt32(currentInst); 126 } 127 /* 2 : skip 8 bits of opcode and 8 bits of low bits */ 128 GateRef currentInst = Load(VariableType::INT8(), pc, IntPtr(2)); 129 GateRef currentInst1 = GetEnvironment()->GetBuilder()->SExtInt1ToInt32(currentInst); 130 GateRef currentInst2 = Int32LSL(currentInst1, Int32(8)); // 8 : set as high 8 bits 131 return Int32Add(currentInst2, ZExtInt8ToInt32(ReadInst8_0(pc))); 132} 133 134GateRef InterpreterStubBuilder::ReadInstSigned32_0(GateRef pc) 135{ 136 if (GetEnvironment()->IsAArch64() || GetEnvironment()->IsAmd64()) { 137 GateRef x = Load(VariableType::INT32(), pc, IntPtr(1)); // 1 : skip 1 byte of bytecode 138 return GetEnvironment()->GetBuilder()->SExtInt1ToInt32(x); 139 } 140 /* 4 : skip 8 bits of opcode and 24 bits of low bits */ 141 GateRef x = Load(VariableType::INT8(), pc, IntPtr(4)); 142 GateRef currentInst = GetEnvironment()->GetBuilder()->SExtInt1ToInt32(x); 143 GateRef currentInst1 = Int32LSL(currentInst, Int32(8)); // 8 : set as high 8 bits 144 GateRef currentInst2 = Int32Add(currentInst1, ZExtInt8ToInt32(ReadInst8_2(pc))); 145 GateRef currentInst3 = Int32LSL(currentInst2, Int32(8)); // 8 : set as high 8 bits 146 GateRef currentInst4 = Int32Add(currentInst3, ZExtInt8ToInt32(ReadInst8_1(pc))); 147 GateRef currentInst5 = Int32LSL(currentInst4, Int32(8)); // 8 : set as high 8 bits 148 return Int32Add(currentInst5, ZExtInt8ToInt32(ReadInst8_0(pc))); 149} 150 151GateRef InterpreterStubBuilder::ReadInst16_0(GateRef pc) 152{ 153 if (GetEnvironment()->IsAArch64() || GetEnvironment()->IsAmd64()) { 154 return Load(VariableType::INT16(), pc, IntPtr(1)); // 1 : skip 1 byte of bytecode 155 } 156 /* 2 : skip 8 bits of opcode and 8 bits of low bits */ 157 GateRef currentInst1 = ZExtInt8ToInt16(ReadInst8_1(pc)); 158 GateRef currentInst2 = Int16LSL(currentInst1, Int16(8)); // 8 : set as high 8 bits 159 return Int16Add(currentInst2, ZExtInt8ToInt16(ReadInst8_0(pc))); 160} 161 162GateRef InterpreterStubBuilder::ReadInst16_1(GateRef pc) 163{ 164 if (GetEnvironment()->IsAArch64() || GetEnvironment()->IsAmd64()) { 165 return Load(VariableType::INT16(), pc, IntPtr(2)); // 2 : skip 2 bytes of bytecode 166 } 167 /* 3 : skip 8 bits of opcode, 8 bits of prefix and 8 bits of low bits */ 168 GateRef currentInst1 = ZExtInt8ToInt16(ReadInst8_2(pc)); 169 GateRef currentInst2 = Int16LSL(currentInst1, Int16(8)); // 8 : set as high 8 bits 170 /* 2 : skip 8 bits of opcode and 8 bits of prefix */ 171 return Int16Add(currentInst2, ZExtInt8ToInt16(ReadInst8_1(pc))); 172} 173 174GateRef InterpreterStubBuilder::ReadInst16_2(GateRef pc) 175{ 176 if (GetEnvironment()->IsAArch64() || GetEnvironment()->IsAmd64()) { 177 return Load(VariableType::INT16(), pc, IntPtr(3)); // 3 : skip 3 bytes of bytecode 178 } 179 /* 4 : skip 8 bits of opcode, first parameter of 16 bits and 8 bits of low bits */ 180 GateRef currentInst1 = ZExtInt8ToInt16(ReadInst8_3(pc)); 181 GateRef currentInst2 = Int16LSL(currentInst1, Int16(8)); // 8 : set as high 8 bits 182 /* 3 : skip 8 bits of opcode and first parameter of 16 bits */ 183 return Int16Add(currentInst2, ZExtInt8ToInt16(ReadInst8_2(pc))); 184} 185 186GateRef InterpreterStubBuilder::ReadInst16_3(GateRef pc) 187{ 188 if (GetEnvironment()->IsAArch64() || GetEnvironment()->IsAmd64()) { 189 return Load(VariableType::INT16(), pc, IntPtr(4)); // 4 : skip 4 bytes of bytecode 190 } 191 /* 5 : skip 8 bits of opcode, 8 bits of prefix, first parameter of 16 bits and 8 bits of low bits */ 192 GateRef currentInst1 = ZExtInt8ToInt16(ReadInst8_4(pc)); 193 GateRef currentInst2 = Int16LSL(currentInst1, Int16(8)); // 8 : set as high 8 bits 194 /* 4 : skip 8 bits of opcode, 8 bits of prefix and first parameter of 16 bits */ 195 return Int16Add(currentInst2, ZExtInt8ToInt16(ReadInst8_3(pc))); 196} 197 198GateRef InterpreterStubBuilder::ReadInst16_4(GateRef pc) 199{ 200 if (GetEnvironment()->IsAArch64() || GetEnvironment()->IsAmd64()) { 201 return Load(VariableType::INT16(), pc, IntPtr(5)); // 5 : skip 5 bytes of bytecode 202 } 203 /* 7 : skip 8 bits of opcode, 8 bits of prefix, first 2 parameters of 16 bits and 8 bits of low bits */ 204 GateRef currentInst1 = ZExtInt8ToInt16(ReadInst8_5(pc)); 205 GateRef currentInst2 = Int16LSL(currentInst1, Int16(8)); // 8 : set as high 8 bits 206 /* 6 : skip 8 bits of opcode, 8 bits of prefix and first 2 parameters of 16 bits */ 207 return Int16Add(currentInst2, ZExtInt8ToInt16(ReadInst8_4(pc))); 208} 209 210GateRef InterpreterStubBuilder::ReadInst16_5(GateRef pc) 211{ 212 if (GetEnvironment()->IsAArch64() || GetEnvironment()->IsAmd64()) { 213 return Load(VariableType::INT16(), pc, IntPtr(6)); // 6 : skip 6 bytes of bytecode 214 } 215 /* 7 : skip 8 bits of opcode, 8 bits of prefix, first 2 parameters of 16 bits and 8 bits of low bits */ 216 GateRef currentInst1 = ZExtInt8ToInt16(ReadInst8_6(pc)); 217 GateRef currentInst2 = Int16LSL(currentInst1, Int16(8)); // 8 : set as high 8 bits 218 /* 6 : skip 8 bits of opcode, 8 bits of prefix and first 2 parameters of 16 bits */ 219 return Int16Add(currentInst2, ZExtInt8ToInt16(ReadInst8_5(pc))); 220} 221 222GateRef InterpreterStubBuilder::ReadInst16_6(GateRef pc) 223{ 224 if (GetEnvironment()->IsAArch64() || GetEnvironment()->IsAmd64()) { 225 return Load(VariableType::INT16(), pc, IntPtr(7)); // 7 : skip 7 bytes of bytecode 226 } 227 /* 7 : skip 8 bits of opcode, 8 bits of prefix, first 2 parameters of 16 bits and 8 bits of low bits */ 228 GateRef currentInst1 = ZExtInt8ToInt16(ReadInst8_7(pc)); 229 GateRef currentInst2 = Int16LSL(currentInst1, Int16(8)); // 8 : set as high 8 bits 230 /* 6 : skip 8 bits of opcode, 8 bits of prefix and first 2 parameters of 16 bits */ 231 return Int16Add(currentInst2, ZExtInt8ToInt16(ReadInst8_6(pc))); 232} 233 234GateRef InterpreterStubBuilder::ReadInst16_7(GateRef pc) 235{ 236 if (GetEnvironment()->IsAArch64() || GetEnvironment()->IsAmd64()) { 237 return Load(VariableType::INT16(), pc, IntPtr(8)); // 8 : skip 8 bytes of bytecode 238 } 239 /* 7 : skip 8 bits of opcode, 8 bits of prefix, first 2 parameters of 16 bits and 8 bits of low bits */ 240 GateRef currentInst1 = ZExtInt8ToInt16(ReadInst8_8(pc)); 241 GateRef currentInst2 = Int16LSL(currentInst1, Int16(8)); // 8 : set as high 8 bits 242 /* 6 : skip 8 bits of opcode, 8 bits of prefix and first 2 parameters of 16 bits */ 243 return Int16Add(currentInst2, ZExtInt8ToInt16(ReadInst8_9(pc))); 244} 245 246GateRef InterpreterStubBuilder::GetFrame(GateRef CurrentSp) 247{ 248 return PtrSub(CurrentSp, IntPtr(AsmInterpretedFrame::GetSize(GetEnvironment()->IsArch32Bit()))); 249} 250 251GateRef InterpreterStubBuilder::GetPcFromFrame(GateRef frame) 252{ 253 return Load(VariableType::NATIVE_POINTER(), frame, 254 IntPtr(AsmInterpretedFrame::GetPcOffset(GetEnvironment()->IsArch32Bit()))); 255} 256 257GateRef InterpreterStubBuilder::GetFunctionFromFrame(GateRef frame) 258{ 259 return Load(VariableType::JS_POINTER(), frame, 260 IntPtr(AsmInterpretedFrame::GetFunctionOffset(GetEnvironment()->IsArch32Bit()))); 261} 262 263GateRef InterpreterStubBuilder::GetNewTarget(GateRef sp) 264{ 265 GateRef function = Load(VariableType::JS_POINTER(), GetFrame(sp), 266 IntPtr(AsmInterpretedFrame::GetFunctionOffset(GetEnvironment()->IsArch32Bit()))); 267 GateRef method = GetMethodFromFunction(function); 268 GateRef callField = GetCallFieldFromMethod(method); 269 // ASSERT: callField has "extra" bit. 270 GateRef numVregs = TruncInt64ToInt32(Int64And(Int64LSR(callField, Int64(MethodLiteral::NumVregsBits::START_BIT)), 271 Int64((1LLU << MethodLiteral::NumVregsBits::SIZE) - 1))); 272 GateRef haveFunc = ZExtInt1ToInt32(Int64NotEqual(Int64And(Int64LSR(callField, 273 Int64(MethodLiteral::HaveFuncBit::START_BIT)), 274 Int64((1LLU << MethodLiteral::HaveFuncBit::SIZE) - 1)), Int64(0))); 275 GateRef idx = ZExtInt32ToPtr(Int32Add(numVregs, haveFunc)); 276 return Load(VariableType::JS_ANY(), sp, PtrMul(IntPtr(JSTaggedValue::TaggedTypeSize()), idx)); 277} 278 279GateRef InterpreterStubBuilder::GetThisFromFrame(GateRef frame) 280{ 281 return Load(VariableType::JS_POINTER(), frame, 282 IntPtr(AsmInterpretedFrame::GetThisOffset(GetEnvironment()->IsArch32Bit()))); 283} 284 285GateRef InterpreterStubBuilder::GetCallSizeFromFrame(GateRef frame) 286{ 287 return Load(VariableType::NATIVE_POINTER(), frame, 288 IntPtr(AsmInterpretedFrame::GetCallSizeOffset(GetEnvironment()->IsArch32Bit()))); 289} 290 291GateRef InterpreterStubBuilder::GetAccFromFrame(GateRef frame) 292{ 293 return Load(VariableType::JS_ANY(), frame, 294 IntPtr(AsmInterpretedFrame::GetAccOffset(GetEnvironment()->IsArch32Bit()))); 295} 296 297GateRef InterpreterStubBuilder::GetEnvFromFrame(GateRef frame) 298{ 299 return Load(VariableType::JS_POINTER(), frame, 300 IntPtr(AsmInterpretedFrame::GetEnvOffset(GetEnvironment()->IsArch32Bit()))); 301} 302 303GateRef InterpreterStubBuilder::GetEnvFromFunction(GateRef function) 304{ 305 return Load(VariableType::JS_POINTER(), function, IntPtr(JSFunction::LEXICAL_ENV_OFFSET)); 306} 307 308GateRef InterpreterStubBuilder::GetProfileTypeInfoFromFunction(GateRef function) 309{ 310 GateRef raw = Load(VariableType::JS_POINTER(), function, IntPtr(JSFunction::RAW_PROFILE_TYPE_INFO_OFFSET)); 311 return Load(VariableType::JS_POINTER(), raw, IntPtr(ProfileTypeInfoCell::VALUE_OFFSET)); 312} 313 314GateRef InterpreterStubBuilder::GetModuleFromFunction(GateRef function) 315{ 316 return Load(VariableType::JS_POINTER(), function, IntPtr(JSFunction::ECMA_MODULE_OFFSET)); 317} 318 319GateRef InterpreterStubBuilder::GetSendableEnvFromModule(GateRef module) 320{ 321 return Load(VariableType::JS_POINTER(), module, IntPtr(SourceTextModule::SENDABLE_ENV_OFFSET)); 322} 323 324GateRef InterpreterStubBuilder::GetHomeObjectFromFunction(GateRef function) 325{ 326 return Load(VariableType::JS_POINTER(), function, IntPtr(JSFunction::HOME_OBJECT_OFFSET)); 327} 328 329GateRef InterpreterStubBuilder::GetConstpoolFromMethod(GateRef method) 330{ 331 return Load(VariableType::JS_POINTER(), method, IntPtr(Method::CONSTANT_POOL_OFFSET)); 332} 333 334GateRef InterpreterStubBuilder::GetModule(GateRef sp) 335{ 336 GateRef currentFunc = GetFunctionFromFrame(GetFrame(sp)); 337 return GetModuleFromFunction(currentFunc); 338} 339 340GateRef InterpreterStubBuilder::GetResumeModeFromGeneratorObject(GateRef obj) 341{ 342 GateRef bitfieldOffset = IntPtr(JSGeneratorObject::BIT_FIELD_OFFSET); 343 GateRef bitfield = Load(VariableType::INT32(), obj, bitfieldOffset); 344 return Int32And( 345 Int32LSR(bitfield, Int32(JSGeneratorObject::ResumeModeBits::START_BIT)), 346 Int32((1LU << JSGeneratorObject::ResumeModeBits::SIZE) - 1)); 347} 348 349GateRef InterpreterStubBuilder::GetResumeModeFromAsyncGeneratorObject(GateRef obj) 350{ 351 GateRef bitfieldOffset = IntPtr(JSAsyncGeneratorObject::BIT_FIELD_OFFSET); 352 GateRef bitfield = Load(VariableType::INT32(), obj, bitfieldOffset); 353 return Int32And( 354 Int32LSR(bitfield, Int32(JSAsyncGeneratorObject::ResumeModeBits::START_BIT)), 355 Int32((1LU << JSAsyncGeneratorObject::ResumeModeBits::SIZE) - 1)); 356} 357 358void InterpreterStubBuilder::SetPcToFrame(GateRef glue, GateRef frame, GateRef value) 359{ 360 Store(VariableType::INT64(), glue, frame, 361 IntPtr(AsmInterpretedFrame::GetPcOffset(GetEnvironment()->IsArch32Bit())), value); 362} 363 364void InterpreterStubBuilder::SetCallSizeToFrame(GateRef glue, GateRef frame, GateRef value) 365{ 366 Store(VariableType::NATIVE_POINTER(), glue, frame, 367 IntPtr(AsmInterpretedFrame::GetCallSizeOffset(GetEnvironment()->IsArch32Bit())), value); 368} 369 370void InterpreterStubBuilder::SetAccToFrame(GateRef glue, GateRef frame, GateRef value) 371{ 372 Store(VariableType::INT64(), glue, frame, 373 IntPtr(AsmInterpretedFrame::GetAccOffset(GetEnvironment()->IsArch32Bit())), value); 374} 375 376void InterpreterStubBuilder::SetEnvToFrame(GateRef glue, GateRef frame, GateRef value) 377{ 378 Store(VariableType::INT64(), glue, frame, 379 IntPtr(AsmInterpretedFrame::GetEnvOffset(GetEnvironment()->IsArch32Bit())), value); 380} 381 382void InterpreterStubBuilder::SetFunctionToFrame(GateRef glue, GateRef frame, GateRef value) 383{ 384 Store(VariableType::INT64(), glue, frame, 385 IntPtr(AsmInterpretedFrame::GetFunctionOffset(GetEnvironment()->IsArch32Bit())), value); 386} 387 388void InterpreterStubBuilder::SetHomeObjectToFunction(GateRef glue, GateRef function, GateRef value) 389{ 390 GateRef offset = IntPtr(JSFunction::HOME_OBJECT_OFFSET); 391 Store(VariableType::JS_ANY(), glue, function, offset, value); 392} 393 394void InterpreterStubBuilder::SetFrameState(GateRef glue, GateRef sp, GateRef function, GateRef acc, 395 GateRef env, GateRef pc, GateRef prev, GateRef type) 396{ 397 GateRef state = GetFrame(sp); 398 SetFunctionToFrame(glue, state, function); 399 SetAccToFrame(glue, state, acc); 400 SetEnvToFrame(glue, state, env); 401 SetPcToFrame(glue, state, pc); 402 GateRef prevOffset = IntPtr(AsmInterpretedFrame::GetBaseOffset(GetEnvironment()->IsArch32Bit())); 403 Store(VariableType::NATIVE_POINTER(), glue, state, prevOffset, prev); 404 GateRef frameTypeOffset = PtrAdd(prevOffset, IntPtr( 405 InterpretedFrameBase::GetTypeOffset(GetEnvironment()->IsArch32Bit()))); 406 Store(VariableType::INT64(), glue, state, frameTypeOffset, type); 407} 408 409GateRef InterpreterStubBuilder::GetCurrentSpFrame(GateRef glue) 410{ 411 bool isArch32 = GetEnvironment()->Is32Bit(); 412 GateRef spOffset = IntPtr(JSThread::GlueData::GetCurrentFrameOffset(isArch32)); 413 return Load(VariableType::NATIVE_POINTER(), glue, spOffset); 414} 415 416void InterpreterStubBuilder::SetCurrentSpFrame(GateRef glue, GateRef value) 417{ 418 GateRef spOffset = IntPtr(JSThread::GlueData::GetCurrentFrameOffset(GetEnvironment()->Is32Bit())); 419 Store(VariableType::NATIVE_POINTER(), glue, glue, spOffset, value); 420} 421 422GateRef InterpreterStubBuilder::GetLastLeaveFrame(GateRef glue) 423{ 424 bool isArch32 = GetEnvironment()->Is32Bit(); 425 GateRef spOffset = IntPtr(JSThread::GlueData::GetLeaveFrameOffset(isArch32)); 426 return Load(VariableType::NATIVE_POINTER(), glue, spOffset); 427} 428 429void InterpreterStubBuilder::SetLastLeaveFrame(GateRef glue, GateRef value) 430{ 431 GateRef spOffset = IntPtr(JSThread::GlueData::GetLeaveFrameOffset(GetEnvironment()->Is32Bit())); 432 Store(VariableType::NATIVE_POINTER(), glue, glue, spOffset, value); 433} 434 435GateRef InterpreterStubBuilder::CheckStackOverflow(GateRef glue, GateRef sp) 436{ 437 GateRef frameBaseOffset = IntPtr(JSThread::GlueData::GetFrameBaseOffset(GetEnvironment()->IsArch32Bit())); 438 GateRef frameBase = Load(VariableType::NATIVE_POINTER(), glue, frameBaseOffset); 439 return Int64UnsignedLessThanOrEqual(sp, 440 PtrAdd(frameBase, IntPtr(JSThread::RESERVE_STACK_SIZE * sizeof(JSTaggedType)))); 441} 442 443GateRef InterpreterStubBuilder::PushArg(GateRef glue, GateRef sp, GateRef value) 444{ 445 GateRef newSp = PtrSub(sp, IntPtr(sizeof(JSTaggedType))); 446 // 0 : skip 0 byte of bytecode 447 Store(VariableType::INT64(), glue, newSp, IntPtr(0), value); 448 return newSp; 449} 450 451GateRef InterpreterStubBuilder::PushUndefined(GateRef glue, GateRef sp, GateRef num) 452{ 453 auto env = GetEnvironment(); 454 Label subEntry(env); 455 env->SubCfgEntry(&subEntry); 456 DEFVARIABLE(newSp, VariableType::NATIVE_POINTER(), sp); 457 DEFVARIABLE(i, VariableType::INT32(), Int32(0)); 458 Label pushUndefinedBegin(env); 459 Label pushUndefinedAgain(env); 460 Label pushUndefinedEnd(env); 461 BRANCH(Int32LessThan(*i, num), &pushUndefinedBegin, &pushUndefinedEnd); 462 LoopBegin(&pushUndefinedBegin); 463 newSp = PushArg(glue, *newSp, Undefined()); 464 i = Int32Add(*i, Int32(1)); // 1 : set as high 1 bits 465 BRANCH(Int32LessThan(*i, num), &pushUndefinedAgain, &pushUndefinedEnd); 466 Bind(&pushUndefinedAgain); 467 LoopEnd(&pushUndefinedBegin); 468 Bind(&pushUndefinedEnd); 469 auto ret = *newSp; 470 env->SubCfgExit(); 471 return ret; 472} 473 474GateRef InterpreterStubBuilder::PushRange(GateRef glue, GateRef sp, GateRef array, GateRef startIndex, GateRef endIndex) 475{ 476 auto env = GetEnvironment(); 477 Label subEntry(env); 478 env->SubCfgEntry(&subEntry); 479 DEFVARIABLE(newSp, VariableType::NATIVE_POINTER(), sp); 480 DEFVARIABLE(i, VariableType::INT32(), endIndex); 481 Label pushArgsBegin(env); 482 Label pushArgsAgain(env); 483 Label pushArgsEnd(env); 484 BRANCH(Int32GreaterThanOrEqual(*i, startIndex), &pushArgsBegin, &pushArgsEnd); 485 LoopBegin(&pushArgsBegin); 486 GateRef arg = GetVregValue(array, ZExtInt32ToPtr(*i)); 487 newSp = PushArg(glue, *newSp, arg); 488 i = Int32Sub(*i, Int32(1)); // 1 : set as high 1 bits 489 BRANCH(Int32GreaterThanOrEqual(*i, startIndex), &pushArgsAgain, &pushArgsEnd); 490 Bind(&pushArgsAgain); 491 LoopEnd(&pushArgsBegin); 492 Bind(&pushArgsEnd); 493 auto ret = *newSp; 494 env->SubCfgExit(); 495 return ret; 496} 497 498GateRef InterpreterStubBuilder::GetStartIdxAndNumArgs(GateRef sp, GateRef restIdx) 499{ 500 auto env = GetEnvironment(); 501 Label subEntry(env); 502 env->SubCfgEntry(&subEntry); 503 DEFVARIABLE(numArgs, VariableType::INT32(), Int32(0)); 504 GateRef state = PtrSub(sp, IntPtr(AsmInterpretedFrame::GetSize(env->IsArch32Bit()))); 505 GateRef function = GetFunctionFromFrame(state); 506 GateRef method = GetMethodFromJSFunctionOrProxy(function); 507 GateRef callField = GetCallFieldFromMethod(method); 508 // ASSERT: callField has "extra" bit. 509 GateRef numVregs = TruncInt64ToInt32(Int64And(Int64LSR(callField, Int64(MethodLiteral::NumVregsBits::START_BIT)), 510 Int64((1LLU << MethodLiteral::NumVregsBits::SIZE) - 1))); 511 GateRef haveFunc = Int64NotEqual(Int64And(Int64LSR(callField, Int64(MethodLiteral::HaveFuncBit::START_BIT)), 512 Int64((1LLU << MethodLiteral::HaveFuncBit::SIZE) - 1)), Int64(0)); 513 GateRef haveNewTarget = Int64NotEqual( 514 Int64And(Int64LSR(callField, Int64(MethodLiteral::HaveNewTargetBit::START_BIT)), 515 Int64((1LLU << MethodLiteral::HaveNewTargetBit::SIZE) - 1)), Int64(0)); 516 GateRef haveThis = Int64NotEqual(Int64And(Int64LSR(callField, Int64(MethodLiteral::HaveThisBit::START_BIT)), 517 Int64((1LLU << MethodLiteral::HaveThisBit::SIZE) - 1)), Int64(0)); 518 GateRef copyArgs = Int32Add(Int32Add(ZExtInt1ToInt32(haveFunc), ZExtInt1ToInt32(haveNewTarget)), 519 ZExtInt1ToInt32(haveThis)); 520 numArgs = TruncInt64ToInt32(Int64And(Int64LSR(callField, Int64(MethodLiteral::NumArgsBits::START_BIT)), 521 Int64((1LLU << MethodLiteral::NumArgsBits::SIZE) - 1))); 522 GateRef fp = Load(VariableType::NATIVE_POINTER(), state, 523 IntPtr(AsmInterpretedFrame::GetFpOffset(env->IsArch32Bit()))); 524 Label actualEqualDeclared(env); 525 Label actualNotEqualDeclared(env); 526 BRANCH(Int32UnsignedGreaterThan(ChangeIntPtrToInt32(PtrSub(fp, sp)), 527 Int32Mul(Int32Add(Int32Add(numVregs, copyArgs), *numArgs), 528 Int32(sizeof(JSTaggedType)))), 529 &actualNotEqualDeclared, &actualEqualDeclared); 530 Bind(&actualNotEqualDeclared); 531 { 532 numArgs = GetInt32OfTInt(Load(VariableType::JS_ANY(), fp, IntPtr(-sizeof(JSTaggedType)))); 533 Jump(&actualEqualDeclared); 534 } 535 Bind(&actualEqualDeclared); 536 GateRef startIdx = Int32Add(Int32Add(numVregs, copyArgs), restIdx); 537 Label numArgsGreater(env); 538 Label numArgsNotGreater(env); 539 Label exit(env); 540 BRANCH(Int32UnsignedGreaterThan(*numArgs, restIdx), &numArgsGreater, &numArgsNotGreater); 541 Bind(&numArgsGreater); 542 { 543 numArgs = Int32Sub(*numArgs, restIdx); 544 Jump(&exit); 545 } 546 Bind(&numArgsNotGreater); 547 { 548 numArgs = Int32(0); 549 Jump(&exit); 550 } 551 Bind(&exit); 552 // 32: high 32 bits = startIdx, low 32 bits = numArgs 553 GateRef ret = Int64Or(Int64LSL(ZExtInt32ToInt64(startIdx), Int64(32)), ZExtInt32ToInt64(*numArgs)); 554 env->SubCfgExit(); 555 return ret; 556} 557 558GateRef InterpreterStubBuilder::GetCurrentFrame(GateRef glue) 559{ 560 return GetLastLeaveFrame(glue); 561} 562 563void InterpreterStubBuilder::UpdateProfileTypeInfoCellToFunction(GateRef glue, GateRef function, 564 GateRef profileTypeInfo, GateRef slotId) 565{ 566 auto env = GetEnvironment(); 567 Label subEntry(env); 568 env->SubCfgEntry(&subEntry); 569 570 Label profileTypeInfoNotUndefined(env); 571 Label slotValueUpdate(env); 572 Label slotValueNotUndefined(env); 573 Label slotValueNotHole(env); 574 Label profileTypeInfoEnd(env); 575 NewObjectStubBuilder newBuilder(this); 576 BRANCH(TaggedIsUndefined(profileTypeInfo), &profileTypeInfoEnd, &profileTypeInfoNotUndefined); 577 Bind(&profileTypeInfoNotUndefined); 578 { 579 GateRef slotValue = GetValueFromTaggedArray(profileTypeInfo, slotId); 580 BRANCH_UNLIKELY(TaggedIsUndefined(slotValue), &slotValueUpdate, &slotValueNotUndefined); 581 Bind(&slotValueUpdate); 582 { 583 GateRef newProfileTypeInfoCell = newBuilder.NewProfileTypeInfoCell(glue, Undefined()); 584 SetValueToTaggedArray(VariableType::JS_ANY(), glue, profileTypeInfo, slotId, newProfileTypeInfoCell, 585 MemoryAttribute::NeedNotShareBarrier()); 586 SetRawProfileTypeInfoToFunction(glue, function, newProfileTypeInfoCell, 587 MemoryAttribute::NeedNotShareBarrier()); 588 Jump(&profileTypeInfoEnd); 589 } 590 Bind(&slotValueNotUndefined); 591 BRANCH_UNLIKELY(TaggedIsHole(slotValue), &profileTypeInfoEnd, &slotValueNotHole); 592 Bind(&slotValueNotHole); 593 { 594 UpdateProfileTypeInfoCellType(glue, slotValue); 595 SetRawProfileTypeInfoToFunction(glue, function, slotValue, MemoryAttribute::NeedNotShareBarrier()); 596 TryToJitReuseCompiledFunc(glue, function, slotValue); 597 } 598 Jump(&profileTypeInfoEnd); 599 } 600 Bind(&profileTypeInfoEnd); 601 602 env->SubCfgExit(); 603} 604 605GateRef InterpreterStubBuilder::ReadInst32_0(GateRef pc) 606{ 607 if (GetEnvironment()->IsAArch64() || GetEnvironment()->IsAmd64()) { 608 return Load(VariableType::INT32(), pc, IntPtr(1)); // 1 : skip 1 byte of bytecode 609 } 610 GateRef currentInst = ZExtInt8ToInt32(ReadInst8_3(pc)); 611 GateRef currentInst1 = Int32LSL(currentInst, Int32(8)); // 8 : set as high 8 bits 612 GateRef currentInst2 = Int32Add(currentInst1, ZExtInt8ToInt32(ReadInst8_2(pc))); 613 GateRef currentInst3 = Int32LSL(currentInst2, Int32(8)); // 8 : set as high 8 bits 614 GateRef currentInst4 = Int32Add(currentInst3, ZExtInt8ToInt32(ReadInst8_1(pc))); 615 GateRef currentInst5 = Int32LSL(currentInst4, Int32(8)); // 8 : set as high 8 bits 616 return Int32Add(currentInst5, ZExtInt8ToInt32(ReadInst8_0(pc))); 617} 618 619GateRef InterpreterStubBuilder::ReadInst32_1(GateRef pc) 620{ 621 if (GetEnvironment()->IsAArch64() || GetEnvironment()->IsAmd64()) { 622 return Load(VariableType::INT32(), pc, IntPtr(2)); // 2 : skip 2 bytes of bytecode 623 } 624 GateRef currentInst = ZExtInt8ToInt32(ReadInst8_4(pc)); 625 GateRef currentInst1 = Int32LSL(currentInst, Int32(8)); // 8 : set as high 8 bits 626 GateRef currentInst2 = Int32Add(currentInst1, ZExtInt8ToInt32(ReadInst8_3(pc))); 627 GateRef currentInst3 = Int32LSL(currentInst2, Int32(8)); // 8 : set as high 8 bits 628 GateRef currentInst4 = Int32Add(currentInst3, ZExtInt8ToInt32(ReadInst8_2(pc))); 629 GateRef currentInst5 = Int32LSL(currentInst4, Int32(8)); // 8 : set as high 8 bits 630 return Int32Add(currentInst5, ZExtInt8ToInt32(ReadInst8_1(pc))); 631} 632 633GateRef InterpreterStubBuilder::ReadInst32_2(GateRef pc) 634{ 635 if (GetEnvironment()->IsAArch64() || GetEnvironment()->IsAmd64()) { 636 return Load(VariableType::INT32(), pc, IntPtr(3)); // 3 : skip 3 bytes of bytecode 637 } 638 GateRef currentInst = ZExtInt8ToInt32(ReadInst8_5(pc)); 639 GateRef currentInst1 = Int32LSL(currentInst, Int32(8)); // 8 : set as high 8 bits 640 GateRef currentInst2 = Int32Add(currentInst1, ZExtInt8ToInt32(ReadInst8_4(pc))); 641 GateRef currentInst3 = Int32LSL(currentInst2, Int32(8)); // 8 : set as high 8 bits 642 GateRef currentInst4 = Int32Add(currentInst3, ZExtInt8ToInt32(ReadInst8_3(pc))); 643 GateRef currentInst5 = Int32LSL(currentInst4, Int32(8)); // 8 : set as high 8 bits 644 return Int32Add(currentInst5, ZExtInt8ToInt32(ReadInst8_2(pc))); 645} 646 647GateRef InterpreterStubBuilder::ReadInst64_0(GateRef pc) 648{ 649 if (GetEnvironment()->IsAArch64() || GetEnvironment()->IsAmd64()) { 650 return Load(VariableType::INT64(), pc, IntPtr(1)); // 1 : skip 1 byte of bytecode 651 } 652 GateRef currentInst = ZExtInt8ToInt64(ReadInst8_7(pc)); 653 GateRef currentInst1 = Int64LSL(currentInst, Int64(8)); // 8 : set as high 8 bits 654 GateRef currentInst2 = Int64Add(currentInst1, ZExtInt8ToInt64(ReadInst8_6(pc))); 655 GateRef currentInst3 = Int64LSL(currentInst2, Int64(8)); // 8 : set as high 8 bits 656 GateRef currentInst4 = Int64Add(currentInst3, ZExtInt8ToInt64(ReadInst8_5(pc))); 657 GateRef currentInst5 = Int64LSL(currentInst4, Int64(8)); // 8 : set as high 8 bits 658 GateRef currentInst6 = Int64Add(currentInst5, ZExtInt8ToInt64(ReadInst8_4(pc))); 659 GateRef currentInst7 = Int64LSL(currentInst6, Int64(8)); // 8 : set as high 8 bits 660 GateRef currentInst8 = Int64Add(currentInst7, ZExtInt8ToInt64(ReadInst8_3(pc))); 661 GateRef currentInst9 = Int64LSL(currentInst8, Int64(8)); // 8 : set as high 8 bits 662 GateRef currentInst10 = Int64Add(currentInst9, ZExtInt8ToInt64(ReadInst8_2(pc))); 663 GateRef currentInst11 = Int64LSL(currentInst10, Int64(8)); // 8 : set as high 8 bits 664 GateRef currentInst12 = Int64Add(currentInst11, ZExtInt8ToInt64(ReadInst8_1(pc))); 665 GateRef currentInst13 = Int64LSL(currentInst12, Int64(8)); // 8 : set as high 8 bits 666 return Int64Add(currentInst13, ZExtInt8ToInt64(ReadInst8_0(pc))); 667} 668 669template<typename... Args> 670void InterpreterStubBuilder::DispatchBase(GateRef target, GateRef glue, Args... args) 671{ 672 GetEnvironment()->GetBuilder()->CallBCHandler(glue, target, {glue, args...}); 673} 674 675void InterpreterStubBuilder::Dispatch(GateRef glue, GateRef sp, GateRef pc, GateRef constpool, GateRef profileTypeInfo, 676 GateRef acc, GateRef hotnessCounter, GateRef format) 677{ 678 GateRef newPc = PtrAdd(pc, format); 679 GateRef opcode = Load(VariableType::INT8(), newPc); 680 GateRef target = PtrMul(ZExtInt32ToPtr(ZExtInt8ToInt32(opcode)), IntPtrSize()); 681 DispatchBase(target, glue, sp, newPc, constpool, profileTypeInfo, acc, hotnessCounter); 682 Return(); 683} 684 685void InterpreterStubBuilder::DispatchLast(GateRef glue, GateRef sp, GateRef pc, GateRef constpool, 686 GateRef profileTypeInfo, GateRef acc, GateRef hotnessCounter) 687{ 688 GateRef target = PtrMul(IntPtr(BytecodeStubCSigns::ID_ExceptionHandler), IntPtrSize()); 689 DispatchBase(target, glue, sp, pc, constpool, profileTypeInfo, acc, hotnessCounter); 690 Return(); 691} 692 693void InterpreterStubBuilder::DispatchDebugger(GateRef glue, GateRef sp, GateRef pc, GateRef constpool, 694 GateRef profileTypeInfo, GateRef acc, GateRef hotnessCounter) 695{ 696 GateRef opcode = Load(VariableType::INT8(), pc); 697 GateRef target = PtrMul(ZExtInt32ToPtr(ZExtInt8ToInt32(opcode)), IntPtrSize()); 698 auto args = { glue, sp, pc, constpool, profileTypeInfo, acc, hotnessCounter }; 699 GetEnvironment()->GetBuilder()->CallBCDebugger(glue, target, args); 700 Return(); 701} 702 703void InterpreterStubBuilder::DispatchDebuggerLast(GateRef glue, GateRef sp, GateRef pc, GateRef constpool, 704 GateRef profileTypeInfo, GateRef acc, GateRef hotnessCounter) 705{ 706 GateRef target = PtrMul(IntPtr(BytecodeStubCSigns::ID_ExceptionHandler), IntPtrSize()); 707 auto args = { glue, sp, pc, constpool, profileTypeInfo, acc, hotnessCounter }; 708 GetEnvironment()->GetBuilder()->CallBCDebugger(glue, target, args); 709 Return(); 710} 711 712GateRef InterpreterStubBuilder::GetHotnessCounterFromMethod(GateRef method) 713{ 714 GateRef x = Load(VariableType::INT16(), method, IntPtr(Method::LITERAL_INFO_OFFSET)); 715 return GetEnvironment()->GetBuilder()->SExtInt1ToInt32(x); 716} 717 718void InterpreterStubBuilder::DispatchWithId(GateRef glue, GateRef sp, GateRef pc, GateRef constpool, 719 GateRef profileTypeInfo, GateRef acc, 720 GateRef hotnessCounter, GateRef index) 721{ 722 GateRef target = PtrMul(index, IntPtrSize()); 723 DispatchBase(target, glue, sp, pc, constpool, profileTypeInfo, acc, hotnessCounter); 724 Return(); 725} 726 727#define DISPATCH_LAST(acc) \ 728 DispatchLast(glue, sp, pc, constpool, profileTypeInfo, acc, hotnessCounter) 729#define DISPATCH(acc) \ 730 Dispatch(glue, sp, pc, constpool, profileTypeInfo, acc, hotnessCounter, offset) 731void InterpreterStubBuilder::CheckException(GateRef glue, GateRef sp, GateRef pc, GateRef constpool, 732 GateRef profileTypeInfo, GateRef acc, GateRef hotnessCounter, 733 GateRef res, GateRef offset) 734{ 735 auto env = GetEnvironment(); 736 Label isException(env); 737 Label notException(env); 738 BRANCH(TaggedIsException(res), &isException, ¬Exception); 739 Bind(&isException); 740 { 741 DISPATCH_LAST(acc); 742 } 743 Bind(¬Exception); 744 { 745 DISPATCH(acc); 746 } 747} 748 749void InterpreterStubBuilder::CheckPendingException(GateRef glue, GateRef sp, GateRef pc, GateRef constpool, 750 GateRef profileTypeInfo, GateRef acc, GateRef hotnessCounter, 751 GateRef res, GateRef offset) 752{ 753 auto env = GetEnvironment(); 754 Label isException(env); 755 Label notException(env); 756 BRANCH(HasPendingException(glue), &isException, ¬Exception); 757 Bind(&isException); 758 { 759 DISPATCH_LAST(acc); 760 } 761 Bind(¬Exception); 762 { 763 DISPATCH(res); 764 } 765} 766 767void InterpreterStubBuilder::CheckExceptionWithVar(GateRef glue, GateRef sp, GateRef pc, GateRef constpool, 768 GateRef profileTypeInfo, GateRef acc, GateRef hotnessCounter, 769 GateRef res, GateRef offset) 770{ 771 auto env = GetEnvironment(); 772 Label isException(env); 773 Label notException(env); 774 BRANCH(TaggedIsException(res), &isException, ¬Exception); 775 Bind(&isException); 776 { 777 DISPATCH_LAST(acc); 778 } 779 Bind(¬Exception); 780 { 781 DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); 782 varAcc = res; 783 DISPATCH(*varAcc); 784 } 785} 786 787void InterpreterStubBuilder::CheckExceptionWithJump(GateRef glue, GateRef sp, GateRef pc, GateRef constpool, 788 GateRef profileTypeInfo, GateRef acc, GateRef hotnessCounter, 789 GateRef res, Label *jump) 790{ 791 auto env = GetEnvironment(); 792 Label isException(env); 793 Label notException(env); 794 BRANCH(TaggedIsException(res), &isException, ¬Exception); 795 Bind(&isException); 796 { 797 DISPATCH_LAST(acc); 798 } 799 Bind(¬Exception); 800 { 801 Jump(jump); 802 } 803} 804 805GateRef InterpreterToolsStubBuilder::GetStringId(const StringIdInfo &info) 806{ 807 if (info.GetStringIdType() == StringIdInfo::StringIdType::STRING_ID) { 808 return info.GetStringId(); 809 } 810 GateRef stringId; 811 switch (info.GetOffset()) { 812 case StringIdInfo::Offset::BYTE_0: { 813 if (info.GetLength() == StringIdInfo::Length::BITS_16) { 814 stringId = ZExtInt16ToInt32(ReadInst16_0(info.GetPc())); 815 } else { 816 std::abort(); 817 } 818 break; 819 } 820 case StringIdInfo::Offset::BYTE_1: { 821 if (info.GetLength() == StringIdInfo::Length::BITS_16) { 822 stringId = ZExtInt16ToInt32(ReadInst16_1(info.GetPc())); 823 } else if (info.GetLength() == StringIdInfo::Length::BITS_32) { 824 stringId = ReadInst32_1(info.GetPc()); 825 } else { 826 std::abort(); 827 } 828 break; 829 } 830 case StringIdInfo::Offset::BYTE_2: { 831 if (info.GetLength() == StringIdInfo::Length::BITS_16) { 832 stringId = ZExtInt16ToInt32(ReadInst16_2(info.GetPc())); 833 } else { 834 std::abort(); 835 } 836 break; 837 } 838 default: { 839 std::abort(); 840 break; 841 } 842 } 843 return stringId; 844} 845#undef DISPATCH_LAST 846#undef DISPATCH 847} // namespace panda::ecmascript::kungfu 848#endif // ECMASCRIPT_COMPILER_INTERPRETER_STUB_INL_H 849