/* * Copyright (c) 2021 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "interpreter_stub-inl.h" #include "ecmascript/base/number_helper.h" #include "ecmascript/compiler/bc_call_signature.h" #include "ecmascript/compiler/llvm_ir_builder.h" #include "ecmascript/compiler/stub-inl.h" #include "ecmascript/compiler/variable_type.h" #include "ecmascript/global_env_constants.h" #include "ecmascript/ic/profile_type_info.h" #include "ecmascript/interpreter/interpreter_assembly.h" #include "ecmascript/js_array.h" #include "ecmascript/js_function.h" #include "ecmascript/js_generator_object.h" #include "ecmascript/message_string.h" #include "ecmascript/tagged_hash_table.h" #include "libpandafile/bytecode_instruction-inl.h" namespace panda::ecmascript::kungfu { #if ECMASCRIPT_ENABLE_ASM_INTERPRETER_LOG #define DECLARE_ASM_HANDLER(name) \ void name##Stub::GenerateCircuit(const CompilationConfig *cfg) \ { \ Stub::GenerateCircuit(cfg); \ GateRef glue = PtrArgument(static_cast(InterpreterHandlerInputs::GLUE)); \ GateRef sp = PtrArgument(static_cast(InterpreterHandlerInputs::SP)); \ GateRef pc = PtrArgument(static_cast(InterpreterHandlerInputs::PC)); \ GateRef constpool = TaggedPointerArgument( \ static_cast(InterpreterHandlerInputs::CONSTPOOL)); \ GateRef profileTypeInfo = TaggedPointerArgument( \ static_cast(InterpreterHandlerInputs::PROFILE_TYPE_INFO)); \ GateRef acc = TaggedArgument(static_cast(InterpreterHandlerInputs::ACC)); \ GateRef hotnessCounter = Int32Argument( \ static_cast(InterpreterHandlerInputs::HOTNESS_COUNTER)); \ DebugPrint(glue, { Int32(GET_MESSAGE_STRING_ID(name)) }); \ GenerateCircuitImpl(glue, sp, pc, constpool, profileTypeInfo, acc, hotnessCounter); \ } \ void name##Stub::GenerateCircuitImpl(GateRef glue, GateRef sp, GateRef pc, \ GateRef constpool, GateRef profileTypeInfo, \ GateRef acc, GateRef hotnessCounter) #else #define DECLARE_ASM_HANDLER(name) \ void name##Stub::GenerateCircuit(const CompilationConfig *cfg) \ { \ Stub::GenerateCircuit(cfg); \ GateRef glue = PtrArgument(static_cast(InterpreterHandlerInputs::GLUE)); \ GateRef sp = PtrArgument(static_cast(InterpreterHandlerInputs::SP)); \ GateRef pc = PtrArgument(static_cast(InterpreterHandlerInputs::PC)); \ GateRef constpool = TaggedPointerArgument( \ static_cast(InterpreterHandlerInputs::CONSTPOOL)); \ GateRef profileTypeInfo = TaggedPointerArgument( \ static_cast(InterpreterHandlerInputs::PROFILE_TYPE_INFO)); \ GateRef acc = TaggedArgument(static_cast(InterpreterHandlerInputs::ACC)); \ GateRef hotnessCounter = Int32Argument( \ static_cast(InterpreterHandlerInputs::HOTNESS_COUNTER)); \ GenerateCircuitImpl(glue, sp, pc, constpool, profileTypeInfo, acc, hotnessCounter); \ } \ void name##Stub::GenerateCircuitImpl(GateRef glue, GateRef sp, GateRef pc, \ GateRef constpool, GateRef profileTypeInfo, \ GateRef acc, GateRef hotnessCounter) #endif #define DISPATCH(format) \ Dispatch(glue, sp, pc, constpool, profileTypeInfo, acc, hotnessCounter, \ IntPtr(BytecodeInstruction::Size(BytecodeInstruction::Format::format))) #define DISPATCH_WITH_ACC(format) \ Dispatch(glue, sp, pc, constpool, profileTypeInfo, *varAcc, hotnessCounter, \ IntPtr(BytecodeInstruction::Size(BytecodeInstruction::Format::format))) #define DISPATCH_LAST() \ DispatchLast(glue, sp, pc, constpool, profileTypeInfo, acc, hotnessCounter) \ #define DISPATCH_LAST_WITH_ACC() \ DispatchLast(glue, sp, pc, constpool, profileTypeInfo, *varAcc, hotnessCounter) \ #define UPDATE_HOTNESS(_sp) \ varHotnessCounter = Int32Add(offset, *varHotnessCounter); \ Branch(Int32LessThan(*varHotnessCounter, Int32(0)), &slowPath, &dispatch); \ Bind(&slowPath); \ { \ varProfileTypeInfo = CallRuntime(glue, RTSTUB_ID(UpdateHotnessCounter), {}); \ varHotnessCounter = Int32(InterpreterAssembly::METHOD_HOTNESS_THRESHOLD); \ Jump(&dispatch); \ } \ Bind(&dispatch); #define USE_PARAMS() \ (void)constpool; \ (void)profileTypeInfo; \ (void)acc; \ (void)hotnessCounter; DECLARE_ASM_HANDLER(HandleLdNanPref) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); varAcc = DoubleBuildTaggedWithNoGC(Double(base::NAN_VALUE)); DISPATCH_WITH_ACC(PREF_NONE); } DECLARE_ASM_HANDLER(HandleLdInfinityPref) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); varAcc = DoubleBuildTaggedWithNoGC(Double(base::POSITIVE_INFINITY)); DISPATCH_WITH_ACC(PREF_NONE); } DECLARE_ASM_HANDLER(HandleLdGlobalThisPref) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); varAcc = GetGlobalObject(glue); DISPATCH_WITH_ACC(PREF_NONE); } DECLARE_ASM_HANDLER(HandleLdUndefinedPref) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); varAcc = Undefined(); DISPATCH_WITH_ACC(PREF_NONE); } DECLARE_ASM_HANDLER(HandleLdNullPref) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); varAcc = Null(); DISPATCH_WITH_ACC(PREF_NONE); } DECLARE_ASM_HANDLER(HandleLdSymbolPref) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); varAcc = CallRuntime(glue, RTSTUB_ID(GetSymbolFunction), {}); DISPATCH_WITH_ACC(PREF_NONE); } DECLARE_ASM_HANDLER(HandleLdGlobalPref) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); varAcc = GetGlobalObject(glue); DISPATCH_WITH_ACC(PREF_NONE); } DECLARE_ASM_HANDLER(HandleLdTruePref) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); varAcc = ChangeInt64ToTagged(Int64(JSTaggedValue::VALUE_TRUE)); DISPATCH_WITH_ACC(PREF_NONE); } DECLARE_ASM_HANDLER(HandleLdFalsePref) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); varAcc = ChangeInt64ToTagged(Int64(JSTaggedValue::VALUE_FALSE)); DISPATCH_WITH_ACC(PREF_NONE); } DECLARE_ASM_HANDLER(HandleThrowDynPref) { CallRuntime(glue, RTSTUB_ID(ThrowDyn), { acc }); DISPATCH_LAST(); } DECLARE_ASM_HANDLER(HandleTypeOfDynPref) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); varAcc = FastTypeOf(glue, acc); DISPATCH_WITH_ACC(PREF_NONE); } DECLARE_ASM_HANDLER(HandleLdLexEnvDynPref) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef state = GetFrame(sp); varAcc = GetEnvFromFrame(state); DISPATCH_WITH_ACC(PREF_NONE); } DECLARE_ASM_HANDLER(HandlePopLexEnvDynPref) { GateRef state = GetFrame(sp); GateRef currentLexEnv = GetEnvFromFrame(state); GateRef parentLexEnv = GetParentEnv(currentLexEnv); SetEnvToFrame(glue, state, parentLexEnv); DISPATCH(PREF_NONE); } DECLARE_ASM_HANDLER(HandleGetUnmappedArgsPref) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); auto env = GetEnvironment(); GateRef res = CallRuntime(glue, RTSTUB_ID(GetUnmapedArgs), {}); Label isException(env); Label notException(env); Branch(TaggedIsException(res), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); varAcc = res; DISPATCH_WITH_ACC(PREF_NONE); } DECLARE_ASM_HANDLER(HandleCopyRestArgsPrefImm16) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); auto env = GetEnvironment(); GateRef restIdx = ZExtInt16ToInt32(ReadInst16_1(pc)); GateRef res = CallRuntime(glue, RTSTUB_ID(CopyRestArgs), { IntBuildTaggedTypeWithNoGC(restIdx) }); Label isException(env); Label notException(env); Branch(TaggedIsException(res), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); varAcc = res; DISPATCH_WITH_ACC(PREF_IMM16); } DECLARE_ASM_HANDLER(HandleCreateArrayWithBufferPrefImm16) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); auto env = GetEnvironment(); GateRef imm = ZExtInt16ToInt32(ReadInst16_1(pc)); GateRef result = GetObjectFromConstPool(constpool, imm); GateRef res = CallRuntime(glue, RTSTUB_ID(CreateArrayWithBuffer), { result }); Label isException(env); Label notException(env); Branch(TaggedIsException(res), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); varAcc = res; DISPATCH_WITH_ACC(PREF_IMM16); } DECLARE_ASM_HANDLER(HandleCreateObjectWithBufferPrefImm16) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); auto env = GetEnvironment(); GateRef imm = ZExtInt16ToInt32(ReadInst16_1(pc)); GateRef result = GetObjectFromConstPool(constpool, imm); GateRef res = CallRuntime(glue, RTSTUB_ID(CreateObjectWithBuffer), { result }); Label isException(env); Label notException(env); Branch(TaggedIsException(res), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); varAcc = res; DISPATCH_WITH_ACC(PREF_IMM16); } DECLARE_ASM_HANDLER(HandleCreateObjectWithExcludedKeysPrefImm16V8V8) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); auto env = GetEnvironment(); GateRef numKeys = ReadInst16_1(pc); GateRef obj = GetVregValue(sp, ZExtInt8ToPtr(ReadInst8_3(pc))); GateRef firstArgRegIdx = ZExtInt8ToInt16(ReadInst8_4(pc)); GateRef res = CallRuntime(glue, RTSTUB_ID(CreateObjectWithExcludedKeys), { Int16BuildTaggedTypeWithNoGC(numKeys), obj, Int16BuildTaggedTypeWithNoGC(firstArgRegIdx) }); Label isException(env); Label notException(env); Branch(TaggedIsException(res), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); varAcc = res; DISPATCH_WITH_ACC(PREF_IMM16_V8_V8); } DECLARE_ASM_HANDLER(HandleCreateObjectHavingMethodPrefImm16) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); auto env = GetEnvironment(); GateRef imm = ZExtInt16ToInt32(ReadInst16_1(pc)); GateRef result = GetObjectFromConstPool(constpool, imm); GateRef res = CallRuntime(glue, RTSTUB_ID(CreateObjectHavingMethod), { result, acc, constpool }); Label isException(env); Label notException(env); Branch(TaggedIsException(res), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); varAcc = res; DISPATCH_WITH_ACC(PREF_IMM16); } DECLARE_ASM_HANDLER(HandleThrowIfSuperNotCorrectCallPrefImm16) { auto env = GetEnvironment(); GateRef imm = ReadInst16_1(pc); GateRef res = CallRuntime(glue, RTSTUB_ID(ThrowIfSuperNotCorrectCall), { Int16BuildTaggedTypeWithNoGC(imm), acc }); // acc is thisValue Label isException(env); Label notException(env); Branch(TaggedIsException(res), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); DISPATCH(PREF_IMM16); } DECLARE_ASM_HANDLER(HandleNewLexEnvDynPrefImm16) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); auto env = GetEnvironment(); GateRef numVars = ReadInst16_1(pc); GateRef res = CallRuntime(glue, RTSTUB_ID(NewLexicalEnvDyn), { Int16BuildTaggedTypeWithNoGC(numVars) }); Label isException(env); Label notException(env); Branch(TaggedIsException(res), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); varAcc = res; SetEnvToFrame(glue, GetFrame(sp), res); DISPATCH_WITH_ACC(PREF_IMM16); } DECLARE_ASM_HANDLER(HandleNewObjDynRangePrefImm16V8) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); auto env = GetEnvironment(); GateRef numArgs = ReadInst16_1(pc); GateRef firstArgRegIdx = ZExtInt8ToInt16(ReadInst8_3(pc)); GateRef firstArgOffset = Int16(2); GateRef ctor = GetVregValue(sp, ZExtInt16ToPtr(firstArgRegIdx)); GateRef newTarget = GetVregValue(sp, PtrAdd(ZExtInt16ToPtr(firstArgRegIdx), IntPtr(1))); #if !ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK Label ctorIsHeapObject(env); Label ctorIsJSFunction(env); Label fastPath(env); Label slowPath(env); Branch(TaggedIsHeapObject(ctor), &ctorIsHeapObject, &slowPath); Bind(&ctorIsHeapObject); Branch(IsJSFunction(ctor), &ctorIsJSFunction, &slowPath); Bind(&ctorIsJSFunction); Branch(IsConstructor(ctor), &fastPath, &slowPath); Bind(&fastPath); { GateRef methodOffset = IntPtr(JSFunction::METHOD_OFFSET); GateRef ctorMethod = Load(VariableType::NATIVE_POINTER(), ctor, methodOffset); Label ctorIsBuiltinsConstructor(env); Label ctorNotBuiltinsConstructor(env); Branch(IsBuiltinsConstructor(ctor), &ctorIsBuiltinsConstructor, &ctorNotBuiltinsConstructor); Bind(&ctorIsBuiltinsConstructor); { // Changed to push newSp like call for further asm. DEFVARIABLE(newSp, VariableType::NATIVE_POINTER(), PointerSub(sp, IntPtr(AsmInterpretedFrame::GetSize(env->IsArch32Bit())))); DEFVARIABLE(i, VariableType::INT32(), ZExtInt16ToInt32(numArgs)); i = Int32Sub(*i, Int32(1)); GateRef startIndex = Int32Add(ZExtInt16ToInt32(firstArgRegIdx), ZExtInt16ToInt32(firstArgOffset)); GateRef endIndex = Int32Add(ZExtInt16ToInt32(firstArgRegIdx), *i); newSp = PushRange(glue, *newSp, sp, startIndex, endIndex); // push this newSp = PushArg(glue, *newSp, Int64(JSTaggedValue::VALUE_UNDEFINED)); // push newTarget newSp = PushArg(glue, *newSp, newTarget); // push func newSp = PushArg(glue, *newSp, ctor); // ASSERT(ctorMethod->GetNumVregsWithCallField() == 0) Label stackOverflow(env); Label stackNotOverflow(env); Branch(CheckStackOverflow(glue, *newSp), &stackOverflow, &stackNotOverflow); Bind(&stackOverflow); { CallRuntime(glue, RTSTUB_ID(ThrowStackOverflowException), {}); DISPATCH_LAST(); } Bind(&stackNotOverflow); SetFrameState(glue, *newSp, ctor, Hole(VariableType::JS_ANY()), Hole(VariableType::JS_ANY()), IntPtr(0), sp, Int64(static_cast(FrameType::ASM_INTERPRETER_FRAME))); SetCurrentSpFrame(glue, *newSp); GateRef numArgsWithThis = Int16Add(numArgs, Int16(1 - static_cast(NUM_MANDATORY_JSFUNC_ARGS))); // 1: this GateRef retValue = CallRuntime(glue, RTSTUB_ID(CallNative), {Int16BuildTaggedTypeWithNoGC(numArgsWithThis)}); SetCurrentSpFrame(glue, sp); Label hasPendingException(env); Label noPendingException(env); Branch(TaggedIsException(retValue), &hasPendingException, &noPendingException); Bind(&hasPendingException); { DISPATCH_LAST(); } Bind(&noPendingException); varAcc = retValue; DISPATCH_WITH_ACC(PREF_IMM16_V8); } Bind(&ctorNotBuiltinsConstructor); // IsFastNewFrameEnter is not considered in asm. GateRef callFieldOffset = IntPtr(JSMethod::GetCallFieldOffset(env->IsArch32Bit())); GateRef callField = Load(VariableType::INT64(), ctorMethod, callFieldOffset); GateRef isNativeMask = Int64(static_cast(1) << JSMethod::IsNativeBit::START_BIT); Label ctorMethodNotNative(env); Branch(Int64NotEqual(Int64And(callField, isNativeMask), Int64(0)), &slowPath, &ctorMethodNotNative); Bind(&ctorMethodNotNative); { SetPcToFrame(glue, GetFrame(sp), pc); SetCallSizeToFrame(glue, GetFrame(sp), IntPtr(BytecodeInstruction::Size(BytecodeInstruction::Format::PREF_IMM16_V8))); DEFVARIABLE(thisObj, VariableType::JS_ANY(), Undefined()); Label ctorIsBase(env); Label ctorNotBase(env); // ASSERT(ctorFunc->IsDerivedConstructor()) Branch(IsBase(ctor), &ctorIsBase, &ctorNotBase); Bind(&ctorIsBase); { thisObj = CallRuntime(glue, RTSTUB_ID(NewThisObject), {ctor, newTarget}); // INTERPRETER_RETURN_IF_ABRUPT(thisObj) Label thisObjIsException(env); Branch(TaggedIsException(*thisObj), &thisObjIsException, &ctorNotBase); Bind(&thisObjIsException); { DISPATCH_LAST(); } } Bind(&ctorNotBase); // Changed to push newSp like call for further asm. DEFVARIABLE(newSp, VariableType::NATIVE_POINTER(), PointerSub(sp, IntPtr(AsmInterpretedFrame::GetSize(env->IsArch32Bit())))); DEFVARIABLE(i, VariableType::INT32(), Int32(0)); GateRef numArgsOffset = Int64(JSMethod::NumArgsBits::START_BIT); GateRef numArgsMask = Int64((static_cast(1) << JSMethod::NumArgsBits::SIZE) - 1); GateRef declaredNumArgs = ChangeInt64ToInt32(Int64And(Int64LSR(callField, numArgsOffset), numArgsMask)); GateRef actualNumArgs = ZExtInt16ToInt32(Int16Sub(numArgs, firstArgOffset)); // exclude func and newTarget // Ignore haveExtra to hide this object in the 2nd last index newSp = PushArg(glue, *newSp, IntBuildTaggedTypeWithNoGC(actualNumArgs)); newSp = PushArg(glue, *newSp, *thisObj); GateRef undefinedNumArgs = Int32Sub(declaredNumArgs, actualNumArgs); newSp = PushUndefined(glue, *newSp, undefinedNumArgs); i = actualNumArgs; i = Int32Add(*i, Int32(1)); // +2 for func and newTarget, -1 to get last index GateRef startIndex = Int32Add(ZExtInt16ToInt32(firstArgRegIdx), ZExtInt16ToInt32(firstArgOffset)); GateRef endIndex = Int32Add(ZExtInt16ToInt32(firstArgRegIdx), *i); newSp = PushRange(glue, *newSp, sp, startIndex, endIndex); GateRef haveThisMask = Int64(static_cast(1) << JSMethod::HaveThisBit::START_BIT); Label ctorMethodHaveThis(env); Label ctorMethodNoThis(env); Branch(Int64NotEqual(Int64And(callField, haveThisMask), Int64(0)), &ctorMethodHaveThis, &ctorMethodNoThis); Bind(&ctorMethodHaveThis); { newSp = PushArg(glue, *newSp, *thisObj); Jump(&ctorMethodNoThis); } Bind(&ctorMethodNoThis); GateRef haveNewTargetMask = Int64(static_cast(1) << JSMethod::HaveNewTargetBit::START_BIT); Label ctorMethodHaveNewTarget(env); Label ctorMethodNoNewTarget(env); Branch(Int64NotEqual(Int64And(callField, haveNewTargetMask), Int64(0)), &ctorMethodHaveNewTarget, &ctorMethodNoNewTarget); Bind(&ctorMethodHaveNewTarget); { newSp = PushArg(glue, *newSp, newTarget); Jump(&ctorMethodNoNewTarget); } Bind(&ctorMethodNoNewTarget); GateRef haveFuncMask = Int64(static_cast(1) << JSMethod::HaveFuncBit::START_BIT); Label ctorMethodHaveFunc(env); Label ctorMethodNoFunc(env); Branch(Int64NotEqual(Int64And(callField, haveFuncMask), Int64(0)), &ctorMethodHaveFunc, &ctorMethodNoFunc); Bind(&ctorMethodHaveFunc); { newSp = PushArg(glue, *newSp, ctor); Jump(&ctorMethodNoFunc); } Bind(&ctorMethodNoFunc); // push vregs GateRef numVregsOffset = Int64(JSMethod::NumVregsBits::START_BIT); GateRef numVregsMask = Int64((static_cast(1) << JSMethod::NumVregsBits::SIZE) - 1); GateRef numVregs = ChangeInt64ToInt32(Int64And(Int64LSR(callField, numVregsOffset), numVregsMask)); newSp = PushUndefined(glue, *newSp, numVregs); Label stackOverflow(env); Label stackNotOverflow(env); Branch(CheckStackOverflow(glue, *newSp), &stackOverflow, &stackNotOverflow); Bind(&stackOverflow); { CallRuntime(glue, RTSTUB_ID(ThrowStackOverflowException), {}); DISPATCH_LAST(); } Bind(&stackNotOverflow); GateRef newEnv = GetEnvFromFunction(ctor); GateRef bytecodeArrayOffset = IntPtr(JSMethod::GetBytecodeArrayOffset(env->IsArch32Bit())); GateRef bytecodeArray = Load(VariableType::NATIVE_POINTER(), ctorMethod, bytecodeArrayOffset); SetFrameState(glue, *newSp, ctor, Hole(VariableType::JS_ANY()), newEnv, bytecodeArray, sp, Int64(static_cast(FrameType::INTERPRETER_CONSTRUCTOR_FRAME))); SetCurrentSpFrame(glue, *newSp); GateRef newConstpool = GetConstpoolFromFunction(ctor); GateRef newProfileTypeInfo = GetProfileTypeInfoFromFunction(ctor); GateRef newHotnessCounter = Load(VariableType::INT32(), ctorMethod, IntPtr(JSMethod::GetHotnessCounterOffset(env->IsArch32Bit()))); Dispatch(glue, *newSp, bytecodeArray, newConstpool, newProfileTypeInfo, Hole(VariableType::JS_ANY()), newHotnessCounter, IntPtr(0)); } } Bind(&slowPath); #endif GateRef firstArgIdx = Int16Add(firstArgRegIdx, firstArgOffset); GateRef length = Int16Sub(numArgs, firstArgOffset); GateRef res = CallRuntime(glue, RTSTUB_ID(NewObjDynRange), { ctor, newTarget, Int16BuildTaggedTypeWithNoGC(firstArgIdx), Int16BuildTaggedTypeWithNoGC(length) }); Label isException(env); Label notException(env); Branch(TaggedIsException(res), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); varAcc = res; DISPATCH_WITH_ACC(PREF_IMM16_V8); } DECLARE_ASM_HANDLER(HandleDefineFuncDynPrefId16Imm16V8) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); auto env = GetEnvironment(); GateRef methodId = ReadInst16_1(pc); GateRef length = ReadInst16_3(pc); GateRef v0 = ReadInst8_5(pc); DEFVARIABLE(result, VariableType::JS_POINTER(), GetObjectFromConstPool(constpool, ZExtInt16ToInt32(methodId))); Label isResolved(env); Label notResolved(env); Label defaultLabel(env); Branch(FunctionIsResolved(*result), &isResolved, ¬Resolved); Bind(&isResolved); { result = CallRuntime(glue, RTSTUB_ID(DefinefuncDyn), { *result }); Label isException(env); Label notException(env); Branch(TaggedIsException(*result), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); { SetConstantPoolToFunction(glue, *result, constpool); Jump(&defaultLabel); } } Bind(¬Resolved); { SetResolvedToFunction(glue, *result, Boolean(true)); Jump(&defaultLabel); } Bind(&defaultLabel); { GateRef hClass = LoadHClass(*result); SetPropertyInlinedProps(glue, *result, hClass, Int16BuildTaggedWithNoGC(length), Int32(JSFunction::LENGTH_INLINE_PROPERTY_INDEX), VariableType::INT64()); GateRef envHandle = GetVregValue(sp, ZExtInt8ToPtr(v0)); SetLexicalEnvToFunction(glue, *result, envHandle); GateRef currentFunc = GetFunctionFromFrame(GetFrame(sp)); SetModuleToFunction(glue, *result, GetModuleFromFunction(currentFunc)); varAcc = *result; DISPATCH_WITH_ACC(PREF_ID16_IMM16_V8); } } DECLARE_ASM_HANDLER(HandleDefineNCFuncDynPrefId16Imm16V8) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); auto env = GetEnvironment(); GateRef methodId = ReadInst16_1(pc); GateRef length = ReadInst16_3(pc); GateRef v0 = ReadInst8_5(pc); DEFVARIABLE(result, VariableType::JS_POINTER(), GetObjectFromConstPool(constpool, ZExtInt16ToInt32(methodId))); Label isResolved(env); Label notResolved(env); Label defaultLabel(env); Branch(FunctionIsResolved(*result), &isResolved, ¬Resolved); Bind(&isResolved); { result = CallRuntime(glue, RTSTUB_ID(DefineNCFuncDyn), { *result }); Label isException(env); Label notException(env); Branch(TaggedIsException(*result), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); { SetConstantPoolToFunction(glue, *result, constpool); Jump(&defaultLabel); } } Bind(¬Resolved); { SetResolvedToFunction(glue, *result, Boolean(true)); Jump(&defaultLabel); } Bind(&defaultLabel); { GateRef hClass = LoadHClass(*result); SetPropertyInlinedProps(glue, *result, hClass, Int16BuildTaggedWithNoGC(length), Int32(JSFunction::LENGTH_INLINE_PROPERTY_INDEX), VariableType::INT64()); GateRef lexEnv = GetVregValue(sp, ZExtInt8ToPtr(v0)); SetLexicalEnvToFunction(glue, *result, lexEnv); SetHomeObjectToFunction(glue, *result, acc); GateRef currentFunc = GetFunctionFromFrame(GetFrame(sp)); SetModuleToFunction(glue, *result, GetModuleFromFunction(currentFunc)); varAcc = *result; DISPATCH_WITH_ACC(PREF_ID16_IMM16_V8); } } DECLARE_ASM_HANDLER(HandleDefineGeneratorFuncPrefId16Imm16V8) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); auto env = GetEnvironment(); GateRef methodId = ReadInst16_1(pc); GateRef length = ReadInst16_3(pc); GateRef v0 = ReadInst8_5(pc); DEFVARIABLE(result, VariableType::JS_POINTER(), GetObjectFromConstPool(constpool, ZExtInt16ToInt32(methodId))); Label isResolved(env); Label notResolved(env); Label defaultLabel(env); Branch(FunctionIsResolved(*result), &isResolved, ¬Resolved); Bind(&isResolved); { result = CallRuntime(glue, RTSTUB_ID(DefineGeneratorFunc), { *result }); Label isException(env); Label notException(env); Branch(TaggedIsException(*result), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); { SetConstantPoolToFunction(glue, *result, constpool); Jump(&defaultLabel); } } Bind(¬Resolved); { SetResolvedToFunction(glue, *result, Boolean(true)); Jump(&defaultLabel); } Bind(&defaultLabel); { GateRef hClass = LoadHClass(*result); SetPropertyInlinedProps(glue, *result, hClass, Int16BuildTaggedWithNoGC(length), Int32(JSFunction::LENGTH_INLINE_PROPERTY_INDEX), VariableType::INT64()); GateRef lexEnv = GetVregValue(sp, ZExtInt8ToPtr(v0)); SetLexicalEnvToFunction(glue, *result, lexEnv); GateRef currentFunc = GetFunctionFromFrame(GetFrame(sp)); SetModuleToFunction(glue, *result, GetModuleFromFunction(currentFunc)); varAcc = *result; DISPATCH_WITH_ACC(PREF_ID16_IMM16_V8); } } DECLARE_ASM_HANDLER(HandleDefineAsyncFuncPrefId16Imm16V8) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); auto env = GetEnvironment(); GateRef methodId = ReadInst16_1(pc); GateRef length = ReadInst16_3(pc); GateRef v0 = ReadInst8_5(pc); DEFVARIABLE(result, VariableType::JS_POINTER(), GetObjectFromConstPool(constpool, ZExtInt16ToInt32(methodId))); Label isResolved(env); Label notResolved(env); Label defaultLabel(env); Branch(FunctionIsResolved(*result), &isResolved, ¬Resolved); Bind(&isResolved); { result = CallRuntime(glue, RTSTUB_ID(DefineAsyncFunc), { *result }); Label isException(env); Label notException(env); Branch(TaggedIsException(*result), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); { SetConstantPoolToFunction(glue, *result, constpool); Jump(&defaultLabel); } } Bind(¬Resolved); { SetResolvedToFunction(glue, *result, Boolean(true)); Jump(&defaultLabel); } Bind(&defaultLabel); { GateRef hClass = LoadHClass(*result); SetPropertyInlinedProps(glue, *result, hClass, Int16BuildTaggedWithNoGC(length), Int32(JSFunction::LENGTH_INLINE_PROPERTY_INDEX), VariableType::INT64()); GateRef lexEnv = GetVregValue(sp, ZExtInt8ToPtr(v0)); SetLexicalEnvToFunction(glue, *result, lexEnv); GateRef currentFunc = GetFunctionFromFrame(GetFrame(sp)); SetModuleToFunction(glue, *result, GetModuleFromFunction(currentFunc)); varAcc = *result; DISPATCH_WITH_ACC(PREF_ID16_IMM16_V8); } } DECLARE_ASM_HANDLER(HandleDefineMethodPrefId16Imm16V8) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); auto env = GetEnvironment(); GateRef methodId = ReadInst16_1(pc); GateRef length = ReadInst16_3(pc); GateRef v0 = ReadInst8_5(pc); DEFVARIABLE(result, VariableType::JS_POINTER(), GetObjectFromConstPool(constpool, ZExtInt16ToInt32(methodId))); Label isResolved(env); Label notResolved(env); Label defaultLabel(env); Branch(FunctionIsResolved(*result), &isResolved, ¬Resolved); Bind(&isResolved); { result = CallRuntime(glue, RTSTUB_ID(DefineMethod), { *result, acc }); Label isException(env); Label notException(env); Branch(TaggedIsException(*result), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); { SetConstantPoolToFunction(glue, *result, constpool); Jump(&defaultLabel); } } Bind(¬Resolved); { SetHomeObjectToFunction(glue, *result, acc); SetResolvedToFunction(glue, *result, Boolean(true)); Jump(&defaultLabel); } Bind(&defaultLabel); { GateRef hClass = LoadHClass(*result); SetPropertyInlinedProps(glue, *result, hClass, Int16BuildTaggedWithNoGC(length), Int32(JSFunction::LENGTH_INLINE_PROPERTY_INDEX), VariableType::INT64()); GateRef lexEnv = GetVregValue(sp, ZExtInt8ToPtr(v0)); SetLexicalEnvToFunction(glue, *result, lexEnv); GateRef currentFunc = GetFunctionFromFrame(GetFrame(sp)); SetModuleToFunction(glue, *result, GetModuleFromFunction(currentFunc)); varAcc = *result; DISPATCH_WITH_ACC(PREF_ID16_IMM16_V8); } } DECLARE_ASM_HANDLER(HandleCallSpreadDynPrefV8V8V8) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); auto env = GetEnvironment(); GateRef func = GetVregValue(sp, ZExtInt8ToPtr(ReadInst8_1(pc))); GateRef obj = GetVregValue(sp, ZExtInt8ToPtr(ReadInst8_2(pc))); GateRef array = GetVregValue(sp, ZExtInt8ToPtr(ReadInst8_3(pc))); GateRef res = CallRuntime(glue, RTSTUB_ID(CallSpreadDyn), { func, obj, array }); Label isException(env); Label notException(env); Branch(TaggedIsException(res), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); { varAcc = res; DISPATCH_WITH_ACC(PREF_V8_V8_V8); } } DECLARE_ASM_HANDLER(HandleAsyncFunctionResolvePrefV8V8V8) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); auto env = GetEnvironment(); GateRef asyncFuncObj = GetVregValue(sp, ZExtInt8ToPtr(ReadInst8_1(pc))); GateRef value = GetVregValue(sp, ZExtInt8ToPtr(ReadInst8_3(pc))); GateRef res = CallRuntime(glue, RTSTUB_ID(AsyncFunctionResolveOrReject), { asyncFuncObj, value, TaggedTrue() }); Label isException(env); Label notException(env); Branch(TaggedIsException(res), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); { varAcc = res; DISPATCH_WITH_ACC(PREF_V8_V8_V8); } } DECLARE_ASM_HANDLER(HandleAsyncFunctionRejectPrefV8V8V8) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); auto env = GetEnvironment(); GateRef asyncFuncObj = GetVregValue(sp, ZExtInt8ToPtr(ReadInst8_1(pc))); GateRef value = GetVregValue(sp, ZExtInt8ToPtr(ReadInst8_3(pc))); GateRef res = CallRuntime(glue, RTSTUB_ID(AsyncFunctionResolveOrReject), { asyncFuncObj, value, TaggedFalse() }); Label isException(env); Label notException(env); Branch(TaggedIsException(res), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); { varAcc = res; DISPATCH_WITH_ACC(PREF_V8_V8_V8); } } DECLARE_ASM_HANDLER(HandleDefineGetterSetterByValuePrefV8V8V8V8) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); auto env = GetEnvironment(); GateRef obj = GetVregValue(sp, ZExtInt8ToPtr(ReadInst8_1(pc))); GateRef prop = GetVregValue(sp, ZExtInt8ToPtr(ReadInst8_2(pc))); GateRef getter = GetVregValue(sp, ZExtInt8ToPtr(ReadInst8_3(pc))); GateRef setter = GetVregValue(sp, ZExtInt8ToPtr(ReadInst8_4(pc))); GateRef res = CallRuntime(glue, RTSTUB_ID(DefineGetterSetterByValue), { obj, prop, getter, setter, acc }); // acc is flag Label isException(env); Label notException(env); Branch(TaggedIsException(res), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); { varAcc = res; DISPATCH_WITH_ACC(PREF_V8_V8_V8_V8); } } DECLARE_ASM_HANDLER(HandleSuperCallPrefImm16V8) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); auto env = GetEnvironment(); GateRef range = ReadInst16_1(pc); GateRef v0 = ZExtInt8ToInt16(ReadInst8_3(pc)); // acc is thisFunc GateRef res = CallRuntime(glue, RTSTUB_ID(SuperCall), { acc, Int16BuildTaggedTypeWithNoGC(v0), Int16BuildTaggedTypeWithNoGC(range) }); Label isException(env); Label notException(env); Branch(TaggedIsException(res), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); { varAcc = res; DISPATCH_WITH_ACC(PREF_IMM16_V8); } } DECLARE_ASM_HANDLER(HandleGetPropIteratorPref) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); auto env = GetEnvironment(); GateRef res = CallRuntime(glue, RTSTUB_ID(GetPropIterator), { *varAcc }); Label isException(env); Label notException(env); Branch(TaggedIsException(res), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST_WITH_ACC(); } Bind(¬Exception); varAcc = res; DISPATCH_WITH_ACC(PREF_NONE); } DECLARE_ASM_HANDLER(HandleAsyncFunctionEnterPref) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); auto env = GetEnvironment(); GateRef res = CallRuntime(glue, RTSTUB_ID(AsyncFunctionEnter), {}); Label isException(env); Label notException(env); Branch(TaggedIsException(res), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST_WITH_ACC(); } Bind(¬Exception); varAcc = res; DISPATCH_WITH_ACC(PREF_NONE); } DECLARE_ASM_HANDLER(HandleLdHolePref) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); varAcc = Hole(); DISPATCH_WITH_ACC(PREF_NONE); } DECLARE_ASM_HANDLER(HandleCreateEmptyObjectPref) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef res = CallRuntime(glue, RTSTUB_ID(CreateEmptyObject), {}); varAcc = res; DISPATCH_WITH_ACC(PREF_NONE); } DECLARE_ASM_HANDLER(HandleCreateEmptyArrayPref) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef res = CallRuntime(glue, RTSTUB_ID(CreateEmptyArray), {}); varAcc = res; DISPATCH_WITH_ACC(PREF_NONE); } DECLARE_ASM_HANDLER(HandleGetIteratorPref) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); auto env = GetEnvironment(); Label isGeneratorObj(env); Label notGeneratorObj(env); Label dispatch(env); Branch(TaggedIsGeneratorObject(*varAcc), &isGeneratorObj, ¬GeneratorObj); Bind(&isGeneratorObj); { Jump(&dispatch); } Bind(¬GeneratorObj); { GateRef res = CallRuntime(glue, RTSTUB_ID(GetIterator), { *varAcc }); Label isException(env); Label notException(env); Branch(TaggedIsException(res), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST_WITH_ACC(); } Bind(¬Exception); varAcc = res; Jump(&dispatch); } Bind(&dispatch); DISPATCH_WITH_ACC(PREF_NONE); } DECLARE_ASM_HANDLER(HandleThrowThrowNotExistsPref) { CallRuntime(glue, RTSTUB_ID(ThrowThrowNotExists), {}); DISPATCH_LAST(); } DECLARE_ASM_HANDLER(HandleThrowPatternNonCoerciblePref) { CallRuntime(glue, RTSTUB_ID(ThrowPatternNonCoercible), {}); DISPATCH_LAST(); } DECLARE_ASM_HANDLER(HandleLdHomeObjectPref) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef thisFunc = GetFunctionFromFrame(GetFrame(sp)); varAcc = GetHomeObjectFromJSFunction(thisFunc); DISPATCH_WITH_ACC(PREF_NONE); } DECLARE_ASM_HANDLER(HandleThrowDeleteSuperPropertyPref) { CallRuntime(glue, RTSTUB_ID(ThrowDeleteSuperProperty), {}); DISPATCH_LAST(); } DECLARE_ASM_HANDLER(HandleDebuggerPref) { DISPATCH(PREF_NONE); } DECLARE_ASM_HANDLER(HandleMul2DynPrefV8) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef left = GetVregValue(sp, ZExtInt8ToPtr(ReadInst8_1(pc))); DEFVARIABLE(result, VariableType::JS_ANY(), Hole()); // fast path result = FastMul(left, acc); Label isHole(env); Label notHole(env); Label dispatch(env); Branch(TaggedIsHole(*result), &isHole, ¬Hole); Bind(&isHole); { // slow path result = CallRuntime(glue, RTSTUB_ID(Mul2Dyn), { left, acc }); Label isException(env); Label notException(env); Branch(TaggedIsException(*result), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); { varAcc = *result; Jump(&dispatch); } } Bind(¬Hole); { varAcc = *result; Jump(&dispatch); } Bind(&dispatch); DISPATCH_WITH_ACC(PREF_V8); } DECLARE_ASM_HANDLER(HandleDiv2DynPrefV8) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef left = GetVregValue(sp, ZExtInt8ToPtr(ReadInst8_1(pc))); DEFVARIABLE(result, VariableType::JS_ANY(), Hole()); // fast path result = FastDiv(left, acc); Label isHole(env); Label notHole(env); Label dispatch(env); Branch(TaggedIsHole(*result), &isHole, ¬Hole); Bind(&isHole); { // slow path result = CallRuntime(glue, RTSTUB_ID(Div2Dyn), { left, acc }); Label isException(env); Label notException(env); Branch(TaggedIsException(*result), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); { varAcc = *result; Jump(&dispatch); } } Bind(¬Hole); { varAcc = *result; Jump(&dispatch); } Bind(&dispatch); DISPATCH_WITH_ACC(PREF_V8); } DECLARE_ASM_HANDLER(HandleMod2DynPrefV8) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef left = GetVregValue(sp, ZExtInt8ToPtr(ReadInst8_1(pc))); DEFVARIABLE(result, VariableType::JS_ANY(), Hole()); // fast path result = FastMod(glue, left, acc); Label isHole(env); Label notHole(env); Label dispatch(env); Branch(TaggedIsHole(*result), &isHole, ¬Hole); Bind(&isHole); { // slow path result = CallRuntime(glue, RTSTUB_ID(Mod2Dyn), { left, acc }); Label isException(env); Label notException(env); Branch(TaggedIsException(*result), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); { varAcc = *result; Jump(&dispatch); } } Bind(¬Hole); { varAcc = *result; Jump(&dispatch); } Bind(&dispatch); DISPATCH_WITH_ACC(PREF_V8); } DECLARE_ASM_HANDLER(HandleEqDynPrefV8) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef left = GetVregValue(sp, ZExtInt8ToPtr(ReadInst8_1(pc))); // fast path DEFVARIABLE(result, VariableType::JS_ANY(), Hole()); result = FastEqual(left, acc); Label isHole(env); Label notHole(env); Label dispatch(env); Branch(TaggedIsHole(*result), &isHole, ¬Hole); Bind(&isHole); { // slow path result = CallRuntime(glue, RTSTUB_ID(EqDyn), { left, acc }); Label isException(env); Label notException(env); Branch(TaggedIsException(*result), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); { varAcc = *result; Jump(&dispatch); } } Bind(¬Hole); { varAcc = *result; Jump(&dispatch); } Bind(&dispatch); DISPATCH_WITH_ACC(PREF_V8); } DECLARE_ASM_HANDLER(HandleNotEqDynPrefV8) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef left = GetVregValue(sp, ZExtInt8ToPtr(ReadInst8_1(pc))); // fast path DEFVARIABLE(result, VariableType::JS_ANY(), Hole()); result = FastEqual(left, acc); Label isHole(env); Label notHole(env); Label dispatch(env); Branch(TaggedIsHole(*result), &isHole, ¬Hole); Bind(&isHole); { // slow path result = CallRuntime(glue, RTSTUB_ID(NotEqDyn), { left, acc }); Label isException(env); Label notException(env); Branch(TaggedIsException(*result), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); { varAcc = *result; Jump(&dispatch); } } Bind(¬Hole); { Label resultIsTrue(env); Label resultNotTrue(env); Branch(TaggedIsTrue(*result), &resultIsTrue, &resultNotTrue); Bind(&resultIsTrue); { varAcc = ChangeInt64ToTagged(TaggedFalse()); Jump(&dispatch); } Bind(&resultNotTrue); { varAcc = ChangeInt64ToTagged(TaggedTrue()); Jump(&dispatch); } } Bind(&dispatch); DISPATCH_WITH_ACC(PREF_V8); } DECLARE_ASM_HANDLER(HandleLessDynPrefV8) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef left = GetVregValue(sp, ZExtInt8ToPtr(ReadInst8_1(pc))); GateRef right = acc; Label leftIsInt(env); Label leftOrRightNotInt(env); Label leftLessRight(env); Label leftNotLessRight(env); Label slowPath(env); Label dispatch(env); Branch(TaggedIsInt(left), &leftIsInt, &leftOrRightNotInt); Bind(&leftIsInt); { Label rightIsInt(env); Branch(TaggedIsInt(right), &rightIsInt, &leftOrRightNotInt); Bind(&rightIsInt); { GateRef intLeft = TaggedGetInt(left); GateRef intRight = TaggedGetInt(right); Branch(Int32LessThan(intLeft, intRight), &leftLessRight, &leftNotLessRight); } } Bind(&leftOrRightNotInt); { Label leftIsNumber(env); Branch(TaggedIsNumber(left), &leftIsNumber, &slowPath); Bind(&leftIsNumber); { Label rightIsNumber(env); Branch(TaggedIsNumber(right), &rightIsNumber, &slowPath); Bind(&rightIsNumber); { // fast path DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0)); DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0)); Label leftIsInt1(env); Label leftNotInt1(env); Label exit1(env); Label exit2(env); Label rightIsInt1(env); Label rightNotInt1(env); Branch(TaggedIsInt(left), &leftIsInt1, &leftNotInt1); Bind(&leftIsInt1); { doubleLeft = ChangeInt32ToFloat64(TaggedGetInt(left)); Jump(&exit1); } Bind(&leftNotInt1); { doubleLeft = TaggedCastToDouble(left); Jump(&exit1); } Bind(&exit1); { Branch(TaggedIsInt(right), &rightIsInt1, &rightNotInt1); } Bind(&rightIsInt1); { doubleRight = ChangeInt32ToFloat64(TaggedGetInt(right)); Jump(&exit2); } Bind(&rightNotInt1); { doubleRight = TaggedCastToDouble(right); Jump(&exit2); } Bind(&exit2); { Branch(DoubleLessThan(*doubleLeft, *doubleRight), &leftLessRight, &leftNotLessRight); } } } } Bind(&leftLessRight); { varAcc = ChangeInt64ToTagged(TaggedTrue()); Jump(&dispatch); } Bind(&leftNotLessRight); { varAcc = ChangeInt64ToTagged(TaggedFalse()); Jump(&dispatch); } Bind(&slowPath); { // slow path GateRef result = CallRuntime(glue, RTSTUB_ID(LessDyn), { left, acc }); Label isException(env); Label notException(env); Branch(TaggedIsException(result), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); { varAcc = result; Jump(&dispatch); } } Bind(&dispatch); DISPATCH_WITH_ACC(PREF_V8); } DECLARE_ASM_HANDLER(HandleLessEqDynPrefV8) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef left = GetVregValue(sp, ZExtInt8ToPtr(ReadInst8_1(pc))); GateRef right = acc; Label leftIsInt(env); Label leftOrRightNotInt(env); Label leftLessEqRight(env); Label leftNotLessEqRight(env); Label slowPath(env); Label dispatch(env); Branch(TaggedIsInt(left), &leftIsInt, &leftOrRightNotInt); Bind(&leftIsInt); { Label rightIsInt(env); Branch(TaggedIsInt(right), &rightIsInt, &leftOrRightNotInt); Bind(&rightIsInt); { GateRef intLeft = TaggedGetInt(left); GateRef intRight = TaggedGetInt(right); Branch(Int32LessThanOrEqual(intLeft, intRight), &leftLessEqRight, &leftNotLessEqRight); } } Bind(&leftOrRightNotInt); { Label leftIsNumber(env); Branch(TaggedIsNumber(left), &leftIsNumber, &slowPath); Bind(&leftIsNumber); { Label rightIsNumber(env); Branch(TaggedIsNumber(right), &rightIsNumber, &slowPath); Bind(&rightIsNumber); { // fast path DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0)); DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0)); Label leftIsInt1(env); Label leftNotInt1(env); Label exit1(env); Label exit2(env); Label rightIsInt1(env); Label rightNotInt1(env); Branch(TaggedIsInt(left), &leftIsInt1, &leftNotInt1); Bind(&leftIsInt1); { doubleLeft = ChangeInt32ToFloat64(TaggedGetInt(left)); Jump(&exit1); } Bind(&leftNotInt1); { doubleLeft = TaggedCastToDouble(left); Jump(&exit1); } Bind(&exit1); { Branch(TaggedIsInt(right), &rightIsInt1, &rightNotInt1); } Bind(&rightIsInt1); { doubleRight = ChangeInt32ToFloat64(TaggedGetInt(right)); Jump(&exit2); } Bind(&rightNotInt1); { doubleRight = TaggedCastToDouble(right); Jump(&exit2); } Bind(&exit2); { Branch(DoubleLessThanOrEqual(*doubleLeft, *doubleRight), &leftLessEqRight, &leftNotLessEqRight); } } } } Bind(&leftLessEqRight); { varAcc = ChangeInt64ToTagged(TaggedTrue()); Jump(&dispatch); } Bind(&leftNotLessEqRight); { varAcc = ChangeInt64ToTagged(TaggedFalse()); Jump(&dispatch); } Bind(&slowPath); { // slow path GateRef result = CallRuntime(glue, RTSTUB_ID(LessEqDyn), { left, acc }); Label isException(env); Label notException(env); Branch(TaggedIsException(result), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); { varAcc = result; Jump(&dispatch); } } Bind(&dispatch); DISPATCH_WITH_ACC(PREF_V8); } DECLARE_ASM_HANDLER(HandleGreaterDynPrefV8) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef left = GetVregValue(sp, ZExtInt8ToPtr(ReadInst8_1(pc))); GateRef right = acc; Label leftIsInt(env); Label leftOrRightNotInt(env); Label leftGreaterRight(env); Label leftNotGreaterRight(env); Label slowPath(env); Label dispatch(env); Branch(TaggedIsInt(left), &leftIsInt, &leftOrRightNotInt); Bind(&leftIsInt); { Label rightIsInt(env); Branch(TaggedIsInt(right), &rightIsInt, &leftOrRightNotInt); Bind(&rightIsInt); { GateRef intLeft = TaggedGetInt(left); GateRef intRight = TaggedGetInt(right); Branch(Int32GreaterThan(intLeft, intRight), &leftGreaterRight, &leftNotGreaterRight); } } Bind(&leftOrRightNotInt); { Label leftIsNumber(env); Branch(TaggedIsNumber(left), &leftIsNumber, &slowPath); Bind(&leftIsNumber); { Label rightIsNumber(env); Branch(TaggedIsNumber(right), &rightIsNumber, &slowPath); Bind(&rightIsNumber); { // fast path DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0)); DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0)); Label leftIsInt1(env); Label leftNotInt1(env); Label exit1(env); Label exit2(env); Label rightIsInt1(env); Label rightNotInt1(env); Branch(TaggedIsInt(left), &leftIsInt1, &leftNotInt1); Bind(&leftIsInt1); { doubleLeft = ChangeInt32ToFloat64(TaggedGetInt(left)); Jump(&exit1); } Bind(&leftNotInt1); { doubleLeft = TaggedCastToDouble(left); Jump(&exit1); } Bind(&exit1); { Branch(TaggedIsInt(right), &rightIsInt1, &rightNotInt1); } Bind(&rightIsInt1); { doubleRight = ChangeInt32ToFloat64(TaggedGetInt(right)); Jump(&exit2); } Bind(&rightNotInt1); { doubleRight = TaggedCastToDouble(right); Jump(&exit2); } Bind(&exit2); { Branch(DoubleGreaterThan(*doubleLeft, *doubleRight), &leftGreaterRight, &leftNotGreaterRight); } } } } Bind(&leftGreaterRight); { varAcc = ChangeInt64ToTagged(TaggedTrue()); Jump(&dispatch); } Bind(&leftNotGreaterRight); { varAcc = ChangeInt64ToTagged(TaggedFalse()); Jump(&dispatch); } Bind(&slowPath); { // slow path GateRef result = CallRuntime(glue, RTSTUB_ID(GreaterDyn), { left, acc }); Label isException(env); Label notException(env); Branch(TaggedIsException(result), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); { varAcc = result; Jump(&dispatch); } } Bind(&dispatch); DISPATCH_WITH_ACC(PREF_V8); } DECLARE_ASM_HANDLER(HandleGreaterEqDynPrefV8) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef left = GetVregValue(sp, ZExtInt8ToPtr(ReadInst8_1(pc))); GateRef right = acc; Label leftIsInt(env); Label leftOrRightNotInt(env); Label leftGreaterEqRight(env); Label leftNotGreaterEQRight(env); Label slowPath(env); Label dispatch(env); Branch(TaggedIsInt(left), &leftIsInt, &leftOrRightNotInt); Bind(&leftIsInt); { Label rightIsInt(env); Branch(TaggedIsInt(right), &rightIsInt, &leftOrRightNotInt); Bind(&rightIsInt); { GateRef intLeft = TaggedGetInt(left); GateRef intRight = TaggedGetInt(right); Branch(Int32GreaterThanOrEqual(intLeft, intRight), &leftGreaterEqRight, &leftNotGreaterEQRight); } } Bind(&leftOrRightNotInt); { Label leftIsNumber(env); Branch(TaggedIsNumber(left), &leftIsNumber, &slowPath); Bind(&leftIsNumber); { Label rightIsNumber(env); Branch(TaggedIsNumber(right), &rightIsNumber, &slowPath); Bind(&rightIsNumber); { // fast path DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0)); DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0)); Label leftIsInt1(env); Label leftNotInt1(env); Label exit1(env); Label exit2(env); Label rightIsInt1(env); Label rightNotInt1(env); Branch(TaggedIsInt(left), &leftIsInt1, &leftNotInt1); Bind(&leftIsInt1); { doubleLeft = ChangeInt32ToFloat64(TaggedGetInt(left)); Jump(&exit1); } Bind(&leftNotInt1); { doubleLeft = TaggedCastToDouble(left); Jump(&exit1); } Bind(&exit1); { Branch(TaggedIsInt(right), &rightIsInt1, &rightNotInt1); } Bind(&rightIsInt1); { doubleRight = ChangeInt32ToFloat64(TaggedGetInt(right)); Jump(&exit2); } Bind(&rightNotInt1); { doubleRight = TaggedCastToDouble(right); Jump(&exit2); } Bind(&exit2); { Branch(DoubleGreaterThanOrEqual(*doubleLeft, *doubleRight), &leftGreaterEqRight, &leftNotGreaterEQRight); } } } } Bind(&leftGreaterEqRight); { varAcc = ChangeInt64ToTagged(TaggedTrue()); Jump(&dispatch); } Bind(&leftNotGreaterEQRight); { varAcc = ChangeInt64ToTagged(TaggedFalse()); Jump(&dispatch); } Bind(&slowPath); { // slow path GateRef result = CallRuntime(glue, RTSTUB_ID(GreaterEqDyn), { left, acc }); Label isException(env); Label notException(env); Branch(TaggedIsException(result), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); { varAcc = result; Jump(&dispatch); } } Bind(&dispatch); DISPATCH_WITH_ACC(PREF_V8); } DECLARE_ASM_HANDLER(SingleStepDebugging) { auto env = GetEnvironment(); DEFVARIABLE(varPc, VariableType::NATIVE_POINTER(), pc); DEFVARIABLE(varSp, VariableType::NATIVE_POINTER(), sp); DEFVARIABLE(varConstpool, VariableType::JS_POINTER(), constpool); DEFVARIABLE(varProfileTypeInfo, VariableType::JS_POINTER(), profileTypeInfo); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); DEFVARIABLE(varHotnessCounter, VariableType::INT32(), hotnessCounter); varPc = TaggedCastToIntPtr(CallRuntime(glue, RTSTUB_ID(JumpToCInterpreter), { constpool, profileTypeInfo, acc, IntBuildTaggedTypeWithNoGC(hotnessCounter)})); Label shouldReturn(env); Label shouldContinue(env); Branch(IntPtrEqual(*varPc, IntPtr(0)), &shouldReturn, &shouldContinue); Bind(&shouldReturn); { if (env->IsAArch64()) { CallNGCRuntime(glue, RTSTUB_ID(ResumeRspAndReturn), {}); } Return(); } Bind(&shouldContinue); { varSp = GetCurrentSpFrame(glue); GateRef frame = GetFrame(*varSp); varAcc = GetAccFromFrame(frame); GateRef function = GetFunctionFromFrame(frame); varProfileTypeInfo = GetProfileTypeInfoFromFunction(function); varConstpool = GetConstpoolFromFunction(function); GateRef method = Load(VariableType::NATIVE_POINTER(), function, IntPtr(JSFunctionBase::METHOD_OFFSET)); varHotnessCounter = GetHotnessCounterFromMethod(method); } Dispatch(glue, *varSp, *varPc, *varConstpool, *varProfileTypeInfo, *varAcc, *varHotnessCounter, IntPtr(0)); } DECLARE_ASM_HANDLER(BCDebuggerEntry) { GateRef frame = GetFrame(sp); SetPcToFrame(glue, frame, pc); // NOTIFY_DEBUGGER_EVENT() CallRuntime(glue, RTSTUB_ID(NotifyBytecodePcChanged), {}); // goto normal handle stub DispatchDebugger(glue, sp, pc, constpool, profileTypeInfo, acc, hotnessCounter); } DECLARE_ASM_HANDLER(BCDebuggerExceptionEntry) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); varAcc = Hole(); GateRef frame = GetFrame(sp); SetPcToFrame(glue, frame, pc); // NOTIFY_DEBUGGER_EVENT() CallRuntime(glue, RTSTUB_ID(NotifyBytecodePcChanged), {}); // goto last handle stub DispatchDebuggerLast(glue, sp, pc, constpool, profileTypeInfo, *varAcc, hotnessCounter); } DECLARE_ASM_HANDLER(HandleOverflow) { FatalPrint(glue, { Int32(GET_MESSAGE_STRING_ID(OPCODE_OVERFLOW)) }); Dispatch(glue, sp, pc, constpool, profileTypeInfo, acc, hotnessCounter, IntPtr(0)); } DECLARE_ASM_HANDLER(HandleLdaDynV8) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef vsrc = ReadInst8_0(pc); varAcc = GetVregValue(sp, ZExtInt8ToPtr(vsrc)); DISPATCH_WITH_ACC(V8); } DECLARE_ASM_HANDLER(HandleStaDynV8) { GateRef vdst = ReadInst8_0(pc); SetVregValue(glue, sp, ZExtInt8ToPtr(vdst), acc); DISPATCH(V8); } DECLARE_ASM_HANDLER(HandleJmpImm8) { auto env = GetEnvironment(); DEFVARIABLE(varProfileTypeInfo, VariableType::JS_POINTER(), profileTypeInfo); DEFVARIABLE(varHotnessCounter, VariableType::INT32(), hotnessCounter); GateRef offset = ReadInstSigned8_0(pc); Label dispatch(env); Label slowPath(env); UPDATE_HOTNESS(sp); Dispatch(glue, sp, pc, constpool, *varProfileTypeInfo, acc, *varHotnessCounter, SExtInt32ToPtr(offset)); } DECLARE_ASM_HANDLER(HandleJmpImm16) { auto env = GetEnvironment(); DEFVARIABLE(varProfileTypeInfo, VariableType::JS_POINTER(), profileTypeInfo); DEFVARIABLE(varHotnessCounter, VariableType::INT32(), hotnessCounter); GateRef offset = ReadInstSigned16_0(pc); Label dispatch(env); Label slowPath(env); UPDATE_HOTNESS(sp); Dispatch(glue, sp, pc, constpool, *varProfileTypeInfo, acc, *varHotnessCounter, SExtInt32ToPtr(offset)); } DECLARE_ASM_HANDLER(HandleJmpImm32) { auto env = GetEnvironment(); DEFVARIABLE(varProfileTypeInfo, VariableType::JS_POINTER(), profileTypeInfo); DEFVARIABLE(varHotnessCounter, VariableType::INT32(), hotnessCounter); GateRef offset = ReadInstSigned32_0(pc); Label dispatch(env); Label slowPath(env); UPDATE_HOTNESS(sp); Dispatch(glue, sp, pc, constpool, *varProfileTypeInfo, acc, *varHotnessCounter, SExtInt32ToPtr(offset)); } DECLARE_ASM_HANDLER(HandleLdLexVarDynPrefImm4Imm4) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef level = ZExtInt8ToInt32(ReadInst4_2(pc)); GateRef slot = ZExtInt8ToInt32(ReadInst4_3(pc)); GateRef state = GetFrame(sp); DEFVARIABLE(currentEnv, VariableType::JS_ANY(), GetEnvFromFrame(state)); DEFVARIABLE(i, VariableType::INT32(), Int32(0)); Label loopHead(env); Label loopEnd(env); Label afterLoop(env); Branch(Int32LessThan(*i, level), &loopHead, &afterLoop); LoopBegin(&loopHead); currentEnv = GetParentEnv(*currentEnv); i = Int32Add(*i, Int32(1)); Branch(Int32LessThan(*i, level), &loopEnd, &afterLoop); Bind(&loopEnd); LoopEnd(&loopHead); Bind(&afterLoop); GateRef variable = GetPropertiesFromLexicalEnv(*currentEnv, slot); varAcc = variable; DISPATCH_WITH_ACC(PREF_IMM4_IMM4); } DECLARE_ASM_HANDLER(HandleLdLexVarDynPrefImm8Imm8) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef level = ZExtInt8ToInt32(ReadInst8_1(pc)); GateRef slot = ZExtInt8ToInt32(ReadInst8_2(pc)); GateRef state = GetFrame(sp); DEFVARIABLE(currentEnv, VariableType::JS_ANY(), GetEnvFromFrame(state)); DEFVARIABLE(i, VariableType::INT32(), Int32(0)); Label loopHead(env); Label loopEnd(env); Label afterLoop(env); Branch(Int32LessThan(*i, level), &loopHead, &afterLoop); LoopBegin(&loopHead); currentEnv = GetParentEnv(*currentEnv); i = Int32Add(*i, Int32(1)); Branch(Int32LessThan(*i, level), &loopEnd, &afterLoop); Bind(&loopEnd); LoopEnd(&loopHead); Bind(&afterLoop); GateRef variable = GetPropertiesFromLexicalEnv(*currentEnv, slot); varAcc = variable; DISPATCH_WITH_ACC(PREF_IMM8_IMM8); } DECLARE_ASM_HANDLER(HandleLdLexVarDynPrefImm16Imm16) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef level = ZExtInt16ToInt32(ReadInst16_1(pc)); GateRef slot = ZExtInt16ToInt32(ReadInst16_3(pc)); GateRef state = GetFrame(sp); DEFVARIABLE(currentEnv, VariableType::JS_ANY(), GetEnvFromFrame(state)); DEFVARIABLE(i, VariableType::INT32(), Int32(0)); Label loopHead(env); Label loopEnd(env); Label afterLoop(env); Branch(Int32LessThan(*i, level), &loopHead, &afterLoop); LoopBegin(&loopHead); currentEnv = GetParentEnv(*currentEnv); i = Int32Add(*i, Int32(1)); Branch(Int32LessThan(*i, level), &loopEnd, &afterLoop); Bind(&loopEnd); LoopEnd(&loopHead); Bind(&afterLoop); GateRef variable = GetPropertiesFromLexicalEnv(*currentEnv, slot); varAcc = variable; DISPATCH_WITH_ACC(PREF_IMM16_IMM16); } DECLARE_ASM_HANDLER(HandleStLexVarDynPrefImm4Imm4V8) { auto env = GetEnvironment(); GateRef level = ZExtInt8ToInt32(ReadInst4_2(pc)); GateRef slot = ZExtInt8ToInt32(ReadInst4_3(pc)); GateRef v0 = ReadInst8_2(pc); GateRef value = GetVregValue(sp, ZExtInt8ToPtr(v0)); GateRef state = GetFrame(sp); DEFVARIABLE(currentEnv, VariableType::JS_ANY(), GetEnvFromFrame(state)); DEFVARIABLE(i, VariableType::INT32(), Int32(0)); Label loopHead(env); Label loopEnd(env); Label afterLoop(env); Branch(Int32LessThan(*i, level), &loopHead, &afterLoop); LoopBegin(&loopHead); currentEnv = GetParentEnv(*currentEnv); i = Int32Add(*i, Int32(1)); Branch(Int32LessThan(*i, level), &loopEnd, &afterLoop); Bind(&loopEnd); LoopEnd(&loopHead); Bind(&afterLoop); SetPropertiesToLexicalEnv(glue, *currentEnv, slot, value); DISPATCH(PREF_IMM4_IMM4_V8); } DECLARE_ASM_HANDLER(HandleStLexVarDynPrefImm8Imm8V8) { auto env = GetEnvironment(); GateRef level = ZExtInt8ToInt32(ReadInst8_1(pc)); GateRef slot = ZExtInt8ToInt32(ReadInst8_2(pc)); GateRef v0 = ReadInst8_3(pc); GateRef value = GetVregValue(sp, ZExtInt8ToPtr(v0)); GateRef state = GetFrame(sp); DEFVARIABLE(currentEnv, VariableType::JS_ANY(), GetEnvFromFrame(state)); DEFVARIABLE(i, VariableType::INT32(), Int32(0)); Label loopHead(env); Label loopEnd(env); Label afterLoop(env); Branch(Int32LessThan(*i, level), &loopHead, &afterLoop); LoopBegin(&loopHead); currentEnv = GetParentEnv(*currentEnv); i = Int32Add(*i, Int32(1)); Branch(Int32LessThan(*i, level), &loopEnd, &afterLoop); Bind(&loopEnd); LoopEnd(&loopHead); Bind(&afterLoop); SetPropertiesToLexicalEnv(glue, *currentEnv, slot, value); DISPATCH(PREF_IMM8_IMM8_V8); } DECLARE_ASM_HANDLER(HandleStLexVarDynPrefImm16Imm16V8) { auto env = GetEnvironment(); GateRef level = ZExtInt16ToInt32(ReadInst16_1(pc)); GateRef slot = ZExtInt16ToInt32(ReadInst16_3(pc)); GateRef v0 = ReadInst8_5(pc); GateRef value = GetVregValue(sp, ZExtInt8ToPtr(v0)); GateRef state = GetFrame(sp); DEFVARIABLE(currentEnv, VariableType::JS_ANY(), GetEnvFromFrame(state)); DEFVARIABLE(i, VariableType::INT32(), Int32(0)); Label loopHead(env); Label loopEnd(env); Label afterLoop(env); Branch(Int32LessThan(*i, level), &loopHead, &afterLoop); LoopBegin(&loopHead); currentEnv = GetParentEnv(*currentEnv); i = Int32Add(*i, Int32(1)); Branch(Int32LessThan(*i, level), &loopEnd, &afterLoop); Bind(&loopEnd); LoopEnd(&loopHead); Bind(&afterLoop); SetPropertiesToLexicalEnv(glue, *currentEnv, slot, value); DISPATCH(PREF_IMM16_IMM16_V8); } DECLARE_ASM_HANDLER(HandleIncDynPrefV8) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef v0 = ReadInst8_1(pc); GateRef value = GetVregValue(sp, ZExtInt8ToPtr(v0)); Label valueIsInt(env); Label valueNotInt(env); Label slowPath(env); Label accDispatch(env); Branch(TaggedIsInt(value), &valueIsInt, &valueNotInt); Bind(&valueIsInt); { GateRef valueInt = TaggedCastToInt32(value); Label valueNoOverflow(env); Branch(Int32Equal(valueInt, Int32(INT32_MAX)), &valueNotInt, &valueNoOverflow); Bind(&valueNoOverflow); { varAcc = IntBuildTaggedWithNoGC(Int32Add(valueInt, Int32(1))); Jump(&accDispatch); } } Bind(&valueNotInt); if (!env->IsAmd64()) { Label valueIsDouble(env); Label valueNotDouble(env); Branch(TaggedIsDouble(value), &valueIsDouble, &valueNotDouble); Bind(&valueIsDouble); { GateRef valueDouble = TaggedCastToDouble(value); varAcc = DoubleBuildTaggedWithNoGC(DoubleAdd(valueDouble, Double(1.0))); Jump(&accDispatch); } Bind(&valueNotDouble); Jump(&slowPath); } else { Jump(&slowPath); } Bind(&slowPath); { // slow path GateRef result = CallRuntime(glue, RTSTUB_ID(IncDyn), { value }); Label isException(env); Label notException(env); Branch(TaggedIsException(result), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); varAcc = result; Jump(&accDispatch); } Bind(&accDispatch); DISPATCH_WITH_ACC(PREF_V8); } DECLARE_ASM_HANDLER(HandleDecDynPrefV8) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef v0 = ReadInst8_1(pc); GateRef value = GetVregValue(sp, ZExtInt8ToPtr(v0)); Label valueIsInt(env); Label valueNotInt(env); Label slowPath(env); Label accDispatch(env); Branch(TaggedIsInt(value), &valueIsInt, &valueNotInt); Bind(&valueIsInt); { GateRef valueInt = TaggedCastToInt32(value); Label valueNoOverflow(env); Branch(Int32Equal(valueInt, Int32(INT32_MIN)), &valueNotInt, &valueNoOverflow); Bind(&valueNoOverflow); { varAcc = IntBuildTaggedWithNoGC(Int32Sub(valueInt, Int32(1))); Jump(&accDispatch); } } Bind(&valueNotInt); if (!env->IsAmd64()) { Label valueIsDouble(env); Label valueNotDouble(env); Branch(TaggedIsDouble(value), &valueIsDouble, &valueNotDouble); Bind(&valueIsDouble); { GateRef valueDouble = TaggedCastToDouble(value); varAcc = DoubleBuildTaggedWithNoGC(DoubleSub(valueDouble, Double(1.0))); Jump(&accDispatch); } Bind(&valueNotDouble); Jump(&slowPath); } else { Jump(&slowPath); } Bind(&slowPath); { // slow path GateRef result = CallRuntime(glue, RTSTUB_ID(DecDyn), { value }); Label isException(env); Label notException(env); Branch(TaggedIsException(result), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); varAcc = result; Jump(&accDispatch); } Bind(&accDispatch); DISPATCH_WITH_ACC(PREF_V8); } DECLARE_ASM_HANDLER(HandleExpDynPrefV8) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef v0 = ReadInst8_1(pc); GateRef base = GetVregValue(sp, ZExtInt8ToPtr(v0)); GateRef result = CallRuntime(glue, RTSTUB_ID(ExpDyn), { base, acc }); Label isException(env); Label notException(env); Branch(TaggedIsException(result), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); varAcc = result; DISPATCH_WITH_ACC(PREF_V8); } DECLARE_ASM_HANDLER(HandleIsInDynPrefV8) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef v0 = ReadInst8_1(pc); GateRef prop = GetVregValue(sp, ZExtInt8ToPtr(v0)); GateRef result = CallRuntime(glue, RTSTUB_ID(IsInDyn), { prop, acc }); // acc is obj Label isException(env); Label notException(env); Branch(TaggedIsException(result), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); varAcc = result; DISPATCH_WITH_ACC(PREF_V8); } DECLARE_ASM_HANDLER(HandleInstanceOfDynPrefV8) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef v0 = ReadInst8_1(pc); GateRef obj = GetVregValue(sp, ZExtInt8ToPtr(v0)); GateRef result = CallRuntime(glue, RTSTUB_ID(InstanceOfDyn), { obj, acc }); Label isException(env); Label notException(env); Branch(TaggedIsException(result), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); varAcc = result; DISPATCH_WITH_ACC(PREF_V8); } DECLARE_ASM_HANDLER(HandleStrictNotEqDynPrefV8) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef v0 = ReadInst8_1(pc); GateRef left = GetVregValue(sp, ZExtInt8ToPtr(v0)); Label strictEqual(env); Label notStrictEqual(env); Label dispatch(env); Branch(FastStrictEqual(glue, left, acc), &strictEqual, ¬StrictEqual); Bind(&strictEqual); { varAcc = ChangeInt64ToTagged(Int64(JSTaggedValue::VALUE_FALSE)); Jump(&dispatch); } Bind(¬StrictEqual); { varAcc = ChangeInt64ToTagged(Int64(JSTaggedValue::VALUE_TRUE)); Jump(&dispatch); } Bind(&dispatch); DISPATCH_WITH_ACC(PREF_V8); } DECLARE_ASM_HANDLER(HandleStrictEqDynPrefV8) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef v0 = ReadInst8_1(pc); GateRef left = GetVregValue(sp, ZExtInt8ToPtr(v0)); Label strictEqual(env); Label notStrictEqual(env); Label dispatch(env); Branch(FastStrictEqual(glue, left, acc), &strictEqual, ¬StrictEqual); Bind(&strictEqual); { varAcc = ChangeInt64ToTagged(Int64(JSTaggedValue::VALUE_TRUE)); Jump(&dispatch); } Bind(¬StrictEqual); { varAcc = ChangeInt64ToTagged(Int64(JSTaggedValue::VALUE_FALSE)); Jump(&dispatch); } Bind(&dispatch); DISPATCH_WITH_ACC(PREF_V8); } DECLARE_ASM_HANDLER(HandleResumeGeneratorPrefV8) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef vs = ReadInst8_1(pc); GateRef obj = GetVregValue(sp, ZExtInt8ToPtr(vs)); GateRef resumeResultOffset = IntPtr(JSGeneratorObject::GENERATOR_RESUME_RESULT_OFFSET); varAcc = Load(VariableType::JS_ANY(), obj, resumeResultOffset); DISPATCH_WITH_ACC(PREF_V8); } DECLARE_ASM_HANDLER(HandleGetResumeModePrefV8) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef vs = ReadInst8_1(pc); GateRef obj = GetVregValue(sp, ZExtInt8ToPtr(vs)); varAcc = IntBuildTaggedWithNoGC(GetResumeModeFromGeneratorObject(obj)); DISPATCH_WITH_ACC(PREF_V8); } DECLARE_ASM_HANDLER(HandleCreateGeneratorObjPrefV8) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef v0 = ReadInst8_1(pc); GateRef genFunc = GetVregValue(sp, ZExtInt8ToPtr(v0)); GateRef result = CallRuntime(glue, RTSTUB_ID(CreateGeneratorObj), { genFunc }); Label isException(env); Label notException(env); Branch(TaggedIsException(result), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); varAcc = result; DISPATCH_WITH_ACC(PREF_V8); } DECLARE_ASM_HANDLER(HandleThrowConstAssignmentPrefV8) { GateRef v0 = ReadInst8_1(pc); GateRef value = GetVregValue(sp, ZExtInt8ToPtr(v0)); CallRuntime(glue, RTSTUB_ID(ThrowConstAssignment), { value }); DISPATCH_LAST(); } DECLARE_ASM_HANDLER(HandleGetTemplateObjectPrefV8) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef v0 = ReadInst8_1(pc); GateRef literal = GetVregValue(sp, ZExtInt8ToPtr(v0)); GateRef result = CallRuntime(glue, RTSTUB_ID(GetTemplateObject), { literal }); Label isException(env); Label notException(env); Branch(TaggedIsException(result), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); varAcc = result; DISPATCH_WITH_ACC(PREF_V8); } DECLARE_ASM_HANDLER(HandleGetNextPropNamePrefV8) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef v0 = ReadInst8_1(pc); GateRef iter = GetVregValue(sp, ZExtInt8ToPtr(v0)); GateRef result = CallRuntime(glue, RTSTUB_ID(GetNextPropName), { iter }); Label isException(env); Label notException(env); Branch(TaggedIsException(result), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); varAcc = result; DISPATCH_WITH_ACC(PREF_V8); } DECLARE_ASM_HANDLER(HandleThrowIfNotObjectPrefV8) { auto env = GetEnvironment(); GateRef v0 = ReadInst8_1(pc); GateRef value = GetVregValue(sp, ZExtInt8ToPtr(v0)); Label isEcmaObject(env); Label notEcmaObject(env); Branch(IsEcmaObject(value), &isEcmaObject, ¬EcmaObject); Bind(&isEcmaObject); { DISPATCH(PREF_V8); } Bind(¬EcmaObject); CallRuntime(glue, RTSTUB_ID(ThrowIfNotObject), {}); DISPATCH_LAST(); } DECLARE_ASM_HANDLER(HandleIterNextPrefV8) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef v0 = ReadInst8_1(pc); GateRef iter = GetVregValue(sp, ZExtInt8ToPtr(v0)); GateRef result = CallRuntime(glue, RTSTUB_ID(IterNext), { iter }); Label isException(env); Label notException(env); Branch(TaggedIsException(result), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); varAcc = result; DISPATCH_WITH_ACC(PREF_V8); } DECLARE_ASM_HANDLER(HandleCloseIteratorPrefV8) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef v0 = ReadInst8_1(pc); GateRef iter = GetVregValue(sp, ZExtInt8ToPtr(v0)); GateRef result = CallRuntime(glue, RTSTUB_ID(CloseIterator), { iter }); Label isException(env); Label notException(env); Branch(TaggedIsException(result), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); varAcc = result; DISPATCH_WITH_ACC(PREF_V8); } DECLARE_ASM_HANDLER(HandleCopyModulePrefV8) { DISPATCH(PREF_V8); } DECLARE_ASM_HANDLER(HandleSuperCallSpreadPrefV8) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef v0 = ReadInst8_1(pc); GateRef array = GetVregValue(sp, ZExtInt8ToPtr(v0)); GateRef result = CallRuntime(glue, RTSTUB_ID(SuperCallSpread), { acc, array }); Label isException(env); Label notException(env); Branch(TaggedIsException(result), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); varAcc = result; DISPATCH_WITH_ACC(PREF_V8); } DECLARE_ASM_HANDLER(HandleDelObjPropPrefV8V8) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef v0 = ReadInst8_1(pc); GateRef v1 = ReadInst8_2(pc); GateRef obj = GetVregValue(sp, ZExtInt8ToPtr(v0)); GateRef prop = GetVregValue(sp, ZExtInt8ToPtr(v1)); GateRef result = CallRuntime(glue, RTSTUB_ID(DelObjProp), { obj, prop }); Label isException(env); Label notException(env); Branch(TaggedIsException(result), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); varAcc = result; DISPATCH_WITH_ACC(PREF_V8_V8); } DECLARE_ASM_HANDLER(HandleNewObjSpreadDynPrefV8V8) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef v0 = ReadInst8_1(pc); GateRef v1 = ReadInst8_2(pc); GateRef func = GetVregValue(sp, ZExtInt8ToPtr(v0)); GateRef newTarget = GetVregValue(sp, ZExtInt8ToPtr(v1)); GateRef result = CallRuntime(glue, RTSTUB_ID(NewObjSpreadDyn), { func, newTarget, acc }); // acc is array Label isException(env); Label notException(env); Branch(TaggedIsException(result), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); varAcc = result; DISPATCH_WITH_ACC(PREF_V8_V8); } DECLARE_ASM_HANDLER(HandleCreateIterResultObjPrefV8V8) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef v0 = ReadInst8_1(pc); GateRef v1 = ReadInst8_2(pc); GateRef value = GetVregValue(sp, ZExtInt8ToPtr(v0)); GateRef flag = GetVregValue(sp, ZExtInt8ToPtr(v1)); GateRef result = CallRuntime(glue, RTSTUB_ID(CreateIterResultObj), { value, flag }); Label isException(env); Label notException(env); Branch(TaggedIsException(result), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); varAcc = result; DISPATCH_WITH_ACC(PREF_V8_V8); } DECLARE_ASM_HANDLER(HandleAsyncFunctionAwaitUncaughtPrefV8V8) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef v0 = ReadInst8_1(pc); GateRef v1 = ReadInst8_2(pc); GateRef asyncFuncObj = GetVregValue(sp, ZExtInt8ToPtr(v0)); GateRef value = GetVregValue(sp, ZExtInt8ToPtr(v1)); GateRef result = CallRuntime(glue, RTSTUB_ID(AsyncFunctionAwaitUncaught), { asyncFuncObj, value }); Label isException(env); Label notException(env); Branch(TaggedIsException(result), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); varAcc = result; DISPATCH_WITH_ACC(PREF_V8_V8); } DECLARE_ASM_HANDLER(HandleThrowUndefinedIfHolePrefV8V8) { auto env = GetEnvironment(); GateRef v0 = ReadInst8_1(pc); GateRef v1 = ReadInst8_2(pc); GateRef hole = GetVregValue(sp, ZExtInt8ToPtr(v0)); Label isHole(env); Label notHole(env); Branch(TaggedIsHole(hole), &isHole, ¬Hole); Bind(¬Hole); { DISPATCH(PREF_V8_V8); } Bind(&isHole); GateRef obj = GetVregValue(sp, ZExtInt8ToPtr(v1)); // assert obj.IsString() CallRuntime(glue, RTSTUB_ID(ThrowUndefinedIfHole), { obj }); DISPATCH_LAST(); } DECLARE_ASM_HANDLER(HandleCopyDataPropertiesPrefV8V8) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef v0 = ReadInst8_1(pc); GateRef v1 = ReadInst8_2(pc); GateRef dst = GetVregValue(sp, ZExtInt8ToPtr(v0)); GateRef src = GetVregValue(sp, ZExtInt8ToPtr(v1)); GateRef result = CallRuntime(glue, RTSTUB_ID(CopyDataProperties), { dst, src }); Label isException(env); Label notException(env); Branch(TaggedIsException(result), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); varAcc = result; DISPATCH_WITH_ACC(PREF_V8_V8); } DECLARE_ASM_HANDLER(HandleStArraySpreadPrefV8V8) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef v0 = ReadInst8_1(pc); GateRef v1 = ReadInst8_2(pc); GateRef dst = GetVregValue(sp, ZExtInt8ToPtr(v0)); GateRef index = GetVregValue(sp, ZExtInt8ToPtr(v1)); GateRef result = CallRuntime(glue, RTSTUB_ID(StArraySpread), { dst, index, acc }); // acc is res Label isException(env); Label notException(env); Branch(TaggedIsException(result), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); varAcc = result; DISPATCH_WITH_ACC(PREF_V8_V8); } DECLARE_ASM_HANDLER(HandleGetIteratorNextPrefV8V8) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef v0 = ReadInst8_1(pc); GateRef v1 = ReadInst8_2(pc); GateRef obj = GetVregValue(sp, ZExtInt8ToPtr(v0)); GateRef method = GetVregValue(sp, ZExtInt8ToPtr(v1)); GateRef result = CallRuntime(glue, RTSTUB_ID(GetIteratorNext), { obj, method }); Label isException(env); Label notException(env); Branch(TaggedIsException(result), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); varAcc = result; DISPATCH_WITH_ACC(PREF_V8_V8); } DECLARE_ASM_HANDLER(HandleSetObjectWithProtoPrefV8V8) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef v0 = ReadInst8_1(pc); GateRef v1 = ReadInst8_2(pc); GateRef proto = GetVregValue(sp, ZExtInt8ToPtr(v0)); GateRef obj = GetVregValue(sp, ZExtInt8ToPtr(v1)); GateRef result = CallRuntime(glue, RTSTUB_ID(SetObjectWithProto), { proto, obj }); Label isException(env); Label notException(env); Branch(TaggedIsException(result), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); varAcc = result; DISPATCH_WITH_ACC(PREF_V8_V8); } DECLARE_ASM_HANDLER(HandleLdObjByValuePrefV8V8) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef v0 = ReadInst8_1(pc); GateRef v1 = ReadInst8_2(pc); GateRef receiver = GetVregValue(sp, ZExtInt8ToPtr(v0)); GateRef propKey = GetVregValue(sp, ZExtInt8ToPtr(v1)); GateRef slotId = ZExtInt8ToInt32(ReadInst8_0(pc)); Label receiverIsHeapObject(env); Label slowPath(env); Label isException(env); Label accDispatch(env); Branch(TaggedIsHeapObject(receiver), &receiverIsHeapObject, &slowPath); Bind(&receiverIsHeapObject); { Label tryIC(env); Label tryFastPath(env); Branch(TaggedIsUndefined(profileTypeInfo), &tryFastPath, &tryIC); Bind(&tryIC); { Label isHeapObject(env); GateRef firstValue = GetValueFromTaggedArray(VariableType::JS_ANY(), profileTypeInfo, slotId); Branch(TaggedIsHeapObject(firstValue), &isHeapObject, &slowPath); Bind(&isHeapObject); { Label loadElement(env); Label tryPoly(env); GateRef secondValue = GetValueFromTaggedArray(VariableType::JS_ANY(), profileTypeInfo, Int32Add(slotId, Int32(1))); DEFVARIABLE(cachedHandler, VariableType::JS_ANY(), secondValue); GateRef hclass = LoadHClass(receiver); Branch(Int64Equal(TaggedCastToWeakReferentUnChecked(firstValue), hclass), &loadElement, &tryPoly); Bind(&loadElement); { GateRef result = LoadElement(receiver, propKey); Label notHole(env); Branch(TaggedIsHole(result), &slowPath, ¬Hole); Bind(¬Hole); Label notException(env); Branch(TaggedIsException(result), &isException, ¬Exception); Bind(¬Exception); varAcc = result; Jump(&accDispatch); } Bind(&tryPoly); { Label firstIsKey(env); Branch(Int64Equal(firstValue, propKey), &firstIsKey, &slowPath); Bind(&firstIsKey); Label loadWithHandler(env); cachedHandler = CheckPolyHClass(secondValue, hclass); Branch(TaggedIsHole(*cachedHandler), &slowPath, &loadWithHandler); Bind(&loadWithHandler); GateRef result = LoadICWithHandler(glue, receiver, receiver, *cachedHandler); Label notHole(env); Branch(TaggedIsHole(result), &tryFastPath, ¬Hole); Bind(¬Hole); Label notException(env); Branch(TaggedIsException(result), &isException, ¬Exception); Bind(¬Exception); varAcc = result; Jump(&accDispatch); } } } Bind(&tryFastPath); { GateRef result = CallStub(glue, CommonStubCSigns::GetPropertyByValue, { glue, receiver, propKey }); Label notHole(env); Branch(TaggedIsHole(result), &slowPath, ¬Hole); Bind(¬Hole); Label notException(env); Branch(TaggedIsException(result), &isException, ¬Exception); Bind(¬Exception); varAcc = result; Jump(&accDispatch); } } Bind(&slowPath); { GateRef result = CallRuntime(glue, RTSTUB_ID(LoadICByValue), { profileTypeInfo, receiver, propKey, IntBuildTaggedTypeWithNoGC(slotId) }); Label notException(env); Branch(TaggedIsException(result), &isException, ¬Exception); Bind(¬Exception); varAcc = result; Jump(&accDispatch); } Bind(&isException); { DISPATCH_LAST(); } Bind(&accDispatch); DISPATCH_WITH_ACC(PREF_V8_V8); } DECLARE_ASM_HANDLER(HandleStObjByValuePrefV8V8) { auto env = GetEnvironment(); GateRef v0 = ReadInst8_1(pc); GateRef v1 = ReadInst8_2(pc); GateRef receiver = GetVregValue(sp, ZExtInt8ToPtr(v0)); GateRef propKey = GetVregValue(sp, ZExtInt8ToPtr(v1)); // slotId = READ_INST_8_0() GateRef slotId = ZExtInt8ToInt32(ReadInst8_0(pc)); Label receiverIsHeapObject(env); Label slowPath(env); Label isException(env); Label notException(env); Branch(TaggedIsHeapObject(receiver), &receiverIsHeapObject, &slowPath); Bind(&receiverIsHeapObject); { Label tryIC(env); Label tryFastPath(env); Branch(TaggedIsUndefined(profileTypeInfo), &tryFastPath, &tryIC); Bind(&tryIC); { Label isHeapObject(env); GateRef firstValue = GetValueFromTaggedArray(VariableType::JS_ANY(), profileTypeInfo, slotId); Branch(TaggedIsHeapObject(firstValue), &isHeapObject, &slowPath); Bind(&isHeapObject); { Label storeElement(env); Label tryPoly(env); GateRef secondValue = GetValueFromTaggedArray(VariableType::JS_ANY(), profileTypeInfo, Int32Add(slotId, Int32(1))); DEFVARIABLE(cachedHandler, VariableType::JS_ANY(), secondValue); GateRef hclass = LoadHClass(receiver); Branch(Int64Equal(TaggedCastToWeakReferentUnChecked(firstValue), hclass), &storeElement, &tryPoly); Bind(&storeElement); { // acc is value GateRef result = ICStoreElement(glue, receiver, propKey, acc, secondValue); Label notHole(env); Branch(TaggedIsHole(result), &slowPath, ¬Hole); Bind(¬Hole); Branch(TaggedIsException(result), &isException, ¬Exception); } Bind(&tryPoly); { Label firstIsKey(env); Branch(Int64Equal(firstValue, propKey), &firstIsKey, &slowPath); Bind(&firstIsKey); Label loadWithHandler(env); cachedHandler = CheckPolyHClass(secondValue, hclass); Branch(TaggedIsHole(*cachedHandler), &slowPath, &loadWithHandler); Bind(&loadWithHandler); GateRef result = StoreICWithHandler(glue, receiver, receiver, acc, *cachedHandler); // acc is value Label notHole(env); Branch(TaggedIsHole(result), &tryFastPath, ¬Hole); Bind(¬Hole); Branch(TaggedIsException(result), &isException, ¬Exception); } } } Bind(&tryFastPath); { GateRef result = CallStub(glue, CommonStubCSigns::SetPropertyByValue, { glue, receiver, propKey, acc }); // acc is value Label notHole(env); Branch(TaggedIsHole(result), &slowPath, ¬Hole); Bind(¬Hole); Branch(TaggedIsException(result), &isException, ¬Exception); } } Bind(&slowPath); { GateRef result = CallRuntime(glue, RTSTUB_ID(StoreICByValue), { profileTypeInfo, receiver, propKey, acc, IntBuildTaggedTypeWithNoGC(slotId) }); Branch(TaggedIsException(result), &isException, ¬Exception); } Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); DISPATCH(PREF_V8_V8); } DECLARE_ASM_HANDLER(HandleStOwnByValuePrefV8V8) { auto env = GetEnvironment(); GateRef v0 = ReadInst8_1(pc); GateRef v1 = ReadInst8_2(pc); GateRef receiver = GetVregValue(sp, ZExtInt8ToPtr(v0)); GateRef propKey = GetVregValue(sp, ZExtInt8ToPtr(v1)); Label isHeapObject(env); Label slowPath(env); Label isException(env); Label notException(env); Branch(TaggedIsHeapObject(receiver), &isHeapObject, &slowPath); Bind(&isHeapObject); Label notClassConstructor(env); Branch(IsClassConstructor(receiver), &slowPath, ¬ClassConstructor); Bind(¬ClassConstructor); Label notClassPrototype(env); Branch(IsClassPrototype(receiver), &slowPath, ¬ClassPrototype); Bind(¬ClassPrototype); { // fast path GateRef result = CallStub(glue, CommonStubCSigns::SetPropertyByValueWithOwn, { glue, receiver, propKey, acc }); // acc is value Label notHole(env); Branch(TaggedIsHole(result), &slowPath, ¬Hole); Bind(¬Hole); Branch(TaggedIsException(result), &isException, ¬Exception); } Bind(&slowPath); { GateRef result = CallRuntime(glue, RTSTUB_ID(StOwnByValue), { receiver, propKey, acc }); Branch(TaggedIsException(result), &isException, ¬Exception); } Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); DISPATCH(PREF_V8_V8); } DECLARE_ASM_HANDLER(HandleLdSuperByValuePrefV8V8) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef v0 = ReadInst8_1(pc); GateRef v1 = ReadInst8_2(pc); GateRef receiver = GetVregValue(sp, ZExtInt8ToPtr(v0)); GateRef propKey = GetVregValue(sp, ZExtInt8ToPtr(v1)); GateRef result = CallRuntime(glue, RTSTUB_ID(LdSuperByValue), { receiver, propKey }); // sp for thisFunc Label isException(env); Label notException(env); Branch(TaggedIsException(result), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); varAcc = result; DISPATCH_WITH_ACC(PREF_V8_V8); } DECLARE_ASM_HANDLER(HandleStSuperByValuePrefV8V8) { auto env = GetEnvironment(); GateRef v0 = ReadInst8_1(pc); GateRef v1 = ReadInst8_2(pc); GateRef receiver = GetVregValue(sp, ZExtInt8ToPtr(v0)); GateRef propKey = GetVregValue(sp, ZExtInt8ToPtr(v1)); // acc is value, sp for thisFunc GateRef result = CallRuntime(glue, RTSTUB_ID(StSuperByValue), { receiver, propKey, acc }); Label isException(env); Label notException(env); Branch(TaggedIsException(result), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); DISPATCH(PREF_V8_V8); } DECLARE_ASM_HANDLER(HandleLdSuperByNamePrefId32V8) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); Label isException(env); Label dispatch(env); GateRef stringId = ReadInst32_1(pc); GateRef v0 = ReadInst8_5(pc); GateRef receiver = GetVregValue(sp, ZExtInt8ToPtr(v0)); GateRef propKey = GetObjectFromConstPool(constpool, stringId); GateRef result = CallRuntime(glue, RTSTUB_ID(LdSuperByValue), { receiver, propKey }); Branch(TaggedIsException(result), &isException, &dispatch); Bind(&isException); { DISPATCH_LAST_WITH_ACC(); } Bind(&dispatch); varAcc = result; DISPATCH_WITH_ACC(PREF_ID32_V8); } DECLARE_ASM_HANDLER(HandleStSuperByNamePrefId32V8) { auto env = GetEnvironment(); Label isException(env); Label dispatch(env); GateRef stringId = ReadInst32_1(pc); GateRef v0 = ReadInst8_5(pc); GateRef receiver = GetVregValue(sp, ZExtInt8ToPtr(v0)); GateRef propKey = GetObjectFromConstPool(constpool, stringId); GateRef result = CallRuntime(glue, RTSTUB_ID(StSuperByValue), { receiver, propKey, acc }); Branch(TaggedIsException(result), &isException, &dispatch); Bind(&isException); { DISPATCH_LAST(); } Bind(&dispatch); DISPATCH(PREF_ID32_V8); } DECLARE_ASM_HANDLER(HandleLdObjByIndexPrefV8Imm32) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef v0 = ReadInst8_1(pc); GateRef receiver = GetVregValue(sp, ZExtInt8ToPtr(v0)); GateRef index = ReadInst32_2(pc); Label fastPath(env); Label slowPath(env); Label isException(env); Label accDispatch(env); Branch(TaggedIsHeapObject(receiver), &fastPath, &slowPath); Bind(&fastPath); { GateRef result = CallStub(glue, CommonStubCSigns::GetPropertyByIndex, { glue, receiver, index }); Label notHole(env); Branch(TaggedIsHole(result), &slowPath, ¬Hole); Bind(¬Hole); Label notException(env); Branch(TaggedIsException(result), &isException, ¬Exception); Bind(¬Exception); varAcc = result; Jump(&accDispatch); } Bind(&slowPath); { GateRef result = CallRuntime(glue, RTSTUB_ID(LdObjByIndex), { receiver, IntBuildTaggedTypeWithNoGC(index), TaggedFalse(), Undefined() }); Label notException(env); Branch(TaggedIsException(result), &isException, ¬Exception); Bind(¬Exception); varAcc = result; Jump(&accDispatch); } Bind(&isException); { DISPATCH_LAST(); } Bind(&accDispatch); DISPATCH_WITH_ACC(PREF_V8_IMM32); } DECLARE_ASM_HANDLER(HandleStObjByIndexPrefV8Imm32) { auto env = GetEnvironment(); GateRef v0 = ReadInst8_1(pc); GateRef receiver = GetVregValue(sp, ZExtInt8ToPtr(v0)); GateRef index = ReadInst32_2(pc); Label fastPath(env); Label slowPath(env); Label isException(env); Label notException(env); Branch(TaggedIsHeapObject(receiver), &fastPath, &slowPath); Bind(&fastPath); { GateRef result = CallStub(glue, CommonStubCSigns::SetPropertyByIndex, { glue, receiver, index, acc }); // acc is value Label notHole(env); Branch(TaggedIsHole(result), &slowPath, ¬Hole); Bind(¬Hole); Branch(TaggedIsException(result), &isException, ¬Exception); } Bind(&slowPath); { GateRef result = CallRuntime(glue, RTSTUB_ID(StObjByIndex), { receiver, IntBuildTaggedTypeWithNoGC(index), acc }); Branch(TaggedIsException(result), &isException, ¬Exception); } Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); DISPATCH(PREF_V8_IMM32); } DECLARE_ASM_HANDLER(HandleStOwnByIndexPrefV8Imm32) { auto env = GetEnvironment(); GateRef v0 = ReadInst8_1(pc); GateRef receiver = GetVregValue(sp, ZExtInt8ToPtr(v0)); GateRef index = ReadInst32_2(pc); Label isHeapObject(env); Label slowPath(env); Label isException(env); Label notException(env); Branch(TaggedIsHeapObject(receiver), &isHeapObject, &slowPath); Bind(&isHeapObject); Label notClassConstructor(env); Branch(IsClassConstructor(receiver), &slowPath, ¬ClassConstructor); Bind(¬ClassConstructor); Label notClassPrototype(env); Branch(IsClassPrototype(receiver), &slowPath, ¬ClassPrototype); Bind(¬ClassPrototype); { // fast path GateRef result = CallStub(glue, CommonStubCSigns::SetPropertyByIndexWithOwn, { glue, receiver, index, acc }); // acc is value Label notHole(env); Branch(TaggedIsHole(result), &slowPath, ¬Hole); Bind(¬Hole); Branch(TaggedIsException(result), &isException, ¬Exception); } Bind(&slowPath); { GateRef result = CallRuntime(glue, RTSTUB_ID(StOwnByIndex), { receiver, IntBuildTaggedTypeWithNoGC(index), acc }); Branch(TaggedIsException(result), &isException, ¬Exception); } Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); DISPATCH(PREF_V8_IMM32); } DECLARE_ASM_HANDLER(HandleStConstToGlobalRecordPrefId32) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); Label isException(env); Label notException(env); GateRef stringId = ReadInst32_1(pc); GateRef propKey = GetValueFromTaggedArray(VariableType::JS_ANY(), constpool, stringId); GateRef result = CallRuntime(glue, RTSTUB_ID(StGlobalRecord), { propKey, *varAcc, TaggedTrue() }); Branch(TaggedIsException(result), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST_WITH_ACC(); } Bind(¬Exception); DISPATCH_WITH_ACC(PREF_ID32); } DECLARE_ASM_HANDLER(HandleStLetToGlobalRecordPrefId32) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); Label isException(env); Label notException(env); GateRef stringId = ReadInst32_1(pc); GateRef propKey = GetValueFromTaggedArray(VariableType::JS_ANY(), constpool, stringId); GateRef result = CallRuntime(glue, RTSTUB_ID(StGlobalRecord), { propKey, *varAcc, TaggedFalse() }); Branch(TaggedIsException(result), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST_WITH_ACC(); } Bind(¬Exception); DISPATCH_WITH_ACC(PREF_ID32); } DECLARE_ASM_HANDLER(HandleStClassToGlobalRecordPrefId32) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); Label isException(env); Label notException(env); GateRef stringId = ReadInst32_1(pc); GateRef propKey = GetValueFromTaggedArray(VariableType::JS_ANY(), constpool, stringId); GateRef result = CallRuntime(glue, RTSTUB_ID(StGlobalRecord), { propKey, *varAcc, TaggedFalse() }); Branch(TaggedIsException(result), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST_WITH_ACC(); } Bind(¬Exception); DISPATCH_WITH_ACC(PREF_ID32); } DECLARE_ASM_HANDLER(HandleNegDynPrefV8) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef vsrc = ReadInst8_1(pc); GateRef value = GetVregValue(sp, ZExtInt8ToPtr(vsrc)); Label valueIsInt(env); Label valueNotInt(env); Label accDispatch(env); Branch(TaggedIsInt(value), &valueIsInt, &valueNotInt); Bind(&valueIsInt); { GateRef valueInt = TaggedCastToInt32(value); Label valueIsZero(env); Label valueNotZero(env); Branch(Int32Equal(valueInt, Int32(0)), &valueIsZero, &valueNotZero); Bind(&valueIsZero); { // Format::PREF_V8: size = 3 varAcc = DoubleBuildTaggedWithNoGC(Double(-0.0)); Jump(&accDispatch); } Bind(&valueNotZero); { varAcc = IntBuildTaggedWithNoGC(Int32Sub(Int32(0), valueInt)); Jump(&accDispatch); } } Bind(&valueNotInt); { Label valueIsDouble(env); Label valueNotDouble(env); Branch(TaggedIsDouble(value), &valueIsDouble, &valueNotDouble); Bind(&valueIsDouble); { GateRef valueDouble = TaggedCastToDouble(value); varAcc = DoubleBuildTaggedWithNoGC(DoubleSub(Double(0), valueDouble)); Jump(&accDispatch); } Label isException(env); Label notException(env); Bind(&valueNotDouble); { // slow path GateRef result = CallRuntime(glue, RTSTUB_ID(NegDyn), { value }); Branch(TaggedIsException(result), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST_WITH_ACC(); } Bind(¬Exception); varAcc = result; Jump(&accDispatch); } } Bind(&accDispatch); DISPATCH_WITH_ACC(PREF_V8); } DECLARE_ASM_HANDLER(HandleNotDynPrefV8) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef vsrc = ReadInst8_1(pc); GateRef value = GetVregValue(sp, ZExtInt8ToPtr(vsrc)); DEFVARIABLE(number, VariableType::INT32(), Int32(0)); Label numberIsInt(env); Label numberNotInt(env); Label accDispatch(env); Branch(TaggedIsInt(value), &numberIsInt, &numberNotInt); Bind(&numberIsInt); { number = TaggedCastToInt32(value); varAcc = IntBuildTaggedWithNoGC(Int32Not(*number)); Jump(&accDispatch); } Bind(&numberNotInt); { Label numberIsDouble(env); Label numberNotDouble(env); Branch(TaggedIsDouble(value), &numberIsDouble, &numberNotDouble); Bind(&numberIsDouble); { GateRef valueDouble = TaggedCastToDouble(value); number = DoubleToInt(glue, valueDouble); varAcc = IntBuildTaggedWithNoGC(Int32Not(*number)); Jump(&accDispatch); } Bind(&numberNotDouble); { // slow path GateRef result = CallRuntime(glue, RTSTUB_ID(NotDyn), { value }); Label isException(env); Label notException(env); Branch(TaggedIsException(result), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST_WITH_ACC(); } Bind(¬Exception); varAcc = result; Jump(&accDispatch); } } Bind(&accDispatch); DISPATCH_WITH_ACC(PREF_V8); } DECLARE_ASM_HANDLER(HandleAnd2DynPrefV8) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef v0 = ReadInst8_1(pc); GateRef left = GetVregValue(sp, ZExtInt8ToPtr(v0)); GateRef right = *varAcc; DEFVARIABLE(opNumber0, VariableType::INT32(), Int32(0)); DEFVARIABLE(opNumber1, VariableType::INT32(), Int32(0)); Label accDispatch(env); Label leftIsNumber(env); Label leftNotNumberOrRightNotNumber(env); Branch(TaggedIsNumber(left), &leftIsNumber, &leftNotNumberOrRightNotNumber); Bind(&leftIsNumber); { Label rightIsNumber(env); Branch(TaggedIsNumber(right), &rightIsNumber, &leftNotNumberOrRightNotNumber); Bind(&rightIsNumber); { Label leftIsInt(env); Label leftIsDouble(env); Branch(TaggedIsInt(left), &leftIsInt, &leftIsDouble); Bind(&leftIsInt); { Label rightIsInt(env); Label rightIsDouble(env); Branch(TaggedIsInt(right), &rightIsInt, &rightIsDouble); Bind(&rightIsInt); { opNumber0 = TaggedCastToInt32(left); opNumber1 = TaggedCastToInt32(right); Jump(&accDispatch); } Bind(&rightIsDouble); { opNumber0 = TaggedCastToInt32(left); GateRef rightDouble = TaggedCastToDouble(right); opNumber1 = DoubleToInt(glue, rightDouble); Jump(&accDispatch); } } Bind(&leftIsDouble); { Label rightIsInt(env); Label rightIsDouble(env); Branch(TaggedIsInt(right), &rightIsInt, &rightIsDouble); Bind(&rightIsInt); { GateRef leftDouble = TaggedCastToDouble(left); opNumber0 = DoubleToInt(glue, leftDouble); opNumber1 = TaggedCastToInt32(right); Jump(&accDispatch); } Bind(&rightIsDouble); { GateRef rightDouble = TaggedCastToDouble(right); GateRef leftDouble = TaggedCastToDouble(left); opNumber0 = DoubleToInt(glue, leftDouble); opNumber1 = DoubleToInt(glue, rightDouble); Jump(&accDispatch); } } } } // slow path Bind(&leftNotNumberOrRightNotNumber); { GateRef taggedNumber = CallRuntime(glue, RTSTUB_ID(And2Dyn), { left, right }); Label isException(env); Label notException(env); Branch(TaggedIsException(taggedNumber), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST_WITH_ACC(); } Bind(¬Exception); { varAcc = taggedNumber; DISPATCH_WITH_ACC(PREF_V8); } } Bind(&accDispatch); { GateRef ret = Int32And(*opNumber0, *opNumber1); varAcc = IntBuildTaggedWithNoGC(ret); DISPATCH_WITH_ACC(PREF_V8); } } DECLARE_ASM_HANDLER(HandleOr2DynPrefV8) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef v0 = ReadInst8_1(pc); GateRef left = GetVregValue(sp, ZExtInt8ToPtr(v0)); GateRef right = *varAcc; DEFVARIABLE(opNumber0, VariableType::INT32(), Int32(0)); DEFVARIABLE(opNumber1, VariableType::INT32(), Int32(0)); Label accDispatch(env); Label leftIsNumber(env); Label leftNotNumberOrRightNotNumber(env); Branch(TaggedIsNumber(left), &leftIsNumber, &leftNotNumberOrRightNotNumber); Bind(&leftIsNumber); { Label rightIsNumber(env); Branch(TaggedIsNumber(right), &rightIsNumber, &leftNotNumberOrRightNotNumber); Bind(&rightIsNumber); { Label leftIsInt(env); Label leftIsDouble(env); Branch(TaggedIsInt(left), &leftIsInt, &leftIsDouble); Bind(&leftIsInt); { Label rightIsInt(env); Label rightIsDouble(env); Branch(TaggedIsInt(right), &rightIsInt, &rightIsDouble); Bind(&rightIsInt); { opNumber0 = TaggedCastToInt32(left); opNumber1 = TaggedCastToInt32(right); Jump(&accDispatch); } Bind(&rightIsDouble); { GateRef rightDouble = TaggedCastToDouble(right); opNumber0 = TaggedCastToInt32(left); opNumber1 = DoubleToInt(glue, rightDouble); Jump(&accDispatch); } } Bind(&leftIsDouble); { Label rightIsInt(env); Label rightIsDouble(env); Branch(TaggedIsInt(right), &rightIsInt, &rightIsDouble); Bind(&rightIsInt); { GateRef leftDouble = TaggedCastToDouble(left); opNumber0 = DoubleToInt(glue, leftDouble); opNumber1 = TaggedCastToInt32(right); Jump(&accDispatch); } Bind(&rightIsDouble); { GateRef rightDouble = TaggedCastToDouble(right); GateRef leftDouble = TaggedCastToDouble(left); opNumber0 = DoubleToInt(glue, leftDouble); opNumber1 = DoubleToInt(glue, rightDouble); Jump(&accDispatch); } } } } // slow path Bind(&leftNotNumberOrRightNotNumber); { GateRef taggedNumber = CallRuntime(glue, RTSTUB_ID(Or2Dyn), { left, right }); Label isException(env); Label notException(env); Branch(TaggedIsException(taggedNumber), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST_WITH_ACC(); } Bind(¬Exception); { varAcc = taggedNumber; DISPATCH_WITH_ACC(PREF_V8); } } Bind(&accDispatch); { GateRef ret = Int32Or(*opNumber0, *opNumber1); varAcc = IntBuildTaggedWithNoGC(ret); DISPATCH_WITH_ACC(PREF_V8); } } DECLARE_ASM_HANDLER(HandleXOr2DynPrefV8) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef v0 = ReadInst8_1(pc); GateRef left = GetVregValue(sp, ZExtInt8ToPtr(v0)); GateRef right = *varAcc; DEFVARIABLE(opNumber0, VariableType::INT32(), Int32(0)); DEFVARIABLE(opNumber1, VariableType::INT32(), Int32(0)); Label accDispatch(env); Label leftIsNumber(env); Label leftNotNumberOrRightNotNumber(env); Branch(TaggedIsNumber(left), &leftIsNumber, &leftNotNumberOrRightNotNumber); Bind(&leftIsNumber); { Label rightIsNumber(env); Branch(TaggedIsNumber(right), &rightIsNumber, &leftNotNumberOrRightNotNumber); Bind(&rightIsNumber); { Label leftIsInt(env); Label leftIsDouble(env); Branch(TaggedIsInt(left), &leftIsInt, &leftIsDouble); Bind(&leftIsInt); { Label rightIsInt(env); Label rightIsDouble(env); Branch(TaggedIsInt(right), &rightIsInt, &rightIsDouble); Bind(&rightIsInt); { opNumber0 = TaggedCastToInt32(left); opNumber1 = TaggedCastToInt32(right); Jump(&accDispatch); } Bind(&rightIsDouble); { GateRef rightDouble = TaggedCastToDouble(right); opNumber0 = TaggedCastToInt32(left); opNumber1 = DoubleToInt(glue, rightDouble); Jump(&accDispatch); } } Bind(&leftIsDouble); { Label rightIsInt(env); Label rightIsDouble(env); Branch(TaggedIsInt(right), &rightIsInt, &rightIsDouble); Bind(&rightIsInt); { GateRef leftDouble = TaggedCastToDouble(left); opNumber0 = DoubleToInt(glue, leftDouble); opNumber1 = TaggedCastToInt32(right); Jump(&accDispatch); } Bind(&rightIsDouble); { GateRef rightDouble = TaggedCastToDouble(right); GateRef leftDouble = TaggedCastToDouble(left); opNumber0 = DoubleToInt(glue, leftDouble); opNumber1 = DoubleToInt(glue, rightDouble); Jump(&accDispatch); } } } } // slow path Bind(&leftNotNumberOrRightNotNumber); { GateRef taggedNumber = CallRuntime(glue, RTSTUB_ID(Xor2Dyn), { left, right }); Label isException(env); Label notException(env); Branch(TaggedIsException(taggedNumber), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST_WITH_ACC(); } Bind(¬Exception); { varAcc = taggedNumber; DISPATCH_WITH_ACC(PREF_V8); } } Bind(&accDispatch); { GateRef ret = Int32Xor(*opNumber0, *opNumber1); varAcc = IntBuildTaggedWithNoGC(ret); DISPATCH_WITH_ACC(PREF_V8); } } DECLARE_ASM_HANDLER(HandleAshr2DynPrefV8) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef v0 = ReadInst8_1(pc); GateRef left = GetVregValue(sp, ZExtInt8ToPtr(v0)); GateRef right = *varAcc; DEFVARIABLE(opNumber0, VariableType::INT32(), Int32(0)); DEFVARIABLE(opNumber1, VariableType::INT32(), Int32(0)); Label accDispatch(env); Label leftIsNumber(env); Label leftNotNumberOrRightNotNumber(env); Branch(TaggedIsNumber(left), &leftIsNumber, &leftNotNumberOrRightNotNumber); Bind(&leftIsNumber); { Label rightIsNumber(env); Branch(TaggedIsNumber(right), &rightIsNumber, &leftNotNumberOrRightNotNumber); Bind(&rightIsNumber); { Label leftIsInt(env); Label leftIsDouble(env); Branch(TaggedIsInt(left), &leftIsInt, &leftIsDouble); Bind(&leftIsInt); { Label rightIsInt(env); Label rightIsDouble(env); Branch(TaggedIsInt(right), &rightIsInt, &rightIsDouble); Bind(&rightIsInt); { opNumber0 = TaggedCastToInt32(left); opNumber1 = TaggedCastToInt32(right); Jump(&accDispatch); } Bind(&rightIsDouble); { GateRef rightDouble = TaggedCastToDouble(right); opNumber0 = TaggedCastToInt32(left); opNumber1 = DoubleToInt(glue, rightDouble); Jump(&accDispatch); } } Bind(&leftIsDouble); { Label rightIsInt(env); Label rightIsDouble(env); Branch(TaggedIsInt(right), &rightIsInt, &rightIsDouble); Bind(&rightIsInt); { GateRef leftDouble = TaggedCastToDouble(left); opNumber0 = DoubleToInt(glue, leftDouble); opNumber1 = TaggedCastToInt32(right); Jump(&accDispatch); } Bind(&rightIsDouble); { GateRef rightDouble = TaggedCastToDouble(right); GateRef leftDouble = TaggedCastToDouble(left); opNumber0 = DoubleToInt(glue, leftDouble); opNumber1 = DoubleToInt(glue, rightDouble); Jump(&accDispatch); } } } } // slow path Bind(&leftNotNumberOrRightNotNumber); { GateRef taggedNumber = CallRuntime(glue, RTSTUB_ID(Ashr2Dyn), { left, right }); Label isException(env); Label notException(env); Branch(TaggedIsException(taggedNumber), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST_WITH_ACC(); } Bind(¬Exception); { varAcc = taggedNumber; DISPATCH_WITH_ACC(PREF_V8); } } Bind(&accDispatch); { GateRef shift = Int32And(*opNumber1, Int32(0x1f)); GateRef ret = Int32ASR(*opNumber0, shift); varAcc = IntBuildTaggedWithNoGC(ret); DISPATCH_WITH_ACC(PREF_V8); } } DECLARE_ASM_HANDLER(HandleShr2DynPrefV8) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef v0 = ReadInst8_1(pc); GateRef left = GetVregValue(sp, ZExtInt8ToPtr(v0)); GateRef right = *varAcc; DEFVARIABLE(opNumber0, VariableType::INT32(), Int32(0)); DEFVARIABLE(opNumber1, VariableType::INT32(), Int32(0)); Label accDispatch(env); Label doShr(env); Label overflow(env); Label notOverflow(env); Label leftIsNumber(env); Label leftNotNumberOrRightNotNumber(env); Branch(TaggedIsNumber(left), &leftIsNumber, &leftNotNumberOrRightNotNumber); Bind(&leftIsNumber); { Label rightIsNumber(env); Branch(TaggedIsNumber(right), &rightIsNumber, &leftNotNumberOrRightNotNumber); Bind(&rightIsNumber); { Label leftIsInt(env); Label leftIsDouble(env); Branch(TaggedIsInt(left), &leftIsInt, &leftIsDouble); Bind(&leftIsInt); { Label rightIsInt(env); Label rightIsDouble(env); Branch(TaggedIsInt(right), &rightIsInt, &rightIsDouble); Bind(&rightIsInt); { opNumber0 = TaggedCastToInt32(left); opNumber1 = TaggedCastToInt32(right); Jump(&doShr); } Bind(&rightIsDouble); { GateRef rightDouble = TaggedCastToDouble(right); opNumber0 = TaggedCastToInt32(left); opNumber1 = DoubleToInt(glue, rightDouble); Jump(&doShr); } } Bind(&leftIsDouble); { Label rightIsInt(env); Label rightIsDouble(env); Branch(TaggedIsInt(right), &rightIsInt, &rightIsDouble); Bind(&rightIsInt); { GateRef leftDouble = TaggedCastToDouble(left); opNumber0 = DoubleToInt(glue, leftDouble); opNumber1 = TaggedCastToInt32(right); Jump(&doShr); } Bind(&rightIsDouble); { GateRef rightDouble = TaggedCastToDouble(right); GateRef leftDouble = TaggedCastToDouble(left); opNumber0 = DoubleToInt(glue, leftDouble); opNumber1 = DoubleToInt(glue, rightDouble); Jump(&doShr); } } } } // slow path Bind(&leftNotNumberOrRightNotNumber); { GateRef taggedNumber = CallRuntime(glue, RTSTUB_ID(Shr2Dyn), { left, right }); Label isException(env); Label notException(env); Branch(TaggedIsException(taggedNumber), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST_WITH_ACC(); } Bind(¬Exception); { varAcc = taggedNumber; Jump(&accDispatch); } } Bind(&doShr); { GateRef shift = Int32And(*opNumber1, Int32(0x1f)); GateRef ret = Int32LSR(*opNumber0, shift); auto condition = Int32UnsignedGreaterThan(ret, Int32(INT32_MAX)); Branch(condition, &overflow, ¬Overflow); Bind(&overflow); { varAcc = DoubleBuildTaggedWithNoGC(ChangeUInt32ToFloat64(ret)); Jump(&accDispatch); } Bind(¬Overflow); { varAcc = IntBuildTaggedWithNoGC(ret); Jump(&accDispatch); } } Bind(&accDispatch); { DISPATCH_WITH_ACC(PREF_V8); } } DECLARE_ASM_HANDLER(HandleShl2DynPrefV8) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef v0 = ReadInst8_1(pc); GateRef left = GetVregValue(sp, ZExtInt8ToPtr(v0)); GateRef right = *varAcc; DEFVARIABLE(opNumber0, VariableType::INT32(), Int32(0)); DEFVARIABLE(opNumber1, VariableType::INT32(), Int32(0)); Label accDispatch(env); Label leftIsNumber(env); Label leftNotNumberOrRightNotNumber(env); Branch(TaggedIsNumber(left), &leftIsNumber, &leftNotNumberOrRightNotNumber); Bind(&leftIsNumber); { Label rightIsNumber(env); Branch(TaggedIsNumber(right), &rightIsNumber, &leftNotNumberOrRightNotNumber); Bind(&rightIsNumber); { Label leftIsInt(env); Label leftIsDouble(env); Branch(TaggedIsInt(left), &leftIsInt, &leftIsDouble); Bind(&leftIsInt); { Label rightIsInt(env); Label rightIsDouble(env); Branch(TaggedIsInt(right), &rightIsInt, &rightIsDouble); Bind(&rightIsInt); { opNumber0 = TaggedCastToInt32(left); opNumber1 = TaggedCastToInt32(right); Jump(&accDispatch); } Bind(&rightIsDouble); { GateRef rightDouble = TaggedCastToDouble(right); opNumber0 = TaggedCastToInt32(left); opNumber1 = DoubleToInt(glue, rightDouble); Jump(&accDispatch); } } Bind(&leftIsDouble); { Label rightIsInt(env); Label rightIsDouble(env); Branch(TaggedIsInt(right), &rightIsInt, &rightIsDouble); Bind(&rightIsInt); { GateRef leftDouble = TaggedCastToDouble(left); opNumber0 = DoubleToInt(glue, leftDouble); opNumber1 = TaggedCastToInt32(right); Jump(&accDispatch); } Bind(&rightIsDouble); { GateRef rightDouble = TaggedCastToDouble(right); GateRef leftDouble = TaggedCastToDouble(left); opNumber0 = DoubleToInt(glue, leftDouble); opNumber1 = DoubleToInt(glue, rightDouble); Jump(&accDispatch); } } } } // slow path Bind(&leftNotNumberOrRightNotNumber); { GateRef taggedNumber = CallRuntime(glue, RTSTUB_ID(Shl2Dyn), { left, right }); Label IsException(env); Label NotException(env); Branch(TaggedIsException(taggedNumber), &IsException, &NotException); Bind(&IsException); { DISPATCH_LAST_WITH_ACC(); } Bind(&NotException); { varAcc = taggedNumber; DISPATCH_WITH_ACC(PREF_V8); } } Bind(&accDispatch); { GateRef shift = Int32And(*opNumber1, Int32(0x1f)); GateRef ret = Int32LSL(*opNumber0, shift); varAcc = IntBuildTaggedWithNoGC(ret); DISPATCH_WITH_ACC(PREF_V8); } } DECLARE_ASM_HANDLER(HandleDefineClassWithBufferPrefId16Imm16Imm16V8V8) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef methodId = ReadInst16_1(pc); GateRef literalId = ReadInst16_3(pc); GateRef length = ReadInst16_5(pc); GateRef v0 = ReadInst8_7(pc); GateRef v1 = ReadInst8_8(pc); GateRef classTemplate = GetObjectFromConstPool(constpool, ZExtInt16ToInt32(methodId)); GateRef literalBuffer = GetObjectFromConstPool(constpool, ZExtInt16ToInt32(literalId)); GateRef lexicalEnv = GetVregValue(sp, ZExtInt8ToPtr(v0)); GateRef proto = GetVregValue(sp, ZExtInt8ToPtr(v1)); DEFVARIABLE(res, VariableType::JS_ANY(), Undefined()); Label isResolved(env); Label isNotResolved(env); Label afterCheckResolved(env); Branch(FunctionIsResolved(classTemplate), &isResolved, &isNotResolved); Bind(&isResolved); { res = CallRuntime(glue, RTSTUB_ID(CloneClassFromTemplate), { classTemplate, proto, lexicalEnv, constpool }); Jump(&afterCheckResolved); } Bind(&isNotResolved); { res = CallRuntime(glue, RTSTUB_ID(ResolveClass), { classTemplate, literalBuffer, proto, lexicalEnv, constpool }); Jump(&afterCheckResolved); } Bind(&afterCheckResolved); Label isException(env); Label isNotException(env); Branch(TaggedIsException(*res), &isException, &isNotException); Bind(&isException); { DISPATCH_LAST_WITH_ACC(); } Bind(&isNotException); GateRef newLexicalEnv = GetVregValue(sp, ZExtInt8ToPtr(v0)); // slow runtime may gc SetLexicalEnvToFunction(glue, *res, newLexicalEnv); CallRuntime(glue, RTSTUB_ID(SetClassConstructorLength), { *res, Int16BuildTaggedTypeWithNoGC(length) }); varAcc = *res; DISPATCH_WITH_ACC(PREF_ID16_IMM16_IMM16_V8_V8); } DECLARE_ASM_HANDLER(HandleLdObjByNamePrefId32V8) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); DEFVARIABLE(result, VariableType::JS_ANY(), Hole()); GateRef slotId = ZExtInt8ToInt32(ReadInst8_0(pc)); GateRef receiver = GetVregValue(sp, ZExtInt8ToPtr(ReadInst8_5(pc))); Label receiverIsHeapObject(env); Label dispatch(env); Label slowPath(env); Label notHole(env); Label hasException(env); Label notException(env); Branch(TaggedIsHeapObject(receiver), &receiverIsHeapObject, &slowPath); Bind(&receiverIsHeapObject); { Label tryIC(env); Label tryFastPath(env); Branch(TaggedIsUndefined(profileTypeInfo), &tryFastPath, &tryIC); Bind(&tryIC); { Label isHeapObject(env); GateRef firstValue = GetValueFromTaggedArray(VariableType::JS_ANY(), profileTypeInfo, slotId); Branch(TaggedIsHeapObject(firstValue), &isHeapObject, &slowPath); Bind(&isHeapObject); { Label tryPoly(env); Label loadWithHandler(env); GateRef secondValue = GetValueFromTaggedArray(VariableType::JS_ANY(), profileTypeInfo, Int32Add(slotId, Int32(1))); DEFVARIABLE(cachedHandler, VariableType::JS_ANY(), secondValue); GateRef hclass = LoadHClass(receiver); Branch(Int64Equal(TaggedCastToWeakReferentUnChecked(firstValue), hclass), &loadWithHandler, &tryPoly); Bind(&tryPoly); { cachedHandler = CheckPolyHClass(firstValue, hclass); Branch(TaggedIsHole(*cachedHandler), &tryFastPath, &loadWithHandler); } Bind(&loadWithHandler); { result = LoadICWithHandler(glue, receiver, receiver, *cachedHandler); Branch(TaggedIsHole(*result), &slowPath, ¬Hole); } } } Bind(&tryFastPath); { GateRef stringId = ReadInst32_1(pc); GateRef propKey = GetValueFromTaggedArray(VariableType::JS_ANY(), constpool, stringId); result = CallStub(glue, CommonStubCSigns::GetPropertyByName, { glue, receiver, propKey }); Branch(TaggedIsHole(*result), &slowPath, ¬Hole); } Bind(¬Hole); { Branch(TaggedIsException(*result), &hasException, ¬Exception); Bind(&hasException); { DISPATCH_LAST_WITH_ACC(); } Bind(¬Exception); varAcc = *result; Jump(&dispatch); } } Bind(&slowPath); { Label isException(env); Label noException(env); GateRef stringId = ReadInst32_1(pc); GateRef propKey = GetValueFromTaggedArray(VariableType::JS_ANY(), constpool, stringId); result = CallRuntime(glue, RTSTUB_ID(LoadICByName), { profileTypeInfo, receiver, propKey, IntBuildTaggedTypeWithNoGC(slotId) }); Branch(TaggedIsException(*result), &isException, &noException); Bind(&isException); { DISPATCH_LAST_WITH_ACC(); } Bind(&noException); varAcc = *result; Jump(&dispatch); } Bind(&dispatch); DISPATCH_WITH_ACC(PREF_ID32_V8); } DECLARE_ASM_HANDLER(HandleStObjByNamePrefId32V8) { auto env = GetEnvironment(); GateRef receiver = GetVregValue(sp, ZExtInt8ToPtr(ReadInst8_5(pc))); GateRef slotId = ZExtInt8ToInt32(ReadInst8_0(pc)); DEFVARIABLE(result, VariableType::INT64(), Hole(VariableType::INT64())); Label checkResult(env); Label dispatch(env); Label slowPath(env); Label receiverIsHeapObject(env); Branch(TaggedIsHeapObject(receiver), &receiverIsHeapObject, &slowPath); Bind(&receiverIsHeapObject); { Label tryIC(env); Label tryFastPath(env); Branch(TaggedIsUndefined(profileTypeInfo), &tryFastPath, &tryIC); Bind(&tryIC); { Label isHeapObject(env); GateRef firstValue = GetValueFromTaggedArray(VariableType::JS_ANY(), profileTypeInfo, slotId); Branch(TaggedIsHeapObject(firstValue), &isHeapObject, &slowPath); Bind(&isHeapObject); { Label tryPoly(env); Label storeWithHandler(env); GateRef secondValue = GetValueFromTaggedArray(VariableType::JS_ANY(), profileTypeInfo, Int32Add(slotId, Int32(1))); DEFVARIABLE(cachedHandler, VariableType::JS_ANY(), secondValue); GateRef hclass = LoadHClass(receiver); Branch(Int64Equal(TaggedCastToWeakReferentUnChecked(firstValue), hclass), &storeWithHandler, &tryPoly); Bind(&tryPoly); { cachedHandler = CheckPolyHClass(firstValue, hclass); Branch(TaggedIsHole(*cachedHandler), &tryFastPath, &storeWithHandler); } Bind(&storeWithHandler); { result = StoreICWithHandler(glue, receiver, receiver, acc, *cachedHandler); Branch(TaggedIsHole(*result), &slowPath, &checkResult); } } } Bind(&tryFastPath); { GateRef stringId = ReadInst32_1(pc); GateRef propKey = GetValueFromTaggedArray(VariableType::JS_ANY(), constpool, stringId); result = CallStub(glue, CommonStubCSigns::SetPropertyByName, { glue, receiver, propKey, acc }); Branch(TaggedIsHole(*result), &slowPath, &checkResult); } } Bind(&slowPath); { GateRef stringId = ReadInst32_1(pc); GateRef propKey = GetValueFromTaggedArray(VariableType::JS_ANY(), constpool, stringId); result = ChangeTaggedPointerToInt64(CallRuntime(glue, RTSTUB_ID(StoreICByName), { profileTypeInfo, receiver, propKey, acc, IntBuildTaggedTypeWithNoGC(slotId) })); Jump(&checkResult); } Bind(&checkResult); { Label isException(env); Branch(TaggedIsException(*result), &isException, &dispatch); Bind(&isException); { DISPATCH_LAST(); } } Bind(&dispatch); DISPATCH(PREF_ID32_V8); } DECLARE_ASM_HANDLER(HandleStOwnByValueWithNameSetPrefV8V8) { auto env = GetEnvironment(); GateRef receiver = GetVregValue(sp, ZExtInt8ToPtr(ReadInst8_1(pc))); GateRef propKey = GetVregValue(sp, ZExtInt8ToPtr(ReadInst8_2(pc))); Label isHeapObject(env); Label slowPath(env); Label notClassConstructor(env); Label notClassPrototype(env); Label notHole(env); Label isException(env); Label notException(env); Label isException1(env); Label notException1(env); Branch(TaggedIsHeapObject(receiver), &isHeapObject, &slowPath); Bind(&isHeapObject); { Branch(IsClassConstructor(receiver), &slowPath, ¬ClassConstructor); Bind(¬ClassConstructor); { Branch(IsClassPrototype(receiver), &slowPath, ¬ClassPrototype); Bind(¬ClassPrototype); { GateRef res = CallStub(glue, CommonStubCSigns::SetPropertyByValueWithOwn, { glue, receiver, propKey, acc }); Branch(TaggedIsHole(res), &slowPath, ¬Hole); Bind(¬Hole); { Branch(TaggedIsException(res), &isException, ¬Exception); Bind(&isException); { DispatchLast(glue, sp, pc, constpool, profileTypeInfo, acc, hotnessCounter); } Bind(¬Exception); CallRuntime(glue, RTSTUB_ID(SetFunctionNameNoPrefix), { acc, propKey }); DISPATCH(PREF_V8_V8); } } } } Bind(&slowPath); { GateRef res = CallRuntime(glue, RTSTUB_ID(StOwnByValueWithNameSet), { receiver, propKey, acc }); Branch(TaggedIsException(res), &isException1, ¬Exception1); Bind(&isException1); { DispatchLast(glue, sp, pc, constpool, profileTypeInfo, acc, hotnessCounter); } Bind(¬Exception1); DISPATCH(PREF_V8_V8); } } DECLARE_ASM_HANDLER(HandleStOwnByNamePrefId32V8) { auto env = GetEnvironment(); GateRef stringId = ReadInst32_1(pc); GateRef propKey = GetValueFromTaggedArray(VariableType::JS_ANY(), constpool, stringId); GateRef receiver = GetVregValue(sp, ZExtInt8ToPtr(ReadInst8_5(pc))); DEFVARIABLE(result, VariableType::INT64(), Hole(VariableType::INT64())); Label checkResult(env); Label dispatch(env); Label isJSObject(env); Label slowPath(env); Branch(IsJSObject(receiver), &isJSObject, &slowPath); Bind(&isJSObject); { Label notClassConstructor(env); Branch(IsClassConstructor(receiver), &slowPath, ¬ClassConstructor); Bind(¬ClassConstructor); { Label fastPath(env); Branch(IsClassPrototype(receiver), &slowPath, &fastPath); Bind(&fastPath); { result = CallStub(glue, CommonStubCSigns::SetPropertyByNameWithOwn, { glue, receiver, propKey, acc }); Branch(TaggedIsHole(*result), &slowPath, &checkResult); } } } Bind(&slowPath); { result = ChangeTaggedPointerToInt64(CallRuntime(glue, RTSTUB_ID(StOwnByName), { receiver, propKey, acc })); Jump(&checkResult); } Bind(&checkResult); { Label isException(env); Branch(TaggedIsException(*result), &isException, &dispatch); Bind(&isException); { DISPATCH_LAST(); } } Bind(&dispatch); DISPATCH(PREF_ID32_V8); } DECLARE_ASM_HANDLER(HandleStOwnByNameWithNameSetPrefId32V8) { auto env = GetEnvironment(); GateRef stringId = ReadInst32_1(pc); GateRef receiver = GetVregValue(sp, ZExtInt8ToPtr(ReadInst8_5(pc))); GateRef propKey = GetValueFromTaggedArray(VariableType::JS_ANY(), constpool, stringId); Label isJSObject(env); Label notJSObject(env); Label notClassConstructor(env); Label notClassPrototype(env); Label notHole(env); Label isException(env); Label notException(env); Label isException1(env); Label notException1(env); Branch(IsJSObject(receiver), &isJSObject, ¬JSObject); Bind(&isJSObject); { Branch(IsClassConstructor(receiver), ¬JSObject, ¬ClassConstructor); Bind(¬ClassConstructor); { Branch(IsClassPrototype(receiver), ¬JSObject, ¬ClassPrototype); Bind(¬ClassPrototype); { GateRef res = CallStub(glue, CommonStubCSigns::SetPropertyByNameWithOwn, { glue, receiver, propKey, acc }); Branch(TaggedIsHole(res), ¬JSObject, ¬Hole); Bind(¬Hole); { Branch(TaggedIsException(res), &isException, ¬Exception); Bind(&isException); DispatchLast(glue, sp, pc, constpool, profileTypeInfo, acc, hotnessCounter); Bind(¬Exception); CallRuntime(glue, RTSTUB_ID(SetFunctionNameNoPrefix), { acc, propKey }); DISPATCH(PREF_ID32_V8); } } } } Bind(¬JSObject); { GateRef res = CallRuntime(glue, RTSTUB_ID(StOwnByNameWithNameSet), { receiver, propKey, acc }); Branch(TaggedIsException(res), &isException1, ¬Exception1); Bind(&isException1); DispatchLast(glue, sp, pc, constpool, profileTypeInfo, acc, hotnessCounter); Bind(¬Exception1); DISPATCH(PREF_ID32_V8); } } DECLARE_ASM_HANDLER(HandleLdFunctionPref) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); varAcc = GetFunctionFromFrame(GetFrame(sp)); DISPATCH_WITH_ACC(PREF_NONE); } DECLARE_ASM_HANDLER(HandleMovV4V4) { GateRef vdst = ZExtInt8ToPtr(ReadInst4_0(pc)); GateRef vsrc = ZExtInt8ToPtr(ReadInst4_1(pc)); GateRef value = GetVregValue(sp, vsrc); SetVregValue(glue, sp, vdst, value); DISPATCH(V4_V4); } DECLARE_ASM_HANDLER(HandleMovDynV8V8) { GateRef vdst = ZExtInt8ToPtr(ReadInst8_0(pc)); GateRef vsrc = ZExtInt8ToPtr(ReadInst8_1(pc)); GateRef value = GetVregValue(sp, vsrc); SetVregValue(glue, sp, vdst, value); DISPATCH(V8_V8); } DECLARE_ASM_HANDLER(HandleMovDynV16V16) { GateRef vdst = ZExtInt16ToPtr(ReadInst16_0(pc)); GateRef vsrc = ZExtInt16ToPtr(ReadInst16_2(pc)); GateRef value = GetVregValue(sp, vsrc); SetVregValue(glue, sp, vdst, value); DISPATCH(V16_V16); } DECLARE_ASM_HANDLER(HandleLdaStrId32) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef stringId = ReadInst32_0(pc); varAcc = GetValueFromTaggedArray(VariableType::JS_ANY(), constpool, stringId); DISPATCH_WITH_ACC(ID32); } DECLARE_ASM_HANDLER(HandleLdaiDynImm32) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef imm = ReadInst32_0(pc); varAcc = IntBuildTaggedWithNoGC(imm); DISPATCH_WITH_ACC(IMM32); } DECLARE_ASM_HANDLER(HandleFldaiDynImm64) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef imm = CastInt64ToFloat64(ReadInst64_0(pc)); varAcc = DoubleBuildTaggedWithNoGC(imm); DISPATCH_WITH_ACC(IMM64); } DECLARE_ASM_HANDLER(HandleJeqzImm8) { auto env = GetEnvironment(); DEFVARIABLE(varProfileTypeInfo, VariableType::JS_ANY(), profileTypeInfo); DEFVARIABLE(varHotnessCounter, VariableType::INT32(), hotnessCounter); GateRef offset = ReadInstSigned8_0(pc); Label accEqualFalse(env); Label accNotEqualFalse(env); Label accIsInt(env); Label accNotInt(env); Label accEqualZero(env); Label accIsDouble(env); Label last(env); Branch(Int64Equal(ChangeTaggedPointerToInt64(acc), TaggedFalse()), &accEqualFalse, &accNotEqualFalse); Bind(&accNotEqualFalse); { Branch(TaggedIsInt(acc), &accIsInt, &accNotInt); Bind(&accIsInt); { Branch(Int32Equal(TaggedGetInt(acc), Int32(0)), &accEqualFalse, &accNotInt); } Bind(&accNotInt); { Branch(TaggedIsDouble(acc), &accIsDouble, &last); Bind(&accIsDouble); { Branch(DoubleEqual(TaggedCastToDouble(acc), Double(0)), &accEqualFalse, &last); } } } Bind(&accEqualFalse); { Label dispatch(env); Label slowPath(env); UPDATE_HOTNESS(sp); Dispatch(glue, sp, pc, constpool, *varProfileTypeInfo, acc, *varHotnessCounter, SExtInt32ToPtr(offset)); } Bind(&last); Dispatch(glue, sp, pc, constpool, *varProfileTypeInfo, acc, *varHotnessCounter, IntPtr(BytecodeInstruction::Size(BytecodeInstruction::Format::PREF_NONE))); } DECLARE_ASM_HANDLER(HandleJeqzImm16) { auto env = GetEnvironment(); DEFVARIABLE(varProfileTypeInfo, VariableType::JS_ANY(), profileTypeInfo); DEFVARIABLE(varHotnessCounter, VariableType::INT32(), hotnessCounter); GateRef offset = ReadInstSigned16_0(pc); Label accEqualFalse(env); Label accNotEqualFalse(env); Label accIsInt(env); Label accNotInt(env); Label accEqualZero(env); Label accIsDouble(env); Label last(env); Branch(Int64Equal(ChangeTaggedPointerToInt64(acc), TaggedFalse()), &accEqualFalse, &accNotEqualFalse); Bind(&accNotEqualFalse); { Branch(TaggedIsInt(acc), &accIsInt, &accNotInt); Bind(&accIsInt); { Branch(Int32Equal(TaggedGetInt(acc), Int32(0)), &accEqualFalse, &accNotInt); } Bind(&accNotInt); { Branch(TaggedIsDouble(acc), &accIsDouble, &last); Bind(&accIsDouble); { Branch(DoubleEqual(TaggedCastToDouble(acc), Double(0)), &accEqualFalse, &last); } } } Bind(&accEqualFalse); { Label dispatch(env); Label slowPath(env); UPDATE_HOTNESS(sp); Dispatch(glue, sp, pc, constpool, *varProfileTypeInfo, acc, *varHotnessCounter, SExtInt32ToPtr(offset)); } Bind(&last); Dispatch(glue, sp, pc, constpool, *varProfileTypeInfo, acc, *varHotnessCounter, IntPtr(BytecodeInstruction::Size(BytecodeInstruction::Format::IMM16))); } DECLARE_ASM_HANDLER(HandleJnezImm8) { auto env = GetEnvironment(); DEFVARIABLE(varProfileTypeInfo, VariableType::JS_ANY(), profileTypeInfo); DEFVARIABLE(varHotnessCounter, VariableType::INT32(), hotnessCounter); GateRef offset = ReadInstSigned8_0(pc); Label accEqualTrue(env); Label accNotEqualTrue(env); Label accIsInt(env); Label accNotInt(env); Label accEqualZero(env); Label accIsDouble(env); Label last(env); Branch(Int64Equal(ChangeTaggedPointerToInt64(acc), TaggedTrue()), &accEqualTrue, &accNotEqualTrue); Bind(&accNotEqualTrue); { Branch(TaggedIsInt(acc), &accIsInt, &accNotInt); Bind(&accIsInt); { Branch(Int32Equal(TaggedGetInt(acc), Int32(0)), &accNotInt, &accEqualTrue); } Bind(&accNotInt); { Branch(TaggedIsDouble(acc), &accIsDouble, &last); Bind(&accIsDouble); { Branch(DoubleEqual(TaggedCastToDouble(acc), Double(0)), &last, &accEqualTrue); } } } Bind(&accEqualTrue); { Label dispatch(env); Label slowPath(env); UPDATE_HOTNESS(sp); Dispatch(glue, sp, pc, constpool, *varProfileTypeInfo, acc, *varHotnessCounter, SExtInt32ToPtr(offset)); } Bind(&last); Dispatch(glue, sp, pc, constpool, *varProfileTypeInfo, acc, *varHotnessCounter, IntPtr(BytecodeInstruction::Size(BytecodeInstruction::Format::PREF_NONE))); } DECLARE_ASM_HANDLER(HandleJnezImm16) { auto env = GetEnvironment(); DEFVARIABLE(varProfileTypeInfo, VariableType::JS_ANY(), profileTypeInfo); DEFVARIABLE(varHotnessCounter, VariableType::INT32(), hotnessCounter); GateRef offset = ReadInstSigned16_0(pc); Label accEqualTrue(env); Label accNotEqualTrue(env); Label accIsInt(env); Label accNotInt(env); Label accEqualZero(env); Label accIsDouble(env); Label last(env); Branch(Int64Equal(ChangeTaggedPointerToInt64(acc), TaggedTrue()), &accEqualTrue, &accNotEqualTrue); Bind(&accNotEqualTrue); { Branch(TaggedIsInt(acc), &accIsInt, &accNotInt); Bind(&accIsInt); { Branch(Int32Equal(TaggedGetInt(acc), Int32(0)), &accNotInt, &accEqualTrue); } Bind(&accNotInt); { Branch(TaggedIsDouble(acc), &accIsDouble, &last); Bind(&accIsDouble); { Branch(DoubleEqual(TaggedCastToDouble(acc), Double(0)), &last, &accEqualTrue); } } } Bind(&accEqualTrue); { Label dispatch(env); Label slowPath(env); UPDATE_HOTNESS(sp); Dispatch(glue, sp, pc, constpool, *varProfileTypeInfo, acc, *varHotnessCounter, SExtInt32ToPtr(offset)); } Bind(&last); Dispatch(glue, sp, pc, constpool, *varProfileTypeInfo, acc, *varHotnessCounter, IntPtr(BytecodeInstruction::Size(BytecodeInstruction::Format::IMM16))); } DECLARE_ASM_HANDLER(HandleReturnDyn) { auto env = GetEnvironment(); DEFVARIABLE(varPc, VariableType::NATIVE_POINTER(), pc); DEFVARIABLE(varSp, VariableType::NATIVE_POINTER(), sp); DEFVARIABLE(varConstpool, VariableType::JS_POINTER(), constpool); DEFVARIABLE(varProfileTypeInfo, VariableType::JS_POINTER(), profileTypeInfo); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); DEFVARIABLE(varHotnessCounter, VariableType::INT32(), hotnessCounter); Label pcEqualNullptr(env); Label pcNotEqualNullptr(env); Label updateHotness(env); Label tryContinue(env); Label dispatch(env); Label slowPath(env); GateRef frame = GetFrame(*varSp); Branch(TaggedIsUndefined(*varProfileTypeInfo), &updateHotness, &tryContinue); Bind(&updateHotness); { GateRef function = GetFunctionFromFrame(frame); GateRef method = Load(VariableType::NATIVE_POINTER(), function, IntPtr(JSFunctionBase::METHOD_OFFSET)); GateRef fistPC = Load(VariableType::NATIVE_POINTER(), method, IntPtr(JSMethod::GetBytecodeArrayOffset(env->IsArch32Bit()))); GateRef offset = Int32Not(TruncPtrToInt32(PtrSub(*varPc, fistPC))); UPDATE_HOTNESS(*varSp); SetHotnessCounter(glue, method, *varHotnessCounter); Jump(&tryContinue); } Bind(&tryContinue); GateRef currentSp = *varSp; varSp = Load(VariableType::NATIVE_POINTER(), frame, IntPtr(AsmInterpretedFrame::GetBaseOffset(env->IsArch32Bit()))); GateRef prevState = GetFrame(*varSp); varPc = GetPcFromFrame(prevState); Branch(IntPtrEqual(*varPc, IntPtr(0)), &pcEqualNullptr, &pcNotEqualNullptr); Bind(&pcEqualNullptr); { SetAccToFrame(glue, frame, *varAcc); if (env->IsAArch64()) { CallNGCRuntime(glue, RTSTUB_ID(ResumeRspAndReturn), {}); } Return(); } Bind(&pcNotEqualNullptr); { #if !ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK SetCurrentSpFrame(glue, *varSp); GateRef frameTypeOffset = IntPtr(AsmInterpretedFrame::GetBaseOffset(env->IsArch32Bit()) + InterpretedFrameBase::GetTypeOffset(env->IsArch32Bit())); GateRef currentFrameType = Load(VariableType::INT64(), frame, frameTypeOffset); Label isFastNewFrameExit(env); Label interpreterStubReturn(env); Branch(Int64Equal(currentFrameType, Int64(static_cast(FrameType::INTERPRETER_CONSTRUCTOR_FRAME))), &isFastNewFrameExit, &interpreterStubReturn); Bind(&isFastNewFrameExit); { GateRef func = GetFunctionFromFrame(frame); Label accNotEcmaObject(env); Branch(IsEcmaObject(*varAcc), &interpreterStubReturn, &accNotEcmaObject); Bind(&accNotEcmaObject); Label funcIsBase(env); Label funcNotBase(env); Branch(IsBase(func), &funcIsBase, &funcNotBase); Bind(&funcIsBase); { GateRef thisObject = GetThisObjectFromFastNewFrame(*varSp); varAcc = thisObject; Jump(&interpreterStubReturn); } Bind(&funcNotBase); Label accIsUndefined(env); Label accNotUndefined(env); Branch(TaggedIsUndefined(*varAcc), &accIsUndefined, &accNotUndefined); Bind(&accNotUndefined); { SetCurrentSpFrame(glue, currentSp); // Exception should be thrown in currentSp instead of prevSp. CallRuntime(glue, RTSTUB_ID(ThrowDerivedMustReturnException), {}); DISPATCH_LAST(); } Bind(&accIsUndefined); GateRef thisObject = GetThisObjectFromFastNewFrame(*varSp); varAcc = thisObject; Jump(&interpreterStubReturn); } Bind(&interpreterStubReturn); #endif GateRef function = GetFunctionFromFrame(prevState); varConstpool = GetConstpoolFromFunction(function); varProfileTypeInfo = GetProfileTypeInfoFromFunction(function); GateRef method = Load(VariableType::NATIVE_POINTER(), function, IntPtr(JSFunctionBase::METHOD_OFFSET)); varHotnessCounter = GetHotnessCounterFromMethod(method); GateRef jumpSize = GetCallSizeFromFrame(prevState); #if ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK CallNGCRuntime(glue, RTSTUB_ID(ResumeRspAndDispatch), { glue, currentSp, *varPc, *varConstpool, *varProfileTypeInfo, *varAcc, *varHotnessCounter, jumpSize }); Return(); #else Dispatch(glue, *varSp, *varPc, *varConstpool, *varProfileTypeInfo, *varAcc, *varHotnessCounter, jumpSize); #endif } } DECLARE_ASM_HANDLER(HandleReturnUndefinedPref) { auto env = GetEnvironment(); DEFVARIABLE(varPc, VariableType::NATIVE_POINTER(), pc); DEFVARIABLE(varSp, VariableType::NATIVE_POINTER(), sp); DEFVARIABLE(varConstpool, VariableType::JS_POINTER(), constpool); DEFVARIABLE(varProfileTypeInfo, VariableType::JS_POINTER(), profileTypeInfo); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); DEFVARIABLE(varHotnessCounter, VariableType::INT32(), hotnessCounter); Label pcEqualNullptr(env); Label pcNotEqualNullptr(env); Label updateHotness(env); Label tryContinue(env); Label dispatch(env); Label slowPath(env); GateRef frame = GetFrame(*varSp); Branch(TaggedIsUndefined(*varProfileTypeInfo), &updateHotness, &tryContinue); Bind(&updateHotness); { GateRef function = GetFunctionFromFrame(frame); GateRef method = Load(VariableType::NATIVE_POINTER(), function, IntPtr(JSFunctionBase::METHOD_OFFSET)); GateRef fistPC = Load(VariableType::NATIVE_POINTER(), method, IntPtr(JSMethod::GetBytecodeArrayOffset(env->IsArch32Bit()))); GateRef offset = Int32Not(TruncPtrToInt32(PtrSub(*varPc, fistPC))); UPDATE_HOTNESS(*varSp); SetHotnessCounter(glue, method, *varHotnessCounter); Jump(&tryContinue); } Bind(&tryContinue); GateRef currentSp = *varSp; varSp = Load(VariableType::NATIVE_POINTER(), frame, IntPtr(AsmInterpretedFrame::GetBaseOffset(env->IsArch32Bit()))); GateRef prevState = GetFrame(*varSp); varPc = GetPcFromFrame(prevState); varAcc = Undefined(); Branch(IntPtrEqual(*varPc, IntPtr(0)), &pcEqualNullptr, &pcNotEqualNullptr); Bind(&pcEqualNullptr); { SetAccToFrame(glue, frame, *varAcc); if (env->IsAArch64()) { CallNGCRuntime(glue, RTSTUB_ID(ResumeRspAndReturn), {}); } Return(); } Bind(&pcNotEqualNullptr); { #if !ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK SetCurrentSpFrame(glue, *varSp); GateRef frameTypeOffset = IntPtr(AsmInterpretedFrame::GetBaseOffset(env->IsArch32Bit()) + InterpretedFrameBase::GetTypeOffset(env->IsArch32Bit())); GateRef currentFrameType = Load(VariableType::INT64(), frame, frameTypeOffset); Label isFastNewFrameExit(env); Label interpreterStubReturn(env); Branch(Int64Equal(currentFrameType, Int64(static_cast(FrameType::INTERPRETER_CONSTRUCTOR_FRAME))), &isFastNewFrameExit, &interpreterStubReturn); Bind(&isFastNewFrameExit); { GateRef func = GetFunctionFromFrame(frame); Label funcIsBase(env); Label funcNotBase(env); Branch(IsBase(func), &funcIsBase, &funcNotBase); Bind(&funcIsBase); { GateRef thisObject = GetThisObjectFromFastNewFrame(*varSp); varAcc = thisObject; Jump(&interpreterStubReturn); } Bind(&funcNotBase); Label accIsUndefined(env); Label accNotUndefined(env); Branch(TaggedIsUndefined(*varAcc), &accIsUndefined, &accNotUndefined); Bind(&accNotUndefined); { SetCurrentSpFrame(glue, currentSp); // Exception should be thrown in currentSp instead of prevSp. CallRuntime(glue, RTSTUB_ID(ThrowDerivedMustReturnException), {}); DISPATCH_LAST(); } Bind(&accIsUndefined); GateRef thisObject = GetThisObjectFromFastNewFrame(*varSp); varAcc = thisObject; Jump(&interpreterStubReturn); } Bind(&interpreterStubReturn); #endif GateRef function = GetFunctionFromFrame(prevState); varConstpool = GetConstpoolFromFunction(function); varProfileTypeInfo = GetProfileTypeInfoFromFunction(function); GateRef method = Load(VariableType::NATIVE_POINTER(), function, IntPtr(JSFunctionBase::METHOD_OFFSET)); varHotnessCounter = GetHotnessCounterFromMethod(method); GateRef jumpSize = GetCallSizeFromFrame(prevState); #if ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK CallNGCRuntime(glue, RTSTUB_ID(ResumeRspAndDispatch), { glue, currentSp, *varPc, *varConstpool, *varProfileTypeInfo, *varAcc, *varHotnessCounter, jumpSize }); Return(); #else Dispatch(glue, *varSp, *varPc, *varConstpool, *varProfileTypeInfo, *varAcc, *varHotnessCounter, jumpSize); #endif } } DECLARE_ASM_HANDLER(HandleSuspendGeneratorPrefV8V8) { auto env = GetEnvironment(); DEFVARIABLE(varPc, VariableType::NATIVE_POINTER(), pc); DEFVARIABLE(varSp, VariableType::NATIVE_POINTER(), sp); DEFVARIABLE(varConstpool, VariableType::JS_POINTER(), constpool); DEFVARIABLE(varProfileTypeInfo, VariableType::JS_POINTER(), profileTypeInfo); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); DEFVARIABLE(varHotnessCounter, VariableType::INT32(), hotnessCounter); Label pcEqualNullptr(env); Label pcNotEqualNullptr(env); Label updateHotness(env); Label tryContinue(env); Label dispatch(env); Label slowPath(env); GateRef genObj = GetVregValue(sp, ZExtInt8ToPtr(ReadInst8_1(pc))); GateRef value = GetVregValue(sp, ZExtInt8ToPtr(ReadInst8_2(pc))); GateRef frame = GetFrame(*varSp); GateRef res = CallRuntime(glue, RTSTUB_ID(SuspendGenerator), { genObj, value }); Label isException(env); Label notException(env); Branch(TaggedIsException(res), &isException, ¬Exception); Bind(&isException); { DispatchLast(glue, *varSp, *varPc, *varConstpool, *varProfileTypeInfo, *varAcc, *varHotnessCounter); } Bind(¬Exception); varAcc = res; Branch(TaggedIsUndefined(*varProfileTypeInfo), &updateHotness, &tryContinue); Bind(&updateHotness); { GateRef function = GetFunctionFromFrame(frame); GateRef method = Load(VariableType::NATIVE_POINTER(), function, IntPtr(JSFunctionBase::METHOD_OFFSET)); GateRef fistPC = Load(VariableType::NATIVE_POINTER(), method, IntPtr(JSMethod::GetBytecodeArrayOffset(env->IsArch32Bit()))); GateRef offset = Int32Not(TruncPtrToInt32(PtrSub(*varPc, fistPC))); UPDATE_HOTNESS(*varSp); SetHotnessCounter(glue, method, *varHotnessCounter); Jump(&tryContinue); } Bind(&tryContinue); #if ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK GateRef currentSp = *varSp; #endif varSp = Load(VariableType::NATIVE_POINTER(), frame, IntPtr(AsmInterpretedFrame::GetBaseOffset(env->IsArch32Bit()))); GateRef prevState = GetFrame(*varSp); varPc = GetPcFromFrame(prevState); Branch(IntPtrEqual(*varPc, IntPtr(0)), &pcEqualNullptr, &pcNotEqualNullptr); Bind(&pcEqualNullptr); { SetAccToFrame(glue, frame, *varAcc); if (env->IsAArch64()) { CallNGCRuntime(glue, RTSTUB_ID(ResumeRspAndReturn), {}); } Return(); } Bind(&pcNotEqualNullptr); { #if !ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK SetCurrentSpFrame(glue, *varSp); #endif GateRef function = GetFunctionFromFrame(prevState); varConstpool = GetConstpoolFromFunction(function); varProfileTypeInfo = GetProfileTypeInfoFromFunction(function); GateRef method = Load(VariableType::NATIVE_POINTER(), function, IntPtr(JSFunctionBase::METHOD_OFFSET)); varHotnessCounter = GetHotnessCounterFromMethod(method); GateRef jumpSize = GetCallSizeFromFrame(prevState); #if ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK CallNGCRuntime(glue, RTSTUB_ID(ResumeRspAndDispatch), { glue, currentSp, *varPc, *varConstpool, *varProfileTypeInfo, *varAcc, *varHotnessCounter, jumpSize }); Return(); #else Dispatch(glue, *varSp, *varPc, *varConstpool, *varProfileTypeInfo, *varAcc, *varHotnessCounter, jumpSize); #endif } } DECLARE_ASM_HANDLER(ExceptionHandler) { auto env = GetEnvironment(); DEFVARIABLE(varPc, VariableType::NATIVE_POINTER(), pc); DEFVARIABLE(varSp, VariableType::NATIVE_POINTER(), sp); DEFVARIABLE(varConstpool, VariableType::JS_POINTER(), constpool); DEFVARIABLE(varProfileTypeInfo, VariableType::JS_POINTER(), profileTypeInfo); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); DEFVARIABLE(varHotnessCounter, VariableType::INT32(), hotnessCounter); Label pcIsInvalid(env); Label pcNotInvalid(env); GateRef exceptionOffset = IntPtr(JSThread::GlueData::GetExceptionOffset(env->IsArch32Bit())); GateRef exception = Load(VariableType::JS_ANY(), glue, exceptionOffset); varPc = TaggedCastToIntPtr(CallRuntime(glue, RTSTUB_ID(UpFrame), {})); Branch(IntPtrEqual(*varPc, IntPtr(0)), &pcIsInvalid, &pcNotInvalid); Bind(&pcIsInvalid); { if (env->IsAArch64()) { CallNGCRuntime(glue, RTSTUB_ID(ResumeRspAndReturn), {}); } Return(); } Bind(&pcNotInvalid); { varSp = GetCurrentFrame(glue); varAcc = exception; // clear exception Store(VariableType::INT64(), glue, glue, IntPtr(0), Hole()); GateRef function = GetFunctionFromFrame(GetFrame(*varSp)); varConstpool = GetConstpoolFromFunction(function); varProfileTypeInfo = GetProfileTypeInfoFromFunction(function); GateRef method = Load(VariableType::NATIVE_POINTER(), function, IntPtr(JSFunctionBase::METHOD_OFFSET)); varHotnessCounter = GetHotnessCounterFromMethod(method); #if ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK CallNGCRuntime(glue, RTSTUB_ID(ResumeCaughtFrameAndDispatch), { glue, *varSp, *varPc, *varConstpool, *varProfileTypeInfo, *varAcc, *varHotnessCounter}); Return(); #else Dispatch(glue, *varSp, *varPc, *varConstpool, *varProfileTypeInfo, *varAcc, *varHotnessCounter, IntPtr(0)); #endif } } DECLARE_ASM_HANDLER(HandleGetModuleNamespacePrefId32) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef stringId = ReadInst32_1(pc); GateRef prop = GetObjectFromConstPool(constpool, stringId); GateRef moduleRef = CallRuntime(glue, RTSTUB_ID(GetModuleNamespace), { prop }); varAcc = moduleRef; DISPATCH_WITH_ACC(PREF_ID32); } DECLARE_ASM_HANDLER(HandleStModuleVarPrefId32) { GateRef stringId = ReadInst32_1(pc); GateRef prop = GetObjectFromConstPool(constpool, stringId); GateRef value = acc; CallRuntime(glue, RTSTUB_ID(StModuleVar), { prop, value }); DISPATCH(PREF_ID32); } DECLARE_ASM_HANDLER(HandleLdModuleVarPrefId32Imm8) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef stringId = ReadInst32_1(pc); GateRef flag = ReadInst8_5(pc); GateRef key = GetObjectFromConstPool(constpool, stringId); GateRef innerFlag = ZExtInt8ToInt32(flag); GateRef moduleVar = CallRuntime(glue, RTSTUB_ID(LdModuleVar), { key, IntBuildTaggedTypeWithNoGC(innerFlag) }); varAcc = moduleVar; DISPATCH_WITH_ACC(PREF_ID32_IMM8); } DECLARE_ASM_HANDLER(HandleTryLdGlobalByNamePrefId32) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef stringId = ReadInst32_1(pc); GateRef prop = GetObjectFromConstPool(constpool, stringId); Label dispatch(env); Label icAvailable(env); Label icNotAvailable(env); Branch(TaggedIsUndefined(profileTypeInfo), &icNotAvailable, &icAvailable); Bind(&icAvailable); { DEFVARIABLE(icResult, VariableType::JS_ANY(), Undefined()); GateRef slotId = ZExtInt8ToInt32(ReadInst8_0(pc)); GateRef handler = GetValueFromTaggedArray(VariableType::JS_ANY(), profileTypeInfo, slotId); Label isHeapObject(env); Label ldMiss(env); Label icResultCheck(env); Branch(TaggedIsHeapObject(handler), &isHeapObject, &ldMiss); Bind(&isHeapObject); { icResult = LoadGlobal(handler); Branch(TaggedIsHole(*icResult), &ldMiss, &icResultCheck); } Bind(&ldMiss); { GateRef globalObject = GetGlobalObject(glue); icResult = CallRuntime(glue, RTSTUB_ID(LoadMiss), { profileTypeInfo, globalObject, prop, IntBuildTaggedTypeWithNoGC(slotId), IntBuildTaggedTypeWithNoGC(Int32(static_cast(ICKind::NamedGlobalLoadIC))) }); Jump(&icResultCheck); } Bind(&icResultCheck); { Label isException(env); Label isNotException(env); Branch(TaggedIsException(*icResult), &isException, &isNotException); Bind(&isException); { DISPATCH_LAST_WITH_ACC(); } Bind(&isNotException); varAcc = *icResult; Jump(&dispatch); } } Bind(&icNotAvailable); { // order: 1. global record 2. global object // if we find a way to get global record, we can inline LdGlobalRecord directly GateRef recordResult = CallRuntime(glue, RTSTUB_ID(LdGlobalRecord), { prop }); Label isFound(env); Label isNotFound(env); Branch(TaggedIsUndefined(recordResult), &isNotFound, &isFound); Bind(&isNotFound); { GateRef globalResult = CallRuntime(glue, RTSTUB_ID(GetGlobalOwnProperty), { prop }); Label isFoundInGlobal(env); Label slowPath(env); Branch(TaggedIsHole(globalResult), &slowPath, &isFoundInGlobal); Bind(&slowPath); { GateRef slowResult = CallRuntime(glue, RTSTUB_ID(TryLdGlobalByName), { prop }); Label isException(env); Label isNotException(env); Branch(TaggedIsException(slowResult), &isException, &isNotException); Bind(&isException); { DISPATCH_LAST_WITH_ACC(); } Bind(&isNotException); varAcc = slowResult; Jump(&dispatch); } Bind(&isFoundInGlobal); { varAcc = globalResult; Jump(&dispatch); } } Bind(&isFound); { varAcc = Load(VariableType::JS_ANY(), recordResult, IntPtr(PropertyBox::VALUE_OFFSET)); Jump(&dispatch); } } Bind(&dispatch); DISPATCH_WITH_ACC(PREF_ID32); } DECLARE_ASM_HANDLER(HandleTryStGlobalByNamePrefId32) { auto env = GetEnvironment(); GateRef stringId = ReadInst32_1(pc); GateRef propKey = GetObjectFromConstPool(constpool, stringId); DEFVARIABLE(result, VariableType::JS_ANY(), Undefined()); Label checkResult(env); Label dispatch(env); Label icAvailable(env); Label icNotAvailable(env); Branch(TaggedIsUndefined(profileTypeInfo), &icNotAvailable, &icAvailable); Bind(&icAvailable); { GateRef slotId = ZExtInt8ToInt32(ReadInst8_0(pc)); GateRef handler = GetValueFromTaggedArray(VariableType::JS_ANY(), profileTypeInfo, slotId); Label isHeapObject(env); Label stMiss(env); Branch(TaggedIsHeapObject(handler), &isHeapObject, &stMiss); Bind(&isHeapObject); { result = StoreGlobal(glue, acc, handler); Branch(TaggedIsHole(*result), &stMiss, &checkResult); } Bind(&stMiss); { GateRef globalObject = GetGlobalObject(glue); result = CallRuntime(glue, RTSTUB_ID(StoreMiss), { profileTypeInfo, globalObject, propKey, acc, IntBuildTaggedTypeWithNoGC(slotId), IntBuildTaggedTypeWithNoGC(Int32(static_cast(ICKind::NamedGlobalStoreIC))) }); Jump(&checkResult); } } Bind(&icNotAvailable); // order: 1. global record 2. global object // if we find a way to get global record, we can inline LdGlobalRecord directly GateRef recordInfo = CallRuntime(glue, RTSTUB_ID(LdGlobalRecord), { propKey }); Label isFound(env); Label isNotFound(env); Branch(TaggedIsUndefined(recordInfo), &isNotFound, &isFound); Bind(&isFound); { result = CallRuntime(glue, RTSTUB_ID(TryUpdateGlobalRecord), { propKey, acc }); Jump(&checkResult); } Bind(&isNotFound); { Label foundInGlobal(env); Label notFoundInGlobal(env); GateRef globalResult = CallRuntime(glue, RTSTUB_ID(GetGlobalOwnProperty), { propKey }); Branch(TaggedIsHole(globalResult), ¬FoundInGlobal, &foundInGlobal); Bind(¬FoundInGlobal); { result = CallRuntime(glue, RTSTUB_ID(ThrowReferenceError), { propKey }); DISPATCH_LAST(); } Bind(&foundInGlobal); { result = CallRuntime(glue, RTSTUB_ID(StGlobalVar), { propKey, acc }); Jump(&checkResult); } } Bind(&checkResult); { Label isException(env); Branch(TaggedIsException(*result), &isException, &dispatch); Bind(&isException); { DISPATCH_LAST(); } } Bind(&dispatch); DISPATCH(PREF_ID32); } DECLARE_ASM_HANDLER(HandleLdGlobalVarPrefId32) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef stringId = ReadInst32_1(pc); GateRef propKey = GetObjectFromConstPool(constpool, stringId); DEFVARIABLE(result, VariableType::JS_ANY(), Undefined()); Label checkResult(env); Label dispatch(env); Label slowPath(env); GateRef globalObject = GetGlobalObject(glue); Label icAvailable(env); Label icNotAvailable(env); Branch(TaggedIsUndefined(profileTypeInfo), &icNotAvailable, &icAvailable); Bind(&icAvailable); { GateRef slotId = ZExtInt8ToInt32(ReadInst8_0(pc)); GateRef handler = GetValueFromTaggedArray(VariableType::JS_ANY(), profileTypeInfo, slotId); Label isHeapObject(env); Label ldMiss(env); Branch(TaggedIsHeapObject(handler), &isHeapObject, &ldMiss); Bind(&isHeapObject); { result = LoadGlobal(handler); Branch(TaggedIsHole(*result), &ldMiss, &checkResult); } Bind(&ldMiss); { result = CallRuntime(glue, RTSTUB_ID(LoadMiss), { profileTypeInfo, globalObject, propKey, IntBuildTaggedTypeWithNoGC(slotId), IntBuildTaggedTypeWithNoGC(Int32(static_cast(ICKind::NamedGlobalLoadIC))) }); Jump(&checkResult); } } Bind(&icNotAvailable); { result = CallRuntime(glue, RTSTUB_ID(GetGlobalOwnProperty), { propKey }); Branch(TaggedIsHole(*result), &slowPath, &dispatch); Bind(&slowPath); { result = CallRuntime(glue, RTSTUB_ID(LdGlobalVar), { globalObject, propKey }); Jump(&checkResult); } } Bind(&checkResult); { Label isException(env); Branch(TaggedIsException(*result), &isException, &dispatch); Bind(&isException); { DISPATCH_LAST_WITH_ACC(); } } Bind(&dispatch); varAcc = *result; DISPATCH_WITH_ACC(PREF_ID32); } DECLARE_ASM_HANDLER(HandleStGlobalVarPrefId32) { auto env = GetEnvironment(); GateRef stringId = ReadInst32_1(pc); GateRef propKey = GetObjectFromConstPool(constpool, stringId); DEFVARIABLE(result, VariableType::JS_ANY(), Undefined()); Label checkResult(env); Label dispatch(env); Label icAvailable(env); Label icNotAvailable(env); Branch(TaggedIsUndefined(profileTypeInfo), &icNotAvailable, &icAvailable); Bind(&icAvailable); { GateRef slotId = ZExtInt8ToInt32(ReadInst8_0(pc)); GateRef handler = GetValueFromTaggedArray(VariableType::JS_ANY(), profileTypeInfo, slotId); Label isHeapObject(env); Label stMiss(env); Branch(TaggedIsHeapObject(handler), &isHeapObject, &stMiss); Bind(&isHeapObject); { result = StoreGlobal(glue, acc, handler); Branch(TaggedIsHole(*result), &stMiss, &checkResult); } Bind(&stMiss); { GateRef globalObject = GetGlobalObject(glue); result = CallRuntime(glue, RTSTUB_ID(StoreMiss), { profileTypeInfo, globalObject, propKey, acc, IntBuildTaggedTypeWithNoGC(slotId), IntBuildTaggedTypeWithNoGC(Int32(static_cast(ICKind::NamedGlobalStoreIC))) }); Jump(&checkResult); } } Bind(&icNotAvailable); { result = CallRuntime(glue, RTSTUB_ID(StGlobalVar), { propKey, acc }); Jump(&checkResult); } Bind(&checkResult); { Label isException(env); Branch(TaggedIsException(*result), &isException, &dispatch); Bind(&isException); { DISPATCH_LAST(); } } Bind(&dispatch); DISPATCH(PREF_ID32); } DECLARE_ASM_HANDLER(HandleCreateRegExpWithLiteralPrefId32Imm8) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); auto env = GetEnvironment(); GateRef stringId = ReadInst32_1(pc); GateRef pattern = GetObjectFromConstPool(constpool, stringId); GateRef flags = ReadInst8_5(pc); GateRef res = CallRuntime(glue, RTSTUB_ID(CreateRegExpWithLiteral), { pattern, Int8BuildTaggedTypeWithNoGC(flags) }); Label isException(env); Label notException(env); Branch(TaggedIsException(res), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); { varAcc = res; DISPATCH_WITH_ACC(PREF_ID32_IMM8); } } DECLARE_ASM_HANDLER(HandleIsTruePref) { DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); varAcc = FastToBoolean(*varAcc); DISPATCH_WITH_ACC(PREF_NONE); } DECLARE_ASM_HANDLER(HandleIsFalsePref) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); Label isTrue(env); Label isFalse(env); Label dispatch(env); auto result = FastToBoolean(*varAcc); Branch(TaggedIsTrue(result), &isTrue, &isFalse); Bind(&isTrue); { varAcc = ChangeInt64ToTagged(TaggedFalse()); Jump(&dispatch); } Bind(&isFalse); { varAcc = ChangeInt64ToTagged(TaggedTrue()); Jump(&dispatch); } Bind(&dispatch); DISPATCH_WITH_ACC(PREF_NONE); } DECLARE_ASM_HANDLER(HandleToNumberPrefV8) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef v0 = ReadInst8_1(pc); GateRef value = GetVregValue(sp, ZExtInt8ToPtr(v0)); Label valueIsNumber(env); Label valueNotNumber(env); Branch(TaggedIsNumber(value), &valueIsNumber, &valueNotNumber); Bind(&valueIsNumber); { varAcc = value; DISPATCH_WITH_ACC(PREF_V8); } Bind(&valueNotNumber); { GateRef res = CallRuntime(glue, RTSTUB_ID(ToNumber), { value }); Label isException(env); Label notException(env); Branch(TaggedIsException(res), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST_WITH_ACC(); } Bind(¬Exception); { varAcc = res; DISPATCH_WITH_ACC(PREF_V8); } } } DECLARE_ASM_HANDLER(HandleAdd2DynPrefV8) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef v0 = ReadInst8_1(pc); GateRef left = GetVregValue(sp, ZExtInt8ToPtr(v0)); GateRef right = *varAcc; GateRef result = FastAdd(left, right); Label notHole(env), slowPath(env); Label accDispatch(env); Branch(TaggedIsHole(result), &slowPath, ¬Hole); Bind(¬Hole); { varAcc = result; Jump(&accDispatch); } // slow path Bind(&slowPath); { GateRef taggedNumber = CallRuntime(glue, RTSTUB_ID(Add2Dyn), { left, right }); Label isException(env); Label notException(env); Branch(TaggedIsException(taggedNumber), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST_WITH_ACC(); } Bind(¬Exception); { varAcc = taggedNumber; Jump(&accDispatch); } } Bind(&accDispatch); DISPATCH_WITH_ACC(PREF_V8); } DECLARE_ASM_HANDLER(HandleSub2DynPrefV8) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef v0 = ReadInst8_1(pc); GateRef left = GetVregValue(sp, ZExtInt8ToPtr(v0)); GateRef right = *varAcc; GateRef result = FastSub(left, right); Label notHole(env), slowPath(env); Label accDispatch(env); Branch(TaggedIsHole(result), &slowPath, ¬Hole); Bind(¬Hole); { varAcc = result; Jump(&accDispatch); } // slow path Bind(&slowPath); { GateRef taggedNumber = CallRuntime(glue, RTSTUB_ID(Sub2Dyn), { left, right }); Label isException(env); Label notException(env); Branch(TaggedIsException(taggedNumber), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST_WITH_ACC(); } Bind(¬Exception); { varAcc = taggedNumber; Jump(&accDispatch); } } Bind(&accDispatch); DISPATCH_WITH_ACC(PREF_V8); } #define CALL_INITIALIZE() \ SetPcToFrame(glue, GetFrame(sp), pc); \ GateRef func = GetVregValue(sp, ZExtInt8ToPtr(funcReg)); \ Label funcIsHeapObject(env); \ Label funcIsCallable(env); \ Label funcNotCallable(env); \ Branch(TaggedIsHeapObject(func), &funcIsHeapObject, &funcNotCallable); \ Bind(&funcIsHeapObject); \ Branch(IsCallable(func), &funcIsCallable, &funcNotCallable); \ Bind(&funcNotCallable); \ { \ CallRuntime(glue, RTSTUB_ID(ThrowNotCallableException), {}); \ DISPATCH_LAST(); \ } \ Bind(&funcIsCallable); \ GateRef method = GetMethodFromJSFunction(func); \ GateRef callField = GetCallFieldFromMethod(method); \ DEFVARIABLE(newSp, VariableType::NATIVE_POINTER(), \ PointerSub(sp, IntPtr(AsmInterpretedFrame::GetSize(env->IsArch32Bit())))) #define CALL_PUSH_ARGS(format) \ DEFVARIABLE(i, VariableType::INT32(), Int32(0)); \ GateRef isNativeMask = Int64(static_cast(1) << JSMethod::IsNativeBit::START_BIT); \ Label methodIsNative(env); \ Label methodNotNative(env); \ Branch(Int64NotEqual(Int64And(callField, isNativeMask), Int64(0)), &methodIsNative, &methodNotNative); \ Bind(&methodIsNative); \ { \ CALL_PUSH_ARGS_##format(); \ SET_VREGS_AND_FRAME_NATIVE(format); \ } \ Bind(&methodNotNative); \ GateRef numArgsOffset = Int64(JSMethod::NumArgsBits::START_BIT); \ GateRef numArgsMask = Int64((static_cast(1) << JSMethod::NumArgsBits::SIZE) - 1); \ GateRef declaredNumArgs = ChangeInt64ToInt32(Int64And(Int64LSR(callField, numArgsOffset), numArgsMask)); \ Label fastPath(env); \ Label slowPath(env); \ Label setVregsAndFrameNotNative(env); \ Branch(Int32Equal(actualNumArgs, declaredNumArgs), &fastPath, &slowPath); \ Bind(&fastPath); \ { \ CALL_PUSH_ARGS_##format(); \ Jump(&setVregsAndFrameNotNative); \ } \ Bind(&slowPath); \ GateRef haveExtraMask = Int64(static_cast(1) << JSMethod::HaveExtraBit::START_BIT); \ Label methodNoExtra(env); \ Label methodHaveExtra(env); \ Branch(Int64NotEqual(Int64And(callField, haveExtraMask), Int64(0)), &methodHaveExtra, &methodNoExtra); \ Bind(&methodNoExtra); \ { \ GateRef undefinedNumArgs = Int32Sub(declaredNumArgs, actualNumArgs); \ newSp = PushUndefined(glue, *newSp, undefinedNumArgs); \ CALL_PUSH_ARGS_NO_EXTRA_##format(); \ Jump(&setVregsAndFrameNotNative); \ } \ Bind(&methodHaveExtra); \ { \ newSp = PushArg(glue, *newSp, IntBuildTaggedTypeWithNoGC(actualNumArgs)); \ GateRef undefinedNumArgs = Int32Sub(declaredNumArgs, actualNumArgs); \ newSp = PushUndefined(glue, *newSp, undefinedNumArgs); \ CALL_PUSH_ARGS_##format(); \ Jump(&setVregsAndFrameNotNative); \ } \ Bind(&setVregsAndFrameNotNative); \ SET_VREGS_AND_FRAME_NOT_NATIVE(format) #define SET_VREGS_AND_FRAME_NATIVE(format) \ Label pushThis(env); \ Label pushThisUndefined(env); \ Label pushNewTarget(env); \ Branch(callThis, &pushThis, &pushThisUndefined); \ Bind(&pushThis); \ { \ GateRef thisValue = GetVregValue(sp, PtrAdd(ZExtInt8ToPtr(funcReg), IntPtr(1))); \ newSp = PushArg(glue, *newSp, thisValue); \ Jump(&pushNewTarget); \ } \ Bind(&pushThisUndefined); \ { \ newSp = PushArg(glue, *newSp, Int64(JSTaggedValue::VALUE_UNDEFINED)); \ Jump(&pushNewTarget); \ } \ Bind(&pushNewTarget); \ newSp = PushArg(glue, *newSp, Int64(JSTaggedValue::VALUE_UNDEFINED)); \ newSp = PushArg(glue, *newSp, func); \ /* ASSERT(JSMethod::NumVregsBits::Decode(callField) == 0) */ \ Label stackOverflow(env); \ Label stackNotOverflow(env); \ Branch(CheckStackOverflow(glue, *newSp), &stackOverflow, &stackNotOverflow); \ Bind(&stackOverflow); \ { \ CallRuntime(glue, RTSTUB_ID(ThrowStackOverflowException), {}); \ DISPATCH_LAST(); \ } \ Bind(&stackNotOverflow); \ SetFrameState(glue, *newSp, func, Hole(VariableType::JS_ANY()), \ Hole(VariableType::JS_ANY()), IntPtr(0), sp, \ Int64(static_cast(FrameType::ASM_INTERPRETER_FRAME))); \ SetCurrentSpFrame(glue, *newSp); \ GateRef retValue = CallRuntime(glue, RTSTUB_ID(CallNative), \ {IntBuildTaggedTypeWithNoGC(actualNumArgs)}); \ SetCurrentSpFrame(glue, sp); \ Label hasPendingException(env); \ Label noPendingException(env); \ Branch(TaggedIsException(retValue), &hasPendingException, &noPendingException); \ Bind(&hasPendingException); \ { \ DISPATCH_LAST(); \ } \ Bind(&noPendingException); \ DEFVARIABLE(varAcc, VariableType::JS_ANY(), retValue); \ DISPATCH_WITH_ACC(format) #define SET_VREGS_AND_FRAME_NOT_NATIVE(format) \ Label funcIsClassConstructor(env); \ Label funcNotClassConstructor(env); \ Branch(IsClassConstructor(func), &funcIsClassConstructor, &funcNotClassConstructor); \ Bind(&funcIsClassConstructor); \ { \ CallRuntime(glue, RTSTUB_ID(ThrowCallConstructorException), {}); \ DISPATCH_LAST(); \ } \ Bind(&funcNotClassConstructor); \ Label notNormalCallType(env); \ Label isNormalCallType(env); \ Branch(Int64Equal(Int64And(callField, Int64(CALL_TYPE_MASK)), Int64(0)), \ &isNormalCallType, ¬NormalCallType); \ Bind(¬NormalCallType); \ { \ GateRef haveThisMask = Int64(static_cast(1) << JSMethod::HaveThisBit::START_BIT); \ Label methodHaveThis(env); \ Label methodNoThis(env); \ Branch(Int64NotEqual(Int64And(callField, haveThisMask), Int64(0)), \ &methodHaveThis, &methodNoThis); \ Bind(&methodHaveThis); \ { \ Label pushThis(env); \ Label pushThisUndefined(env); \ Branch(callThis, &pushThis, &pushThisUndefined); \ Bind(&pushThis); \ { \ GateRef thisValue = GetVregValue(sp, PtrAdd(ZExtInt8ToPtr(funcReg), IntPtr(1))); \ newSp = PushArg(glue, *newSp, thisValue); \ Jump(&methodNoThis); \ } \ Bind(&pushThisUndefined); \ { \ newSp = PushArg(glue, *newSp, Int64(JSTaggedValue::VALUE_UNDEFINED)); \ Jump(&methodNoThis); \ } \ } \ Bind(&methodNoThis); \ GateRef haveNewTargetMask = Int64(static_cast(1) << JSMethod::HaveNewTargetBit::START_BIT); \ Label methodHaveNewTarget(env); \ Label methodNoNewTarget(env); \ Branch(Int64NotEqual(Int64And(callField, haveNewTargetMask), Int64(0)), \ &methodHaveNewTarget, &methodNoNewTarget); \ Bind(&methodHaveNewTarget); \ { \ newSp = PushArg(glue, *newSp, Int64(JSTaggedValue::VALUE_UNDEFINED)); \ Jump(&methodNoNewTarget); \ } \ Bind(&methodNoNewTarget); \ GateRef haveFuncMask = Int64(static_cast(1) << JSMethod::HaveFuncBit::START_BIT); \ Label methodHaveFunc(env); \ Label methodNoFunc(env); \ Branch(Int64NotEqual(Int64And(callField, haveFuncMask), Int64(0)), \ &methodHaveFunc, &methodNoFunc); \ Bind(&methodHaveFunc); \ { \ newSp = PushArg(glue, *newSp, func); \ Jump(&methodNoFunc); \ } \ Bind(&methodNoFunc); \ Jump(&isNormalCallType); \ } \ Bind(&isNormalCallType); \ { \ GateRef numVregsOffset = Int64(JSMethod::NumVregsBits::START_BIT); \ GateRef numVregsMask = Int64((static_cast(1) << JSMethod::NumVregsBits::SIZE) - 1); \ GateRef numVregs = ChangeInt64ToInt32(Int64And(Int64LSR(callField, numVregsOffset), numVregsMask)); \ newSp = PushUndefined(glue, *newSp, numVregs); \ Label stackOverflow(env); \ Label stackNotOverflow(env); \ Branch(CheckStackOverflow(glue, *newSp), &stackOverflow, &stackNotOverflow); \ Bind(&stackOverflow); \ { \ CallRuntime(glue, RTSTUB_ID(ThrowStackOverflowException), {}); \ DISPATCH_LAST(); \ } \ Bind(&stackNotOverflow); \ SetCallSizeToFrame(glue, GetFrame(sp), \ IntPtr(BytecodeInstruction::Size(BytecodeInstruction::Format::format))); \ GateRef newEnv = GetEnvFromFunction(func); \ GateRef bytecodeArrayOffset = IntPtr(JSMethod::GetBytecodeArrayOffset(env->IsArch32Bit())); \ GateRef bytecodeArray = Load(VariableType::NATIVE_POINTER(), method, bytecodeArrayOffset); \ SetFrameState(glue, *newSp, func, Hole(VariableType::JS_ANY()), newEnv, bytecodeArray, sp, \ Int64(static_cast(FrameType::ASM_INTERPRETER_FRAME))); \ SetCurrentSpFrame(glue, *newSp); \ GateRef newConstpool = GetConstpoolFromFunction(func); \ GateRef newProfileTypeInfo = GetProfileTypeInfoFromFunction(func); \ GateRef newHotnessCounter = GetHotnessCounterFromMethod(method); \ Dispatch(glue, *newSp, bytecodeArray, newConstpool, newProfileTypeInfo, \ Hole(VariableType::JS_ANY()), newHotnessCounter, IntPtr(0)); \ } #define CALL_PUSH_ARGS_PREF_V8() \ static_cast(0) // do nothing when 0 arg #define CALL_PUSH_ARGS_NO_EXTRA_PREF_V8() \ static_cast(0) // do nothing when 0 arg #define CALL_PUSH_ARGS_PREF_V8_V8() \ GateRef a0Value = GetVregValue(sp, ZExtInt8ToPtr(a0)); \ newSp = PushArg(glue, *newSp, a0Value) #define CALL_PUSH_ARGS_NO_EXTRA_PREF_V8_V8() \ Label push0(env); \ Label skip0(env); \ Branch(Int32GreaterThanOrEqual(declaredNumArgs, \ Int32(InterpreterAssembly::ActualNumArgsOfCall::CALLARG1)), &push0, &skip0); \ Bind(&push0); \ { \ GateRef a0Value = GetVregValue(sp, ZExtInt8ToPtr(a0)); \ newSp = PushArg(glue, *newSp, a0Value); \ Jump(&skip0); \ } \ Bind(&skip0) #define CALL_PUSH_ARGS_PREF_V8_V8_V8() \ GateRef a1Value = GetVregValue(sp, ZExtInt8ToPtr(a1)); \ newSp = PushArg(glue, *newSp, a1Value); \ CALL_PUSH_ARGS_PREF_V8_V8() #define CALL_PUSH_ARGS_NO_EXTRA_PREF_V8_V8_V8() \ Label push1(env); \ Label skip1(env); \ Branch(Int32GreaterThanOrEqual(declaredNumArgs, \ Int32(InterpreterAssembly::ActualNumArgsOfCall::CALLARGS2)), &push1, &skip1); \ Bind(&push1); \ { \ GateRef a1Value = GetVregValue(sp, ZExtInt8ToPtr(a1)); \ newSp = PushArg(glue, *newSp, a1Value); \ Jump(&skip1); \ } \ Bind(&skip1); \ CALL_PUSH_ARGS_NO_EXTRA_PREF_V8_V8() #define CALL_PUSH_ARGS_PREF_V8_V8_V8_V8() \ GateRef a2Value = GetVregValue(sp, ZExtInt8ToPtr(a2)); \ newSp = PushArg(glue, *newSp, a2Value); \ CALL_PUSH_ARGS_PREF_V8_V8_V8() #define CALL_PUSH_ARGS_NO_EXTRA_PREF_V8_V8_V8_V8() \ Label push2(env); \ Label skip2(env); \ Branch(Int32GreaterThanOrEqual(declaredNumArgs, \ Int32(InterpreterAssembly::ActualNumArgsOfCall::CALLARGS3)), &push2, &skip2); \ Bind(&push2); \ { \ GateRef a2Value = GetVregValue(sp, ZExtInt8ToPtr(a2)); \ newSp = PushArg(glue, *newSp, a2Value); \ Jump(&skip2); \ } \ Bind(&skip2); \ CALL_PUSH_ARGS_NO_EXTRA_PREF_V8_V8_V8() #define CALL_PUSH_ARGS_PREF_IMM16_V8() \ i = actualNumArgs; \ CALL_PUSH_ARGS_I() #define CALL_PUSH_ARGS_NO_EXTRA_PREF_IMM16_V8() \ /* i = std::min(actualNumArgs, declaredNumArgs) */ \ i = actualNumArgs; \ Label declaredNumArgsSmaller(env); \ Label callPushArgsI(env); \ Branch(Int32LessThan(*i, declaredNumArgs), &callPushArgsI, &declaredNumArgsSmaller); \ Bind(&declaredNumArgsSmaller); \ i = declaredNumArgs; \ Jump(&callPushArgsI); \ Bind(&callPushArgsI); \ CALL_PUSH_ARGS_I() #define CALL_PUSH_ARGS_I() \ Label pushWithThis(env); \ Label pushWithoutThis(env); \ Label pushArgsEnd(env); \ Branch(callThis, &pushWithThis, &pushWithoutThis); \ Bind(&pushWithThis); \ { \ i = Int32Add(*i, Int32(1)); /* 1: skip this */ \ GateRef startIndex = Int32Add(ZExtInt8ToInt32(funcReg), Int32(2)); /* 2: skip this */ \ GateRef endIndex = Int32Add(ZExtInt8ToInt32(funcReg), *i); \ newSp = PushRange(glue, *newSp, sp, startIndex, endIndex); \ Jump(&pushArgsEnd); \ } \ Bind(&pushWithoutThis); \ { \ GateRef startIndex = Int32Add(ZExtInt8ToInt32(funcReg), Int32(1)); \ GateRef endIndex = Int32Add(ZExtInt8ToInt32(funcReg), *i); \ newSp = PushRange(glue, *newSp, sp, startIndex, endIndex); \ Jump(&pushArgsEnd); \ } \ Bind(&pushArgsEnd) DECLARE_ASM_HANDLER(HandleCallArg0DynPrefV8) { GateRef actualNumArgs = Int32(InterpreterAssembly::ActualNumArgsOfCall::CALLARG0); GateRef funcReg = ReadInst8_1(pc); #if ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK USE_PARAMS() GateRef func = GetVregValue(sp, ZExtInt8ToPtr(funcReg)); GateRef jumpSize = IntPtr(BytecodeInstruction::Size(BytecodeInstruction::Format::PREF_V8)); JSCallDispatch(glue, func, actualNumArgs, jumpSize, JSCallMode::CALL_ARG0, {}); #else auto env = GetEnvironment(); CALL_INITIALIZE(); GateRef callThis = False(); CALL_PUSH_ARGS(PREF_V8); #endif } DECLARE_ASM_HANDLER(HandleCallArg1DynPrefV8V8) { GateRef actualNumArgs = Int32(InterpreterAssembly::ActualNumArgsOfCall::CALLARG1); GateRef funcReg = ReadInst8_1(pc); GateRef a0 = ReadInst8_2(pc); #if ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK USE_PARAMS() GateRef func = GetVregValue(sp, ZExtInt8ToPtr(funcReg)); GateRef a0Value = GetVregValue(sp, ZExtInt8ToPtr(a0)); GateRef jumpSize = IntPtr(BytecodeInstruction::Size(BytecodeInstruction::Format::PREF_V8_V8)); JSCallDispatch(glue, func, actualNumArgs, jumpSize, JSCallMode::CALL_ARG1, { a0Value }); #else auto env = GetEnvironment(); CALL_INITIALIZE(); GateRef callThis = False(); CALL_PUSH_ARGS(PREF_V8_V8); #endif } DECLARE_ASM_HANDLER(HandleCallArgs2DynPrefV8V8V8) { GateRef actualNumArgs = Int32(InterpreterAssembly::ActualNumArgsOfCall::CALLARGS2); GateRef funcReg = ReadInst8_1(pc); GateRef a0 = ReadInst8_2(pc); GateRef a1 = ReadInst8_3(pc); #if ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK USE_PARAMS() GateRef func = GetVregValue(sp, ZExtInt8ToPtr(funcReg)); GateRef a0Value = GetVregValue(sp, ZExtInt8ToPtr(a0)); GateRef a1Value = GetVregValue(sp, ZExtInt8ToPtr(a1)); GateRef jumpSize = IntPtr(BytecodeInstruction::Size(BytecodeInstruction::Format::PREF_V8_V8_V8)); JSCallDispatch(glue, func, actualNumArgs, jumpSize, JSCallMode::CALL_ARG2, { a0Value, a1Value }); #else auto env = GetEnvironment(); CALL_INITIALIZE(); GateRef callThis = False(); CALL_PUSH_ARGS(PREF_V8_V8_V8); #endif } DECLARE_ASM_HANDLER(HandleCallArgs3DynPrefV8V8V8V8) { GateRef actualNumArgs = Int32(InterpreterAssembly::ActualNumArgsOfCall::CALLARGS3); GateRef funcReg = ReadInst8_1(pc); GateRef a0 = ReadInst8_2(pc); GateRef a1 = ReadInst8_3(pc); GateRef a2 = ReadInst8_4(pc); #if ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK USE_PARAMS() GateRef func = GetVregValue(sp, ZExtInt8ToPtr(funcReg)); GateRef a0Value = GetVregValue(sp, ZExtInt8ToPtr(a0)); GateRef a1Value = GetVregValue(sp, ZExtInt8ToPtr(a1)); GateRef a2Value = GetVregValue(sp, ZExtInt8ToPtr(a2)); GateRef jumpSize = IntPtr(BytecodeInstruction::Size(BytecodeInstruction::Format::PREF_V8_V8_V8_V8)); JSCallDispatch(glue, func, actualNumArgs, jumpSize, JSCallMode::CALL_ARG3, { a0Value, a1Value, a2Value }); #else auto env = GetEnvironment(); CALL_INITIALIZE(); GateRef callThis = False(); CALL_PUSH_ARGS(PREF_V8_V8_V8_V8); #endif } DECLARE_ASM_HANDLER(HandleCallIRangeDynPrefImm16V8) { GateRef actualNumArgs = ZExtInt16ToInt32(ReadInst16_1(pc)); GateRef funcReg = ReadInst8_3(pc); #if ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK USE_PARAMS() GateRef func = GetVregValue(sp, ZExtInt8ToPtr(funcReg)); GateRef argv = PtrAdd(sp, PtrMul( PtrAdd(ZExtInt8ToPtr(funcReg), IntPtr(1)), IntPtr(8))); // 1: skip function GateRef jumpSize = IntPtr(BytecodeInstruction::Size(BytecodeInstruction::Format::PREF_IMM16_V8)); GateRef numArgs = ChangeInt32ToIntPtr(actualNumArgs); JSCallDispatch(glue, func, actualNumArgs, jumpSize, JSCallMode::CALL_WITH_ARGV, { numArgs, argv }); #else auto env = GetEnvironment(); CALL_INITIALIZE(); GateRef callThis = False(); CALL_PUSH_ARGS(PREF_IMM16_V8); #endif } DECLARE_ASM_HANDLER(HandleCallIThisRangeDynPrefImm16V8) { GateRef actualNumArgs = Int32Sub(ZExtInt16ToInt32(ReadInst16_1(pc)), Int32(1)); // 1: exclude this GateRef funcReg = ReadInst8_3(pc); #if ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK USE_PARAMS() GateRef func = GetVregValue(sp, ZExtInt8ToPtr(funcReg)); GateRef argv = PtrAdd(sp, PtrMul( PtrAdd(ZExtInt8ToPtr(funcReg), IntPtr(2)), IntPtr(8))); // 2: skip function&this GateRef jumpSize = IntPtr(BytecodeInstruction::Size(BytecodeInstruction::Format::PREF_IMM16_V8)); GateRef numArgs = ChangeInt32ToIntPtr(actualNumArgs); JSCallDispatch(glue, func, actualNumArgs, jumpSize, JSCallMode::CALL_THIS_WITH_ARGV, { numArgs, argv }); #else auto env = GetEnvironment(); CALL_INITIALIZE(); GateRef callThis = True(); CALL_PUSH_ARGS(PREF_IMM16_V8); #endif } DECLARE_ASM_HANDLER(HandleLdBigIntPrefId32) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef stringId = ReadInst32_1(pc); GateRef numberBigInt = GetObjectFromConstPool(constpool, stringId); GateRef res = CallRuntime(glue, RTSTUB_ID(LdBigInt), { numberBigInt }); Label isException(env); Label notException(env); Branch(TaggedIsException(res), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); varAcc = res; DISPATCH_WITH_ACC(PREF_ID32); } DECLARE_ASM_HANDLER(HandleNewLexEnvWithNameDynPrefImm16Imm16) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); GateRef numVars = ReadInst16_1(pc); GateRef scopeId = ReadInst16_3(pc); GateRef res = CallRuntime(glue, RTSTUB_ID(NewLexicalEnvWithNameDyn), { Int16BuildTaggedTypeWithNoGC(numVars), Int16BuildTaggedTypeWithNoGC(scopeId) }); Label isException(env); Label notException(env); Branch(TaggedIsException(res), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); varAcc = res; GateRef state = GetFrame(sp); SetEnvToFrame(glue, state, res); DISPATCH_WITH_ACC(PREF_IMM16_IMM16); } void InterpreterStub::JSCallDispatch(GateRef glue, GateRef func, GateRef actualNumArgs, GateRef jumpSize, JSCallMode mode, std::initializer_list args) { auto env = GetEnvironment(); GateRef sp = PtrArgument(static_cast(InterpreterHandlerInputs::SP)); GateRef pc = PtrArgument(static_cast(InterpreterHandlerInputs::PC)); GateRef constpool = TaggedPointerArgument( static_cast(InterpreterHandlerInputs::CONSTPOOL)); GateRef profileTypeInfo = TaggedPointerArgument( static_cast(InterpreterHandlerInputs::PROFILE_TYPE_INFO)); GateRef acc = TaggedArgument(static_cast(InterpreterHandlerInputs::ACC)); GateRef hotnessCounter = Int32Argument( static_cast(InterpreterHandlerInputs::HOTNESS_COUNTER)); // 1. call initialize Label funcIsHeapObject(env); Label funcIsCallable(env); Label funcNotCallable(env); // save pc SetPcToFrame(glue, GetFrame(sp), pc); Branch(TaggedIsHeapObject(func), &funcIsHeapObject, &funcNotCallable); Bind(&funcIsHeapObject); Branch(IsCallable(func), &funcIsCallable, &funcNotCallable); Bind(&funcNotCallable); { CallRuntime(glue, RTSTUB_ID(ThrowNotCallableException), {}); DISPATCH_LAST(); } Bind(&funcIsCallable); GateRef method = GetMethodFromJSFunction(func); GateRef callField = GetCallFieldFromMethod(method); GateRef isNativeMask = Int64(static_cast(1) << JSMethod::IsNativeBit::START_BIT); // 2. call dispatch Label methodIsNative(env); Label methodNotNative(env); Branch(Int64NotEqual(Int64And(callField, isNativeMask), Int64(0)), &methodIsNative, &methodNotNative); auto data = std::begin(args); // 3. call native Bind(&methodIsNative); { GateRef nativeCode = Load(VariableType::NATIVE_POINTER(), method, IntPtr(JSMethod::GetBytecodeArrayOffset(env->IsArch32Bit()))); GateRef retValue = 0; GateRef newTarget = Undefined(); GateRef thisValue = Undefined(); switch (mode) { case JSCallMode::CALL_ARG0: retValue = CallNGCRuntime(glue, RTSTUB_ID(PushCallArgsAndDispatchNative), { glue, nativeCode, actualNumArgs, func, newTarget, thisValue }); break; case JSCallMode::CALL_ARG1: retValue = CallNGCRuntime(glue, RTSTUB_ID(PushCallArgsAndDispatchNative), { glue, nativeCode, actualNumArgs, func, newTarget, thisValue, data[0]}); break; case JSCallMode::CALL_ARG2: retValue = CallNGCRuntime(glue, RTSTUB_ID(PushCallArgsAndDispatchNative), { glue, nativeCode, actualNumArgs, func, newTarget, thisValue, data[0], data[1] }); break; case JSCallMode::CALL_ARG3: retValue = CallNGCRuntime(glue, RTSTUB_ID(PushCallArgsAndDispatchNative), { glue, nativeCode, actualNumArgs, func, newTarget, thisValue, data[0], data[1], data[2] }); break; case JSCallMode::CALL_THIS_WITH_ARGV: { auto argv = data[1]; thisValue = GetVregValue(argv, IntPtr(-1)); // -1: this is just before argv [[fallthrough]]; } case JSCallMode::CALL_WITH_ARGV: retValue = CallNGCRuntime(glue, RTSTUB_ID(PushCallIRangeAndDispatchNative), { glue, nativeCode, func, thisValue, data[0], data[1] }); break; case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV: break; default: UNREACHABLE(); } Label hasPendingException(env); Label noPendingException(env); Branch(TaggedIsException(retValue), &hasPendingException, &noPendingException); Bind(&hasPendingException); { DISPATCH_LAST(); } Bind(&noPendingException); Dispatch(glue, sp, pc, constpool, profileTypeInfo, retValue, hotnessCounter, jumpSize); } // 4. call nonNative Bind(&methodNotNative); GateRef numArgsOffset = Int64(JSMethod::NumArgsBits::START_BIT); GateRef numArgsMask = Int64((static_cast(1) << JSMethod::NumArgsBits::SIZE) - 1); GateRef declaredNumArgs = ChangeInt64ToInt32(Int64And(Int64LSR(callField, numArgsOffset), numArgsMask)); Label fastPath(env); Label slowPath(env); // 5. fast call Branch(Int32Equal(actualNumArgs, declaredNumArgs), &fastPath, &slowPath); Bind(&fastPath); { switch (mode) { case JSCallMode::CALL_ARG0: CallNGCRuntime(glue, RTSTUB_ID(PushCallArgs0AndDispatch), { glue, sp, func, method, callField }); break; case JSCallMode::CALL_ARG1: CallNGCRuntime(glue, RTSTUB_ID(PushCallArgs1AndDispatch), { glue, sp, func, method, callField, data[0] }); break; case JSCallMode::CALL_ARG2: CallNGCRuntime(glue, RTSTUB_ID(PushCallArgs2AndDispatch), { glue, sp, func, method, callField, data[0], data[1] }); break; case JSCallMode::CALL_ARG3: CallNGCRuntime(glue, RTSTUB_ID(PushCallArgs3AndDispatch), { glue, sp, func, method, callField, data[0], data[1], data[2] }); break; case JSCallMode::CALL_WITH_ARGV: CallNGCRuntime(glue, RTSTUB_ID(PushCallIRangeAndDispatch), { glue, sp, func, method, callField, data[0], data[1] }); break; case JSCallMode::CALL_THIS_WITH_ARGV: CallNGCRuntime(glue, RTSTUB_ID(PushCallIThisRangeAndDispatch), { glue, sp, func, method, callField, data[0], data[1] }); break; case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV: break; default: UNREACHABLE(); } Return(); } // 6. slow call Bind(&slowPath); { switch (mode) { case JSCallMode::CALL_ARG0: CallNGCRuntime(glue, RTSTUB_ID(PushCallArgs0AndDispatchSlowPath), { glue, sp, func, method, callField }); break; case JSCallMode::CALL_ARG1: CallNGCRuntime(glue, RTSTUB_ID(PushCallArgs1AndDispatchSlowPath), { glue, sp, func, method, callField, data[0] }); break; case JSCallMode::CALL_ARG2: CallNGCRuntime(glue, RTSTUB_ID(PushCallArgs2AndDispatchSlowPath), { glue, sp, func, method, callField, data[0], data[1] }); break; case JSCallMode::CALL_ARG3: CallNGCRuntime(glue, RTSTUB_ID(PushCallArgs3AndDispatchSlowPath), { glue, sp, func, method, callField, data[0], data[1], data[2] }); break; case JSCallMode::CALL_WITH_ARGV: CallNGCRuntime(glue, RTSTUB_ID(PushCallIRangeAndDispatchSlowPath), { glue, sp, func, method, callField, data[0], data[1] }); break; case JSCallMode::CALL_THIS_WITH_ARGV: CallNGCRuntime(glue, RTSTUB_ID(PushCallIThisRangeAndDispatchSlowPath), { glue, sp, func, method, callField, data[0], data[1] }); break; case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV: break; default: UNREACHABLE(); } Return(); } } #undef DECLARE_ASM_HANDLER #undef DISPATCH #undef DISPATCH_WITH_ACC #undef DISPATCH_LAST #undef DISPATCH_LAST_WITH_ACC #undef USE_PARAMS } // namespace panda::ecmascript::kungfu