[INTERPRETER]

* OPT: Native array optimizations are better. For arrays with one 
  dimension, reading is about 70% faster than gambas2, and writing 40% 
  faster.
* OPT: Collection array accessors were optimized too. Reading is about 50%
  faster and writing 60% faster. Be careful: only the array accessors were
  optimized, not the full hash table access, which is the slower part of 
  the process.


git-svn-id: svn://localhost/gambas/trunk@1036 867c0c6c-44f3-4631-809d-bfa615b0a4ec
This commit is contained in:
Benoît Minisini 2008-01-24 10:42:42 +00:00
parent 6ac9fbe05b
commit 7cc9986bda
11 changed files with 118 additions and 85 deletions

View File

@ -3748,3 +3748,4 @@ PUBLIC SUB DrawTitle(hForm AS Object)
hForm.Title = sTitle '& " - " & Project.Name
END

View File

@ -85,11 +85,11 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: DataControl.class:76 DataView.class:195
#: DataControl.class:76 DataView.class:198
msgid "True"
msgstr "Vrai"
#: DataControl.class:77 DataView.class:195
#: DataControl.class:77 DataView.class:198
msgid "False"
msgstr "Faux"
@ -137,34 +137,34 @@ msgstr "Suivant"
msgid "End"
msgstr "Fin"
#: FMain.class:102
#: FMain.class:104
msgid "Id"
msgstr ""
#: FMain.class:107
#: FMain.class:109
msgid "Color"
msgstr ""
#: FMain.class:112
#: FMain.class:114
msgid "First Name"
msgstr ""
#: FMain.class:117
#: FMain.class:119
msgid "Name"
msgstr ""
#: FMain.class:122
#: FMain.class:124
msgid "Birth"
msgstr ""
#: FMain.class:127
#: FMain.class:129
msgid "Active"
msgstr ""
#: FMain.class:132
#: FMain.class:134
msgid "Salary"
msgstr ""
#: FMain.class:137
#: FMain.class:139
msgid "Comment"
msgstr ""

View File

@ -7,7 +7,7 @@ Library=gb.form
Library=gb.db
Library=gb.db.form
Authors=Benoît Minisini
Environment="GB_GUI=gb.gtk"
Environment="GB_GUI="
TabSize=2
Translate=1
Language=en

View File

@ -124,7 +124,7 @@ void *GB_ArrayGet(GB_ARRAY array, int index);
void GB_CollectionNew(GB_COLLECTION *col, int mode);
int GB_CollectionCount(GB_COLLECTION col);
void GB_CollectionSet(GB_COLLECTION col, const char *key, int len, GB_VARIANT *value);
int GB_CollectionSet(GB_COLLECTION col, const char *key, int len, GB_VARIANT *value);
int GB_CollectionGet(GB_COLLECTION col, const char *key, int len, GB_VARIANT *value);
int GB_CollectionEnum(GB_COLLECTION col, GB_VARIANT *value, char **key, int *len);

View File

@ -100,8 +100,9 @@ static void *get_data(CARRAY *_object, int index)
return (void *)((char *)(THIS->data) + index * TYPE_sizeof_memory(THIS->type));
}
#define get_data_multi CARRAY_get_data_multi
static void *get_data_multi(CARRAY *_object, GB_INTEGER *arg, int nparam)
void *CARRAY_get_data_multi(CARRAY *_object, GB_INTEGER *arg, int nparam)
{
int index;

View File

@ -68,5 +68,6 @@ void CARRAY_split(CARRAY *_object, const char *str, int lstr, const char *sep, c
void CARRAY_reverse(void *_object, void *_param);
void CARRAY_get_value(CARRAY *_object, int index, VALUE *value);
#define CARRAY_invert(_array) CARRAY_reverse(_array, NULL)
void *CARRAY_get_data_multi(CARRAY *_object, GB_INTEGER *arg, int nparam);
#endif

View File

@ -59,7 +59,6 @@ static void collection_free(CCOLLECTION *col)
HASH_TABLE_delete(&col->hash_table);
}
static void *collection_get_key(CCOLLECTION *col, const char *key, int len)
{
if (!key || !*key)
@ -344,7 +343,7 @@ int GB_CollectionCount(GB_COLLECTION col)
return HASH_TABLE_size(((CCOLLECTION *)col)->hash_table);
}
void GB_CollectionSet(GB_COLLECTION col, const char *key, int len, GB_VARIANT *value)
int GB_CollectionSet(GB_COLLECTION col, const char *key, int len, GB_VARIANT *value)
{
VARIANT *data;
@ -353,9 +352,11 @@ void GB_CollectionSet(GB_COLLECTION col, const char *key, int len, GB_VARIANT *v
else
{
data = (VARIANT *)collection_add_key((CCOLLECTION *)col, key, len);
if (data)
GB_StoreVariant(value, data);
if (!data)
return TRUE;
GB_StoreVariant(value, data);
}
return FALSE;
}
int GB_CollectionGet(GB_COLLECTION col, const char *key, int len, GB_VARIANT *value)

View File

@ -247,8 +247,8 @@ typedef
unsigned mmapped : 1; /* mmap() was used to load the class */
unsigned swap : 1; /* class endianness was swapped */
unsigned enum_static : 1; /* if class enumeration is static */
//unsigned quick_array : 1; /* array accessor optimizations can apply */
unsigned _flag : 3; /* 30 */
unsigned quick_array : 2; /* array accessor optimization type */
unsigned _flag : 1; /* 30 */
short n_desc; /* 32 number of descriptions */
CLASS_DESC_SYMBOL *table; /* 36 class description */
@ -258,8 +258,8 @@ typedef
CLASS_EVENT *event; /* 44 event description */
CLASS_DESC_METHOD *array_get; /* 48 quick array get method */
CLASS_DESC_METHOD *array_put; /* 52 quick array put method */
int _reserved2; /* 48 quick array get method */
int _reserved3; /* 52 quick array put method */
int (*check)(); /* 56 method for checking that an object is valid */
@ -304,6 +304,14 @@ typedef
}
CLASS_SPECIAL;
typedef
enum {
CQA_NONE = 0,
CQA_ARRAY = 1,
CQA_COLLECTION = 2
}
CLASS_QUICK_ARRAY;
typedef
enum
{

View File

@ -81,7 +81,7 @@ typedef
struct {
GB_DESC *desc;
CLASS **class;
bool array;
int array;
}
CLASS_INIT;
@ -97,7 +97,7 @@ static CLASS_INIT init_list[] =
{ NATIVE_Component, NULL },
{ NATIVE_Components, NULL },
{ NATIVE_Object, NULL },
{ NATIVE_Collection, &CLASS_Collection },
{ NATIVE_Collection, &CLASS_Collection, CQA_COLLECTION },
// { NATIVE_List, NULL },
{ NATIVE_Error, NULL },
{ NATIVE_Stream, &CLASS_Stream },
@ -118,18 +118,18 @@ static CLASS_INIT init_list[] =
{ NATIVE_ArrayBounds, NULL },
{ NATIVE_Array, &CLASS_Array },
{ NATIVE_BooleanArray, &CLASS_BooleanArray, TRUE },
{ NATIVE_ByteArray, &CLASS_ByteArray, TRUE },
{ NATIVE_ShortArray, &CLASS_ShortArray, TRUE },
{ NATIVE_IntegerArray, &CLASS_IntegerArray, TRUE },
{ NATIVE_FloatArray, &CLASS_FloatArray, TRUE },
{ NATIVE_SingleArray, &CLASS_SingleArray, TRUE },
{ NATIVE_DateArray, &CLASS_DateArray, TRUE },
{ NATIVE_StringArray, &CLASS_StringArray, TRUE },
{ NATIVE_ObjectArray, &CLASS_ObjectArray, TRUE },
{ NATIVE_VariantArray, &CLASS_VariantArray, TRUE },
{ NATIVE_LongArray, &CLASS_LongArray, TRUE },
{ NATIVE_PointerArray, &CLASS_PointerArray, TRUE },
{ NATIVE_BooleanArray, &CLASS_BooleanArray, CQA_ARRAY },
{ NATIVE_ByteArray, &CLASS_ByteArray, CQA_ARRAY },
{ NATIVE_ShortArray, &CLASS_ShortArray, CQA_ARRAY },
{ NATIVE_IntegerArray, &CLASS_IntegerArray, CQA_ARRAY },
{ NATIVE_FloatArray, &CLASS_FloatArray, CQA_ARRAY },
{ NATIVE_SingleArray, &CLASS_SingleArray, CQA_ARRAY },
{ NATIVE_DateArray, &CLASS_DateArray, CQA_ARRAY },
{ NATIVE_StringArray, &CLASS_StringArray, CQA_ARRAY },
{ NATIVE_ObjectArray, &CLASS_ObjectArray, CQA_ARRAY },
{ NATIVE_VariantArray, &CLASS_VariantArray, CQA_ARRAY },
{ NATIVE_LongArray, &CLASS_LongArray, CQA_ARRAY },
{ NATIVE_PointerArray, &CLASS_PointerArray, CQA_ARRAY },
{ NATIVE_SubCollection, &CLASS_SubCollection },
@ -141,7 +141,6 @@ void CLASS_init_native(void)
{
CLASS_INIT *init;
CLASS *class;
CLASS_DESC_METHOD *cdm;
/* NOTE: The 'Class' class must be first in the global class table */
CLASS_Class = CLASS_find("Class");
@ -155,11 +154,7 @@ void CLASS_init_native(void)
class = CLASS_register(init->desc);
if (init->class != NULL)
*init->class = class;
if (init->array)
{
class->array_get = (CLASS_DESC_METHOD *)CLASS_get_desc(class, class->special[SPEC_GET]);
class->array_put = (CLASS_DESC_METHOD *)CLASS_get_desc(class, class->special[SPEC_PUT]);
}
class->quick_array = init->array;
}
}

View File

@ -29,6 +29,7 @@
#include "gbx_array.h"
#include "gbx_c_array.h"
#include "gbx_c_collection.h"
#include "gbx_api.h"
void EXEC_pop_unknown(void)
@ -248,7 +249,7 @@ void EXEC_pop_array(ushort code)
ARRAY_DESC *desc;
val = &SP[-np];
goto *jump[(code & 0xC0) >> 6];
goto *jump[(code >> 6) & 3];
__POP_GENERIC:
@ -260,10 +261,10 @@ __POP_GENERIC:
EXEC_object(val, &class, &object, &defined);
if (defined && class->array_put)
if (defined && class->quick_array)
{
*PC |= 2 << 6;
goto __POP_QUICK_ARRAY_2;
goto __POP_ARRAY_2; // Check number of arguments by not going to __POP_QUICK_ARRAY immediately
}
*PC |= 3 << 6;
@ -293,24 +294,38 @@ __POP_QUICK_ARRAY:
EXEC_object(val, &class, &object, &defined);
__POP_QUICK_ARRAY_2:
if (class->quick_array == CQA_ARRAY)
{
TYPE type = ((CARRAY *)object)->type;
swap = val[0];
val[0] = val[-1];
val[-1] = swap;
VALUE_conv(&val[0], type);
for (i = 1; i < np; i++)
VALUE_conv(&val[i], T_INTEGER);
data = CARRAY_get_data_multi((CARRAY *)object, (GB_INTEGER *)&val[1], np - 1);
if (!data)
PROPAGATE();
VALUE_write(val, data, type);
SP = val + 1;
RELEASE_MANY(SP, 2);
//OBJECT_UNREF(&object, "EXEC_push_array");
}
else // CQA_COLLECTION
{
VALUE_conv(&val[-1], T_VARIANT);
VALUE_conv(&val[1], T_STRING);
if (GB_CollectionSet((GB_COLLECTION)object, val[1]._string.addr + val[1]._string.start, val[1]._string.len, (GB_VARIANT *)&val[-1]))
PROPAGATE();
RELEASE_MANY(SP, 3);
}
swap = val[0];
val[0] = val[-1];
val[-1] = swap;
VALUE_conv(&val[0], ((CARRAY *)object)->type);
for (i = 1; i < np; i++)
VALUE_conv(&val[i], T_INTEGER);
EXEC.nparvar = np - 2;
if (EXEC_call_native(class->array_put->exec, object, class->array_put->type, val))
PROPAGATE();
SP = val + 1;
POP();
POP();
//OBJECT_UNREF(&object, "EXEC_push_array");
return;
__POP_ARRAY:
@ -319,21 +334,14 @@ __POP_ARRAY:
__POP_ARRAY_2:
/* remplace l'objet par la valeur <20>ins<6E>er */
/* swap object and value to be inserted */
swap = val[0];
val[0] = val[-1];
val[-1] = swap;
/*printf("<< EXEC_pop_array: np = %d SP = %d\n", np, SP - (VALUE *)STACK_base);
save_SP = SP - np;*/
if (EXEC_special(SPEC_PUT, class, object, np, TRUE))
THROW(E_NARRAY, class->name);
/*printf(">> EXEC_pop_array: SP = %d\n", SP - (VALUE *)STACK_base);
if (SP != save_SP)
printf("**** SP should be %d\n", save_SP - (VALUE *)STACK_base);*/
POP(); /* on lib<69>e l'objet */
POP(); /* free the object */
}

View File

@ -32,8 +32,9 @@
#include "gbx_string.h"
#include "gbx_array.h"
#include "gbx_c_array.h"
#include "gbx_c_collection.h"
#include "gbx_api.h"
void EXEC_push_unknown(ushort code)
{
@ -435,7 +436,7 @@ void EXEC_push_array(ushort code)
val = &SP[-np];
np--;
goto *jump[(code & 0xC0) >> 6];
goto *jump[(code >> 6) & 3];
__PUSH_GENERIC:
@ -447,10 +448,10 @@ __PUSH_GENERIC:
EXEC_object(val, &class, &object, &defined);
if (defined && class->array_get)
if (defined && class->quick_array)
{
*PC |= 2 << 6;
goto __PUSH_ARRAY_2;
goto __PUSH_ARRAY_2; // Check number of arguments by not going to __PUSH_QUICK_ARRAY immediately
}
*PC |= 3 << 6;
@ -477,19 +478,36 @@ __PUSH_STATIC_ARRAY:
__PUSH_QUICK_ARRAY:
EXEC_object(val, &class, &object, &defined);
__PUSH_QUICK_ARRAY_2:
for (i = 1; i <= np; i++)
VALUE_conv(&val[i], T_INTEGER);
EXEC.nparvar = np - 1;
if (EXEC_call_native(class->array_get->exec, object, class->array_get->type, &val[1]))
PROPAGATE();
if (class->quick_array == CQA_ARRAY)
{
for (i = 1; i <= np; i++)
VALUE_conv(&val[i], T_INTEGER);
data = CARRAY_get_data_multi((CARRAY *)object, (GB_INTEGER *)&val[1], np);
if (!data)
PROPAGATE();
VALUE_read(val, data, ((CARRAY *)object)->type);
SP = val;
PUSH();
}
else /* CQA_COLLECTION */
{
VALUE_conv(&val[1], T_STRING);
GB_CollectionGet((GB_COLLECTION)object, val[1]._string.addr + val[1]._string.start, val[1]._string.len, (GB_VARIANT *)val);
RELEASE(&val[1]);
SP = val;
PUSH();
}
//EXEC.nparvar = np - 1;
//if (EXEC_call_native(class->array_get->exec, object, class->array_get->type, &val[1]))
// PROPAGATE();
//SP = val;
//COPY_VALUE(SP, &TEMP);
//PUSH();
SP = val;
COPY_VALUE(SP, &TEMP);
PUSH();
OBJECT_UNREF(&object, "EXEC_push_array");
return;