module: Re-implement using library constructors/destructors (#2018)
By using constructors/destructors we unify the case of static linking with that of dynamic linking, and we reuse the build flag FEATURE_INIT_FINI. Using constructors/destructors also allows us to cover the case where library constructor/destructor functionality is unavailable, because we can expose the module registration/unregistration functions as global symbols, to be called explicitly from within the application. Fixes https://github.com/jerryscript-project/jerryscript/issues/1952 JerryScript-DCO-1.0-Signed-off-by: Gabriel Schulhof gabriel.schulhof@intel.com
This commit is contained in:
committed by
Zoltan Herczeg
parent
8d916a44f1
commit
81952f3cd0
@@ -18,13 +18,6 @@
|
||||
|
||||
#include "jerryscript.h"
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define JERRYX_NATIVE_MODULES_SUPPORTED
|
||||
#endif /* __GNUC__ */
|
||||
|
||||
#ifdef JERRYX_NATIVE_MODULES_SUPPORTED
|
||||
#include "jerryscript-ext/section.impl.h"
|
||||
|
||||
/**
|
||||
* Declare the signature for the module initialization function.
|
||||
*/
|
||||
@@ -34,23 +27,69 @@ typedef jerry_value_t (*jerryx_native_module_on_resolve_t) (void);
|
||||
* Declare the structure used to define a module. One should only make use of this structure via the
|
||||
* JERRYX_NATIVE_MODULE macro declared below.
|
||||
*/
|
||||
typedef struct
|
||||
typedef struct jerryx_native_module_t
|
||||
{
|
||||
jerry_char_t *name; /**< name of the module */
|
||||
jerryx_native_module_on_resolve_t on_resolve; /**< function that returns a new instance of the module */
|
||||
const jerry_char_t *name_p; /**< name of the module */
|
||||
const jerryx_native_module_on_resolve_t on_resolve; /**< function that returns a new instance of the module */
|
||||
struct jerryx_native_module_t *next_p; /**< pointer to next module in the list */
|
||||
} jerryx_native_module_t;
|
||||
|
||||
/**
|
||||
* Declare a helper macro that expands to the declaration of a variable of type jerryx_native_module_t placed into the
|
||||
* specially-named linker section "jerryx_modules" where the JerryScript module resolver
|
||||
* jerryx_module_native_resolver () will look for it.
|
||||
* Declare the constructor and destructor attributes. These evaluate to nothing if this extension is built without
|
||||
* library constructor/destructor support.
|
||||
*/
|
||||
#define JERRYX_NATIVE_MODULE(module_name, on_resolve_cb) \
|
||||
static const jerryx_native_module_t _module JERRYX_SECTION_ATTRIBUTE(jerryx_modules) = \
|
||||
{ \
|
||||
.name = ((jerry_char_t *) #module_name), \
|
||||
.on_resolve = (on_resolve_cb) \
|
||||
};
|
||||
#ifdef ENABLE_INIT_FINI
|
||||
#define JERRYX_MODULE_CONSTRUCTOR_ATTRIBUTE __attribute__((constructor))
|
||||
#define JERRYX_MODULE_DESTRUCTOR_ATTRIBUTE __attribute__((destructor))
|
||||
#define JERRYX_MODULE_REGISTRATION_QUALIFIER static
|
||||
#else /* !ENABLE_INIT_FINI */
|
||||
#define JERRYX_MODULE_CONSTRUCTOR_ATTRIBUTE
|
||||
#define JERRYX_MODULE_DESTRUCTOR_ATTRIBUTE
|
||||
#define JERRYX_MODULE_REGISTRATION_QUALIFIER
|
||||
#endif /* ENABLE_INIT_FINI */
|
||||
|
||||
/**
|
||||
* Having two levels of macros allows strings to be used unquoted.
|
||||
*/
|
||||
#define JERRYX_NATIVE_MODULE(module_name, on_resolve_cb) \
|
||||
JERRYX_NATIVE_MODULE_IMPLEM(module_name, on_resolve_cb)
|
||||
|
||||
#define JERRYX_NATIVE_MODULE_IMPLEM(module_name, on_resolve_cb) \
|
||||
static jerryx_native_module_t _ ## module_name ## _definition = \
|
||||
{ \
|
||||
.name_p = (jerry_char_t *) #module_name, \
|
||||
.on_resolve = (on_resolve_cb), \
|
||||
.next_p = NULL \
|
||||
}; \
|
||||
\
|
||||
JERRYX_MODULE_REGISTRATION_QUALIFIER void \
|
||||
module_name ## _register (void) JERRYX_MODULE_CONSTRUCTOR_ATTRIBUTE; \
|
||||
JERRYX_MODULE_REGISTRATION_QUALIFIER void \
|
||||
module_name ## _register (void) \
|
||||
{ \
|
||||
jerryx_native_module_register(&_##module_name##_definition); \
|
||||
} \
|
||||
\
|
||||
JERRYX_MODULE_REGISTRATION_QUALIFIER void \
|
||||
module_name ## _unregister (void) \
|
||||
JERRYX_MODULE_DESTRUCTOR_ATTRIBUTE; \
|
||||
JERRYX_MODULE_REGISTRATION_QUALIFIER void \
|
||||
module_name ## _unregister (void) \
|
||||
{ \
|
||||
jerryx_native_module_unregister(&_##module_name##_definition); \
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a native module. This makes it available for loading via jerryx_module_resolve, when
|
||||
* jerryx_module_native_resolver is passed in as a possible resolver.
|
||||
*/
|
||||
void jerryx_native_module_register (jerryx_native_module_t *module_p);
|
||||
|
||||
/**
|
||||
* Unregister a native module. This removes the module from the list of available native modules, meaning that
|
||||
* subsequent calls to jerryx_module_resolve with jerryx_module_native_resolver will not be able to find it.
|
||||
*/
|
||||
void jerryx_native_module_unregister (jerryx_native_module_t *module_p);
|
||||
|
||||
/**
|
||||
* Declare the JerryScript module resolver so that it may be added to an array of jerryx_module_resolver_t items and
|
||||
@@ -58,8 +97,6 @@ typedef struct
|
||||
*/
|
||||
bool jerryx_module_native_resolver (const jerry_char_t *name, jerry_value_t *result);
|
||||
|
||||
#endif /* JERRYX_NATIVE_MODULES_SUPPORTED */
|
||||
|
||||
/**
|
||||
* Declare the function pointer type for module resolvers.
|
||||
*/
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
/* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef JERRYX_SECTION_IMPL_H
|
||||
#define JERRYX_SECTION_IMPL_H
|
||||
|
||||
/**
|
||||
* Define the name of a section
|
||||
*
|
||||
* @param name the name of the section without quotes
|
||||
*/
|
||||
#ifdef __MACH__
|
||||
#define JERRYX_SECTION_NAME(name) "__DATA," #name
|
||||
#else /* !__MACH__ */
|
||||
#define JERRYX_SECTION_NAME(name) #name
|
||||
#endif /* __MACH__ */
|
||||
|
||||
/**
|
||||
* Expands to the proper __attribute__(()) qualifier for appending a variable to a section.
|
||||
*/
|
||||
#define JERRYX_SECTION_ATTRIBUTE(name) \
|
||||
__attribute__ ((used, section (JERRYX_SECTION_NAME (name)), aligned (sizeof (void *))))
|
||||
|
||||
/**
|
||||
* Declare references to a section that contains an array of items.
|
||||
*
|
||||
* @param name the name of the section (without quotes)
|
||||
* @param type the type of the elements stored in the array
|
||||
*
|
||||
* This macro declares two extern const variables such that their type is an array of @p type and their names are
|
||||
* constructed by prefixing @p name with "__start_" and "__stop_". They evaluate to the starting and ending address
|
||||
* of the section @p name.
|
||||
*/
|
||||
#ifdef __MACH__
|
||||
#define JERRYX_SECTION_DECLARE(name, type) \
|
||||
extern const type __start_ ## name[] __asm("section$start$__DATA$" #name); \
|
||||
extern const type __stop_ ## name[] __asm("section$end$__DATA$" #name);
|
||||
#else /* !__MACH__ */
|
||||
#define JERRYX_SECTION_DECLARE(name, type) \
|
||||
extern const type __start_ ## name[] __attribute__((weak)); \
|
||||
extern const type __stop_ ## name[] __attribute__((weak));
|
||||
#endif /* __MACH__ */
|
||||
|
||||
#endif /* !JERRYX_SECTION_IMPL_H */
|
||||
Reference in New Issue
Block a user