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