Jump to content
  • Advertisement
Sign in to follow this  
cvet

Wrong bytecode with funcdef in shared interface

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

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello.

AngelScript revision 1923.

 

How to reproduce:

module->SaveByteCode(...); -> ok

module->LoadByteCode(...); -> first restore is ok

module->SaveByteCode(...); -> give different output compare to first call of SaveByteCode (very small difference, about 6 bytes on 10kb)

module->LoadByteCode(...); -> error in ReadUsedFunctions on line 622

 

Code must be something like it:

funcdef void CALLBACK();

shared interface A

{

    void Func(CALLBACK@ callback);

}

class B : A

{

    void Func(CALLBACK@ callback){}

}

 

If this not help than i try localize problem more precisely.

Edited by cvet

Share this post


Link to post
Share on other sites
Advertisement

Unfortunately it was not enough. I tried the following:

 

// Test repeated save/loads with shared interfaces and funcdefs
// http://www.gamedev.net/topic/656784-wrong-bytecode-with-funcdef-in-shared-interface/
{
  engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
  engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);
 
  mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
  mod->AddScriptSection("test",
    "funcdef void CALLBACK(); \n"
    "shared interface A \n"
    "{ \n"
    "    void Func(CALLBACK@ callback); \n"
    "} \n"
    "class B : A \n"
    "{ \n"
    "    void Func(CALLBACK@ callback){} \n"
    "} \n");
  r = mod->Build();
  if( r < 0 )
    TEST_FAILED;
 
  CBytecodeStream stream(__FILE__"shared");
  r = mod->SaveByteCode(&stream);
  if( r < 0 )
    TEST_FAILED;
 
  asDWORD crc1 = ComputeCRC32(&stream.buffer[0], asUINT(stream.buffer.size()));
 
  r = mod->LoadByteCode(&stream);
  if( r < 0 )
    TEST_FAILED;
 
  CBytecodeStream stream2(__FILE__"shared2");
  r = mod->SaveByteCode(&stream2);
  if( r < 0 )
    TEST_FAILED;
 
  asDWORD crc2 = ComputeCRC32(&stream2.buffer[0], asUINT(stream2.buffer.size()));
 
  if( crc1 != crc2 )
    TEST_FAILED;
 
  r = mod->LoadByteCode(&stream2);
  if( r < 0 )
    TEST_FAILED;
 
  engine->Release();
}

 

I also tried loading the bytecode into a different module, or even a different engine, but none of the tests reproduced the problem.

 

If you can figure out in what part of asCWriter that the output is different in the second save, it might help me understand exactly what is causing it.

Share this post


Link to post
Share on other sites

I localize problem to this:

 

Module1:

funcdef void CALLBACK();

 

Module2:

funcdef void CALLBACK();
void Foo1(CALLBACK@){}
void Foo2(){Foo1(null);}

 

Steps:

Module1 load from code

Module2 load from code

Module1->SaveByteCode

Module2->SaveByteCode

Module1->LoadByteCode

Module2->LoadByteCode

Module1->SaveByteCode

Module2->SaveByteCode -> give different output

Module1->LoadByteCode

Module2->LoadByteCode -> give error

Share this post


Link to post
Share on other sites

Still, no luck.

 

I updated the test with like this:

 

// Test repeated save/loads with shared interfaces and funcdefs
// http://www.gamedev.net/topic/656784-wrong-bytecode-with-funcdef-in-shared-interface/
{
  engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
  engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);
 
  asIScriptModule *mod1 = engine->GetModule(0, asGM_ALWAYS_CREATE);
  mod1->AddScriptSection("test",
    "funcdef void CALLBACK(); \n");
  r = mod1->Build();
  if( r < 0 )
    TEST_FAILED;
 
  asIScriptModule *mod2 = engine->GetModule(0, asGM_ALWAYS_CREATE);
  mod2->AddScriptSection("test",
    "funcdef void CALLBACK(); \n"
    "void Foo1(CALLBACK@){} \n"
    "void Foo2(){Foo1(null);} \n");
  r = mod2->Build();
  if( r < 0 )
    TEST_FAILED;
 
  CBytecodeStream stream1(__FILE__"shared1");
  r = mod1->SaveByteCode(&stream1);
  if( r < 0 )
    TEST_FAILED;
 
  CBytecodeStream stream2(__FILE__"shared2");
  r = mod2->SaveByteCode(&stream2);
  if( r < 0 )
    TEST_FAILED;
 
  asDWORD crc1 = ComputeCRC32(&stream2.buffer[0], asUINT(stream2.buffer.size()));
 
  r = mod1->LoadByteCode(&stream1);
  if( r < 0 )
    TEST_FAILED;
 
  r = mod2->LoadByteCode(&stream2);
  if( r < 0 )
    TEST_FAILED;
 
  CBytecodeStream stream3(__FILE__"shared1");
  r = mod1->SaveByteCode(&stream3);
  if( r < 0 )
    TEST_FAILED;
 
  CBytecodeStream stream4(__FILE__"shared2");
  r = mod2->SaveByteCode(&stream4);
  if( r < 0 )
    TEST_FAILED;
 
  asDWORD crc2 = ComputeCRC32(&stream4.buffer[0], asUINT(stream4.buffer.size()));
 
  if( crc1 != crc2 )
    TEST_FAILED;
 
  r = mod1->LoadByteCode(&stream3);
  if( r < 0 )
    TEST_FAILED;
 
  r = mod2->LoadByteCode(&stream4);
  if( r < 0 )
    TEST_FAILED;
 
  engine->Release();
}

 

 

Unfortunately the test still doesn't reproduce the problem.

 

Perhaps to reproduce it something specific needs to be registered with the engine too?

Share this post


Link to post
Share on other sites

This test case must reproduce problem:



bool Test()
{
	bool fail = false;
	int r;
	COutStream out;
	asIScriptModule *mod1, *mod2;
	asIScriptEngine *engine;

	CBytecodeStream stream1(__FILE__"shared1");
	CBytecodeStream stream2(__FILE__"shared2");
	CBytecodeStream stream3(__FILE__"shared3");
	CBytecodeStream stream4(__FILE__"shared4");

	asDWORD crc1, crc2;

	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);

		mod1 = engine->GetModule(0, asGM_ALWAYS_CREATE);
		mod1->AddScriptSection("test",
			"funcdef void CALLBACK();\n");
		r = mod1->Build();
		if( r < 0 )
			TEST_FAILED;
		mod2 = engine->GetModule(0, asGM_ALWAYS_CREATE);
		mod2->AddScriptSection("test",
			"funcdef void CALLBACK(); \n"
			"void Foo1(CALLBACK@){} \n"
			"void Foo2(){Foo1(null);}\n");
		r = mod2->Build();
		if( r < 0 )
			TEST_FAILED;

		r = mod1->SaveByteCode(&stream1);
		if( r < 0 )
			TEST_FAILED;
		r = mod2->SaveByteCode(&stream2);
		if( r < 0 )
			TEST_FAILED;

		crc1 = ComputeCRC32(&stream2.buffer[0], asUINT(stream2.buffer.size()));

		engine->Release();
	}

	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);

		mod1 = engine->GetModule(0, asGM_ALWAYS_CREATE);
		r = mod1->LoadByteCode(&stream1);
		if( r < 0 )
			TEST_FAILED;
		mod2 = engine->GetModule(0, asGM_ALWAYS_CREATE);
		r = mod2->LoadByteCode(&stream2);
		if( r < 0 )
			TEST_FAILED;

		r = mod1->SaveByteCode(&stream3);
		if( r < 0 )
			TEST_FAILED;
		r = mod2->SaveByteCode(&stream4);
		if( r < 0 )
			TEST_FAILED;

		crc2 = ComputeCRC32(&stream4.buffer[0], asUINT(stream4.buffer.size()));
		if( crc1 != crc2 )
			TEST_FAILED;

		engine->Release();
	}

	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);

		mod1 = engine->GetModule(0, asGM_ALWAYS_CREATE);
		r = mod1->LoadByteCode(&stream3);
		if( r < 0 )
			TEST_FAILED;
		mod2 = engine->GetModule(0, asGM_ALWAYS_CREATE);
		r = mod2->LoadByteCode(&stream4);
		if( r < 0 )
			TEST_FAILED;

		engine->Release();
	}

	// Success
	return fail;
}
Edited by cvet

Share this post


Link to post
Share on other sites

Yes, now I'm able to reproduce the error. I'll let you know as soon as I have a fix available.

 

Thanks for the help so far.

Share this post


Link to post
Share on other sites

I've fixed the problem in revision 1931.

 

The problem was when loading the bytecode with the funcdef. The funcdef was incorrectly marked as owned by the module. This is what caused the bytecode to be saved slightly differently in the second iteration and ultimately why the bytecode failed to load again.

 

Regards,

Andreas

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!