Apparatus and methods for optimising foreign function calls
Patent Information
- Authority / Receiving Office
- WO · WO
- Patent Type
- Applications
- Current Assignee / Owner
- Filing Date
- 2025-02-05
- Publication Date
- 2026-08-13
Smart Images

Figure EP2025052979_13082026_PF_FP_ABST
Abstract
Description
[0001] APPARATUS AND METHODS FOR OPTIMISING FOREIGN FUNCTION CALLS
[0002] TECHNICAL FIELD
[0003] The present disclosure relates to the field of improving the efficiency of foreign function calls used to transfer between one programming language to another, in particular to using effect handlers to reduce the overhead associated with using the foreign function interface.
[0004] BACKGROUND
[0005] There are a large number of programming languages in existence. Moreover, new programming languages are constantly being created, e.g., to address specific problems in a manner that is convenient to the program creator. Broadly speaking, programming languages can be classified as high-level or low-level, where high-level languages are generally written to be intelligible to, and directly exposed to, an end-user. By contrast, low-level languages are machine-dependent, and are not generally intended to be intelligible by humans, and are difficult to debug . High-level languages tend to require a greater degree of ‘interpretation’ by a computer before they can be run or even compiled. Low-level languages on the other hand, for example assembly language, are machine interpretable and may directly run by a processor. Lower-level languages that are closer in form to machine code and therefore do not require the overhead of interpretation are faster.
[0006] As a result, it is commonplace for a high-level language, written by a human, to call on low-level languages to implement certain functions more efficiently. Indeed, it is ubiquitous that multiple different program languages are designed to interact with one another in order in a synergistic manner. One such example C programming language (which nowadays is considered a low-level language), in which it is often desirable for a programming language to support calling C code both for performance reasons, and for the sake of reusing and interacting with existing software. Most significantly used programming languages have some facility for achieving this interaction, often known as a Foreign Function Interface (FFI).
[0007] An FFI typically manages the problems that arise when two programming languages cooperate, especially the cooperation between high and low-level languages. For example, FFIs might manage different calling conventions, mapping types from one language to another, moving between managed memory and unmanaged memory (C code has no automatic memory management) etc.
[0008] Although programs written in C are generally faster than those in other languages (especially high-level or interpreted languages, such as Python), FFI calls from a host language into C can incur significant performance cost. This is the result of things like allocations to wrap native types in host types, garbage collector management (since some languages, including C code, lack this facility), context switches, allocations to store stack context and the like. All of these things have to be managed for every single FFI call, and therefore every time a host language wishes to invoke some function in a different programming language.
[0009] It is, therefore, an object of the present disclosure to solve the aforementioned problems associated with multiple FFI calls to manage the interaction between different programming languages. The foregoing and other objects are achieved by the subject matter of the independent claims. Further implementation forms are apparent from the dependent claims, the description and the figures.SUMMARY
[0010] In view of the scenarios above, improved apparatus and methods for handling FFI calls are needed to reduce or avoid the overhead associated with FFI calls and to improve efficiency. This can be done by providing, inter alia, suitable effect handlers that are able to coalesce multiple foreign function calls into an abstracted form and thereby transfer the abstracted foreign functions via a single FFI call. This is advantageous because, amongst other things, it improves the overall efficiency of code involving multiple FFI calls by significantly reducing the overhead necessarily associated with FFI calls. Advantageously, any overhead and performance cost that may be associated with running one or more effect handlers is still significantly less costly than performing a large number of FFI calls, and therefore using effect handlers as described herein provides an overall net efficiency improvement.
[0011] A first aspect of the present disclosure provides an apparatus comprising one or more processors for combining a plurality of foreign function interface, FFI, calls into a single FFI call, wherein each of the plurality of FFI calls is configured to cause a function expressed in a first programming language to be executed by the one or more processors in a second programming language, the apparatus configured to:
[0012] obtain a plurality of functions, identified in the first programming language, associated with an FFI call;
[0013] for each of the obtained functions, use a first effect handler arranged to:
[0014] obtain parameters required to execute the function in the second programming language; and write the parameters for executing the function to an executable list of function parameters; execute a single FFI call arranged to cause the one or more processors to interpret each item in the executable list to thereby cause each of the plurality of functions to be executed using the second programming language.
[0015] In example implementations, each of the functions is a foreign function configured to be executed using the second programming language and not configured to be executed using the first programming language.
[0016] In example implementations, the apparatus is configured to write the parameters for each function to the executable list by executing an effect controlled by the effect handler, wherein execution of the effect causes an interruption of the processing state at the point at which the effect is called.
[0017] In example implementations, the apparatus is configured to engage the first effect handler to execute the effect for each function instead of executing the FFI call associated with each function.
[0018] In example implementations, the interrupted processing state is resumed after execution of the effect has completed.
[0019] In example implementations, the first programming language is a high-level language, HLL, and the second programming language is a low-level language. [In implementations, the second programming language being is C or C++. Advantageously, executing the functions in the second programming language is faster than executing the functions in the first programming language.
[0020] In example implementations, the single FFI call contains a loop, and wherein executing the single FFI call causes the one or more processors to iterate through each function defined in the executable list and dispatch the function to be executed using the second programming language. For example, wherein the one or more processors may be configured to decode each function written to the executable list for executing using the second programming language.
[0021] In example implementations, parameters for each function comprise i) arguments for implementing the function and ii) an identifier of the function, and wherein the apparatus is configured to cause each effect, handled by the effect handler, to append the parameters to the executable list.In example implementations, code expressed in the first programming language contains a plurality of FFI calls associated with each of the plurality of functions, and wherein the apparatus is configured to automatically replace each FFI call in the code with code arranged to engage the effect handler. In example implementations, the apparatus is configured to automatically replace each FFI call in the code by:
[0022] identifying the plurality of FFI calls in the code;
[0023] for each of the identified FFI calls:
[0024] generate an effect object using a string or enumeration that contains parameters required to execute the function; generate effect code configured to cause the first effect handler to perform the effect;
[0025] replace the FFI code with the generated effect code;
[0026] generate the single FFI call, wherein the single FFI call is arranged to interpret the executable list.
[0027] In example implementations, there are no dataflow dependencies between any of the FFI calls associated with the plurality of functions.
[0028] In example implementations, the first effect handler is arranged to use dynamic binding to perform an effect, wherein the effect corresponds to the steps of i) obtaining parameters required to execute the function in the second programming language; and ii) writing the parameters for executing the function to the executable list of function parameters.
[0029] In example implementations, the apparatus configured to:
[0030] identify a further one or more functions in the first programming language associated with an FFI call; determining that the further one or more functions cannot be combined with the plurality of obtained functions; using a further effect handler to execute one or more FFI calls corresponding to the further one or more functions, wherein the further effect handler is at a higher level within a stack associated with the first programming language than the effect handler. In example implementations, determining that the further one or more functions cannot be combined with the plurality of obtained functions comprises determining that the further one or more functions have data dependency with at least one other function of the one or more obtained function or the further one or more functions.
[0031] In example implementations, the plurality of functions is configured to control a user interface, UI. For example, the user interface may be a graphical user interface, GUI.
[0032] A second aspect of the present disclosure provides a computer-implemented method comprising combining a plurality of foreign function interface, FFI, calls into a single FFI call, wherein each of the plurality of FFI calls is configured to cause a function expressed in a first programming language to be executed by the one or more processors in a second programming language, the method comprising, using one or more processors:
[0033] obtaining a plurality of functions, identified in the first programming language, associated with an FFI call; for each of the obtained functions, using a first effect handler to:
[0034] obtain parameters required to execute the function in the second programming language; and write the parameters for executing the function to an executable list of function parameters; executing a single FFI call to cause the one or more processors to interpret each item in the executable list to thereby cause each of the plurality of functions to be executed using the second programming language.A third aspect of the present disclosure provides a computer program stored in non-transitory form and including code instructions which, when executed on one or more processors, causes the one or more processors to execute any of the methods disclosed herein.
[0035] BRIEF DESCRIPTION OF THE DRAWINGS
[0036] The present disclosure is described by way of example, with reference to the accompanying drawings, in which:
[0037] Figure 1 shows an overview of how prior art methods manage foreign function interface (FFI) calls;
[0038] Figure 2 shows an overview of how multiple FFI calls may be managed according to presently described embodiments; Figure 3 illustrates an example operation of an effect handler in the context of a program stack;
[0039] Figure 4 illustrates a detailed comparison of a prior art method of issuing FFI calls and an example of managing a plurality of host instructions using an effect handler and a single FFI call; and
[0040] Figure 5 is a flowchart illustrating a method of managing a plurality of host instructions using effect handlers and a single FFI call according to present embodiments.
[0041] DETAILED DESCRIPTION
[0042] In the following description the terms ‘host language’ and ‘native language’ are used in the context of two languages cooperating to perform an FFI call. The term ‘host language’ refers, unless otherwise specified, to the language which specifies a function to be performed in another language by way of an FFI call. The ‘native’ language is the language that actually performs the function specified by the host language, after having been initiated by way of an FFI call. The term native is used to reflect the fact that it is closer to the machine-level operations. In some examples, therefore, the host language may be a high-level language that the user programs directly, and the native language may be a lower-level language such, or even assembly or machine code. Elsewhere in the present specification, the host language is referred to as a first programming language, and the native language is referred to as the second programming language.
[0043] As mentioned above, performing FFI calls between a host language and a native language is advantageous since the function may be compute-intensive and thus more efficient to execute using a lower-level language. However, there is an inherent cost associated with each FFI call because of the overhead that is necessary when performing an FFI call. As mentioned above, the overhead is a result of a large amount of bookkeeping (wrapping native types in host types, garbage collector management, etc) needed to manage an FFI call correctly.
[0044] The cost of performing an FFI is naturally not a hindrance in many cases, e.g., where only a small percentage of the total execution of the host language relies on FFI calls. Indeed, in many examples, using a small number of FFI calls to improve the efficiency of certain functions will result in an overall speed-up. However, if the number of FFI calls increases and thus represents a larger proportion of the code execution, there is a tipping point at which the sheer number of FFI calls results in an overall slow-down of the program. This is because, although low-level programs such as in C are generally faster than other languages, FFI calls from a host language into C can incur significant performance costs. One scenario in which using FFI calls becomes problematic (for the reasons explained above) is user interfaces, which can require a large number of FFI calls to enable the cooperation between a front-end user interface and back-end computations.Figure 1 shows a simple schematic 100 illustrating the operation of FFI calls. In this example, a plurality of FFI calls 102 are expressed in a high-level language (HLL). The nature of the FFI call is that it instructs the program to execute the function in a different language, in this example C code. Each HLL FFI call 102 requires its own overhead in carrying out the FFI. In other words, by default, each FFI call is treated on an individual basis, and the bookkeeping overhead that is performed is repeated for each FFI call. In order to execute the function, the function in the HLL is mapped onto a function in the native C code. Other overhead may include moving between managed and unmanaged memory, and wrapping native types in host types. This is illustrated in Figure 1 by way of indicating that each HLL function 102 crosses a notional “FFI boundary” 104. Each function 102 originally defined in the HHL is then performed as a corresponding C function 106. It can therefore be seen that there is a 1:1:1 mapping between HHL function 102, FFI call, and executed C function 106.
[0045] Each time a function crosses the FFI boundary, a significant amount of overhead is incurred which results in a performance cost. Thus, designing a program with a large proportion of FFI calls becomes self-defeating past a certain point because the overhead involved in performing a large number of FFI calls outweighs the benefit of the speedup enjoyed by execution in the native code. In theory, one way to circumvent this problem would be to simply hand-optimise existing (host) code to either avoid FFI calls, to reduce their number, improve data mapping, and / or improve the performance of repeated calls (by improvement management of caching, shared data structures, locality and the like). However, such workarounds would have to be done individually, and repeatedly for each new code base. In some cases, such workarounds may not be possible. Moreover, these workarounds do not address the root cause of FFI performance issues, which is their very existence. The present disclosure provides a solution that can entirely overcome the aforementioned problems, i.e., by coalescing a plurality of FFI calls into a single FFI call without compromising the underlying functionality of the program.
[0046] Figure 2 illustrates the general principle of the presently disclosed method 200 for coalescing multiple FFI calls 102. In this simple example, instead of each FFI call resulting in an individual and separate call that crosses the FFI boundary 104, each FFI call is collected by one or more effect handers 202. In Figure 2, only a single effect handler 202 is shown for illustrative clarity. The effect handler, in the first instance, replaces each FFI call with a performance of an effect. Thus, the code containing FFI calls to be replaced 102 is executed in the context of an effect handler to delimit the scope of replacement. Specifically, a handler can be installed to cover only a limited portion of code, as desired by the programmer, rather than installing the handler globally.
[0047] This effect contains an abstraction of the FFI call it replaced, for example, an enumeration or string containing the name of the foreign function. Any relevant arguments and / or parameters needed for carrying out the foreign function are also extracted by the effect handler and included in an array field to be used on the native side. These arguments and / or parameters do not need to be converted as they should already be types that can be passed through the FFI.
[0048] Once the effect handler 202 has incorporated the FFI calls 102 into an appropriate form, which may be called an “effectful code block”, the array containing the list of abstracted FFI calls is passed as an argument to a new, single, FFI call. This is illustrated in Figure 2 by the single arrow shown crossing the FFI boundary 104. Once the new FFI call has passed the original FFI calls 104, now in abstracted form, through to the native side, a native code decoder and dispatcher 204 operates to actually perform the foreign functions. This performance may include iterating through each element (i.e., function, with corresponding parameters) in the array, decoding the representation of the foreign function, and calling the original foreign function from the native code side, as indicated by the plurality of ‘C functions’ 106 in Figure 2. Thus, Figure 2 illustrates that the end result is the performance of exactly the same set of C functions 106 as in the prior art example in Figure 1. Thus, from the perspective of an observer or end-user, the same foreign functions specified in the host’s HLL result in exactly the same native functions 106 being performed in the examples of Figure 1 and Figure 2. However, advantageously, the use of the effect handler 202 in the example of Figure 2 allows all but one FFI call to be eliminated, and as a result a significant performance boost will beachieved due to the reduction in overhead. Thus, the perspective of an observer or end-user, the example in Figure 2 will be more efficient at no expense to the reliability or results of the foreign functions.
[0049] Effect handlers, also known as “algebraic effect handlers”, are a known programming language innovation that allows the separation of what computation is to occur with the how and where of the implementation of that computation. Effect Elandlers thus allow a computational effect to be performed, and the state of the execution at the point of performance to be saved and resumed later. Effect handlers are similar to computational exception handling in computer programming. Briefly, exception handling is the process by which anomalous, unexpected, or exceptional conditions are responded to by a computer program, where those anomalous, unexpected, or exceptional conditions require some form of special processing. In general, an exception breaks the normal flow of execution for a program and, instead of continuing with the program, executes a predetermined exception handler. In other words, exception handling involves interrupting the flow of a program by determining an anomaly, determining a set of predetermined steps to deal with the exception (if they exist), and terminating the program in a predetermined manner. An example might be the handling of a division by zero, which can be predetermined as “undefined”, and which a programmer may predetermine some response that enables the program to terminate as desired. Effect handlers, on the other hand, extend this behaviour by allowing the resumption of the performance of the original program. Thus, performing an effect transfers control to a dynamically scoped handler up the stack. However, an effect handler is also passed the continuation of the computation after where the effect was called, known as the resumption. The programmer has the option to resume the resumption and return control back to the point where the effect was performed. Effect handlers thus make use of a property in computer programming called, late binding, also called dynamic binding. This is a computer programming mechanism in which the method being called upon an object, or the function being called with arguments, is looked up by name at runtime instead of being pre-compiled. In other words, a name is associated with a particular operation or object at runtime, rather than during compilation.
[0050] Effect handlers can be used to implement exceptions, separation of concerns (e.g. logging etc.), lightweight concurrency, controlled access to state and IO and many other features. Some user interface frameworks (e.g. Jetpack, React) use constructs similar to a limited version of effects. These are used for specific situations, e.g. mostly encapsulating access to state, however, in known UI frameworks these effect-like constructs cannot be arbitrarily handled and do not support later resumption. Only a few production-level languages actually include effect handlers as part of the language framework. However, an advantage of effect handlers is that they can be defined using libraries and thus incorporated into a variety of programming languages, including C or C++, for example.Figure 3 illustrates the mechanism of an effect handler in general terms, i.e., outside the specific context of abstracting the effects of foreign functions. The mechanism 300 illustrated in Figure 3 relates to the following pseudo-code, in which the corresponding steps of Figure 3 are indicated as comments following the “ / / ” sign:
[0051] "
[0052] "
[0053] "
[0054]
[0055] Code run in the context of an effect handler is run on a separate stack context from its parent. This is shown in Figure 3 in which the original stack 302 is shown as distinct from the new stack 304 associated with the effectful block. The context of the original stack 302 is saved at the point that the original stack’s program is interrupted to perform the effect. In the case of Figure 3, the function 306 illustrated within the original stack 302 may correspond to whatever belongs in the “main” function shown above. When an effect is performed, the system traverses up the stack looking for the handler that matches the type of effect performed. When the handler is found, the current stack context is saved, and encapsulated in a resumption when (and if) the resumption takes place.
[0056] After the handler has been found, the stack is switched to the new stack 304 and the context of the handler code, and the handler code executed. In the above code-snippet, the handler code lies within the ‘Try” block, which is also indicated as ‘Try block” 308 in Figure 3.
[0057] The handler then obtains the effect to be performed and the resumption object. The nature of the effect is not defined in the above code snippet, but is simply referred to as “Effect ( ) ”. The resumption object is referred to in the above code snippet as “Resumption”. As shown in Figure 3, the effect is performed in the new stack 304. After the effect has been performed, the handler has the option of resuming the resumption object, which involves transferring control back to the original code that performed the effect, immediately after the performance. This is shown in Figure 3 by blocks “handle effect” 312 and “resume” 314. The handler thus restores the stack context that was saved at the time of performance of the effect. After resumption, the remainder of the “try block” is performed. In this case, as shown in the above code snippet, this would involve simply outputting “now we have resumed”. After this, the original program carries on using the original stack. Consequently, the order of operations of the code snippet above is non-linear, as shown by the order of the steps of Figure 3 that are indicated as comments in the snippet.
[0058] Alternatively to the example in Figure 3, if the handler does not resume, when execution leaves the handler context the control will continue at the point immediately after the effectful code was run.Returning to the use of effect handlers to merge multiple FFI calls into a single FFI call, one presumption of this approach is that there exist no dataflow dependencies between FFI calls to be merged. If, in some examples, two or more foreign functions to be called to have data dependencies, this is easily resolvable by performing dependencies foreign functions as separate calls. As mentioned above, instead of performing an FFI call to execute each foreign function in native code on an individual basis, each FFI call is replaced by performing an effect. This effect can then be implemented as an abstraction of the FFI call it replaces. For example, the replacement of FFI calls can be automated via simple lexical rewriting, abstract syntax tree rewriting, or modifying a lower-level IR (immediate representation). It should be appreciated that the replacement of the FFI call is not usually part of the effect / handler system. Thus, the replacement of an FFI call by a call to perform an effect can be done by hand (e.g., by a human programmer) or automatically.
[0059] Any arguments (encompassed within the ‘parameters’ referred to elsewhere in the present disclosure) are included as an array field of the effect object. An effect handler is installed that handles this effect, and appends the packaged abstraction containing the FFI call parameters to some form of list (e.g., an array, vector, or list type data structure) that can be iterated over. Although this assumes that the original order of FFI calls is preserved, in some examples effect handlers allow the order of their abstracted counterparts to be modified e.g., optimisation. This is generally possible because, as mentioned, a precondition for coalescing FFI calls as disclosed herein is generally that there are no dataflow dependencies between the coalesced FFI calls.
[0060] This abstraction is performed for each foreign function that would otherwise have been called with an FFI call, and the list structure containing the abstracted calls forms an ‘effectful code block’ . It should be appreciated that the ‘effectful code block’ is the portion of code that performs the effect, and is associated with one or more effect handlers. Thus, the ‘effectful code block’ is analogous to the ‘Try” block of code in the code snippet above. Once the effectful code block is complete, the array containing the list of abstracted FFI calls is passed as an argument to a new FFI call. This new FFI call is thus the only call that actually passes the FFI boundary 104 in order to perform the foreign functions. The FFI call will then loop through each element of the array, and for each element in the array:
[0061] i) decode the representation of the abstracted FFI call into the relevant native code;
[0062] ii) call the foreign function from the native code side.
[0063] Figure 4 illustrates the above-described process 400 of abstracting a plurality of foreign function functions, and deploying them in the native code side using only a single FFI call. Each block on the left-hand side represents a separate foreign function 102. In prior art methods, each of these foreign functions 102 would be called by a separate FFI call, and incur the overhead of performing repeated FFI calls. In the present method, each foreign function is instead handled by an effect handler 202 which, as described above, extracts relevant names, arguments, and parameters for each function. The collection of abstracted functions is appended to a list, which in F igure 4 is indicated at the “encoded array” 402. Once the final foreign function has been tracked, the encoded array 402 is passed into a single, newly generated call. This is indicated in Figure 4 by the arrow crossing the FFI boundary 104 between the encoded array 422 and the render tree 404. In this example, the ‘render tree’ is a function on the native code side that decodes the array and calls the original native functions.
[0064] On the native code side, as described above, each element of the encoded array 402 is iterated over to decode and extract the original foreign function code. This is indicated in Figure 4 by the step “delegates to existing backend functions”. Each foreign function 106, corresponding to the original function 102 expressed in the host language, is then performed using the native code.Automation
[0065] As disclosed above, program code can be altered by effect handlers such that FFI calls are replaced by effects. This can be done manually, but may also be performed automatically. Broadly speaking, this may involve identifying the plurality of FFI calls in the host language and, for each of the identified FFI calls: i) generate an ‘effect object’ (either using a string or enumeration) that contains parameters required to execute the function, and ii) generate effect code configured to cause the effect handler to perform the effect. The generated code is added to an executable list that contains parameters for each function and thereby allows each function to be performed. Finally, the FFI code is replaced with the generated effect code, and a single FFI call is generated wherein the single FFI call is arranged to interpret the executable list.
[0066] In a more detailed example, an automatic re-write procedure may involve the following steps:
[0067] i) Identify an FFI call;
[0068] ii) Create a string from the name of the function or generate an enumeration, and append to it every time a new call is encountered. The abstraction is chosen such that it is compatible with an FFI call;
[0069] iii) Generate an ‘effect object’ construction with the string or enumeration as one parameter, and the arguments to the original call as the remaining arguments;
[0070] iv) Generate a ‘perform expression’ with the previously generated effect object as its argument;
[0071] v) Generate the handler code that handles this effect type and inserts the relevant parameters and arguments into an array;
[0072] vi) Generate a new, single, foreign function that takes an executable list of these FFI call abstractions as an argument;
[0073] vii) Generate the loop that loops through the executable list;
[0074] viii) Generate the conditional code that matches the function call abstraction and generates the call to the original native call.
[0075] An aspect of computer programming that in part enables the use of effect handlers is the concept of dynamic binding, also referred to as late binding. Dynamic binding, in essence, relates to looking up the name of a function or object at runtime instead. In static binding, this lookup would be performed prior to execution, e.g., during compilation. Dynamic binding is what enables the clean separation of performing a specific effect from the behaviour of that effect.
[0076] Dynamic binding also enables other useful functionality, for example where there are a mix of FFI calls that may not by default be coalesced. For example, a user may wish to mix some FFI calls that happen immediately with a set of coalesced functions that are sent via a single FFI call. In another example, a user may wish to mix FFI calls that have data dependency with those that do not. This could cause problems if all FFI calls have been automatically replaced with effects, as described above in respect of the automation.
[0077] Advantageously, effect handlers allow the coalescing of foreign functions to be scoped to particular code blocks by the use of dynamic binding. For example, an ‘outer’ top-level handler within a stack could be deployed to handle the ‘standard’ case of individual FFI calls being executed one by one, and a lower-level ‘inner’ handler can handle the coalescing of FFI calls that are able to be combined (e.g., because they have no data dependency).
[0078] Effect handlers could also allow a hybrid option in which FFI calls are run sequentially, but with a producer / consumer mode in which the effect handler can populate the array of FFI calls, while a separate thread executes them individually.Figure 5 is a flowchart illustrating a method for combining a plurality of FFI calls into a single FFI call, wherein each of the plurality of FFI calls is configured to cause a function expressed in a first programming language to be executed in a second programming language.
[0079] Step SI 00 comprises obtaining a plurality of functions, identified in the first programming language, associated with an FFI call. The first programming language may be a high-level language, e.g., one written by a human programmer. The step of obtaining may involve identifying functions associated with an FFI call. Alternatively, a list of all FFI calls may be predetermined or compiled elsewhere, in which case the list of functions is simply obtained.
[0080] Step SI 02 comprises, for each of the obtained functions, using an effect handler to obtain parameters required to execute the function in the second programming language. As described above, the FFI call itself is replaced by an effect performed by an effect handler. As explained above, performing an effect in this context means that the effect contains an abstraction of the FFI call it replaces, e.g., an array containing the name of the function and its parameters. This step corresponds, in one example, to the operation of the ‘effect handler’ 202 shown in Figure 4.
[0081] Step SI 04 comprises, for each of the obtained functions, using the effect handler to write the parameters for executing the function to an executable list of function parameters. In this context, the meaning of the term ‘parameters’ encompasses all fields needed for the function to be executed by the second programming language. Parameters thus include the name of the foreign function and all arguments. It should be appreciated that the list is executable in the second programming language, and in this context the meaning of ‘execution’ encompasses any one or more of interpretation, decoding, scheduling, and dispatching of the foreign function to the second programming language prior to the actual execution of the foreign function. This step corresponds, in one example, to the operation of the ‘effect handler’ 202 shown in Figure 4 in which the effect handler generates the ‘encoded array’ 402.
[0082] Step SI 06 comprises executing a single FFI call that causes one or more processors to interpret each item in the executable list to thereby cause each of the plurality of functions to be executed using the second programming language. This corresponds to the aspect of Figure 4 which shows the “render tree” being delegated to existing backend functions, after passing the FFI boundary, thereby generating foreign functions within the native code (i.e., the second programming language) for execution. In this disclosure, when the subject of a phase is described as being "configured to" or “arranged to”, followed by a term defining a condition or function, this is used to indicate that the subject of the phrase is in a state in which it has that condition, or is able to perform that function, without the subject being modified or further configured.
[0083] Some implementations may be described using the expressions “one / an embodiment” or “one / an implementation” or “one / an example”, along with their derivatives. These terms mean that a particular feature, structure, or characteristic described in connection with the embodiment is included in at least one embodiment. The appearances of the phrase “in some implementations” in various places in the specification are not necessarily all referring to the same embodiment. Moreover, unless otherwise noted the features described above are recognized to be usable together in any combination. Thus, any features discussed separately may be employed in combination with each other unless it is noted that the features are incompatible with each other.
[0084] The applicant hereby discloses in isolation each individual feature described herein and any combination of two or more such features, to the extent that such features or combinations are capable of being carried out based on the present specification as a whole in the light of the common general knowledge of a person skilled in the art, irrespective of whether such features or combinations of features solve any problems disclosed herein, and without limitation to the scope of the claims. The applicant indicates that aspects of the present disclosure may consist of any such individual feature or combination of features. In viewof the foregoing description, it will be evident to a person skilled in the art that various modifications may be made within the scope of the appended claims.
[0085] The foregoing description of example embodiments has been presented for the purposes of illustration and description. It is not intended to be exhaustive or to limit the present disclosure to the precise forms disclosed. Many modifications and variations are possible in light of this disclosure. It is intended that the scope of the present disclosure be limited not by this detailed description, but rather by the claims appended hereto. Future filed applications claiming priority to this application may claim the disclosed subject matter in a different manner and may generally include any set of one or more limitations as variously disclosed or otherwise demonstrated herein.
Claims
CLAIMS1. An apparatus comprising one or more processors for combining a plurality of foreign function interface, FFI, calls into a single FFI call, wherein each of the plurality of FFI calls is configured to cause a function expressed in a first programming language to be executed by the one or more processors in a second programming language, the apparatus configured to: obtain a plurality of functions, identified in the first programming language, associated with an FFI call;for each of the obtained functions, use a first effect handler arranged to:obtain parameters required to execute the function in the second programming language; and write the parameters for executing the function to an executable list of function parameters;execute a single FFI call arranged to cause the one or more processors to interpret each item in the executable list to thereby cause each of the plurality of functions to be executed using the second programming language.
2. The apparatus of claim 1 , wherein the apparatus is configured to write the parameters for each function to the executable list by executing an effect controlled by the effect handler, wherein execution of the effect causes an interruption of the processing state at the point at which the effect is called.
3. An apparatus of any preceding claim, wherein the apparatus is configured to engage the first effect handler to execute the effect for each function instead of executing the FFI call associated with each function.
4. An apparatus of any preceding claim, wherein the interrupted processing state is resumed after execution of the effect has completed.
5. An apparatus of any preceding claim, wherein the first programming language is a high-level language, HLL, and the second programming language is a low-level language.
6. An apparatus of any preceding claim, wherein the single FFI call contains a loop, and wherein executing the single FFI call causes the one or more processors to iterate through each function defined in the executable list and dispatch the function to be executed using the second programming language.
7. An apparatus of any preceding claim, wherein parameters for each function comprise i) arguments for implementing the function and ii) an identifier of the function, and wherein the apparatus is configured to cause each effect, handled by the effect handler, to append the parameters to the executable list.
8. An apparatus of claim 3, wherein code expressed in the first programming language contains a plurality of FFI calls associated with each of the plurality of functions, and wherein the apparatus is configured to automatically replace each FFI call in the code with code arranged to engage the effect handler.
9. The apparatus of claim 8, wherein the apparatus is configured to automatically replace each FFI call in the code by:identifying the plurality of FFI calls in the code;for each of the identified FFI calls:generate an effect object using a string or enumeration that contains parameters required to execute the function; generate effect code configured to cause the first effect handler to perform the effect;replace the FFI code with the generated effect code;generate the single FFI call, wherein the single FFI call is arranged to interpret the executable list.
10. An apparatus of any preceding claim, wherein there are no dataflow dependencies between any of the FFI calls associated with the plurality of functions.
11. An apparatus of any preceding claim, wherein the first effect handler is arranged to use dynamic binding to perform an effect, wherein the effect corresponds to the steps of i) obtaining parameters required to execute the function in the second programming language; and ii) writing the parameters for executing the function to the executable list of function parameters.
12. An apparatus of any preceding claims, wherein the apparatus configured to:identify a further one or more functions in the first programming language associated with an FFI call; determining that the further one or more functions cannot be combined with the plurality of obtained functions; using a further effect handler to execute one or more FFI calls corresponding to the further one or more functions,wherein the further effect handler is at a higher level within a stack associated with the first programming language than the effect handler.
13. The apparatus of any preceding claim, wherein the plurality of functions is configured to control a user interface, UI.
14. A computer-implemented method comprising combining a plurality of foreign function interface, FFI, calls into a single FFI call, wherein each of the plurality of FFI calls is configured to cause a function expressed in a first programming language to be executed by the one or more processors in a second programming language, the method comprising, using one or more processors:obtaining a plurality of functions, identified in the first programming language, associated with an FFI call; for each of the obtained functions, using a first effect handler to:obtain parameters required to execute the function in the second programming language; and write the parameters for executing the function to an executable list of function parameters;executing a single FFI call to cause the one or more processors to interpret each item in the executable list to thereby cause each of the plurality of functions to be executed using the second programming language.
15. A computer program stored in non-transitory form and including code instructions which, when executed on one or more processors, causes the one or more processors to execute the method according to claim 14.