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
26namespace 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) \
36JSTaggedType 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
59DEF_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
77DEF_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
90DEF_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
101DEF_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
123DEF_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
142DEF_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
159DEF_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