From 7cc9986bdae950f0b27e3867d5703bc11987230d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Minisini?= Date: Thu, 24 Jan 2008 10:42:42 +0000 Subject: [PATCH] [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 --- app/src/gambas3/Project.module | 1 + comp/src/gb.db.form/.lang/fr.po | 20 +++++----- comp/src/gb.db.form/.project | 2 +- main/gbx/gbx_api.h | 2 +- main/gbx/gbx_c_array.c | 3 +- main/gbx/gbx_c_array.h | 1 + main/gbx/gbx_c_collection.c | 9 +++-- main/gbx/gbx_class.h | 16 ++++++-- main/gbx/gbx_class_init.c | 35 ++++++++--------- main/gbx/gbx_exec_pop.c | 66 ++++++++++++++++++--------------- main/gbx/gbx_exec_push.c | 48 ++++++++++++++++-------- 11 files changed, 118 insertions(+), 85 deletions(-) diff --git a/app/src/gambas3/Project.module b/app/src/gambas3/Project.module index 5ddbd9876..ee48a966d 100644 --- a/app/src/gambas3/Project.module +++ b/app/src/gambas3/Project.module @@ -3748,3 +3748,4 @@ PUBLIC SUB DrawTitle(hForm AS Object) hForm.Title = sTitle '& " - " & Project.Name END + diff --git a/comp/src/gb.db.form/.lang/fr.po b/comp/src/gb.db.form/.lang/fr.po index 01ee5b32f..58fe006a3 100644 --- a/comp/src/gb.db.form/.lang/fr.po +++ b/comp/src/gb.db.form/.lang/fr.po @@ -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 "" diff --git a/comp/src/gb.db.form/.project b/comp/src/gb.db.form/.project index 0c874a5bf..76811bef8 100644 --- a/comp/src/gb.db.form/.project +++ b/comp/src/gb.db.form/.project @@ -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 diff --git a/main/gbx/gbx_api.h b/main/gbx/gbx_api.h index 546003cab..0c446ed35 100644 --- a/main/gbx/gbx_api.h +++ b/main/gbx/gbx_api.h @@ -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); diff --git a/main/gbx/gbx_c_array.c b/main/gbx/gbx_c_array.c index 2272ba41f..1f54e98f0 100644 --- a/main/gbx/gbx_c_array.c +++ b/main/gbx/gbx_c_array.c @@ -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; diff --git a/main/gbx/gbx_c_array.h b/main/gbx/gbx_c_array.h index 9c50cb228..e384d33ad 100644 --- a/main/gbx/gbx_c_array.h +++ b/main/gbx/gbx_c_array.h @@ -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 diff --git a/main/gbx/gbx_c_collection.c b/main/gbx/gbx_c_collection.c index eac1fec64..a37c612ff 100644 --- a/main/gbx/gbx_c_collection.c +++ b/main/gbx/gbx_c_collection.c @@ -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) diff --git a/main/gbx/gbx_class.h b/main/gbx/gbx_class.h index f857611e4..bd399ada2 100644 --- a/main/gbx/gbx_class.h +++ b/main/gbx/gbx_class.h @@ -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 { diff --git a/main/gbx/gbx_class_init.c b/main/gbx/gbx_class_init.c index 14eea2003..d12672f18 100644 --- a/main/gbx/gbx_class_init.c +++ b/main/gbx/gbx_class_init.c @@ -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; } } diff --git a/main/gbx/gbx_exec_pop.c b/main/gbx/gbx_exec_pop.c index 009a7e0ce..f0b651f01 100644 --- a/main/gbx/gbx_exec_pop.c +++ b/main/gbx/gbx_exec_pop.c @@ -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 �ins�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�e l'objet */ + POP(); /* free the object */ } diff --git a/main/gbx/gbx_exec_push.c b/main/gbx/gbx_exec_push.c index 0f754bcda..8c31de244 100644 --- a/main/gbx/gbx_exec_push.c +++ b/main/gbx/gbx_exec_push.c @@ -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;