1 /* 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef ECMASCRIPT_COMPILER_BUILTINS_STUB_H 17 #define ECMASCRIPT_COMPILER_BUILTINS_STUB_H 18 19 #include "ecmascript/base/config.h" 20 #include "ecmascript/compiler/builtins/builtins_call_signature.h" 21 #include "ecmascript/compiler/interpreter_stub.h" 22 #include "ecmascript/ecma_runtime_call_info.h" 23 #include "ecmascript/ecma_string.h" 24 25 namespace panda::ecmascript::kungfu { 26 class BuiltinsStubBuilder : public StubBuilder { 27 public: BuiltinsStubBuilder(StubBuilder * parent)28 explicit BuiltinsStubBuilder(StubBuilder *parent) 29 :StubBuilder(parent) {} BuiltinsStubBuilder(CallSignature * callSignature,Environment * env)30 BuiltinsStubBuilder(CallSignature *callSignature, Environment *env) 31 : StubBuilder(callSignature, env) {} 32 ~BuiltinsStubBuilder() override = default; 33 NO_MOVE_SEMANTIC(BuiltinsStubBuilder); 34 NO_COPY_SEMANTIC(BuiltinsStubBuilder); 35 virtual void GenerateCircuit() override = 0; 36 GetGlue(GateRef info)37 inline GateRef GetGlue(GateRef info) 38 { 39 return Load(VariableType::NATIVE_POINTER(), info, 40 IntPtr(EcmaRuntimeCallInfo::GetThreadOffset(GetEnvironment()->IsArch32Bit()))); 41 } 42 GetNumArgs(GateRef info)43 inline GateRef GetNumArgs(GateRef info) 44 { 45 return Load(VariableType::INT64(), info, 46 IntPtr(EcmaRuntimeCallInfo::GetNumArgsOffset(GetEnvironment()->IsArch32Bit()))); 47 } 48 GetFunction(GateRef info)49 inline GateRef GetFunction(GateRef info) 50 { 51 return Load(VariableType::JS_ANY(), info, 52 IntPtr(EcmaRuntimeCallInfo::GetStackArgsOffset(GetEnvironment()->IsArch32Bit()))); 53 } 54 GetNewTarget(GateRef info)55 inline GateRef GetNewTarget(GateRef info) 56 { 57 GateRef newTargetOffset = IntPtr(EcmaRuntimeCallInfo::GetNewTargetOffset(GetEnvironment()->IsArch32Bit())); 58 return Load(VariableType::JS_ANY(), info, newTargetOffset); 59 } 60 GetThis(GateRef info)61 inline GateRef GetThis(GateRef info) 62 { 63 GateRef thisOffset = IntPtr(EcmaRuntimeCallInfo::GetThisOffset(GetEnvironment()->IsArch32Bit())); 64 return Load(VariableType::JS_ANY(), info, thisOffset); 65 } 66 GetCallArg0(GateRef numArg)67 inline GateRef GetCallArg0(GateRef numArg) 68 { 69 auto env = GetEnvironment(); 70 Label subentry(env); 71 env->SubCfgEntry(&subentry); 72 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined()); 73 Label isValid(env); 74 Label exit(env); 75 Branch(Int32GreaterThan(TruncPtrToInt32(numArg), Int32(0)), &isValid, &exit); 76 Bind(&isValid); 77 { 78 result = TaggedArgument(static_cast<size_t>(BuiltinsArgs::ARG0_OR_ARGV)); 79 Jump(&exit); 80 } 81 Bind(&exit); 82 auto res = *result; 83 env->SubCfgExit(); 84 return res; 85 } 86 GetCallArg1(GateRef numArg)87 inline GateRef GetCallArg1(GateRef numArg) 88 { 89 auto env = GetEnvironment(); 90 Label subentry(env); 91 env->SubCfgEntry(&subentry); 92 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined()); 93 Label isValid(env); 94 Label exit(env); 95 Branch(Int32GreaterThan(TruncPtrToInt32(numArg), Int32(1)), &isValid, &exit); 96 Bind(&isValid); 97 { 98 result = TaggedArgument(static_cast<size_t>(BuiltinsArgs::ARG1)); 99 Jump(&exit); 100 } 101 Bind(&exit); 102 auto res = *result; 103 env->SubCfgExit(); 104 return res; 105 } 106 GetCallArg2(GateRef numArg)107 inline GateRef GetCallArg2(GateRef numArg) 108 { 109 auto env = GetEnvironment(); 110 Label subentry(env); 111 env->SubCfgEntry(&subentry); 112 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined()); 113 Label isValid(env); 114 Label exit(env); 115 // 2: 2 args 116 Branch(Int32GreaterThan(TruncPtrToInt32(numArg), Int32(2)), &isValid, &exit); 117 Bind(&isValid); 118 { 119 result = TaggedArgument(static_cast<size_t>(BuiltinsArgs::ARG2)); 120 Jump(&exit); 121 } 122 Bind(&exit); 123 auto res = *result; 124 env->SubCfgExit(); 125 return res; 126 } 127 GetArgv()128 inline GateRef GetArgv() 129 { 130 return PtrArgument(static_cast<size_t>(BuiltinsArgs::ARG0_OR_ARGV)); 131 } 132 133 // not check whether index is valid, if not sure, invoke GetArg GetArgNCheck(GateRef index)134 inline GateRef GetArgNCheck(GateRef index) 135 { 136 GateRef argv = GetArgv(); 137 return Load(VariableType::JS_ANY(), argv, PtrMul(index, IntPtr(JSTaggedValue::TaggedTypeSize()))); 138 } 139 140 GateRef GetArg(GateRef numArgs, GateRef index); 141 142 GateRef CallSlowPath(GateRef nativeCode, GateRef glue, GateRef thisValue, GateRef numArgs, GateRef func, 143 GateRef newTarget, const char* comment = nullptr); 144 IsNumberYearMonthDay(GateRef year,GateRef month,GateRef day)145 inline GateRef IsNumberYearMonthDay(GateRef year, GateRef month, GateRef day) 146 { 147 GateRef condition = BoolAnd(TaggedIsNumber(year), TaggedIsNumber(month)); 148 return BoolAnd(condition, TaggedIsNumber(day)); 149 } 150 }; 151 152 #define DECLARE_BUILTINS_STUB_CLASS(name) \ 153 class name##StubBuilder : public BuiltinsStubBuilder { \ 154 public: \ 155 name##StubBuilder(CallSignature *callSignature, Environment *env) \ 156 : BuiltinsStubBuilder(callSignature, env) {} \ 157 ~name##StubBuilder() = default; \ 158 NO_MOVE_SEMANTIC(name##StubBuilder); \ 159 NO_COPY_SEMANTIC(name##StubBuilder); \ 160 void GenerateCircuit() override; \ 161 \ 162 private: \ 163 void GenerateCircuitImpl(GateRef glue, GateRef nativeCode, GateRef func, GateRef newTarget, \ 164 GateRef thisValue, GateRef numArgs); \ 165 }; 166 BUILTINS_STUB_LIST(DECLARE_BUILTINS_STUB_CLASS) 167 #undef DECLARE_BUILTINS_STUB_CLASS 168 } // namespace panda::ecmascript::kungfu 169 #endif // ECMASCRIPT_COMPILER_BUILTINS_STUB_H 170