/* * Copyright (C) 2019 Intel Corporation. All rights reserved. * * 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. */ /** * @file jeff-export.h * @date Wed Aug 3 18:17:30 2011 * * @brief Exported interface for operating or executing JEFF files. * All interface names start with "jeff_", which is the namespace name * of this module. */ #ifndef JEFF_EXPORT_H #define JEFF_EXPORT_H #include "bni.h" #include "korp_types.h" /******************************************************************** * Exported internal types ********************************************************************/ /** * JEFF file handle type */ struct JeffFileHeaderLinked; typedef struct JeffFileHeaderLinked *jeff_file_t; /** * JEFF class type */ struct JeffClassHeaderLinked; typedef struct JeffClassHeaderLinked *jeff_class_t; /** * VM instance handle type */ struct JeffInstanceLocalRoot; typedef struct JeffInstanceLocalRoot *jeff_instance_t; /** * Record of one native method's definition. */ struct JeffNativeMethodDef { /* Mangled name of the native method. NULL for initialization functions. */ const char *mangled_name; /* Points to the native C function. */ void (*func_ptr)(uint32 *); /* Return size type of the native function. */ uint32 return_size_type; }; /******************************************************************** * Interface for operating global environment of the JEFF VM ********************************************************************/ /** * Load the core library from the given file buffer and initialize the * runtime environment (global objects etc.) of the VM. The thread * calls this function becomes the supervisor thread, which belongs to * a unique supervisor instance. Currently, if this init failed, * partially initialized states of the VM runtime environment won't be * cleaned up, so the VM must be shutdown and restarted. method_defs * points to an array of native method definition records. * Initialization functions must be in the front of the array and * following native method definitions must be sorted by their mangled * names. * * @param file the JEFF file of the core library * @param file_size the size of the JEFF file of the core library * @param method_defs native method definition records * @param method_defs_num number of native method records * @param heap the heap for the current (supervisor) instance * * @return true if succeeds, otherwise the error cannot be recovered */ bool jeff_runtime_init(jeff_file_t file, unsigned file_size, struct JeffNativeMethodDef *method_defs, unsigned method_defs_num, void *heap); /** * Load a JEFF file into the VM from the given file buffer. It can be * called from any VM thread. * * @param file the JEFF file to be loaded * @param size the size of the JEFF file * @param is_library whether the JEFF file is a library * @param allow_to_load a function that returns true if classes in the * given package is allowed to be loaded. The NULL function pointer * allows all packages. * @param allow_to_link a function that returns true if classes in the * given package is allowed to be linked to. The NULL function * pointer allows all packages. * * @return true if succeeds, otherwise detailed error information is * passed to vmci_diagnostic_print. The caller can catch it by * implementing that function. */ bool jeff_runtime_load(jeff_file_t file, unsigned size, bool is_library, bool (*allow_to_load)(const uint8 *pname, unsigned len), bool (*allow_to_link)(const uint8 *pname, unsigned plen, const uint8 *cname, unsigned clen)); /** * Unload a JEFF file from the VM. All resources related to the JEFF * file except the JEFF file itself are released. It can be called * from any VM thread. * * @param file the JEFF file to be unloaded * * @return true if succeeds, otherwise detailed error information is * passed to vmci_diagnostic_print. The caller can catch it by * implementing that function. */ bool jeff_runtime_unload(jeff_file_t file); /** * Return the JEFF file with the given file uid. * * @param fuid the unique id of a loaded JEFF file * * @return the JEFF file is exists, otherwise NULL */ jeff_file_t jeff_runtime_fuid_to_file(unsigned fuid); /** * Return the file uid of the given JEFF file. * * @param file a loaded JEFF file * * @return the unique id of the given JEFF file */ unsigned jeff_runtime_file_to_fuid(jeff_file_t file); /** * Create a supervisor thread belonging to the supervisor instance. * Threads that may interact with VM core must be either the main * thread of supervisor instance (which calls jeff_runtime_init) or * created by this function so that VM core required data structures * can be set up correctly. * * @param start_routine the start routine of the new thread * @param arg argument to the start routine * * @return true if succeeds, false otherwise */ bool jeff_runtime_create_supervisor_thread(void* (*start_routine)(void *), void *arg); /** * Create a supervisor thread belonging to the supervisor instance. * Threads that may interact with VM core must be either the main * thread of supervisor instance (which calls jeff_runtime_init) or * created by this function so that VM core required data structures * can be set up correctly. * * @param start_routine the start routine of the new thread * @param arg argument to the start routine * @param prio thread priority * * @return true if succeeds, false otherwise */ bool jeff_runtime_create_supervisor_thread_with_prio(void* (*start_routine)(void *), void *arg, int prio); /******************************************************************** * Interface for operating instance local environment ********************************************************************/ /** * Create a VM instance with the given JEFF file as its main file, * (i.e. the file containing the main class of the VM instance). This * function can be called from any VM thread, but it must be isolated * from JEFF file's unloading operation so that the main file won't be * unloaded before it's locked by the new instance. All instance * local memory except stacks of threads are allocated from the given * heap. If succeeds, it increases reference count of the main_file * and returns the handle of the new VM instance. The new instance's * main thread will run the start_routine with argument arg. If the * cleanup_routine is not NULL, it will be called after start_routine * returns and just before the main thread exits. It will also be * called after the instance is destroied. It is guaranteed to be * called exactly once no matter how the instance terminates. * * @param main_file the main JEFF file of the new instance * @param heap the private heap of the new instance * @param stack_depth the maximal nesting levels of Java methods of * the new instance. It must be <= 16 * 1024. Otherwise the instance * creation will fail. * @param start_routine start routine of the main thread. Don't * destroy the heap or inform other thread to do this at the end of * this routine since after it returns, VM core will call destroy * functions on objects allocated in this heap (e.g. locks and * condition variables). Do the destroying or informing of destroying * in the cleanup_routine. * @param arg the instance argument that will be passed to the start * routine. It can be get or set by jeff_runtime_get_instance_arg and * jeff_runtime_set_instance arg from threads of the instance. The * caller can use it to store instance local data. * @param cleanup_routine the optional cleanup routine for the * instance, which may be NULL. It may be executed in the end of the * main thread of the created instance by this function if this * instance exits normally, or it may be executed in a thread of other * instance in case this instance is being killed by that instance. * In both cases, this routine regards it is executed in a thread of * this instance (the instance created by this function) because * jeff_runtime_get_instance_arg will always return the argument of * this instance. * * @return the VM instance handle if succeeds, NULL otherwise */ jeff_instance_t jeff_runtime_create_instance(jeff_file_t main_file, void *heap, unsigned stack_depth, void* (*start_routine)(void *), void *arg, void (*cleanup_routine)(void)); /** * Destroy the given VM instance and decrease the reference count of * its main file and all explicitly used JEFF files. It can be called * from any VM thread. If there are alive threads of the instance, * they will be terminated mandatorily and then the cleanup routine is * called if it's not NULL. * * @param handle the handle of the instance to be destroyed */ void jeff_runtime_destroy_instance(jeff_instance_t handle); /** * Retrieve the current instance's argument. * * @return the current instance's argument */ void* jeff_runtime_get_instance_arg(void); /** * Set the current instance's argument. * * @return the new argument for the current instance */ void jeff_runtime_set_instance_arg(void *arg); /** * Retrieve the current instance's heap. * * @return the current instance's heap */ void* jeff_runtime_get_instance_heap(void); /** * Suspend all threads of the given VM instance. This function can * only be called from thread that is not of the given VM instance. * * @param handle the handle of the instance to be suspended */ void jeff_runtime_suspend_instance(jeff_instance_t handle); /** * Resume all threads of the given VM instance. This function can * only be called from thread that is not of the given VM instance. * * @param handle the handle of the instance to be resumed */ void jeff_runtime_resume_instance(jeff_instance_t handle); /** * Interrupt all threads of the given VM instance. This function can * only be called from thread that is not of the given VM instance. * * @param handle the handle of the instance to be interrupted * @param by_force whether the interruption is by force */ void jeff_runtime_interrupt_instance(jeff_instance_t handle, bool by_force); /** * Wait for the given VM instance to terminate. * * @param ilr the VM instance to be waited for * @param mills wait millseconds to return */ void jeff_runtime_wait_for_instance(jeff_instance_t ilr, int mills); /******************************************************************** * Interface for operating thread local environment ********************************************************************/ /** * Return true if there is an uncaught exception (thrown during * running an application or applet command). * * @return true if there is an uncaught exception */ bool jeff_runtime_check_uncaught_exception(void); /** * Print qualified name of the uncaught exception (and stack trace if * enabled) by calling vmci_diagnostic_print. */ void jeff_runtime_print_uncaught_exception(void); /** * Clear the uncaught exception. */ void jeff_runtime_reset_uncaught_exception(void); /** * Change current thread to a safe state (VMWAIT). After calling this * and before calling jeff_runtime_exit_safe_state, all operations * must be safe, i.e. no GC or system level resource operations are * allowed because in a safe state, the VM instance is assumed to be * able to perform GC, JDWP or termination at any time. Usually, this * function is called just before the native code is going to wait for * something and the exiting safe state function is called just after * the waiting returns. */ void jeff_runtime_enter_safe_state(void); /** * Change current thread to an unsafe state (RUNNING) so that unsafe * operations can also be done. */ void jeff_runtime_exit_safe_state(void); /** * Set thread local error code for the current thread. * * @param code the error code to be set */ void jeff_runtime_set_error(unsigned code); /** * Get the last error code of current thread. * * @return the last error code of current thread */ unsigned jeff_runtime_get_error(void); /******************************************************************** * Interface for GC support ********************************************************************/ /** * Traverse all objects of the given heap that are global or locate in * threads' frames and return them by calling vmci_gc_rootset_elem. * This function will suspend all threads except the current one of * the VM instance owning the given heap before traversing. It * traverses either all or none of the rootset objects, and returns * true and false respectively. If it returns false, the GC process * shouldn't proceed and is not necessary to unmark anything because * no objects are marked. The function jeff_runtime_gc_finished must * be called if and only if this function returns true so as to resume * threads that are suspended during GC process. * * @param heap the heap for which rootset objects are looked up * * @return true if succeeds, false otherwise */ bool jeff_runtime_traverse_gc_rootset(void *heap); /** * Get the reference offset table of the given object. If the * returned value R >= 0, *ret points to the reference offset table of * the object and R is the number of offsets in the table. Otherwise, * if the returned value R < 0, all reference fields of the object * must be in a continuous region (usually the object is an array), * then *ret is the offset to the first field in the region and R is * the number of such fields in the region. * * @param obj pointer to the Java object * @param ret points to a pointer for storing the reference offset * table if return value >= 0, or for storing the offset to the first * object reference in the Java object if return value < 0 * * @return number of offsets in the reference_offset table if >= 0, or * number of object references in the object if < 0 */ int jeff_object_get_reference_offsets(const jobject obj, uint16 **ret); /** * Inform the containing VM instance that GC has finished and all * suspended threads can be resumed. This function must be called if * and only if jeff_runtime_traverse_gc_rootset returns true. */ void jeff_runtime_gc_finished(void); /******************************************************************** * Interface for tooling support ********************************************************************/ /** * This function is used to suspend the main thread of VM instance so * that debugger can have chance to connect to the VM instance, set * breakpoints and do any other debug settings. It must be called * from the main thread of VM instance at the point just after VM * instance initialization finishes and just before application code * is to be executed. */ void jeff_tool_suspend_self(void); /** * Start up tool agent thread for the given VM instance. It can be * called from any VM thread. * * @param handle the VM instance for which tool agent is started up * @param queue queue of the tool agent * @return true if succeeds, false otherwise */ bool jeff_tool_start_agent(jeff_instance_t handle, void *queue); /******************************************************************** * Interface for toolkit support ********************************************************************/ /** * Return the JEFF class pointer of the given class name. * * @param class_name the qualified class name * * @return the JEFF class pointer */ jeff_class_t jeff_tool_get_jeff_class(const char *class_name); /** * Get the mangled class name of the given class. * * @param clz the JEFF class * @param buf buffer for returning the mangled name * @param buf_size size of the buffer * * @return actual size of the mangled class name including the * terminating null byte */ unsigned jeff_tool_get_mangled_class_name(jeff_class_t clz, char *buf, unsigned buf_size); /** * Get class index of given class in its containing JEFF file. * * @param clz the JEFF class * * @return class index in the containing JEFF file */ int jeff_tool_get_class_index(jeff_class_t clz); /** * Callback handler prototype for traversing fields of class. * * @param arg argument passed to the handler from caller * @param access_flag access flag of the method * @param name the field name * @param descriptor mangled field type descriptor * @param offset the offset of the field in the class * @param size size of the field */ typedef void (*JeffToolFieldHandler)(void *arg, unsigned access_flag, const char *name, const char *descriptor, unsigned offset, unsigned size); /** * Traverse all fields of the given class, including those inherited * from super classes. The fields are traversed in the same order as * the field layout of the class. * * @param arg argument to be passed to the handler * @param clz the JEFF class * @param instance instance fields or static fielts * @param handler the callback handler for each field */ void jeff_tool_foreach_field(void *arg, jeff_class_t clz, bool instance, JeffToolFieldHandler handler); /** * Callback handler prototype for traversing methods of class. * * @param arg argument passed to the handler from caller * @param access_flag access flag of the method * @param name mangled name of the method * @param descriptor mangled method arguments descriptor * @param retune_type mangled descriptor of method's return type */ typedef void (*JeffToolMethodHandler)(void *arg, unsigned access_flag, const char *name, const char *descriptor, const char *return_type); /** * Traverse all methods of the given class. * * @param arg argument to be passed to the handler * @param clz the JEFF class * @param handler the callback handler for each method */ void jeff_tool_foreach_method(void *arg, jeff_class_t clz, JeffToolMethodHandler handler); /** * Callback handler prototype for traversing classes of main file. * * @param arg argument passed to the handler from caller * @param clz pointer to one class in the main file */ typedef void (*JeffToolClassHandler)(void *arg, jeff_class_t clz); /** * Traverse all classes of the main file. * * @param arg argument to be passed to the handler * @param handler the callback handler for each class */ void jeff_tool_foreach_class(void *arg, JeffToolClassHandler handler); /******************************************************************** * Interface for executing applications ********************************************************************/ /** * Initialize global environment for executing Java applications. * * @return true if succeeds, false otherwise */ bool jeff_application_env_init(void); /** * Find the unique class containing a public static "main * ([Ljava.lang.String;)V" method from the main JEFF file of the * current instance and execute that method. * * @param argc the number of arguments * @param argv the arguments array * * @return true if the main method is called, false otherwise (e.g. an * exception occurs when preparing the arguments Java string array) */ bool jeff_application_execute(int argc, char *argv[]); /******************************************************************** * Interface for executing applets ********************************************************************/ /** * Initialize global environment for executing applets. * * @return true if succeeds, false otherwise */ bool jeff_applet_env_init(void); /** * Start to run from com.intel.runtime.core.RuntimeContext.main with a * default message queue size and a default service class object. If * the main JEFF file of the current VM instance contains exactly one * class that is derived from com.intel.util.IntelApplet, then use it * as the default service class. * * @param queue_size the default main message queue size * @param default_service_class qualified class name of the default * service class (entry point class), which must be in the main JEFF * file. If NULL, find the default main class with rules described * above. * * @return true if succeeds, false otherwise */ bool jeff_applet_start(int queue_size, const char *default_service_class); #endif