1 /*
2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "ecmascript/object_factory.h"
16 #include "ecmascript/stubs/runtime_stubs.h"
17
18 #include "ecmascript/ecma_macros.h"
19 #include "ecmascript/js_tagged_value.h"
20 #include "ecmascript/ecma_vm.h"
21 #include "ecmascript/frames.h"
22 #include "ecmascript/global_env.h"
23 #include "ecmascript/runtime_call_id.h"
24 #include "ecmascript/js_function.h"
25
26 namespace panda::ecmascript {
27 #if defined(__clang__)
28 #pragma clang diagnostic push
29 #pragma clang diagnostic ignored "-Wunused-parameter"
30 #elif defined(__GNUC__)
31 #pragma GCC diagnostic push
32 #pragma GCC diagnostic ignored "-Wunused-parameter"
33 #endif
34
35 #define DEF_RUNTIME_STUBS(name) \
36 JSTaggedType RuntimeStubs::name(uintptr_t argGlue, uint32_t argc, uintptr_t argv) \
37
38 #define RUNTIME_STUBS_HEADER(name) \
39 auto thread = JSThread::GlueToJSThread(argGlue); \
40 [[maybe_unused]] EcmaHandleScope handleScope(thread) \
41
42 #define CONVERT_ARG_TAGGED_TYPE_CHECKED(name, index) \
43 ASSERT((index) < argc); \
44 JSTaggedType name = *(reinterpret_cast<JSTaggedType *>(argv) + (index))
45
46 #define CONVERT_ARG_TAGGED_CHECKED(name, index) \
47 ASSERT((index) < argc); \
48 JSTaggedValue name = JSTaggedValue(*(reinterpret_cast<JSTaggedType *>(argv) + (index)))
49
50 #define CONVERT_ARG_HANDLE_CHECKED(type, name, index) \
51 ASSERT((index) < argc); \
52 JSHandle<type> name(&(reinterpret_cast<JSTaggedType *>(argv)[index]))
53
54 #define CONVERT_ARG_PTR_CHECKED(type, name, index) \
55 ASSERT((index) < argc); \
56 type name = reinterpret_cast<type>(*(reinterpret_cast<JSTaggedType *>(argv) + (index)))
57
58 #ifndef NDEBUG
DEF_RUNTIME_STUBS(DefineAotFunc)59 DEF_RUNTIME_STUBS(DefineAotFunc)
60 {
61 RUNTIME_STUBS_HEADER(DefineAotFunc);
62 CONVERT_ARG_TAGGED_CHECKED(funcIndex, 0);
63 CONVERT_ARG_TAGGED_CHECKED(numArgs, 1);
64 EcmaVM *ecmaVm = thread->GetEcmaVM();
65 ObjectFactory *factory = ecmaVm->GetFactory();
66 JSHandle<GlobalEnv> env = ecmaVm->GetGlobalEnv();
67 auto codeEntry = thread->GetFastStubEntry(funcIndex.GetInt());
68 JSHandle<Method> method = factory->NewMethodForNativeFunction(reinterpret_cast<void *>(codeEntry));
69 method->SetAotCodeBit(true);
70 method->SetNativeBit(false);
71 method->SetNumArgsWithCallField(numArgs.GetInt());
72 method->SetCodeEntryOrLiteral(reinterpret_cast<uintptr_t>(codeEntry));
73 JSHandle<JSFunction> jsfunc = factory->NewJSFunction(env, method);
74 return jsfunc.GetTaggedValue().GetRawData();
75 }
76
DEF_RUNTIME_STUBS(GetPrintFunc)77 DEF_RUNTIME_STUBS(GetPrintFunc)
78 {
79 RUNTIME_STUBS_HEADER(GetPrintFunc);
80 EcmaVM *ecmaVm = thread->GetEcmaVM();
81 ObjectFactory *factory = ecmaVm->GetFactory();
82 auto env = ecmaVm->GetGlobalEnv();
83 JSHandle<JSTaggedValue> globalObject(thread, env->GetGlobalObject());
84 JSHandle<JSTaggedValue> printString(thread, factory->NewFromStdString("print").GetTaggedValue());
85
86 return JSObject::GetProperty(thread, globalObject, printString).
87 GetValue().GetTaggedValue().GetRawData();
88 }
89
DEF_RUNTIME_STUBS(GetBindFunc)90 DEF_RUNTIME_STUBS(GetBindFunc)
91 {
92 RUNTIME_STUBS_HEADER(GetBindFunc);
93 CONVERT_ARG_HANDLE_CHECKED(JSTaggedValue, target, 0);
94 EcmaVM *ecmaVm = thread->GetEcmaVM();
95 ObjectFactory *factory = ecmaVm->GetFactory();
96 JSHandle<JSTaggedValue> bindString(thread, factory->NewFromStdString("bind").GetTaggedValue());
97
98 return JSObject::GetProperty(thread, target, bindString).GetValue().GetTaggedValue().GetRawData();
99 }
100
DEF_RUNTIME_STUBS(DefineProxyFunc)101 DEF_RUNTIME_STUBS(DefineProxyFunc)
102 {
103 RUNTIME_STUBS_HEADER(DefineProxyFunc);
104 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
105 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
106 CONVERT_ARG_HANDLE_CHECKED(JSTaggedValue, targetHandle, 0);
107 // 1. handler has no "Call"
108 JSFunction *function = env->GetObjectFunction().GetObject<JSFunction>();
109 JSHandle<JSTaggedValue> hclass(thread, function);
110 ASSERT(targetHandle->IsECMAObject());
111
112 JSHandle<JSTaggedValue> handlerHandle(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(hclass), hclass));
113 ASSERT(handlerHandle->IsECMAObject());
114 ASSERT(targetHandle->IsECMAObject());
115
116 JSHandle<JSProxy> proxyHandle = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle);
117 ASSERT(*proxyHandle != nullptr);
118 // check taggedvalue
119 proxyHandle.GetTaggedValue().D();
120 return proxyHandle.GetTaggedValue().GetRawData();
121 }
122
DEF_RUNTIME_STUBS(DefineProxyHandler)123 DEF_RUNTIME_STUBS(DefineProxyHandler)
124 {
125 RUNTIME_STUBS_HEADER(DefineProxyHandler);
126 CONVERT_ARG_HANDLE_CHECKED(JSTaggedValue, funcHandle, 0);
127 ASSERT(funcHandle->IsECMAObject());
128 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
129 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
130 JSFunction* function = env->GetObjectFunction().GetObject<JSFunction>();
131 JSHandle<JSTaggedValue> hclass(thread, function);
132
133 JSHandle<JSTaggedValue> handlerHandle(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(hclass), hclass));
134 ASSERT(handlerHandle->IsECMAObject());
135 // 1. handler has "Call"
136 JSHandle<JSTaggedValue> funcKey = thread->GlobalConstants()->GetHandledApplyString();
137 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(handlerHandle), funcKey, funcHandle);
138 handlerHandle.GetTaggedValue().D();
139 return handlerHandle.GetTaggedValue().GetRawData();
140 }
141
DEF_RUNTIME_STUBS(DefineProxyFunc2)142 DEF_RUNTIME_STUBS(DefineProxyFunc2)
143 {
144 RUNTIME_STUBS_HEADER(DefineProxyFunc2);
145 CONVERT_ARG_HANDLE_CHECKED(JSTaggedValue, targetHandle, 0);
146 CONVERT_ARG_HANDLE_CHECKED(JSTaggedValue, handlerHandle, 1);
147 // 1. handler has "Call"
148 ASSERT(handlerHandle->IsECMAObject());
149 ASSERT(targetHandle->IsECMAObject());
150
151 JSHandle<JSProxy> proxyHandle = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle);
152 targetHandle.GetTaggedValue().D();
153 handlerHandle.GetTaggedValue().D();
154 proxyHandle.GetTaggedValue().D();
155 ASSERT(*proxyHandle != nullptr);
156 return proxyHandle.GetTaggedValue().GetRawData();
157 }
158
DEF_RUNTIME_STUBS(DumpTaggedType)159 DEF_RUNTIME_STUBS(DumpTaggedType)
160 {
161 RUNTIME_STUBS_HEADER(DumpTaggedType);
162 CONVERT_ARG_HANDLE_CHECKED(JSTaggedValue, value, 0);
163 ASSERT(value->IsECMAObject());
164 value->D();
165 return value.GetTaggedValue().GetRawData();
166 }
167 #endif
168 } // namespace panda::ecmascript
169