Advertisement

Variable temporaries in bytecode

Started by February 07, 2014 11:01 PM
2 comments, last by WitchLord 10 years, 9 months ago

I've got the following script:


void main()
{
    array<string> arr;
    arr.insertLast("hello");

    const string s = arr[0];
    Print(s);
}

The array is the add_ons one and Print() is being registered as follows:


r = engine->RegisterGlobalFunction("void Print(string &in)", asFUNCTION(PrintString), asCALL_CDECL);

That produces the following byte code:


void main()

Temps: 2, 4

Variables:
 001: array<string> arr
 003: const string s
 002: string {noname}


- 3,2 -    array<string> arr;
    0   4 *    SUSPEND
    1   4 *    VarDecl  0
    1   4 *    CALL     114           (array<string>@ factstub())
    3   4 *    STOREOBJ v1
- 4,2 -    arr.insertLast("hello");
    4   4 *    SUSPEND
    5   4 *    STR      0         (l:5 s:"hello")
    6   6 *    CALLSYS  33           (const string& _string_factory_(const int, const uint8&in))
    8   4 *    PshRPtr
    9   5 *    PSF      v2
   10   6 *    CALLSYS  35           (string::string(const string&in))
   12   4 *    ObjInfo  v2, 1
   12   4 *    VAR      v2
   13   5 *    PshVPtr  v1
   14   6 *    GETREF   1
   15   6 *    CALLSYS  122           (void array::insertLast(const string&in))
   17   4 *    PSF      v2
   18   5 *    CALLSYS  36           (string::~string())
- 6,2 -    const string s = arr[0];
   20   4 *    ObjInfo  v2, 0
   20   4 *    SUSPEND
   21   4 *    VarDecl  1
   21   4 *    PshC4    0x0          (i:0, f:0)
   23   5 *    PshVPtr  v1
   24   6 *    CALLSYS  118           (string& array::opIndex(uint))
   26   4 *    PshRPtr
   27   5 *    PSF      v3
   28   6 *    CALLSYS  34           (string::string())
   30   5 *    ObjInfo  v3, 1
   30   5 *    PSF      v3
   31   6 *    CALLSYS  37           (string& string::opAssign(const string&in))
- 7,2 -    Print(s);
   33   4 *    SUSPEND
   34   4 *    PSF      v2
   35   5 *    CALLSYS  34           (string::string())
   37   4 *    ObjInfo  v2, 1
   37   4 *    PSF      v3
   38   5 *    PSF      v2
   39   6 *    CALLSYS  37           (string& string::opAssign(const string&in))
   41   4 *    PSF      v2
   42   5 *    CALLSYS  107           (void Print(string&in))
   44   4 *    PSF      v2
   45   5 *    CALLSYS  36           (string::~string())
- 8,2 -    }
   47   4 *    ObjInfo  v2, 0
   47   4 *    SUSPEND
   48   4 *    PSF      v3
   49   5 *    CALLSYS  36           (string::~string())
   51   4 *    ObjInfo  v3, 0
   51   4 *    FREE     v1, 145445320
   53   4 * 0:
   53   4 *    RET      0

In the byte code corresponding to the Print() call, why is a string temporary being created? I thought the "in" designation on Print()'s param was supposed to instruct the compiler that Print() will not modify that param..

Thank you very much!

'in' just instructs the compiler that the reference will be used as input value, it cannot be certain the value will not be modified just with this. To avoid the copy you need to declare the parameter as (const string &in).

Regards,

Andreas

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Advertisement

You're right, here it is with the const:


void main()

Temps: 8, 15

Variables:
 002: array<string> arr
 014: const string s
 008: string {noname}


- 3,5 -    array<string> arr;
    0  15 *    SUSPEND
    1  15 *    VarDecl  0
    1  15 *    CALL     114           (array<string>@ factstub())
    3  15 *    STOREOBJ v2
- 4,5 -    arr.insertLast("hello");
    4  15 *    SUSPEND
    5  15 *    STR      0         (l:5 s:"hello")
    6  18 *    CALLSYS  33           (const string& _string_factory_(const int, const uint8&in))
    8  15 *    PshRPtr
    9  17 *    PSF      v8
   10  19 *    CALLSYS  35           (string::string(const string&in))
   12  15 *    ObjInfo  v8, 1
   12  15 *    VAR      v8
   13  17 *    PshVPtr  v2
   14  19 *    GETREF   2
   15  19 *    CALLSYS  122           (void array::insertLast(const string&in))
   17  15 *    PSF      v8
   18  17 *    CALLSYS  36           (string::~string())
- 6,5 -    const string s = arr[0];
   20  15 *    ObjInfo  v8, 0
   20  15 *    SUSPEND
   21  15 *    VarDecl  1
   21  15 *    PshC4    0x0          (i:0, f:0)
   23  16 *    PshVPtr  v2
   24  18 *    CALLSYS  118           (string& array::opIndex(uint))
   26  15 *    PshRPtr
   27  17 *    PSF      v14
   28  19 *    CALLSYS  34           (string::string())
   30  17 *    ObjInfo  v14, 1
   30  17 *    PSF      v14
   31  19 *    CALLSYS  37           (string& string::opAssign(const string&in))
- 7,5 -    Print(s);
   33  15 *    SUSPEND
   34  15 *    PSF      v14
   35  17 *    CALLSYS  107           (void Print(const string&in))
- 8,2 -    }
   37  15 *    SUSPEND
   38  15 *    PSF      v14
   39  17 *    CALLSYS  36           (string::~string())
   41  15 *    ObjInfo  v14, 0
   41  15 *    FREE     v2, 0x7fdc30e016c0           (i:140583689524928, f:6.94576e-310)
   44  15 * 0:
   44  15 *    RET      0

How about for this case?


void main()
{
    array<string> arr;
    arr.insertLast("hello");

    Print(arr[0]);
}

Is it not possible to pass the pointer that comes back from opIndex() straight into the Print() ?


void main()

Temps: 8, 9

Variables:
 002: array<string> arr
 008: string {noname}


- 3,5 -    array<string> arr;
    0   9 *    SUSPEND
    1   9 *    VarDecl  0
    1   9 *    CALL     114           (array<string>@ factstub())
    3   9 *    STOREOBJ v2
- 4,5 -    arr.insertLast("hello");
    4   9 *    SUSPEND
    5   9 *    STR      0         (l:5 s:"hello")
    6  12 *    CALLSYS  33           (const string& _string_factory_(const int, const uint8&in))
    8   9 *    PshRPtr
    9  11 *    PSF      v8
   10  13 *    CALLSYS  35           (string::string(const string&in))
   12   9 *    ObjInfo  v8, 1
   12   9 *    VAR      v8
   13  11 *    PshVPtr  v2
   14  13 *    GETREF   2
   15  13 *    CALLSYS  122           (void array::insertLast(const string&in))
   17   9 *    PSF      v8
   18  11 *    CALLSYS  36           (string::~string())
- 6,5 -    Print(arr[0]);
   20   9 *    ObjInfo  v8, 0
   20   9 *    SUSPEND
   21   9 *    PshC4    0x0          (i:0, f:0)
   23  10 *    PshVPtr  v2
   24  12 *    CALLSYS  118           (string& array::opIndex(uint))
   26   9 *    PshRPtr
   27  11 *    PSF      v8
   28  13 *    CALLSYS  35           (string::string(const string&in))
   30   9 *    ObjInfo  v8, 1
   30   9 *    PSF      v8
   31  11 *    CALLSYS  107           (void Print(const string&in))
   33   9 *    PSF      v8
   34  11 *    CALLSYS  36           (string::~string())
- 7,2 -    }
   36   9 *    ObjInfo  v8, 0
   36   9 *    SUSPEND
   37   9 *    FREE     v2, 0x7f83f2c14de0           (i:140204690197984, f:6.92703e-310)
   40   9 * 0:
   40   9 *    RET      0

No, in this case it is not possible because the string is not a local variable and is not guaranteed to stay alive for the duration of the call to Print().

Remember, AngelScript is supposed to be secure, i.e. the script writer shouldn't be able to crash the application however hard he tries. For that reason the AngelScript compiler will have to do some things that wouldn't otherwise be done in a language like C++.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

This topic is closed to new replies.

Advertisement