View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0000628 | LDMud 3.3 | Portability | public | 2009-04-19 13:34 | 2009-05-05 13:27 |
Reporter | zesstra | Assigned To | zesstra | ||
Priority | high | Severity | major | Reproducibility | N/A |
Status | resolved | Resolution | fixed | ||
Platform | x86_64 | OS | MacOS X | OS Version | 10.5.x |
Product Version | 3.3.718 | ||||
Target Version | 3.3.719 | Fixed in Version | 3.3.719 | ||
Summary | 0000628: Inconsistent data for F_NUMBER is generated on LP64 systems | ||||
Description | F_NUMBER in interpret.c expects the number to be in the host format. It reads sizeof(p_int) chars following the F_NUMBER instruction into svp[1]->u.number. Unfortunately, the compiler does generate two different F_NUMBER: - L_NUMBER writes sizeof(p_int) chars into the bytecode after F_NUMBER. - ins_number() writes a int32 into the bytecode after F_NUMBER. I don't know why nobody noticed this problem, it is quite weird. ins_number() seems to be rarely used. | ||||
Tags | No tags attached. | ||||
Attached Files | 0001-Fix-F_NUMBER-generation.patch (4,152 bytes)
From df56a1f99b435edc08d8a3570e9df0325c01b636 Mon Sep 17 00:00:00 2001 From: zesstra <zesstra@zesstra.de> Date: Sun, 19 Apr 2009 22:14:14 +0200 Subject: [PATCH] Fix F_NUMBER generation. The compiler generated F_NUMBER at more than one places. ins_number() did only write a int32 into the bytecode, all the other places write a p_int, which interpret.c expects. The patch added ins_p_int(), upd_p_int() and read_p_int(). ins_number() calls ins_p_int() upon generating the F_NUMBER instruction. Additionally upon storing a number (L_NUMBER) and in the unary '-' upd_p_int() is called instead of a direct memcpy(). (memcpy() is faster, but I think it is much more risky to forget a place to change...) Signed-off-by: zesstra <zesstra@zesstra.de> --- src/prolang.y | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 files changed, 57 insertions(+), 8 deletions(-) diff --git a/src/prolang.y b/src/prolang.y index 4c55b9d..7ea8e29 100644 --- a/src/prolang.y +++ b/src/prolang.y @@ -2053,8 +2053,60 @@ read_long (mp_uint offset) } /* read_long() */ /*-------------------------------------------------------------------------*/ +static INLINE void +ins_p_int (p_int num) + +/* Add the number <num> to the A_PROGRAM area in a fixed byteorder. + */ +{ + if (realloc_a_program(sizeof(num))) + { + /* F_NUMBER expects the number in the host format. Therefore memcpy() + * is OK. interpret.c will read the number with memcpy() as well. + * TODO: use a suitable PUT_ from bytecode.h (change in interpret.c as well!) + */ + memcpy(mem_block[A_PROGRAM].block + CURRENT_PROGRAM_SIZE, &num, sizeof(num)); + CURRENT_PROGRAM_SIZE += sizeof(num); + } + else + { + yyerrorf("Out of memory: program size %"PRIuMPINT"\n" + , mem_block[A_PROGRAM].current_size + sizeof(num)); + } +} /* ins_p_int() */ + +/*-------------------------------------------------------------------------*/ +static INLINE void +upd_p_int (mp_uint offset, p_int num) + +/* Store the number <num> at <offset> in the A_PROGRAM area in a fixed byteorder. + */ +{ + /* F_NUMBER expects the number in the host format. Therefore memcpy() + * is OK. interpret.c will read the number with memcpy() as well. + * TODO: use a suitable PUT_ from bytecode.h (change in interpret.c as well!) + */ + memcpy(mem_block[A_PROGRAM].block + offset, &num, sizeof(num)); + +} /* upd_p_int() */ + +/*-------------------------------------------------------------------------*/ +static p_int +read_p_int (mp_uint offset) + +/* Return the <number> stored at <offset> in the A_PROGRAM area. + */ +{ + p_int number; + /* TODO: use GET_ function from bytecode.h */ + memcpy(&number, mem_block[A_PROGRAM].block + offset, sizeof(number)); + + return number; +} /* read_p_int() */ + +/*-------------------------------------------------------------------------*/ static void -ins_number (long num) +ins_number (p_int num) /* Insert code to push number <num> onto the stack. * The function tries to find the shortest sequence to do so. @@ -2082,7 +2134,7 @@ ins_number (long num) else { ins_f_code(F_NUMBER); - ins_long(num); + ins_p_int(num); } } /* ins_number() */ @@ -9930,12 +9982,9 @@ expr0: F_NUMBER ) { p_int number; - - memcpy(&number, &(mem_block[A_PROGRAM].block[last_expression+1]) - , sizeof(number)); + number = read_p_int(last_expression + 1); number = -number; - memcpy(&(mem_block[A_PROGRAM].block[last_expression+1]), &number - , sizeof(number)); + upd_p_int(last_expression + 1, number); } else { @@ -10106,7 +10155,7 @@ expr4: else { add_f_code(F_NUMBER); - memcpy(__PREPARE_INSERT__p, &$1, sizeof $1); + upd_p_int((char*)__PREPARE_INSERT__p - mem_block[A_PROGRAM].block, $1); current += 1 + sizeof (p_int); $$.type = Type_Number; } -- 1.6.1 0002-Fixes-insert_pop_value.patch (5,334 bytes)
From d5c5882d90fe6add24add3c67db7336090a24fb3 Mon Sep 17 00:00:00 2001 From: zesstra <zesstra@zesstra.de> Date: Mon, 4 May 2009 17:40:36 +0200 Subject: [PATCH 2/2] Fixes insert_pop_value(). insert_pop_value() removes the last value from the stack. If possible, it patches the code to prevent that value from being computed at all (by removing the last expression). Unfortunately the function assumed that all opertions have no data following in the bytecode. This patches changes it and enabled optimization/removal of operations with data. Signed-off-by: zesstra <zesstra@zesstra.de> --- src/prolang.y | 111 ++++++++++++++++++++++++++++++++++++--------------------- 1 files changed, 70 insertions(+), 41 deletions(-) diff --git a/src/prolang.y b/src/prolang.y index 7ea8e29..c01eac8 100644 --- a/src/prolang.y +++ b/src/prolang.y @@ -14145,58 +14145,87 @@ insert_pop_value (void) */ { - if (last_expression == CURRENT_PROGRAM_SIZE-1) + /* We don't have to fear sideeffects and try to prevent + * the value from being generated if the last expression is not too long + * ago. + */ + if (last_expression == CURRENT_PROGRAM_SIZE - 1) { - /* We don't have to fear sideeffects and try to prevent - * the value from being generated. - */ + /* The following ops have no data in the bytecode. */ switch ( mem_block[A_PROGRAM].block[last_expression]) { - case F_ASSIGN: - mem_block[A_PROGRAM].block[last_expression] = + /* The following ops have no data in the bytecode. */ + case F_ASSIGN: + mem_block[A_PROGRAM].block[last_expression] = F_VOID_ASSIGN; - break; - case F_ADD_EQ: - mem_block[A_PROGRAM].block[last_expression] = + break; + case F_ADD_EQ: + mem_block[A_PROGRAM].block[last_expression] = F_VOID_ADD_EQ; - break; - case F_PRE_INC: - case F_POST_INC: - mem_block[A_PROGRAM].block[last_expression] = + break; + case F_PRE_INC: + case F_POST_INC: + mem_block[A_PROGRAM].block[last_expression] = F_INC; - break; - case F_PRE_DEC: - case F_POST_DEC: - mem_block[A_PROGRAM].block[last_expression] = + break; + case F_PRE_DEC: + case F_POST_DEC: + mem_block[A_PROGRAM].block[last_expression] = F_DEC; - break; - case F_CONST0: - case F_CONST1: - case F_NCONST1: - mem_block[A_PROGRAM].current_size = last_expression; - break; - case F_CLIT: - case F_NCLIT: - case F_CSTRING0: - case F_CSTRING1: - case F_CSTRING2: - mem_block[A_PROGRAM].current_size = last_expression-1; - break; - case F_STRING: - mem_block[A_PROGRAM].current_size = last_expression-2; - break; - case F_NUMBER: - mem_block[A_PROGRAM].current_size = last_expression-4; - break; - default: ins_f_code(F_POP_VALUE); + break; + case F_CONST0: + case F_CONST1: + case F_NCONST1: + mem_block[A_PROGRAM].current_size = last_expression; + break; + default: + ins_f_code(F_POP_VALUE); + break; } - last_expression = -1; + } + else if (last_expression == CURRENT_PROGRAM_SIZE - 2) + { + /* The following ops are followed by 1 chars of data in the bytecode. */ + switch ( mem_block[A_PROGRAM].block[last_expression]) + { + case F_CLIT: + case F_NCLIT: + case F_CSTRING0: + case F_CSTRING1: + case F_CSTRING2: + case F_CSTRING3: + mem_block[A_PROGRAM].current_size = last_expression; + break; + default: + ins_f_code(F_POP_VALUE); + break; + } + } + else if (last_expression == CURRENT_PROGRAM_SIZE - 3) + { + /* The following ops are followed by 2 chars of data in the bytecode. */ + if ( mem_block[A_PROGRAM].block[last_expression] == F_STRING) + mem_block[A_PROGRAM].current_size = last_expression; + else + ins_f_code(F_POP_VALUE); + } + else if (last_expression == CURRENT_PROGRAM_SIZE - sizeof(p_int)) + { + /* The following ops are followed by sizeof(p_int) chars of data in + * the bytecode. */ + if ( mem_block[A_PROGRAM].block[last_expression] == F_NUMBER) + mem_block[A_PROGRAM].current_size = last_expression; + else + ins_f_code(F_POP_VALUE); } else - /* The last expression is too long ago: just pop whatever there - * is on the stack. - */ + { + /* last expression unknown or too long ago - just pop whatever there + * is on the stack */ ins_f_code(F_POP_VALUE); + } + + last_expression = -1; } /* insert_pop_value() */ /*-------------------------------------------------------------------------*/ -- 1.6.1 | ||||
|
The patch adds ins_p_int(), upd_p_int() and read_p_int(). ins_number() now calls ins_p_int() upon generating the F_NUMBER instruction. Additionally upon storing a number (L_NUMBER) and in the unary '-' upd_p_int() is called instead of a direct memcpy(). (memcpy() is faster, but I think it is much more risky to forget a place to change...) |
|
Gnomi noticed, that insert_pop_value() is not working properly, because it did not take into account, that the operations have different payloads of data following. I attached a patch which should rectify this. Could someone have a short look? BTW: insert_pop_value() would now always set last_expression to -1, this may have side effects, I didn't notice. If this is the case, it has to be changed. |
|
Ok, great. This issue should then be fixed by r2562 and r2563. |
Date Modified | Username | Field | Change |
---|---|---|---|
2009-04-19 13:34 | zesstra | New Issue | |
2009-04-19 13:34 | zesstra | Status | new => assigned |
2009-04-19 13:34 | zesstra | Assigned To | => zesstra |
2009-04-19 14:17 | zesstra | File Added: 0001-Fix-F_NUMBER-generation.patch | |
2009-04-19 14:18 | zesstra | Note Added: 0001059 | |
2009-05-05 12:46 | zesstra | File Added: 0002-Fixes-insert_pop_value.patch | |
2009-05-05 12:50 | zesstra | Note Added: 0001079 | |
2009-05-05 13:27 | zesstra | Note Added: 0001080 | |
2009-05-05 13:27 | zesstra | Status | assigned => resolved |
2009-05-05 13:27 | zesstra | Fixed in Version | => 3.3.719 |
2009-05-05 13:27 | zesstra | Resolution | open => fixed |