Host object APIs: Difference between revisions
(New page: This page describes the current native model in tamarin tracing. Everything works by running the GlobalOptimizer on abc's to be compiled into the host application. Typically there are...) |
(→Types) |
||
| Line 99: | Line 99: | ||
# Namespace == Namespacep | # Namespace == Namespacep | ||
# Number == double | # Number == double | ||
# UDT == ScriptObjectp | |||
Having every host class exposed as a ScriptObjectp feels bad. Currently we're just doing things like: | |||
typedef FooBar ScriptObject; | |||
So that C++ code can use FooBar* instead of ScriptObjectp. We'd like to make this even more type-safe. Perhaps something like: | |||
template<const char *TNAME> | |||
class NativeObject | |||
{ | |||
ScriptObjectp obj; | |||
NativeObject(ScriptObjectp obj) :obj(obj) | |||
{ | |||
ASSERT_TYPE(obj, TNAME); | |||
} | |||
} | |||
typedef NativeObject<"FooBar"> FooBar; | |||
So everytime you assign a ScriptObjectp into a FooBar the type will be validated, ASSERT_TYPE can be made to be a DEBUG only thing. | |||
==Thats it! Or details== | ==Thats it! Or details== | ||
Revision as of 05:53, 30 April 2008
This page describes the current native model in tamarin tracing.
Everything works by running the GlobalOptimizer on abc's to be compiled into the host application. Typically there are two abc's the application specific host objects and the avmplus builtin objects. GlobalOptimizer is like a linker and merges the abcs and performs various optimizations. It also produces a .h and .cpp file that provide all the C++ native linkage.
The philosophy behind tamarin tracing is to expose as much to the trace JIT optimizer as possible, as such the native API is very limited. For instance you can't do these things from C++:
- try/catch exceptions
- get/set properties
- invoke arbritrary methods/properties
- construct objects
Ideally as much as possible is written in JS and native code is only invoked when absolutely needed.
Startup
To bootstrap the VM GlobalOptimizer generates an entry point. Creating a VM looks like this:
using namespace avmplus; Configuration vm_config; //vm_config.optimizer = 0; //vm_config.verbose = 1; avm vm = host_init(gc, vm_config, host_abc_data, sizeof(host_abc_data));
The "host" string is provided to the GlobalOptimizer invocation. The generated header introduces all the "host_" symbols. The data can be provided as is or the host can provide alternate data, for instance maybe the data isn't compiled into the application but loaded from the disk. "avm" is an opaque pointer that's really an AbcEnv under the covers but that shouldn't be exposed.
Storing C++ pointers in JS
native class ScriptPlayer;
class Foo {
var foo:ScriptPlayer;
}
Rules:
- value is always undefined, ie the pointer value is opaque to JS
- values can be stored/retrieved from Array, Object and Dictionary (including weak keys)
JS to C++
JS:
class Foo
{
private native function callout():void;
}
C++:
#include "GENERATED_HEADER.h"
namespace avmplus
{
AVMPLUS_NATIVE_METHOD(void, Foo_private_callout)
{
...
}
}
Rules:
- No native constructors
- No rest arguments
- No varargs
- C++ must be in avmplus namespace, the builtin abcs can be merged so the generated header contains the builtins from avmplus core.
C++ to JS
JS:
[native]
function do_something(foo:ScriptPlayer):void
{
try {
...
} catch(e) {}
}
C++:
ScriptPlayer *sp; avmplus::host_do_something(vm, sp);
Rules:
- Must catch exceptions (what if they want to throw? TBD)
- toplevel functions only (no class functions static or instance) this keeps the implementation simple
- the vm pointer is what the _init routine returns
Types
- JS == C++
- void == void
- * == BoxReturnType
- int == int32_t
- uint == uint32_t
- Boolean == bool
- String == Stringp
- Namespace == Namespacep
- Number == double
- UDT == ScriptObjectp
Having every host class exposed as a ScriptObjectp feels bad. Currently we're just doing things like:
typedef FooBar ScriptObject;
So that C++ code can use FooBar* instead of ScriptObjectp. We'd like to make this even more type-safe. Perhaps something like:
template<const char *TNAME>
class NativeObject
{
ScriptObjectp obj;
NativeObject(ScriptObjectp obj) :obj(obj)
{
ASSERT_TYPE(obj, TNAME);
}
}
typedef NativeObject<"FooBar"> FooBar;
So everytime you assign a ScriptObjectp into a FooBar the type will be validated, ASSERT_TYPE can be made to be a DEBUG only thing.
Thats it! Or details
String
Currently we don't want to expose AvmCore to the host, but right now you need to do this to create a String:
((AvmCore*)((AbcEnv*)vm)->core())->constantString("c string")
Domain
But wait how do I dynamically load code into the VM? Like abc compiled dynamically or loaded from a swf or something. Construct a ByteArray from native code using and pass it into a callin that uses Domain.loadBytes.
Want to get a Class object from a String to construct a class from a dynamically loaded library, use Domain.getClass.