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/js_tagged_value.h"
19 #include "ecmascript/global_env.h"
20 #include "ecmascript/js_function.h"
21
22 namespace panda::ecmascript {
23 #if defined(__clang__)
24 #pragma clang diagnostic push
25 #pragma clang diagnostic ignored "-Wunused-parameter"
26 #elif defined(__GNUC__)
27 #pragma GCC diagnostic push
28 #pragma GCC diagnostic ignored "-Wunused-parameter"
29 #endif
30
31 #define DEF_RUNTIME_STUBS(name) \
32 JSTaggedType RuntimeStubs::name(uintptr_t argGlue, uint32_t argc, uintptr_t argv) \
33
34 #define RUNTIME_STUBS_HEADER(name) \
35 auto thread = JSThread::GlueToJSThread(argGlue); \
36 [[maybe_unused]] EcmaHandleScope handleScope(thread) \
37
38 #define CONVERT_ARG_TAGGED_TYPE_CHECKED(name, index) \
39 ASSERT((index) < argc); \
40 JSTaggedType name = *(reinterpret_cast<JSTaggedType *>(argv) + (index))
41
42 #define CONVERT_ARG_TAGGED_CHECKED(name, index) \
43 ASSERT((index) < argc); \
44 JSTaggedValue name = JSTaggedValue(*(reinterpret_cast<JSTaggedType *>(argv) + (index)))
45
46 #define CONVERT_ARG_HANDLE_CHECKED(type, name, index) \
47 ASSERT((index) < argc); \
48 JSHandle<type> name(&(reinterpret_cast<JSTaggedType *>(argv)[index]))
49
50 #define CONVERT_ARG_PTR_CHECKED(type, name, index) \
51 ASSERT((index) < argc); \
52 type name = reinterpret_cast<type>(*(reinterpret_cast<JSTaggedType *>(argv) + (index)))
53
54 #ifndef NDEBUG
DEF_RUNTIME_STUBS(DefineAotFunc)55 DEF_RUNTIME_STUBS(DefineAotFunc)
56 {
57 RUNTIME_STUBS_HEADER(DefineAotFunc);
58 CONVERT_ARG_TAGGED_CHECKED(funcIndex, 0);
59 CONVERT_ARG_TAGGED_CHECKED(numArgs, 1);
60 EcmaVM *ecmaVm = thread->GetEcmaVM();
61 ObjectFactory *factory = ecmaVm->GetFactory();
62 JSHandle<GlobalEnv> env = ecmaVm->GetGlobalEnv();
63 auto codeEntry = thread->GetFastStubEntry(funcIndex.GetInt());
64 JSHandle<Method> method = factory->NewMethodForNativeFunction(reinterpret_cast<void *>(codeEntry));
65 method->SetAotCodeBit(true);
66 method->SetNativeBit(false);
67 method->SetNumArgsWithCallField(numArgs.GetInt());
68 method->SetCodeEntryOrLiteral(reinterpret_cast<uintptr_t>(codeEntry));
69 JSHandle<JSFunction> jsfunc = factory->NewJSFunction(env, method);
70 return jsfunc.GetTaggedValue().GetRawData();
71 }
72
DEF_RUNTIME_STUBS(GetPrintFunc)73 DEF_RUNTIME_STUBS(GetPrintFunc)
74 {
75 RUNTIME_STUBS_HEADER(GetPrintFunc);
76 EcmaVM *ecmaVm = thread->GetEcmaVM();
77 ObjectFactory *factory = ecmaVm->GetFactory();
78 auto env = ecmaVm->GetGlobalEnv();
79 JSHandle<JSTaggedValue> globalObject(thread, env->GetGlobalObject());
80 JSHandle<JSTaggedValue> printString(thread, factory->NewFromStdString("print").GetTaggedValue());
81
82 return JSObject::GetProperty(thread, globalObject, printString).
83 GetValue().GetTaggedValue().GetRawData();
84 }
85
DEF_RUNTIME_STUBS(GetBindFunc)86 DEF_RUNTIME_STUBS(GetBindFunc)
87 {
88 RUNTIME_STUBS_HEADER(GetBindFunc);
89 CONVERT_ARG_HANDLE_CHECKED(JSTaggedValue, target, 0);
90 EcmaVM *ecmaVm = thread->GetEcmaVM();
91 ObjectFactory *factory = ecmaVm->GetFactory();
92 JSHandle<JSTaggedValue> bindString(thread, factory->NewFromStdString("bind").GetTaggedValue());
93
94 return JSObject::GetProperty(thread, target, bindString).GetValue().GetTaggedValue().GetRawData();
95 }
96
DEF_RUNTIME_STUBS(DefineProxyFunc)97 DEF_RUNTIME_STUBS(DefineProxyFunc)
98 {
99 RUNTIME_STUBS_HEADER(DefineProxyFunc);
100 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
101 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
102 CONVERT_ARG_HANDLE_CHECKED(JSTaggedValue, targetHandle, 0);
103 // 1. handler has no "Call"
104 JSFunction *function = env->GetObjectFunction().GetObject<JSFunction>();
105 JSHandle<JSTaggedValue> hclass(thread, function);
106 ASSERT(targetHandle->IsECMAObject());
107
108 JSHandle<JSTaggedValue> handlerHandle(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(hclass), hclass));
109 ASSERT(handlerHandle->IsECMAObject());
110 ASSERT(targetHandle->IsECMAObject());
111
112 JSHandle<JSProxy> proxyHandle = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle);
113 ASSERT(*proxyHandle != nullptr);
114 // check taggedvalue
115 proxyHandle.GetTaggedValue().D();
116 return proxyHandle.GetTaggedValue().GetRawData();
117 }
118
DEF_RUNTIME_STUBS(DefineProxyHandler)119 DEF_RUNTIME_STUBS(DefineProxyHandler)
120 {
121 RUNTIME_STUBS_HEADER(DefineProxyHandler);
122 CONVERT_ARG_HANDLE_CHECKED(JSTaggedValue, funcHandle, 0);
123 ASSERT(funcHandle->IsECMAObject());
124 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
125 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
126 JSFunction* function = env->GetObjectFunction().GetObject<JSFunction>();
127 JSHandle<JSTaggedValue> hclass(thread, function);
128
129 JSHandle<JSTaggedValue> handlerHandle(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(hclass), hclass));
130 ASSERT(handlerHandle->IsECMAObject());
131 // 1. handler has "Call"
132 JSHandle<JSTaggedValue> funcKey = thread->GlobalConstants()->GetHandledApplyString();
133 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(handlerHandle), funcKey, funcHandle);
134 handlerHandle.GetTaggedValue().D();
135 return handlerHandle.GetTaggedValue().GetRawData();
136 }
137
DEF_RUNTIME_STUBS(DefineProxyFunc2)138 DEF_RUNTIME_STUBS(DefineProxyFunc2)
139 {
140 RUNTIME_STUBS_HEADER(DefineProxyFunc2);
141 CONVERT_ARG_HANDLE_CHECKED(JSTaggedValue, targetHandle, 0);
142 CONVERT_ARG_HANDLE_CHECKED(JSTaggedValue, handlerHandle, 1);
143 // 1. handler has "Call"
144 ASSERT(handlerHandle->IsECMAObject());
145 ASSERT(targetHandle->IsECMAObject());
146
147 JSHandle<JSProxy> proxyHandle = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle);
148 targetHandle.GetTaggedValue().D();
149 handlerHandle.GetTaggedValue().D();
150 proxyHandle.GetTaggedValue().D();
151 ASSERT(*proxyHandle != nullptr);
152 return proxyHandle.GetTaggedValue().GetRawData();
153 }
154
DEF_RUNTIME_STUBS(DumpTaggedType)155 DEF_RUNTIME_STUBS(DumpTaggedType)
156 {
157 RUNTIME_STUBS_HEADER(DumpTaggedType);
158 CONVERT_ARG_HANDLE_CHECKED(JSTaggedValue, value, 0);
159 ASSERT(value->IsECMAObject());
160 value->D();
161 return value.GetTaggedValue().GetRawData();
162 }
163 #endif
164 } // namespace panda::ecmascript
165