/* * 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); 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), { IntToTaggedTypeNGC(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), { Int16ToTaggedTypeNGC(numKeys), obj, Int16ToTaggedTypeNGC(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), { Int16ToTaggedTypeNGC(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 state = GetFrame(sp); auto parent = GetEnvFromFrame(state); GateRef res = NewLexicalEnv(glue, ZExtInt16ToInt32(numVars), parent); 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); DEFVARIABLE(res, VariableType::JS_ANY(), Undefined()); DEFVARIABLE(thisObj, VariableType::JS_ANY(), Undefined()); 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 actualNumArgs = ZExtInt16ToInt32(Int16Sub(numArgs, firstArgOffset)); Label ctorIsHeapObject(env); Label ctorIsJSFunction(env); Label fastPath(env); Label slowPath(env); Label checkResult(env); Label threadCheck(env); Label dispatch(env); Label ctorIsBase(env); Label ctorNotBase(env); Label isException(env); Label callRuntime(env); Label newObject(env); Label newObjectCheckException(env); GateRef isBase = IsBase(ctor); Branch(TaggedIsHeapObject(ctor), &ctorIsHeapObject, &slowPath); Bind(&ctorIsHeapObject); Branch(IsJSFunction(ctor), &ctorIsJSFunction, &slowPath); Bind(&ctorIsJSFunction); Branch(IsConstructor(ctor), &fastPath, &slowPath); Bind(&fastPath); { Branch(isBase, &ctorIsBase, &ctorNotBase); Bind(&ctorIsBase); { Label isHeapObject(env); Label checkJSObject(env); auto protoOrHclass = Load(VariableType::JS_ANY(), ctor, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET)); Branch(TaggedIsHeapObject(protoOrHclass), &isHeapObject, &callRuntime); Bind(&isHeapObject); Branch(IsJSHClass(protoOrHclass), &checkJSObject, &callRuntime); Bind(&checkJSObject); auto objectType = GetObjectType(protoOrHclass); Branch(Int32Equal(objectType, Int32(static_cast(JSType::JS_OBJECT))), &newObject, &callRuntime); Bind(&newObject); { thisObj = NewJSObject(glue, protoOrHclass); Jump(&newObjectCheckException); } Bind(&callRuntime); { thisObj = CallRuntime(glue, RTSTUB_ID(NewThisObject), {ctor}); Jump(&newObjectCheckException); } Bind(&newObjectCheckException); Branch(TaggedIsException(*res), &isException, &ctorNotBase); } Bind(&ctorNotBase); GateRef argv = PtrAdd(sp, PtrMul( PtrAdd(firstArgRegIdx, firstArgOffset), IntPtr(8))); // 8: skip function&this res = JSCallDispatch(glue, ctor, actualNumArgs, JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV, { ChangeInt32ToIntPtr(actualNumArgs), argv, *thisObj }); Jump(&threadCheck); } Bind(&slowPath); GateRef firstArgIdx = Int16Add(firstArgRegIdx, firstArgOffset); GateRef length = Int16Sub(numArgs, firstArgOffset); res = CallRuntime(glue, RTSTUB_ID(NewObjDynRange), { ctor, ctor, Int16ToTaggedTypeNGC(firstArgIdx), Int16ToTaggedTypeNGC(length) }); Jump(&checkResult); Bind(&checkResult); { Branch(TaggedIsException(*res), &isException, &dispatch); } Bind(&threadCheck); { Branch(HasPendingException(glue), &isException, &dispatch); } Bind(&isException); { DISPATCH_LAST(); } Bind(&dispatch); 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, Int16ToTaggedNGC(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, Int16ToTaggedNGC(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, Int16ToTaggedNGC(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, Int16ToTaggedNGC(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, Int16ToTaggedNGC(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, Int16ToTaggedTypeNGC(v0), Int16ToTaggedTypeNGC(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); GateRef currentSp = *varSp; varSp = TaggedCastToIntPtr(CallRuntime(glue, RTSTUB_ID(JumpToCInterpreter), { constpool, profileTypeInfo, acc, IntToTaggedTypeNGC(hotnessCounter)})); GateRef frame = GetFrame(*varSp); varPc = GetPcFromFrame(frame); Label shouldReturn(env); Label shouldContinue(env); Branch(IntPtrEqual(*varPc, IntPtr(0)), &shouldReturn, &shouldContinue); Bind(&shouldReturn); { CallNGCRuntime(glue, RTSTUB_ID(ResumeRspAndReturn), { Undefined(), *varSp, currentSp }); Return(); } Bind(&shouldContinue); { 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 = IntToTaggedNGC(Int32Add(valueInt, Int32(1))); Jump(&accDispatch); } } Bind(&valueNotInt); { 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); } 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 = IntToTaggedNGC(Int32Sub(valueInt, Int32(1))); Jump(&accDispatch); } } Bind(&valueNotInt); { 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); } 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 = IntToTaggedNGC(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); Label isHeapObject(env); Branch(TaggedIsHeapObject(value), &isHeapObject, ¬EcmaObject); Bind(&isHeapObject); Branch(TaggedObjectIsEcmaObject(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); Label notHeapObject(env); GateRef firstValue = GetValueFromTaggedArray(VariableType::JS_ANY(), profileTypeInfo, slotId); Branch(TaggedIsHeapObject(firstValue), &isHeapObject, ¬HeapObject); 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), &slowPath, ¬Hole); Bind(¬Hole); Label notException(env); Branch(TaggedIsException(result), &isException, ¬Exception); Bind(¬Exception); varAcc = result; Jump(&accDispatch); } } Bind(¬HeapObject); { Branch(TaggedIsUndefined(firstValue), &slowPath, &tryFastPath); } } Bind(&tryFastPath); { GateRef result = 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, IntToTaggedTypeNGC(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); Label notHeapObject(env); GateRef firstValue = GetValueFromTaggedArray(VariableType::JS_ANY(), profileTypeInfo, slotId); Branch(TaggedIsHeapObject(firstValue), &isHeapObject, ¬HeapObject); 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), &slowPath, ¬Hole); Bind(¬Hole); Branch(TaggedIsException(result), &isException, ¬Exception); } } Bind(¬HeapObject); { Branch(TaggedIsUndefined(firstValue), &slowPath, &tryFastPath); } } Bind(&tryFastPath); { GateRef result = SetPropertyByValue(glue, receiver, propKey, acc, false); 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, IntToTaggedTypeNGC(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 = SetPropertyByValue(glue, receiver, propKey, acc, true); // 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 = 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, IntToTaggedTypeNGC(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 = SetPropertyByIndex(glue, receiver, index, acc, false); 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, IntToTaggedTypeNGC(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 = SetPropertyByIndex(glue, receiver, index, acc, true); // 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, IntToTaggedTypeNGC(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 = IntToTaggedNGC(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 = IntToTaggedNGC(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 = IntToTaggedNGC(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 = IntToTaggedNGC(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 = IntToTaggedNGC(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 = IntToTaggedNGC(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 = IntToTaggedNGC(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 = IntToTaggedNGC(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 = IntToTaggedNGC(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, Int16ToTaggedTypeNGC(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); Label notHeapObject(env); GateRef firstValue = GetValueFromTaggedArray(VariableType::JS_ANY(), profileTypeInfo, slotId); Branch(TaggedIsHeapObject(firstValue), &isHeapObject, ¬HeapObject); 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), &slowPath, &loadWithHandler); } Bind(&loadWithHandler); { result = LoadICWithHandler(glue, receiver, receiver, *cachedHandler); Branch(TaggedIsHole(*result), &slowPath, ¬Hole); } } Bind(¬HeapObject); { Branch(TaggedIsUndefined(firstValue), &slowPath, &tryFastPath); } } Bind(¬Hole); { Branch(TaggedIsException(*result), &hasException, ¬Exception); Bind(&hasException); { DISPATCH_LAST_WITH_ACC(); } Bind(¬Exception); varAcc = *result; Jump(&dispatch); } Bind(&tryFastPath); { DispatchWithId(glue, sp, pc, constpool, profileTypeInfo, receiver, hotnessCounter, BCSTUB_ID(InterpreterGetPropertyByName)); } } 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, IntToTaggedTypeNGC(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); Label notHeapObject(env); GateRef firstValue = GetValueFromTaggedArray(VariableType::JS_ANY(), profileTypeInfo, slotId); Branch(TaggedIsHeapObject(firstValue), &isHeapObject, ¬HeapObject); 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), &slowPath, &storeWithHandler); } Bind(&storeWithHandler); { result = StoreICWithHandler(glue, receiver, receiver, acc, *cachedHandler); Branch(TaggedIsHole(*result), &slowPath, &checkResult); } } Bind(¬HeapObject); { Branch(TaggedIsUndefined(firstValue), &slowPath, &tryFastPath); } } Bind(&tryFastPath); { GateRef stringId = ReadInst32_1(pc); GateRef propKey = GetValueFromTaggedArray(VariableType::JS_ANY(), constpool, stringId); result = SetPropertyByName(glue, receiver, propKey, acc, false); 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, IntToTaggedTypeNGC(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 = SetPropertyByValue(glue, receiver, propKey, acc, true); 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 = SetPropertyByName(glue, receiver, propKey, acc, true); 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 = SetPropertyByName(glue, receiver, propKey, acc, true); 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 = IntToTaggedNGC(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); { CallNGCRuntime(glue, RTSTUB_ID(ResumeRspAndReturn), { *varAcc, *varSp, currentSp }); Return(); } Bind(&pcNotEqualNullptr); { 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); CallNGCRuntime(glue, RTSTUB_ID(ResumeRspAndDispatch), { glue, currentSp, *varPc, *varConstpool, *varProfileTypeInfo, *varAcc, *varHotnessCounter, jumpSize }); Return(); } } 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); { CallNGCRuntime(glue, RTSTUB_ID(ResumeRspAndReturn), { *varAcc, *varSp, currentSp }); Return(); } Bind(&pcNotEqualNullptr); { 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); CallNGCRuntime(glue, RTSTUB_ID(ResumeRspAndDispatch), { glue, currentSp, *varPc, *varConstpool, *varProfileTypeInfo, *varAcc, *varHotnessCounter, jumpSize }); Return(); } } 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); 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); { CallNGCRuntime(glue, RTSTUB_ID(ResumeRspAndReturn), { *varAcc, *varSp, currentSp }); Return(); } Bind(&pcNotEqualNullptr); { 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); CallNGCRuntime(glue, RTSTUB_ID(ResumeRspAndDispatch), { glue, currentSp, *varPc, *varConstpool, *varProfileTypeInfo, *varAcc, *varHotnessCounter, jumpSize }); Return(); } } 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), {})); varSp = GetCurrentFrame(glue); Branch(IntPtrEqual(*varPc, IntPtr(0)), &pcIsInvalid, &pcNotInvalid); Bind(&pcIsInvalid); { CallNGCRuntime(glue, RTSTUB_ID(ResumeUncaughtFrameAndReturn), { glue, *varSp, *varAcc }); Return(); } Bind(&pcNotInvalid); { varAcc = exception; // clear exception Store(VariableType::INT64(), glue, glue, exceptionOffset, 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); CallNGCRuntime(glue, RTSTUB_ID(ResumeCaughtFrameAndDispatch), { glue, *varSp, *varPc, *varConstpool, *varProfileTypeInfo, *varAcc, *varHotnessCounter}); Return(); } } 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, IntToTaggedTypeNGC(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 notHeapObject(env); Label ldMiss(env); Label icResultCheck(env); Branch(TaggedIsHeapObject(handler), &isHeapObject, ¬HeapObject); Bind(&isHeapObject); { icResult = LoadGlobal(handler); Branch(TaggedIsHole(*icResult), &ldMiss, &icResultCheck); } Bind(¬HeapObject); { Branch(TaggedIsHole(handler), &icNotAvailable, &ldMiss); } Bind(&ldMiss); { GateRef globalObject = GetGlobalObject(glue); icResult = CallRuntime(glue, RTSTUB_ID(LoadMiss), { profileTypeInfo, globalObject, prop, IntToTaggedTypeNGC(slotId), IntToTaggedTypeNGC(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, IntToTaggedTypeNGC(slotId), IntToTaggedTypeNGC(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 notHeapObject(env); Label ldMiss(env); Branch(TaggedIsHeapObject(handler), &isHeapObject, ¬HeapObject); Bind(&isHeapObject); { result = LoadGlobal(handler); Branch(TaggedIsHole(*result), &ldMiss, &checkResult); } Bind(¬HeapObject); { Branch(TaggedIsHole(handler), &icNotAvailable, &ldMiss); } Bind(&ldMiss); { result = CallRuntime(glue, RTSTUB_ID(LoadMiss), { profileTypeInfo, globalObject, propKey, IntToTaggedTypeNGC(slotId), IntToTaggedTypeNGC(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, IntToTaggedTypeNGC(slotId), IntToTaggedTypeNGC(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, Int8ToTaggedTypeNGC(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); } DECLARE_ASM_HANDLER(HandleCallArg0DynPrefV8) { auto env = GetEnvironment(); GateRef actualNumArgs = Int32(InterpreterAssembly::ActualNumArgsOfCall::CALLARG0); GateRef funcReg = ReadInst8_1(pc); GateRef func = GetVregValue(sp, ZExtInt8ToPtr(funcReg)); GateRef jumpSize = IntPtr(BytecodeInstruction::Size(BytecodeInstruction::Format::PREF_V8)); GateRef res = JSCallDispatch(glue, func, actualNumArgs, JSCallMode::CALL_ARG0, {}); Label isException(env); Label notException(env); Branch(HasPendingException(glue), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); Dispatch(glue, sp, pc, constpool, profileTypeInfo, res, hotnessCounter, jumpSize); } DECLARE_ASM_HANDLER(HandleCallArg1DynPrefV8V8) { auto env = GetEnvironment(); GateRef actualNumArgs = Int32(InterpreterAssembly::ActualNumArgsOfCall::CALLARG1); GateRef funcReg = ReadInst8_1(pc); GateRef a0 = ReadInst8_2(pc); GateRef func = GetVregValue(sp, ZExtInt8ToPtr(funcReg)); GateRef a0Value = GetVregValue(sp, ZExtInt8ToPtr(a0)); GateRef jumpSize = IntPtr(BytecodeInstruction::Size(BytecodeInstruction::Format::PREF_V8_V8)); GateRef res = JSCallDispatch(glue, func, actualNumArgs, JSCallMode::CALL_ARG1, { a0Value }); Label isException(env); Label notException(env); Branch(HasPendingException(glue), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); Dispatch(glue, sp, pc, constpool, profileTypeInfo, res, hotnessCounter, jumpSize); } DECLARE_ASM_HANDLER(HandleCallArgs2DynPrefV8V8V8) { auto env = GetEnvironment(); GateRef actualNumArgs = Int32(InterpreterAssembly::ActualNumArgsOfCall::CALLARGS2); GateRef funcReg = ReadInst8_1(pc); GateRef a0 = ReadInst8_2(pc); GateRef a1 = ReadInst8_3(pc); 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)); GateRef res = JSCallDispatch(glue, func, actualNumArgs, JSCallMode::CALL_ARG2, { a0Value, a1Value }); Label isException(env); Label notException(env); Branch(HasPendingException(glue), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); Dispatch(glue, sp, pc, constpool, profileTypeInfo, res, hotnessCounter, jumpSize); } DECLARE_ASM_HANDLER(HandleCallArgs3DynPrefV8V8V8V8) { auto env = GetEnvironment(); 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); 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)); GateRef res = JSCallDispatch(glue, func, actualNumArgs, JSCallMode::CALL_ARG3, { a0Value, a1Value, a2Value }); Label isException(env); Label notException(env); Branch(HasPendingException(glue), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); Dispatch(glue, sp, pc, constpool, profileTypeInfo, res, hotnessCounter, jumpSize); } DECLARE_ASM_HANDLER(HandleCallIRangeDynPrefImm16V8) { auto env = GetEnvironment(); GateRef actualNumArgs = ZExtInt16ToInt32(ReadInst16_1(pc)); GateRef funcReg = ReadInst8_3(pc); 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); GateRef res = JSCallDispatch(glue, func, actualNumArgs, JSCallMode::CALL_WITH_ARGV, { numArgs, argv }); Label isException(env); Label notException(env); Branch(HasPendingException(glue), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); Dispatch(glue, sp, pc, constpool, profileTypeInfo, res, hotnessCounter, jumpSize); } DECLARE_ASM_HANDLER(HandleCallIThisRangeDynPrefImm16V8) { auto env = GetEnvironment(); GateRef actualNumArgs = Int32Sub(ZExtInt16ToInt32(ReadInst16_1(pc)), Int32(1)); // 1: exclude this GateRef funcReg = ReadInst8_3(pc); funcReg = ZExtInt8ToPtr(funcReg); GateRef func = GetVregValue(sp, funcReg); GateRef thisValue = GetVregValue(sp, PtrAdd(funcReg, IntPtr(1))); GateRef argv = PtrAdd(sp, PtrMul( PtrAdd(funcReg, IntPtr(2)), IntPtr(8))); // 2: skip function&this GateRef jumpSize = IntPtr(BytecodeInstruction::Size(BytecodeInstruction::Format::PREF_IMM16_V8)); GateRef numArgs = ChangeInt32ToIntPtr(actualNumArgs); GateRef res = JSCallDispatch(glue, func, actualNumArgs, JSCallMode::CALL_THIS_WITH_ARGV, { numArgs, argv, thisValue }); Label isException(env); Label notException(env); Branch(HasPendingException(glue), &isException, ¬Exception); Bind(&isException); { DISPATCH_LAST(); } Bind(¬Exception); Dispatch(glue, sp, pc, constpool, profileTypeInfo, res, hotnessCounter, jumpSize); } 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), { Int16ToTaggedTypeNGC(numVars), Int16ToTaggedTypeNGC(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); } DECLARE_ASM_HANDLER(InterpreterGetPropertyByName) { auto env = GetEnvironment(); DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); DEFVARIABLE(result, VariableType::JS_ANY(), Hole()); Label checkResult(env); Label dispatch(env); Label slowPath(env); Label isException(env); GateRef receiver = acc; GateRef stringId = ReadInst32_1(pc); GateRef propKey = GetValueFromTaggedArray(VariableType::JS_ANY(), constpool, stringId); result = GetPropertyByName(glue, receiver, propKey); Branch(TaggedIsHole(*result), &slowPath, &checkResult); Bind(&slowPath); { GateRef slotId = ZExtInt8ToInt32(ReadInst8_0(pc)); result = CallRuntime(glue, RTSTUB_ID(LoadICByName), { profileTypeInfo, receiver, propKey, IntToTaggedTypeNGC(slotId) }); Jump(&checkResult); } Bind(&checkResult); { Branch(TaggedIsException(*result), &isException, &dispatch); Bind(&isException); { DISPATCH_LAST_WITH_ACC(); } } Bind(&dispatch); varAcc = *result; DISPATCH_WITH_ACC(PREF_ID32_V8); } DECLARE_ASM_HANDLER(NewObjectDynRangeThrowException) { CallRuntime(glue, RTSTUB_ID(ThrowDerivedMustReturnException), {}); DISPATCH_LAST(); } #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