Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Constructors are broken in 2.27.0 #4

Closed
justin12343 opened this issue Aug 3, 2013 · 27 comments
Closed

Constructors are broken in 2.27.0 #4

justin12343 opened this issue Aug 3, 2013 · 27 comments

Comments

@justin12343
Copy link

Apparently, a null pointer is stored in the object register after the constructor of a script class is executed. I'm using the method outlined in the manual to instantiate a script class from C++. The code worked fine in 2.26.3, but it does not in 2.27.0 with JIT enabled.

void Object::CallConstructor()
{
if (constructorCalled)
return;

asIScriptContext *context = scriptManager->GetContext();

if (context == NULL)
    return;

if (context->Prepare( funcConstructor) < 0)
{
    printf( "There was an error preparing the context.\n");
    return;
}

*((Object**)context->GetAddressOfArg(0)) = this;
//AddRef();

int r = context->Execute();

if (r != asEXECUTION_FINISHED)
{
    if (r == asEXECUTION_EXCEPTION)
    {
        const char *exception = context->GetExceptionString();
        printf( "An Exception, '%s', Occurred In The Constructor.\n", exception);
        return;
    }

    if (r == asERROR)
    {
        printf( "An Unexpected Error Occurred In The Constructor.\n");
        return;
    }
}
else
{
    pScrObj = *((asIScriptObject**)context->GetAddressOfReturnValue());// <--- NULL HERE
    pScrObj->AddRef(); //Must Be Called or else Pure Virtual Error!

    context->Unprepare();
    constructorCalled = true;
}

}

@ScottDillman
Copy link

I'm seeing this same behavior with 2.27.1

@ThyReaper
Copy link
Member

Which case within context->GetAddressOfReturnValue() is returning the null? I compared everywhere that those returns are set within AngelScript and the jit and didn't see a disagreement, so it would help to narrow it down.

@ScottDillman
Copy link

I'll try to come up with a small test case, maybe Justin has one handy, I only ran into this problem about 30 mins ago..

@justin12343
Copy link
Author

The jit seems to not compile any scripts at all in 2.27.1 for me at this point.

This is the very first script that is compiled in my engine:

shared class Base_Object
{
//========== Constructor / Destructor ===========
Base_Object( Object @obj)
{
@this.object = obj;
x = object.x;
y = object.y;
sprite_index = -1;
mask_index = sprite_index;
image_index = object.image_index;
depth = object.depth;
}

//=========== Events =============
void Create(){}
void Destroy(){}
void Alarm1(){}
void Alarm2(){}
void Alarm3(){}
void Alarm4(){}
void Alarm5(){}
void Alarm6(){}
void Alarm7(){}
void Alarm8(){}
void Alarm9(){}
void Alarm10(){}
void Alarm11(){}

void BeginStep(){}
void Step(){}
void EndStep(){}

void Collision( int objType, int objId, Object @other){}

void Key( int key){}
void KeyPressed( int key){}
void KeyReleased( int key){}

void MouseButton( int button){}
void MouseButtonPressed( int button){}
void MouseButtonReleased( int button){}

void JoystickButton( int id, int button){}
void JoystickButtonPressed( int id, int button){}
void JoystickButtonReleased( int id, int button){}

void OutsideRoom(){}
void OutsideView(){}
void IntersectBoundary(){}

void GameStart(){}
void GameEnd(){}

void RoomStart(){}
void RoomEnd(){}

void NoMoreLives(){}
void NoMoreHealth(){}

void AnimationEnd(){}
void EndOfPath(){}
void Draw(){}

//======= Collision =========
bool place_meeting( float mX, float mY, int type)
{
return object.PlaceMeeting( mX, mY, type);
}

bool place_meeting_depth( float mX, float mY, int depth, int type)
{
    return object.PlaceMeetingDepth( mX, mY, type, depth);
}

Base_Object @object_place( float mX, float mY, int type)
{
    Base_Object @base = null;
    Object @obj = object.ObjectPlace( mX, mY, type);

    if (@obj != null)
        @base = cast<Base_Object>(@obj.GetScriptObject());

    return base;
}

bool collision_rectangle( float x1, float y1, float x2, float y2, int type)
{
    return object.CollisionRectangle( x1, y1, x2, y2, type);
} 

//========== Misc ===========
uint GetId()
{
return object.GetId();
}

void SetRect( int l, int t, int w, int h)
{
    object.general_rect.left = l;
    object.general_rect.top = t;
    object.general_rect.right = l+w;
    object.general_rect.bottom = t+h;
}

/*Base_Object@ opAssign(Base_Object_IMP @in)
{
    return @cast<Base_Object>( @in.GetScriptObject());
}*/

//======= Variables =========
Object @object;
float x;
float y;
int sprite_index;
int mask_index;
int image_index;
int depth;
}

//*******************************************************************************************************************

I'm thinking there's problem with classes because it doesn't fail when compiling just a simple function. The assert in the following code section fails because there is a null pointer to scriptData:

void asCScriptFunction::JITCompile()
{
asIJITCompiler *jit = engine->GetJITCompiler();
if( !jit )
return;

asASSERT( scriptData );

..........

Even something as simple as this doesn't compile:

class test
{
void t(){}
}

Now with further investigation I found that the function for "t()" in the virtual function table of asIObjectType is valid. Shouldn't angelscript be calling JITCompile() on this function?

@justin12343
Copy link
Author

Ok, forget everything above. That was a bug in 2.27.1. Now that I've updated to the WIP version, the problem is back. The context never sets a valid pointer to the object register, so in turn GetAddressOfReturnValue only returns a null pointer. This doesn't happen with the jit disabled, so I'm assuming something changed with the way classes are constructed.

@ThyReaper
Copy link
Member

As far as I can see objectRegister is set by the JIT in identical ways to AngelScript. I need to know which return "void *asCContext::GetAddressOfReturnValue()" is returning 0 from.

@justin12343
Copy link
Author

if( !dt->IsObjectHandle() )
{
if( m_initialFunction->DoesReturnOnStack() )
{
// The address of the return value was passed as the first argument, after the object pointer
int offset = 0;
if( m_initialFunction->objectType )
offset += AS_PTR_SIZE;

            return *(void**)(&m_regs.stackFramePointer[offset]);
        }

        return *(void**)&m_regs.objectRegister;
    }
    return &m_regs.objectRegister;//<--------------------------------------------------- Returns 0 here
}

@ThyReaper
Copy link
Member

Very few areas touch objectRegister, and they're very simple, so I can't see what's going wrong. Is the function returning 0, or a pointer to a 0?

@justin12343
Copy link
Author

It returns the null pointer that is stored in the object register. This seems to happen with all of my constructors.

@ThyReaper
Copy link
Member

This line:
return &m_regs.objectRegister;
Does not return the value of the object register, only its location. I'm just trying to clarify, because you say the function is returning a 0, but that line should not be able to.

@justin12343
Copy link
Author

Sorry for the confusion. It returns a null pointer, not a value of 0.

@ThyReaper
Copy link
Member

So you're saying "return &m_regs.objectRegister" is returning a null pointer? That shouldn't be possible.

@justin12343
Copy link
Author

That's what's happening.

@ThyReaper
Copy link
Member

I don't see what that could have to do with the jit. That statement cannot return a null pointer unless "this" is null and both m_regs and objectRegister are at 0 offset of their base class. Have you tried recompiling AngelScript/your project?

@justin12343
Copy link
Author

I've recompiled both AngelScript and my project numerous times and the results are still the same. The "this" pointer checks fine, both in the context and in my code, and m_regs is fine as far as I can tell, I.E. it holds similar values as it would without JIT instructions enabled, but m_regs.objectRegister points to a null address.

I tried this simple test case:

SCRIPT:
class test
{
test(){}
}

CODE:
asIObjectType test_type = module->GetObjectTypeByName( "test");
asIScriptObject *obj = (asIScriptObject
)scriptManager->GetEngine()->CreateScriptObject( test_type);
//The comment window is weird. I am casting void* to (asIScriptObject*) if you can't see

CreateScriptObject nearly uses identical code to that of which I was using the call the "test" class' constructor. As I figured, it fails after attempting to increase the reference counter of the script object because it points to a null address. This same code works without JIT instructions enabled.

@ThyReaper
Copy link
Member

asIScriptEngine::CreateScriptObject works for me. I am unable to reproduce your issue.

@justin12343
Copy link
Author

In 2.27.1 correct?

@justin12343
Copy link
Author

Can you upload an executable and the source or a msvc project?

@ThyReaper
Copy link
Member

We're using the SVN build which has variably been 2.26, 2.27, and 2.28 over time. I cannot provide executable or source for our project.

@justin12343
Copy link
Author

I didn't mean upload your major project (by all means, don't do that lol), but a test program and/or its source where you've gotten it to work with the latest version of AS. I've gone as far as integrating the jit code directly into the angelscript project and recompiling the libs, but I'm still getting the same problem. I hope I'm not asking for too much.

@ThyReaper
Copy link
Member

I've pushed all of our local changes to the JIT. We are using the most recent SVN version of AngelScript, and experience no issues with CreateScriptObejct or similar code.

@justin12343
Copy link
Author

I'm still having the same problem, so I've made a simple Console app that isolates the issue:
http://www.mediafire.com/download/ijsp95fr6ild1hh/asJit_AS_1725_trunk_null_pointer_test_.zip

This is with angelscript revision 1725 and your updated JIT code.

@ThyReaper
Copy link
Member

That is built with Visual Studio 2012, which I am not using. It is possible 2012 has some incompatibility with the jit that 2010 does not have.

@justin12343
Copy link
Author

I don't know what the problem could be. I get the same error even when compiling with the Visual Studio 2010 platform toolset.

Here is the VS 2010 version of things:
http://www.mediafire.com/?dl9vyrdr87ckiw6

@ScottDillman
Copy link

Adding the following JIT setting temporarily fixed my problem:

JIT_NO_SCRIPT_CALLS

Don't know if that helps or not, but figured I would mention it..

@ThyReaper
Copy link
Member

I knew of an issue during jit-compile with script calls, but I wasn't aware they were having destructive side effects during execution. I'll look into it.

@ThyReaper
Copy link
Member

Angelscript's callstack size changed and that value is not accessible from outside as_context.cpp. I updated the value for the JIT which should fix script calls, and hopefully the issue in general. Please reopen if the issue persists.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants