Sign in to follow this  
WitchLord

AngelScript 2.5.0 WIP 2

Recommended Posts

WitchLord    4677
It's been a while since I released new features, but it has been for a good reason. Much of the compiler and virtual machine has been rewritten to use three-op instructions and to do less copying of objects in instructions. You will likely see quite a bit of a performance increase, though how much depends on your scripts. I believe there are still places where I can optimize the script engine even more, but I'm satisfied for now and I'll go back to concentrate on new features instead. In terms of features this new release brings some change in the way parameter references work, mainly the &inout parameter references. In earlier versions this type passed a reference to a clone of the object to the function and when the function returned that clone was then copied back to the original object. To do this the argument expression had to be evaluated twice, which caused a lot of confusion. Worse yet, intuitively developers thought that changing the parameter reference inside the function would also immediately change the original object that could for example be a global variable. For this version I found a better solution, which is more efficient and less confusion, though a bit more restrictive. If the reference' life time can be guaranteed during the execution of the function the reference to the original object is passed in to the function, so there will be no extra copies, nor will the changes on the original object be deferred until the return of the function. The catch is that the reference' life time must be guaranteed, which can only be done in case the reference points to a local variable, or if it is an object that support object handles. For references that do not have this condition the script compiler will generate an error like this: 'Reference cannot be guaranteed. Copy the value to a local variable first'. I hope that this will be much less confusing to the developers, and that the extra restrictions won't be too hindering. The &in reference stays the same, i.e. it makes a copy of the value, even though the life-time of the reference is guaranteed. This is because any changes to the reference shouldn't be reflected upon the real object. One important difference with this new WIP is the const &in, in this case the function won't be able to change the object, thus the compiler passes the true reference if it can be guaranteed. This is especially useful registered operators, which should in almost all cases be written to take the operands as const &in, for better performance. The &out reference also stays the same, i.e. the reference passed to the function is to an empty value (or an object initialized by the default constructor). The output value is copied to the true reference once the funtion returns. The argument expression is only evaluated after the function returns. I've also been able to change the library so that registered operators can now use any type of references, thus you will finally be able to write those stream classes, both for input and output. The registered operators should have the following signatures:
stream &f(stream &inout, const type &in) // << operator
stream &f(stream &inout, type &out)      // >> operator
The stream class should support object handles. For the upcoming WIP versions I will be adding better debugging support, with access to variables on the context stack. And I will also concentrate on preparing the library for 64bit port. Regards, Andreas [edit]Released WIP 2[/edit] [Edited by - WitchLord on December 28, 2005 7:01:07 PM]

Share this post


Link to post
Share on other sites
Tylon    181
Excellent, keep it up!

I have been very much looking forward to the new &inout! So I take it, &inout is the most efficient form of parameter passing, as there should be no object copying going on at all, right? So for performance reasons, when passing larger objects to functions, it would be good idea to use &inout even in cases where you would use &in (function not modifying the object)?

Thanks

Share this post


Link to post
Share on other sites
WitchLord    4677
Thanks guys! :D

Let me know what kind performance improvements you get.

In the case where the function will not be allowed to change the argument I think that const &in would be the preferred way. In all situations where &inout is accepted const &in is just as efficient, but where &inout is not accepted const &in still works, though with an extra copy.

Here's an example where &inout won't be accepted:


void funcInOut(int &inout a)
{
a = 0;
}

void main()
{
int var;
int[] array(1);

funcInOut(var); // This works
funcInOut(array[0]); // This doesn't
}


With objects that support object handles, it is another situation:


struct MyObj
{
int prop;
};

void funcInOut(MyObj &inout a)
{
a.prop = 0;
}

void main()
{
MyObj var;
MyObj[] array(1);

funcInOut(var); // This works
funcInOut(array[0]); // This also works
}


I'd prefer not to have to limit the reference parameters at all, but in order to guarantee safety (as in sandbox) this is the best I could come up with. If I can improve it further in the future I will.

Regards,
Andreas

Share this post


Link to post
Share on other sites
Deyja    920
I recall you once considered including an 'unsafe' seperate compiling mode that handled references just as 1.x did - the same as C++. What is the status on this?

Share this post


Link to post
Share on other sites
LDenninger    122
Maybe you've stated it already somewhere - if so, just point me to it,
but why is the in/out stuff necessary anyway ?

Why not just use the 'normal' syntax,
"int i" means copy it,
"int &i" means it's a reference that can be changed,
"const int &i" means it can't be changed, so it can be copied or treated internally how you like ?

Share this post


Link to post
Share on other sites
WitchLord    4677
Deyja:

I'm getting closer to implementing this everyday. It may even make it into the final 2.5.0 version.

I'm also planning on adding support for pointers, the same way they work in C++. The pointers would only be available in the 'unsafe' mode, of course.

LDenninger:

I do it this way for compatibility with C++. If AngelScript didn't support native calls to C++ functions I probably wouldn't allow references at all, and only use the object handles for this purpose.

The reason for the in, out, and inout keywords is that AngelScript needs to be able to guarantee the life-time of the references, otherwise it would be possible to end up with dangling pointers. Using these keywords AngelScript will be able to make the best choices based on the need of the developer.

Regards,
Andreas

Share this post


Link to post
Share on other sites
Lbas    122
Quote:
Original post by WitchLord
Deyja:

I'm getting closer to implementing this everyday. It may even make it into the final 2.5.0 version.

I'm also planning on adding support for pointers, the same way they work in C++. The pointers would only be available in the 'unsafe' mode, of course.


Hi Andreas,

What's a great news !

I'm confident I didn't upgrade to 2.x (still using 1.x) for that reason. Script users of my tools don't want to worry about such complicated reference counter principles, they just like to get object pointers (or references) and handle it as in C++ (when I explain them such changes, I'm getting many reproaches :)).

I've to say that I really hesitated to switch to another scripting language (despite of the extra work required), because 1.x suffer from some functionnality (such as implicit cast) and 2.x suffer from that strange imposed reference management (this is just my opinion), whereas I really like using AngelScript (until 2.x) for its ease of use in both developper and user point of view. Another solution for me would be to expand 1.x functionnality myself, but it would be really too bad to not continue sharing your great work ! Please help us (1.x users) :)

Lbas

Share this post


Link to post
Share on other sites
WitchLord    4677
:)

I'm aware that there are quite a few projects out there still using version 1.x because of the lack of direct pointers in AS 2.x. This is the main reason why I will do my best to introduce pointers again.

Regards,
Andreas

Share this post


Link to post
Share on other sites
Deyja    920
I'll add that, though I originally didn't upgrade because of that pointer thing, I've continued to fail to upgrade because of laziness. I could pass everything by value with minimal performance loss anyway. :)

Share this post


Link to post
Share on other sites
Deyja    920
Also, I should point out that you can still use pointers in 2.x, you just need to write some wrappers and register everything properly. :) One of the things I see a lot of people here fail to understand is that what the script sees and what the application sees don't need to be the same. You twist it around so the script sees just about anything.

Share this post


Link to post
Share on other sites
LDenninger    122
Quote:
Original post by WitchLord
I do it this way for compatibility with C++. If AngelScript didn't support native calls to C++ functions I probably wouldn't allow references at all, and only use the object handles for this purpose.

The reason for the in, out, and inout keywords is that AngelScript needs to be able to guarantee the life-time of the references, otherwise it would be possible to end up with dangling pointers. Using these keywords AngelScript will be able to make the best choices based on the need of the developer.

Regards,
Andreas


OK, but what I still don't understand :
why do you need the 'in' 'out' and 'inout' keywords ?

The way I see it, they would be implied by the definition, right ?
- 'in' would be any value that can be copied on the stack and then be used ("blah(int i)")
- 'out' and 'inout' would be a reference that is in- and/or output ("blah(int &i)")
- 'const' would define any variable that can not be changed - however you implement that.

why is the normal 'reference' definition (&) and 'const' definition (const &)
not enough to decide how to handle things ?

Share this post


Link to post
Share on other sites
Rain Dog    136
I think it might have to be with the fact that the script engine has no idea what C++ is going to do with the code. The script engine can guarantee that an object is not going to be destroyed/modified by function calls when those function calls only call script code. However, when your script functions call C++ code with objects that the script engine instantiated or otherwise controls, it has no idea, and will never have any idea what the C++ code is going to do with said object, thus, I believe it is forced to add this in, out, inout syntax to tell the script compiler what it should expect from the C++ code.


Am I right here WL?

Share this post


Link to post
Share on other sites
abrken    130
Quote:
Original post by WitchLord
:)

I'm aware that there are quite a few projects out there still using version 1.x because of the lack of direct pointers in AS 2.x. This is the main reason why I will do my best to introduce pointers again.

Regards,
Andreas


Wouah, this should be annouced as "best news of the day" !!!!

I will upgrade the day I will be able to do this aagain :

in_pAsEngine->RegisterGlobalFunction("int32 atol(bstr in_szText)", asFUNCTION(atol), asCALL_CDECL);


Direct Libc integration !

AbrKen.

Share this post


Link to post
Share on other sites
WitchLord    4677
LDenninger:

The problem is that &inout, which would be just & in C++, has some restrictions in AngelScript. The expression must be either an object type that support object handles, or a local variable, otherwise the life-time of reference cannot be guaranteed during the function call. I do not want to force developers to live with these restrictions for parameter references, therefore &in and &out are necessary to make it easier to write the script code.

&in could be implemented as const &, but then the parameter couldn't be altered, which would be another restriction of the syntax. Not something critical though, but still.

&out cannot be implemented in C++ syntax. This one makes AngelScript pass a reference to a local temporary variable, and when the function returns the argument expression is evaluated and assigned the value of the temporary variable. It works more like an extra return value than a parameter reference.

Rain Dog is also correct in that with the in, out, and inout keywords the application can tell AngelScript what the intention of the references are so that AngelScript can make the most efficient choices.

Nothing is written in stone however, so I may change this in the future. But I'm quite satisfied with how it works right now. An alternative would be to have the following options:

Normal parameter reference - & - which would have the same restrictions that &inout has now.
Const parameter reference - const & - would work just like const &in do now. This would be the preferred way, at least for registered functions, as it imposes the less restrictions on the script expressions.
Out values - out - which would no longer be called a reference but to C++ it would look like a reference that it could write to.

Yet another possibility would be to allow multiple return values, but that would need a syntax completely different from C++, though there would no longer be a need for &out references.

abrken:

If atol() and similar functions are your only concern then you don't have to wait for pointers in 2.x. The bstr type is still supported in 2.x, it's just not a standard add-on because I feel that the asCScriptString is much better. You can find the implementation for the bstr type in the test_feature folder.

You could use autohandles to make sure the string is properly freed after the call.

I understand that pointers would make it easier though. :)

Regards,
Andreas


Share this post


Link to post
Share on other sites
WitchLord    4677
I've uploaded version 2.5.0 WIP 2 of AngelScript. This will probably be the last WIP release before the final 2.5.0 version. I will at least not implement any new features in this version as I've already begun work on version 2.5.1.

New features for this WIP are:

  • Added support for character literals.
  • Added functions to the asIScriptContext interface that allow the application to enumerate variables on the stack and examine their values. (Thanks Ivan Marinov)
  • Added a new compile time flag: AS_ALLOW_UNSAFE_REFERENCES. When this is defined the library will allow parameter references without the in, out, or inout keywords. These parameters references will also work just like normal C++ parameter references, without any restrictions.

    For the next working I will be implementing support for class methods and constructors for the script declared structures. After that I will also implement inheritance for script structures. There will also be some way of allowing script classes to inherit from application defined classes, though this will likely not work for all application registered classes.

    Regards,
    Andreas Jönsson


    PS. Support for pointers didn't make it into this version, but I promise that they will be implemented in a not so far future. At least now you have the option to use parameter references that work the same way as in C++.

    Share this post


    Link to post
    Share on other sites

    Create an account or sign in to comment

    You need to be a member in order to leave a comment

    Create an account

    Sign up for a new account in our community. It's easy!

    Register a new account

    Sign in

    Already have an account? Sign in here.

    Sign In Now

    Sign in to follow this