# AngelScript 2.20.1 is released

This topic is 2532 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

This version has been mostly about internal improvements where the compiler and VM are now allocating local variables of registered value types on the stack instead of on the heap. If your scripts you a lot of those you should see a pretty good performance increase, as there will be less dynamic memory allocations.

There was a bug fix to the debug methods in the asIScriptContext. The call stack index used to inspect functions higher up on the call stack was inverted, so the methods were actually returning the information of the wrong function. If you are using these methods you may need to adjust your code when picking up this version.

Regards,
Andreas

##### Share on other sites
I just upgraded from 2.19.2 to 2.20.1 and I have a strange crash.

The script code is (this worked in 2.19.2) :

void testR(const Vector2&in position)
{
print("testR " + position.x + "," + position.y + "\n");
}

void testV(Vector2 position)
{
print("testV " + position.x + "," + position.y + "\n");
}

void start()
{
FluidParticle@ p = Level.fluids.getActive(0);
testR(p.position);
testV(p.position); // Crash
}

Everytime a value is passed from a "const T&" to the value "T", it crashes with a NULL object pointer (ie. "position" is NULL in testV if I do a subtraction for example).

Here are some register functions :

r = engine->RegisterObjectType("Vector2", sizeof(Vector2f), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_CA); assert( r >= 0 );

r = engine->RegisterObjectMethod("FluidSystem", "FluidParticle@ getActive(int i)", asMETHOD(FluidSystem, getActive), asCALL_THISCALL); assert(r >= 0);

r = engine->RegisterObjectMethod("FluidParticle", "const Vector2& get_position() const", asMETHODPR(FluidParticle, position, () const, const Vector2f&), asCALL_THISCALL); assert(r >= 0);

To implement Vector2, I took the math3d sample.

EDIT : apparently the copy constructor is called after testR has finished, probably before testV is called

void Vector2CopyConstructor(const Vector2f &other, Vector2f *self)
{
new(self) Vector2f(other);
}

and other contains { x = 0.00000, y = correct_but_is_x } and just after in the memory there is the correct y value. Also, self already has the correct values.

EDIT : actually the copy constructor is called a second time just after and this time self is not init and other has the correct values, however, just after that, the next ExecuteNext crashes here (as_context.cpp line 2414) :

case asBC_RDR4:
*(asDWORD*)(l_fp - asBC_SWORDARG0(l_bc)) = **(asDWORD**)®s.valueRegister;
l_bc++;
break;

Remi Gillig.

[Edited by - speps on December 21, 2010 8:26:30 AM]

##### Share on other sites
I've received another bug report similar to yours. It seems there are still some problems with the allocation of value types on the stack.

Please turn this off until I can have this fixed:

In as_compiler.cpp, function AllocateVariableNotIn, before line 3163, set the variable forceOnHeap = true. This will make the code go back to the previous behaviour and allocate all registered types on the heap.

##### Share on other sites
OK that fixed it for now. Too bad, I was hoping for a little performance boost from this particular change.

Remi Gillig.

##### Share on other sites
Unfortunately I'll be on vacation for a couple of weeks and probably won't have time to fix it before the plane leaves on Friday. But I'll do what I can to have it fixed as soon as possible.

##### Share on other sites
I've checked in the work around for now (rev 771), so at least the latest revision in the SVN won't have these problems until I can have them fixed.

##### Share on other sites
Thanks, I'll wait for the fix :)

##### Share on other sites
This bug has been fixed in revision 777 (along with a couple of other fixes).

##### Share on other sites
I upgraded AngelScript but I still have problems with copy constructors.

void Vector2CopyConstructor(const Vector2f &other, Vector2f *self) { new(self) Vector2f(other); } r = engine->RegisterObjectBehaviour("Vector2", asBEHAVE_CONSTRUCT, "void f(const Vector2& in)", asFUNCTION(Vector2CopyConstructor), asCALL_CDECL_OBJLAST); assert( r >= 0 );

The variable "other" points to an inaccessible portion of memory. I'll investigate further.

EDIT : The script line where this happens is :

Vector2 test = Vector2(Level.camera.lookAt);

Where Camera is registered like this :

void RegisterCamera(asIScriptEngine *engine) { int r; // Register the type r = engine->RegisterObjectType("Camera", 0, asOBJ_REF); assert(r >= 0); r = engine->RegisterObjectBehaviour("Camera", asBEHAVE_ADDREF, "void f()", asMETHOD(Camera, addRef), asCALL_THISCALL); assert(r >= 0); r = engine->RegisterObjectBehaviour("Camera", asBEHAVE_RELEASE, "void f()", asMETHOD(Camera, release), asCALL_THISCALL); assert(r >= 0); r = engine->RegisterObjectMethod("Camera", "const Vector2& get_lookAt() const", asMETHODPR(Camera, lookAt, () const, const Vector2f&), asCALL_THISCALL); assert(r >= 0); r = engine->RegisterObjectMethod("Camera", "void set_lookAt(const Vector2 &in)", asMETHODPR(Camera, lookAt, (const Vector2f&), void), asCALL_THISCALL); assert(r >= 0); r = engine->RegisterObjectMethod("Camera", "float get_zoom() const", asMETHODPR(Camera, zoom, () const, float), asCALL_THISCALL); assert(r >= 0); r = engine->RegisterObjectMethod("Camera", "void set_zoom(float z)", asMETHODPR(Camera, zoom, (float), void), asCALL_THISCALL); assert(r >= 0); }

r = engine->RegisterObjectMethod("LevelType", "Camera@ get_camera()", asMETHOD(Level, camera), asCALL_THISCALL); assert(r >= 0);

BUT this works :
Vector2 test(Level.camera.lookAt);

##### Share on other sites
Thanks. I've fixed this problem in revision 779.

This bug was probably quite old though, as it was related to the property accessors and not the allocation of objects on the stack.

##### Share on other sites
Using r779, there still seems to be problems, sorry to bother you. I have a quite large script code base and I would like to avoid rewriting it as much as possible.

This line gives "Null pointer access" :
Vector2 targetAnchor = _cameraDef[Level.cameraID - 1]._targetCameraWeight <= 0.0f ? Vector2(Level.camera.lookAt) : _cameraDef[Level.cameraID - 1]._targetCameraAncor;
(Also, the cast to Vector2 is there in the first place to avoid "Both sides of the expression must be of the same type".)

However, this equivalent code is fine (when placed at the same line in the same file) :
Vector2 targetAnchor; if (_cameraDef[Level.cameraID - 1]._targetCameraWeight <= 0.0f) { targetAnchor = Vector2(Level.camera.lookAt); } else { targetAnchor = _cameraDef[Level.cameraID - 1]._targetCameraAncor; } 

Remi Gillig

##### Share on other sites
I'll look into it.

Aparently my test cases aren't covering enough situations to catch these problems. But it's good that you're able to isolate the problems so that I can fix them quickly and make them part of my test cases for future changes.

##### Share on other sites
I've fixed this in revision 780.

Please don't hesitate to let me know if you find other problems.

##### Share on other sites
It does not seem to crash anymore but all my scripted events are not called anymore which is a little bit annoying. I'll get back when I have more information.

Thanks for all the fixes so far, you've been really helpful

EDIT : I forgot to say that my events are called on PC but not on PS3 actually, they were fine with 2.20.0

EDIT : Okay nevermind, mistake from my side here, you can't declare parameters as passed by value on PS3, I forgot that some days ago when I added some script functions, everything seems to work perfectly. Thanks for everything

##### Share on other sites
Thanks for confirming the fixes. And thanks for providing useful bug reports, it really helps in identifying the bugs and fixes.

Regards,
Andreas

##### Share on other sites
I just found a small bug with the std::string addon :
string s = "hello"; for (int i = 0; i < 10; ++i) { print(s + i + "\n"); }

This outputs :
hello0 hello01 hello012 hello0123 hello01234 hello012345 hello0123456 hello01234567 hello012345678 hello0123456789

##### Share on other sites
Fixed in revision 781. Thanks.

Thanks a lot

##### Share on other sites
Hello,

It's me again and I have a new bug. We compile on a new platform which is Xbox 360 and it crashes.

Here is the as_content.cpp (line 2371) part :
 case asBC_WRTV1: // The pointer in the register points to a byte, and *(l_fp - offset) too **(asBYTE**)&regs.valueRegister = *(asBYTE*)(l_fp - asBC_SWORDARG0(l_bc)); l_bc++; break;

The script part :
class ArrayOf { bool[] _boolList; int _numOfStockedObject; ArrayOf(int arraySizeMax) { _boolList.resize(arraySizeMax); _numOfStockedObject = 0; for(int i = 0; i < arraySizeMax; ++i) { _boolList = false; } } }

It's the line inside the "for" that seems to crash (this is the last one in the line callback).

The compiler options : AS_XBOX360 AS_XENON (from asGetLibraryOptions).

EDIT : I use revision 781.

Remi Gillig.

##### Share on other sites
It's probably due to the XBOX 360 being a big-endian CPU.

Would it be possible for you to confirm whether the problem happens when compiling with AS_MAX_PORTABILITY, i.e. without using the native calling conventions? That would help narrow determine whether problem is in the as_callfunc_xenon.cpp or not.

##### Share on other sites
I can't do that because all my script exported functions are in native conventions only. Refactoring or adding the support for the generic calling convention will take me quite a long time because there are a lot of them.

However, I can try to help as much as I can with compiler options, code fixes. Tell me if you prefer me to try things directly with you (fix/compile/test etc.).

EDIT : also it already seems to handle the case for big endian in as_config.h :
 #if _XBOX_VER >= 200 // 360 uses a Xenon processor (which is a modified 64bit PPC) #define AS_XBOX360 #define AS_XENON #define AS_BIG_ENDIAN #else

Cheers,
Rémi Gillig.

##### Share on other sites
I'll see if I can reproduce the problem on my Mac where I can run the rosetta simulator for a PPC processor. If the problem is not in the as_callfunc_xenon.cpp code I should be able to find it.

##### Share on other sites
Okay, let me know if you need more information on the crashes I have like specific values of variables. I had crashes happen in other cases of the ExecuteNext switch than the one I put in example.

EDIT : Maybe there were modifications to as_callfunc_ppc.cpp that were not applied to as_callfunc_xenon.cpp (the comments say it was based on ppc). I can also give you some hardware information if necessary.

##### Share on other sites
I couldn't reproduce the problem on my mac with ppc, but I took a closer look at as_callfunc_xenon.cpp and believe I discovered the problem. When the native function was returning a bool as_callfunc_xenon.cpp did an endian swap. The problem was that it didn't check if the bool type was returned by value or by reference, so it messed up the reference to the bool returned by the index operator.

As I was reviewing the code I also fixed a couple of other bugs, such as the code not handling int8 and int16 types correctly. There are also a couple of more bugs that I saw but didn't fix, because it would require more testing, e.g. the code doesn't support int64 parameters, nor passing objects by value.

Obviously I haven't been able to test these changes, so I may have broken some things while changing the code. Please let me know if everything is working as before and if the bug you reported has been fixed too.

The code fixes are in SVN revision 789.

##### Share on other sites
Thanks a lot, I'll report back on Monday from work. I think passing objects by value is used in my code so I could be able to help you on that too.

Cheers,
Remi Gillig.