Commit 742d8f325997f4d86adbd602f976548a995a34d3

Authored by Alain Prouté
1 parent 54a181da

literal strings are no more pemanent

anubis_dev/compiler/src/vminstr.c
@@ -329,11 +329,6 @@ int instruction_size(Expr instr, int offset) @@ -329,11 +329,6 @@ int instruction_size(Expr instr, int offset)
329 case micro_peek_copy_push_mixed: 329 case micro_peek_copy_push_mixed:
330 return 10; 330 return 10;
331 331
332 -#if 0  
333 - case load_adm:  
334 - return 9; /* 1 + 4 + 4 */  
335 -#endif  
336 -  
337 case _switch: 332 case _switch:
338 case type_large_switch: 333 case type_large_switch:
339 return 2 + 4*length(cdr(instr)); 334 return 2 + 4*length(cdr(instr));
@@ -376,7 +371,8 @@ int instruction_size(Expr instr, int offset) @@ -376,7 +371,8 @@ int instruction_size(Expr instr, int offset)
376 371
377 case string: 372 case string:
378 case string_push: 373 case string_push:
379 - return 1+4+4+strlen(string_content(compiled_strings[integer_value(cdr(instr))].string))+1; 374 + /* new format since version 1.13 (see vm/vm.cpp) */
  375 + return 1+4+strlen(string_content(compiled_strings[integer_value(cdr(instr))].string));
380 376
381 case program: 377 case program:
382 { 378 {
@@ -971,11 +967,13 @@ void translate_instruction(U8 *code_addr, @@ -971,11 +967,13 @@ void translate_instruction(U8 *code_addr,
971 *(((U32 *)(*ptr))) = len = 967 *(((U32 *)(*ptr))) = len =
972 strlen(string_content(compiled_strings[integer_value(cdr(instr))].string)); 968 strlen(string_content(compiled_strings[integer_value(cdr(instr))].string));
973 *ptr += sizeof(U32); 969 *ptr += sizeof(U32);
974 - *(((U32 *)(*ptr))) = 0; /* null counter => permanent string */  
975 - *ptr += sizeof(U32); 970 + /* the two lines below eliminated since version 1.13 */
  971 + //*(((U32 *)(*ptr))) = 0; /* null counter => permanent string */
  972 + //*ptr += sizeof(U32);
976 for (i = 0; i < len; i++) 973 for (i = 0; i < len; i++)
977 *((*ptr)++) = 172^((string_content(compiled_strings[integer_value(cdr(instr))].string))[i]); 974 *((*ptr)++) = 172^((string_content(compiled_strings[integer_value(cdr(instr))].string))[i]);
978 - *((*ptr)++) = 172; 975 + /* the line below eliminated since version 1.13 */
  976 + //*((*ptr)++) = 172;
979 break; 977 break;
980 978
981 case program: /* (program instruction ... instruction) */ 979 case program: /* (program instruction ... instruction) */
@@ -1682,22 +1680,6 @@ void translate_instruction(U8 *code_addr, @@ -1682,22 +1680,6 @@ void translate_instruction(U8 *code_addr,
1682 } 1680 }
1683 break; 1681 break;
1684 1682
1685 -#if 0  
1686 - case load_adm: /* (load_adm module_name, type_description) */  
1687 - {  
1688 - *((*ptr)++) = i_load_adm;  
1689 - instr = cdr(instr);  
1690 - *(((U32 *)(*ptr))) = length(instr);  
1691 - *ptr += sizeof(U32);  
1692 - while(consp(instr))  
1693 - {  
1694 - *((*ptr)++) = (U8)(integer_value(car(instr)));  
1695 - instr = cdr(instr);  
1696 - }  
1697 - }  
1698 - break;  
1699 -#endif  
1700 -  
1701 case begin_op: 1683 case begin_op:
1702 *((*ptr)++) = i_begin_op; 1684 *((*ptr)++) = i_begin_op;
1703 { 1685 {
anubis_dev/include/bytecode.h
@@ -222,7 +222,6 @@ typedef enum @@ -222,7 +222,6 @@ typedef enum
222 item(get_mvar_monitors)\ 222 item(get_mvar_monitors)\
223 item(xchg_mvv)\ 223 item(xchg_mvv)\
224 item(get_mvv)\ 224 item(get_mvv)\
225 - item(load_adm)\  
226 item(load_int_small)\ 225 item(load_int_small)\
227 item(load_int_big)\ 226 item(load_int_big)\
228 item(begin_op)\ 227 item(begin_op)\
anubis_dev/vm/src/anbexec.cpp
@@ -244,7 +244,7 @@ U32 read32(FILE *fp) @@ -244,7 +244,7 @@ U32 read32(FILE *fp)
244 void syntax(void) 244 void syntax(void)
245 { 245 {
246 LOGINFO("anbexec version %d.%d.%d.%d\n" 246 LOGINFO("anbexec version %d.%d.%d.%d\n"
247 - " (Build date: %s )\n" 247 + " (Build date: %s %s)\n"
248 #ifdef _WITH_SSL_ 248 #ifdef _WITH_SSL_
249 " (%s)\n" 249 " (%s)\n"
250 #endif 250 #endif
@@ -272,7 +272,7 @@ void syntax(void) @@ -272,7 +272,7 @@ void syntax(void)
272 " --csv_sep:<sep> defines which separator to use when outputing profiling\n" 272 " --csv_sep:<sep> defines which separator to use when outputing profiling\n"
273 " data as CSV. Default is ',' (comma).\n" 273 " data as CSV. Default is ',' (comma).\n"
274 " --perf activate performance computing (load average)\n" 274 " --perf activate performance computing (load average)\n"
275 - , maj_version, min_version, rel_version, build_version, __DATE__, 275 + , maj_version, min_version, rel_version, build_version, __DATE__,__TIME__,
276 #ifdef _WITH_SSL_ 276 #ifdef _WITH_SSL_
277 OPENSSL_VERSION_TEXT, 277 OPENSSL_VERSION_TEXT,
278 #endif 278 #endif
@@ -424,7 +424,7 @@ int load_module(struct Exec_Mod_struct *mod, @@ -424,7 +424,7 @@ int load_module(struct Exec_Mod_struct *mod,
424 /* code segment must be aligned on 0 mod 4 */ 424 /* code segment must be aligned on 0 mod 4 */
425 assert((((U32)code)&3) == 0); 425 assert((((U32)code)&3) == 0);
426 426
427 - /* make the code apermanent byte array */ 427 + /* make the code a permanent byte array */
428 ((U32 *)code)[0] = 0; 428 ((U32 *)code)[0] = 0;
429 /* put the size at its place */ 429 /* put the size at its place */
430 ((U32 *)code)[1] = code_size; 430 ((U32 *)code)[1] = code_size;
anubis_dev/vm/src/dynamic_module.cpp
@@ -414,31 +414,30 @@ U32 number_of_module_slots = 0; /* total number @@ -414,31 +414,30 @@ U32 number_of_module_slots = 0; /* total number
414 /* Note: the initial primary module is also recorded in this array, and counted */ 414 /* Note: the initial primary module is also recorded in this array, and counted */
415 415
416 /* Resizing the modules array depending on the number of modules. 416 /* Resizing the modules array depending on the number of modules.
417 - We arrange so that there is always at least one free slot. Hence, we can  
418 - store a new module, without worrying about resizing the modules array.  
419 - Of course, after this operation we must eventually try to resize it.  
420 - We also maybe resize it down when a module is collected.  
421 417
422 The precise policy is the following: 418 The precise policy is the following:
423 419
424 - When anbexec starts, an array of 'module_slot_steps' slots is allocated. 420 - When anbexec starts, an array of 'module_slot_steps' slots is allocated.
425 - - when a module is added to the array, it is inserted so that the 'module_begin'  
426 - fields remain in increasing order, and the array is resized if full. 421 + - when a module is added to the array, it is inserted so that the 'byte_code'
  422 + fields remain in increasing order (and the array is previously resized if full).
427 - when a module is discarded, the modules above it are shifted down in the array, 423 - when a module is discarded, the modules above it are shifted down in the array,
428 so that the modules are all at the beginning of the array without any hole between them. 424 so that the modules are all at the beginning of the array without any hole between them.
429 The number of modules currently present in the array is always 'number_of_modules'. 425 The number of modules currently present in the array is always 'number_of_modules'.
430 426
431 - 'resize_module_array' is called when anbexec starts, so that there is at least one free  
432 - slot at the beginning. 427 + 'resize_module_array' is called when anbexec starts in order to put the primary module
  428 + in the array .
433 429
434 */ 430 */
435 int /* 0 = out of memory, 1 = ok */ 431 int /* 0 = out of memory, 1 = ok */
436 resize_modules_array(void) 432 resize_modules_array(void)
437 { 433 {
  434 +
  435 + printf("resize_modules_array: modules: %\ld slots: %ld\n",number_of_modules,number_of_module_slots); fflush(stdout);
  436 +
438 /**/ 437 /**/
439 if (modules == NULL) 438 if (modules == NULL)
440 { 439 {
441 - printf("initial allocation of modules array.\n"); fflush(stdout); 440 + printf("Initial allocation of modules array.\n"); fflush(stdout);
442 U32 seg = (U32)malloc(sizeof(struct Exec_Mod_struct)*module_slots_step); 441 U32 seg = (U32)malloc(sizeof(struct Exec_Mod_struct)*module_slots_step);
443 if ((U32 *)seg == NULL) return 0; 442 if ((U32 *)seg == NULL) return 0;
444 modules = (struct Exec_Mod_struct *)seg; 443 modules = (struct Exec_Mod_struct *)seg;
@@ -448,7 +447,7 @@ int /* 0 = out of memory, 1 = ok */ @@ -448,7 +447,7 @@ int /* 0 = out of memory, 1 = ok */
448 if (number_of_modules == number_of_module_slots) 447 if (number_of_modules == number_of_module_slots)
449 { 448 {
450 /* the array needs to be enlarged */ 449 /* the array needs to be enlarged */
451 - printf("enlarging modules array.\n"); fflush(stdout); 450 + printf("Enlarging modules array.\n"); fflush(stdout);
452 U32 seg = (U32)realloc((void *)modules, 451 U32 seg = (U32)realloc((void *)modules,
453 sizeof(struct Exec_Mod_struct)*(number_of_module_slots+module_slots_step)); 452 sizeof(struct Exec_Mod_struct)*(number_of_module_slots+module_slots_step));
454 if ((U32 *)seg == NULL) return 0; /* enlargement failed */ 453 if ((U32 *)seg == NULL) return 0; /* enlargement failed */
@@ -546,18 +545,17 @@ int find_module_index(U8* reference) @@ -546,18 +545,17 @@ int find_module_index(U8* reference)
546 'find_module_index' defined above.*/ 545 'find_module_index' defined above.*/
547 546
548 547
549 - /*** Adding a module to the array. *****************************************************/  
550 -  
551 -void check_module_order() 548 +void check_module_order() /* several verifications on the modules array */
552 { 549 {
553 U32 k; 550 U32 k;
554 551
555 for (k = 0; k < number_of_modules; k++) 552 for (k = 0; k < number_of_modules; k++)
556 { 553 {
557 - printf("index %lu module address: %lu (cnt = %ld)\n", 554 + printf("index %lu module address: %lu (cnt = %ld) %s\n",
558 k, 555 k,
559 (U32)(modules[k].byte_code), 556 (U32)(modules[k].byte_code),
560 - ((U32 *)(modules[k].byte_code))[0]); fflush(stdout); 557 + ((U32 *)(modules[k].byte_code))[0],
  558 + ((modules[k].flags)&mf_secondary_adm) ? "" : "(primary module)"); fflush(stdout);
561 } 559 }
562 560
563 for (k = 0; k < number_of_modules - 1; k++) 561 for (k = 0; k < number_of_modules - 1; k++)
@@ -567,6 +565,8 @@ void check_module_order() @@ -567,6 +565,8 @@ void check_module_order()
567 } 565 }
568 566
569 567
  568 + /*** Adding a module to the array. *****************************************************/
  569 +
570 int /* 0 = out of memory, 1 = ok */ 570 int /* 0 = out of memory, 1 = ok */
571 add_module( U32 flags, 571 add_module( U32 flags,
572 U8* byte_code, 572 U8* byte_code,
@@ -576,6 +576,26 @@ int /* 0 = out of memory, 1 = ok */ @@ -576,6 +576,26 @@ int /* 0 = out of memory, 1 = ok */
576 { 576 {
577 U32 index = find_module_index(byte_code); 577 U32 index = find_module_index(byte_code);
578 U32 k; 578 U32 k;
  579 +
  580 + /* Resize the array if needed.
  581 +
  582 + Why we must do it before adding the module:
  583 +
  584 + - the first reason is that the array may be full.
  585 +
  586 + - but there is another reason. When I wrote this the first time I arranged so that
  587 + the modules array always has at least one free slot, so that it was possible
  588 + to add the module and enlarge the array only after this operation. But actually,
  589 + it does not work because the syscall 'relocate_code' (in syscall.cpp) is where we
  590 + add the new relocated module to the array (in other words, it calls 'add_module'),
  591 + and uses the 'duc_non_empty' register for knowing if the module has already
  592 + been relocated when it comes back after having given up because 'add_module'
  593 + returned 0 the first time. The second time, it calls 'add_module' again.
  594 + Hence, it is necessary that 'add_module' does not add the module if the array
  595 + cannot be enlarged. Otherwise, the module could be recorded several times.
  596 +
  597 + */
  598 + if (!resize_modules_array()) return 0;
579 599
580 printf("add_module: index found: %lu\n",index); fflush(stdout); 600 printf("add_module: index found: %lu\n",index); fflush(stdout);
581 601
@@ -610,9 +630,7 @@ int /* 0 = out of memory, 1 = ok */ @@ -610,9 +630,7 @@ int /* 0 = out of memory, 1 = ok */
610 number_of_modules++; 630 number_of_modules++;
611 631
612 check_module_order(); 632 check_module_order();
613 -  
614 - /* resize the array if needed */  
615 - return resize_modules_array(); 633 + return 1;
616 } 634 }
617 635
618 636
@@ -626,7 +644,7 @@ void @@ -626,7 +644,7 @@ void
626 if (show_module_loading) printf("Unloading module %d\n",index); 644 if (show_module_loading) printf("Unloading module %d\n",index);
627 645
628 /* free the module segment */ 646 /* free the module segment */
629 - allocator->FreeDataSegment((U32 *)((modules[index].byte_code)-8)); 647 + allocator->FreeDataSegment((U32 *)((modules[index].byte_code)));
630 number_of_modules--; 648 number_of_modules--;
631 649
632 /* shift next modules one slot down */ 650 /* shift next modules one slot down */
@@ -645,7 +663,7 @@ void @@ -645,7 +663,7 @@ void
645 // sizeof(struct Exec_Mod_struct)*(number_of_modules-index)); /* number of bytes to be moved */ 663 // sizeof(struct Exec_Mod_struct)*(number_of_modules-index)); /* number of bytes to be moved */
646 664
647 /* if possible reduce the size of the modules array */ 665 /* if possible reduce the size of the modules array */
648 - resize_modules_array(); 666 + resize_modules_array();
649 } 667 }
650 668
651 669
@@ -653,9 +671,19 @@ void @@ -653,9 +671,19 @@ void
653 void vcopy_module_ref(U8 *ref) 671 void vcopy_module_ref(U8 *ref)
654 { 672 {
655 int index = find_module_index(ref); 673 int index = find_module_index(ref);
  674 + return;
  675 + if ((modules[index].flags)&mf_secondary_adm) /* don't do anything for primary module */
  676 + {
  677 + (*((U32 *)((modules[index].byte_code))))++; /* increment counter of module */
  678 + }
  679 +}
  680 +
  681 +void multiple_vcopy_module_ref(U8 *ref,U32 n) /* in case we need to make n virtual copies */
  682 +{
  683 + int index = find_module_index(ref);
656 if ((modules[index].flags)&mf_secondary_adm) /* don't do anything for primary module */ 684 if ((modules[index].flags)&mf_secondary_adm) /* don't do anything for primary module */
657 { 685 {
658 - (*((U32 *)((modules[index].byte_code)-8)))++; /* increment counter of module */ 686 + (*((U32 *)((modules[index].byte_code)))) += n;
659 } 687 }
660 } 688 }
661 689
@@ -663,12 +691,14 @@ void vcopy_module_ref(U8 *ref) @@ -663,12 +691,14 @@ void vcopy_module_ref(U8 *ref)
663 void vdelete_module_ref(U8 *ref, AnubisAllocator *allocator) 691 void vdelete_module_ref(U8 *ref, AnubisAllocator *allocator)
664 { 692 {
665 int index = find_module_index(ref); 693 int index = find_module_index(ref);
  694 + return;
666 if ((modules[index].flags)&mf_secondary_adm) /* don't do anything for primary module */ 695 if ((modules[index].flags)&mf_secondary_adm) /* don't do anything for primary module */
667 { 696 {
668 - (*((U32 *)((modules[index].byte_code)-8)))--; /* decrement counter of module */  
669 - if (!(*((U32 *)((modules[index].byte_code)-8)))) /* if down to 0 */ 697 + if (*((U32 *)((modules[index].byte_code)))) /* beware of permanent modules */
  698 + (*((U32 *)((modules[index].byte_code))))--; /* decrement counter of module */
  699 + if (!(*((U32 *)((modules[index].byte_code))))) /* if down to 0 */
670 { 700 {
671 - remove_module(index, allocator); 701 + //remove_module(index, allocator);
672 } 702 }
673 } 703 }
674 } 704 }
anubis_dev/vm/src/secondary_module.anubis
@@ -24,7 +24,7 @@ @@ -24,7 +24,7 @@
24 global define String 24 global define String
25 secondary_module 25 secondary_module
26 = 26 =
27 - "Bla bla blo.\n". 27 + "Bla bla blu.\n".
28 28
29 29
30 30
anubis_dev/vm/src/vm.cpp
@@ -5,8 +5,25 @@ @@ -5,8 +5,25 @@
5 5
6 **************************************************************************************/ 6 **************************************************************************************/
7 7
  8 +
  9 +
  10 + /*
  11 +
  12 + This file contains:
  13 +
  14 + (1) Some global variables.
  15 + (2) Tools for exceptions.
  16 + (3) Tools for running virtual machines.
  17 + (4) Type description tools (serialize).
  18 + (5) All virtual machine instructions.
8 19
9 -/* Serializing/unserializing stuff is in serialize.cpp */ 20 +
  21 + Serializing/unserializing stuff is in 'serialize.cpp'.
  22 +
  23 + */
  24 +
  25 +
  26 +
10 27
11 28
12 29
@@ -80,7 +97,6 @@ extern &quot;C&quot; @@ -80,7 +97,6 @@ extern &quot;C&quot;
80 97
81 USING_NAMESPACE(CM); 98 USING_NAMESPACE(CM);
82 99
83 -char *dummy_string;  
84 100
85 101
86 /* Important change since version 1.6.5: virtual machine instructions are reached by a 102 /* Important change since version 1.6.5: virtual machine instructions are reached by a
@@ -157,27 +173,71 @@ char *dummy_string; @@ -157,27 +173,71 @@ char *dummy_string;
157 173
158 //extern int strcasecmp (const char *S1, const char *S2); 174 //extern int strcasecmp (const char *S1, const char *S2);
159 175
  176 +
  177 + /******************************************************
  178 + * *
  179 + * (1) Some global variables. *
  180 + * *
  181 + ******************************************************/
  182 +
  183 +char * dummy_string;
  184 +U32 anubis_empty_string;
  185 +U32 anubis_empty_byte_array; // initialized at start
160 186
161 -int counting_instructions = 0;  
162 -int show_syscalls = 0; 187 +int counting_instructions = 0;
  188 +int show_syscalls = 0;
  189 +
  190 +int start_end_debug = 0;
  191 +U32 start_debug = 0;
  192 +U32 end_debug = 0;
  193 +
  194 +#define vmbuf_size (2000)
  195 +char vmbuf[vmbuf_size];
  196 +
  197 +int jpeg_fatal_error = 0;
  198 +
  199 +fd_set descriptors_waited_for_input;
  200 +fd_set the_fd_set;
  201 +fd_set the_fd_read_set;
  202 +fd_set the_fd_write_set;
  203 +fd_set the_fd_except_set;
  204 +
  205 +struct timeval timeout_no_wait = {0,0};
  206 +
  207 +#define ptd_to_name_buf_size (1025)
  208 +char ptd_to_name_buf[ptd_to_name_buf_size];
  209 +
  210 +AnubisAllocator *the_default_ssl_allocator = NULL;
  211 +AnubisAllocator *current_ssl_allocator = NULL;
163 212
164 -U32 anubis_empty_string;  
165 -U32 anubis_empty_byte_array; // initialized at start 213 +#ifdef record_allocations
  214 +int passed = 0;
  215 +U32* passed_seg;
  216 +U32 passed_cnt_old = 0;
  217 +U32 passed_seg_IP = 0;
  218 +#endif
  219 +
  220 +#ifdef debug_vm
  221 +U32 IPcode = 0;
  222 +#endif
166 223
167 -int start_end_debug = 0;  
168 -U32 start_debug = 0;  
169 -U32 end_debug = 0; 224 +
170 225
171 -extern String anubis_directory;  
172 -extern String my_anubis_directory;  
173 -extern String trusted_certs_directory;  
174 -extern int must_restart_flag; 226 +extern String anubis_directory;
  227 +extern String my_anubis_directory;
  228 +extern String trusted_certs_directory;
  229 +extern int must_restart_flag;
  230 +
175 231
176 -#define vmbuf_size (2000)  
177 -char vmbuf[vmbuf_size];  
178 232
179 -int jpeg_fatal_error = 0;  
180 233
  234 + /*************************************************
  235 + * *
  236 + * (2) Tools for exceptions. *
  237 + * *
  238 + *************************************************/
  239 +
  240 +
181 void jpeg_anb_error_exit(j_common_ptr cinfo) 241 void jpeg_anb_error_exit(j_common_ptr cinfo)
182 { 242 {
183 jpeg_fatal_error = 1; 243 jpeg_fatal_error = 1;
@@ -251,21 +311,17 @@ void compare_watched_code(U32 ip) @@ -251,21 +311,17 @@ void compare_watched_code(U32 ip)
251 } 311 }
252 #endif 312 #endif
253 313
254 -//U32 memory_seg_size = initial_memory_seg_size;  
255 314
256 -#define check_stack(n) do { if (MAM(m_SP)+(n) >= MAM(m_SP_end)) {\  
257 - MAM(m_status) = need_bigger_stack; goto end; }} while(0)  
258 315
259 -fd_set descriptors_waited_for_input;  
260 -fd_set the_fd_set;  
261 -fd_set the_fd_read_set;  
262 -fd_set the_fd_write_set;  
263 -fd_set the_fd_except_set; 316 + /*****************************************************************
  317 + * *
  318 + * (3) Tools for running virtual machines. *
  319 + * *
  320 + *****************************************************************/
264 321
265 -struct timeval timeout_no_wait = {0,0}; 322 +#define check_stack(n) do { if (MAM(m_SP)+(n) >= MAM(m_SP_end)) {\
  323 + MAM(m_status) = need_bigger_stack; goto end; }} while(0)
266 324
267 -#define ptd_to_name_buf_size (1025)  
268 -char ptd_to_name_buf[ptd_to_name_buf_size];  
269 325
270 /*--------------------------------------------------------------*/ 326 /*--------------------------------------------------------------*/
271 #define item(n) #n, 327 #define item(n) #n,
@@ -291,6 +347,7 @@ char *syscall32_names[] = { @@ -291,6 +347,7 @@ char *syscall32_names[] = {
291 "dummy" }; 347 "dummy" };
292 #undef sc32_item 348 #undef sc32_item
293 349
  350 + /* getting the name of an instruction */
294 const char *instr_name(int i, int n) 351 const char *instr_name(int i, int n)
295 { 352 {
296 if (i == i_syscall) 353 if (i == i_syscall)
@@ -301,18 +358,6 @@ const char *instr_name(int i, int n) @@ -301,18 +358,6 @@ const char *instr_name(int i, int n)
301 return instr_names[i]; 358 return instr_names[i];
302 } 359 }
303 360
304 -//char *short_string(VMWorkSort ws)  
305 -//{  
306 -// switch (ws)  
307 -// {  
308 -// case computing: return "c";  
309 -// case deleting: return "d";  
310 -// case equaling: return "e";  
311 -// case serializing: return "s";  
312 -// case unserializing: return "u";  
313 -// default: return "?";  
314 -// }  
315 -//}  
316 #endif 361 #endif
317 362
318 363
@@ -350,6 +395,13 @@ const char *instr_name(int i, int n) @@ -350,6 +395,13 @@ const char *instr_name(int i, int n)
350 #define serial_words_increment (1024) 395 #define serial_words_increment (1024)
351 396
352 397
  398 +
  399 +
  400 + /*******************************************************
  401 + * *
  402 + * (4) Type description tools (serialize). *
  403 + * *
  404 + *******************************************************/
353 405
354 406
355 /* Checking that a word represents a valid datum of a given small type. */ 407 /* Checking that a word represents a valid datum of a given small type. */
@@ -524,28 +576,24 @@ int check_small_alt_datum(U32 datum, U32 *start_bit_a, U8 **alt_des_a) @@ -524,28 +576,24 @@ int check_small_alt_datum(U32 datum, U32 *start_bit_a, U8 **alt_des_a)
524 return 1; 576 return 1;
525 } 577 }
526 578
527 -AnubisAllocator *the_default_ssl_allocator = NULL;  
528 -AnubisAllocator *current_ssl_allocator = NULL;  
529 -  
530 -#ifdef record_allocations  
531 - int passed = 0;  
532 - U32* passed_seg;  
533 - U32 passed_cnt_old = 0;  
534 - U32 passed_seg_IP = 0;  
535 -#endif  
536 579
537 -#ifdef debug_vm  
538 -U32 IPcode = 0;  
539 -#endif  
540 580
541 -  
542 -  
543 - 581 + /**************************************************
  582 + * *
  583 + * (5) All virtual machine instructions. *
  584 + * *
  585 + **************************************************/
  586 +
544 587
545 /* All instructions of the virtual machine as member functions of AnubisProcess ('mi' = 588 /* All instructions of the virtual machine as member functions of AnubisProcess ('mi' =
546 'member instruction'). */ 589 'member instruction'). */
547 590
548 591
  592 +
  593 +
  594 +
  595 +
  596 +
549 /* The 'invalid' instruction should never be executed. If the machine is led to execute 597 /* The 'invalid' instruction should never be executed. If the machine is led to execute
550 this instruction, this means that the code is probably corrupted. The action is 598 this instruction, this means that the code is probably corrupted. The action is
551 to stop the virtual machine, with an 'invalid_instruction' status. The scheduler will 599 to stop the virtual machine, with an 'invalid_instruction' status. The scheduler will
@@ -847,7 +895,15 @@ ci_decl(peek_copy_push_function) @@ -847,7 +895,15 @@ ci_decl(peek_copy_push_function)
847 /* peek d */ 895 /* peek d */
848 x = *(MAM(m_SP)-get32(1)-1); 896 x = *(MAM(m_SP)-get32(1)-1);
849 /* copy_function */ 897 /* copy_function */
850 - if (!(x&1)) if (*((U32 *)(x)) != 0) (*((U32 *)(x)))++; 898 + if (x&1)
  899 + { /* top level function */
  900 + vcopy_module_ref((U8 *)x);
  901 + }
  902 + else
  903 + { /* closure function */
  904 + if (*((U32 *)(x)) != 0)
  905 + (*((U32 *)(x)))++;
  906 + }
851 /* push */ 907 /* push */
852 *(MAM(m_SP)++) = x; 908 *(MAM(m_SP)++) = x;
853 MAM(m_R) = x; 909 MAM(m_R) = x;
@@ -863,7 +919,15 @@ ci_decl(peek_copy_function) @@ -863,7 +919,15 @@ ci_decl(peek_copy_function)
863 /* peek d */ 919 /* peek d */
864 x = *(MAM(m_SP)-get32(1)-1); 920 x = *(MAM(m_SP)-get32(1)-1);
865 /* copy_function */ 921 /* copy_function */
866 - if (!(x&1)) if (*((U32 *)(x)) != 0) (*((U32 *)(x)))++; 922 + if (x&1)
  923 + { /* top level function */
  924 + vcopy_module_ref((U8 *)x);
  925 + }
  926 + else
  927 + { /* closure function */
  928 + if (*((U32 *)(x)) != 0)
  929 + (*((U32 *)(x)))++;
  930 + }
867 MAM(m_R) = x; 931 MAM(m_R) = x;
868 MAM(m_IP) += 1+4; 932 MAM(m_IP) += 1+4;
869 } 933 }
@@ -1062,9 +1126,15 @@ ci_decl(micro_peek_copy_function) @@ -1062,9 +1126,15 @@ ci_decl(micro_peek_copy_function)
1062 /* micro_peek */ 1126 /* micro_peek */
1063 MAM(m_R) = ((U32 *)(*(MAM(m_SP)-get32(1)-1)))[3+get32(5)]; 1127 MAM(m_R) = ((U32 *)(*(MAM(m_SP)-get32(1)-1)))[3+get32(5)];
1064 /* copy_function */ 1128 /* copy_function */
1065 - if (!(MAM(m_R)&1)) 1129 + if (MAM(m_R)&1)
  1130 + { /* top level function */
  1131 + vcopy_module_ref((U8 *)(MAM(m_R)));
  1132 + }
  1133 + else
  1134 + { /* closure function */
1066 if (*((U32 *)(MAM(m_R))) != 0) 1135 if (*((U32 *)(MAM(m_R))) != 0)
1067 (*((U32 *)(MAM(m_R))))++; 1136 (*((U32 *)(MAM(m_R))))++;
  1137 + }
1068 MAM(m_IP) += 1+4+4; 1138 MAM(m_IP) += 1+4+4;
1069 } 1139 }
1070 1140
@@ -1078,9 +1148,15 @@ ci_decl(micro_peek_copy_push_function) @@ -1078,9 +1148,15 @@ ci_decl(micro_peek_copy_push_function)
1078 /* micro_peek */ 1148 /* micro_peek */
1079 MAM(m_R) = ((U32 *)(*(MAM(m_SP)-get32(1)-1)))[3+get32(5)]; 1149 MAM(m_R) = ((U32 *)(*(MAM(m_SP)-get32(1)-1)))[3+get32(5)];
1080 /* copy_function */ 1150 /* copy_function */
1081 - if (!(MAM(m_R)&1)) 1151 + if (MAM(m_R)&1)
  1152 + { /* top level function */
  1153 + vcopy_module_ref((U8 *)(MAM(m_R)));
  1154 + }
  1155 + else
  1156 + { /* closure function */
1082 if (*((U32 *)(MAM(m_R))) != 0) 1157 if (*((U32 *)(MAM(m_R))) != 0)
1083 (*((U32 *)(MAM(m_R))))++; 1158 (*((U32 *)(MAM(m_R))))++;
  1159 + }
1084 /* push */ 1160 /* push */
1085 *(MAM(m_SP)++) = MAM(m_R); /* push MAM(m_R) on top of stack */ 1161 *(MAM(m_SP)++) = MAM(m_R); /* push MAM(m_R) on top of stack */
1086 MAM(m_IP) += 1+4+4; 1162 MAM(m_IP) += 1+4+4;
@@ -1451,11 +1527,11 @@ ci_decl(unstore_copy_function) @@ -1451,11 +1527,11 @@ ci_decl(unstore_copy_function)
1451 /* extract the function and put it on the stack */ 1527 /* extract the function and put it on the stack */
1452 *MAM(m_SP) = *((U32 *)(((U8 *)((MAM(m_R))&pointer_mask))+get8(1))); 1528 *MAM(m_SP) = *((U32 *)(((U8 *)((MAM(m_R))&pointer_mask))+get8(1)));
1453 if ((*MAM(m_SP))&1) 1529 if ((*MAM(m_SP))&1)
1454 - {  
1455 - /* no virtual copy for top level functions */ 1530 + { /* top level function */
  1531 + vcopy_module_ref((U8 *)(MAM(m_R)));
1456 } 1532 }
1457 else 1533 else
1458 - { 1534 + { /* closure function */
1459 if (*((U32 *)(*MAM(m_SP))) != 0) 1535 if (*((U32 *)(*MAM(m_SP))) != 0)
1460 (*((U32 *)(*MAM(m_SP))))++; 1536 (*((U32 *)(*MAM(m_SP))))++;
1461 } 1537 }
@@ -1622,11 +1698,16 @@ ci_decl(jmp) @@ -1622,11 +1698,16 @@ ci_decl(jmp)
1622 Size: 1+4 1698 Size: 1+4
1623 1699
1624 The purpose of this instruction is to put the address contained in its operand into 1700 The purpose of this instruction is to put the address contained in its operand into
1625 - MAM(m_R). The address is always the absolute address of a subroutine. */ 1701 + MAM(m_R). The address is always the absolute address of a top level function .
  1702 +
  1703 + Since version 1.13, the module containing this function has a counter which must be incremented.
  1704 + */
1626 ci_decl(address) 1705 ci_decl(address)
1627 { 1706 {
1628 trace 1707 trace
1629 - MAM(m_R) = get32(1); 1708 + U32 code_addr = get32(1);
  1709 + MAM(m_R) = code_addr;
  1710 + vcopy_module_ref((U8 *)code_addr);
1630 MAM(m_IP) += 1+4; 1711 MAM(m_IP) += 1+4;
1631 } 1712 }
1632 1713
@@ -1828,9 +1909,15 @@ ci_decl(put_copy_function) @@ -1828,9 +1909,15 @@ ci_decl(put_copy_function)
1828 trace 1909 trace
1829 U32 datum = *(MAM(m_SP)-get8(1)-1); 1910 U32 datum = *(MAM(m_SP)-get8(1)-1);
1830 ((U32 *)MAM(m_R))[3+get8(2)] = datum; 1911 ((U32 *)MAM(m_R))[3+get8(2)] = datum;
1831 - if (!(datum&1)) 1912 + if (datum&1)
  1913 + { /* top level function */
  1914 + vcopy_module_ref((U8 *)datum);
  1915 + }
  1916 + else
  1917 + { /* closure function */
1832 if (((U32 *)(datum))[0]) 1918 if (((U32 *)(datum))[0])
1833 (((U32 *)(datum))[0])++; 1919 (((U32 *)(datum))[0])++;
  1920 + }
1834 MAM(m_IP) += 1+1+1; 1921 MAM(m_IP) += 1+1+1;
1835 } 1922 }
1836 1923
@@ -1868,9 +1955,15 @@ ci_decl(put_micro_copy_function) @@ -1868,9 +1955,15 @@ ci_decl(put_micro_copy_function)
1868 trace 1955 trace
1869 U32 datum = ((U32 *)(*(MAM(m_SP)-get8(1)-1)))[3+get8(2)]; 1956 U32 datum = ((U32 *)(*(MAM(m_SP)-get8(1)-1)))[3+get8(2)];
1870 ((U32 *)MAM(m_R))[3+get8(3)] = datum; 1957 ((U32 *)MAM(m_R))[3+get8(3)] = datum;
1871 - if (!(datum&1)) 1958 + if (datum&1)
  1959 + { /* top level function */
  1960 + vcopy_module_ref((U8 *)datum);
  1961 + }
  1962 + else
  1963 + { /* closure function */
1872 if (((U32 *)(datum))[0]) 1964 if (((U32 *)(datum))[0])
1873 (((U32 *)(datum))[0])++; 1965 (((U32 *)(datum))[0])++;
  1966 + }
1874 MAM(m_IP) += 1+1+1+1; 1967 MAM(m_IP) += 1+1+1+1;
1875 } 1968 }
1876 1969
@@ -1947,12 +2040,17 @@ ci_decl(put_micro_copy_mixed) @@ -1947,12 +2040,17 @@ ci_decl(put_micro_copy_mixed)
1947 Size: 1+4+4 2040 Size: 1+4+4
1948 2041
1949 A closure is currently under construction in MAM(m_R). This instruction must copy the two 2042 A closure is currently under construction in MAM(m_R). This instruction must copy the two
1950 - addresses at byte offsets 4 and 8 in the closure. */ 2043 + addresses at byte offsets 4 and 8 in the closure.
  2044 +
  2045 + Since version 1.13, the module containing this function has a counter which must be incremented.
  2046 +*/
1951 ci_decl(put_closure_labels) 2047 ci_decl(put_closure_labels)
1952 { 2048 {
1953 trace 2049 trace
1954 - ((U32 *)MAM(m_R))[1] = get32(1); 2050 + U32 code_addr = get32(1);
  2051 + ((U32 *)MAM(m_R))[1] = code_addr;
1955 ((U32 *)MAM(m_R))[2] = get32(5); 2052 ((U32 *)MAM(m_R))[2] = get32(5);
  2053 + vcopy_module_ref((U8 *)code_addr);
1956 MAM(m_IP) += 1+4+4; 2054 MAM(m_IP) += 1+4+4;
1957 } 2055 }
1958 2056
@@ -2588,16 +2686,24 @@ ci_decl(mvar_slots_del_function) @@ -2588,16 +2686,24 @@ ci_decl(mvar_slots_del_function)
2588 2686
2589 (*(MAM(m_SP)-1))--; /* decrement counter before using it as an index*/ 2687 (*(MAM(m_SP)-1))--; /* decrement counter before using it as an index*/
2590 datum = ((U32 *)(*(MAM(m_SP)-2)))[5+(*(MAM(m_SP)-1))]; /* datum to be virtually deleted */ 2688 datum = ((U32 *)(*(MAM(m_SP)-2)))[5+(*(MAM(m_SP)-1))]; /* datum to be virtually deleted */
2591 - if (datum && /* beware of 0 pseudo datum */  
2592 - !(datum&1) && /* and if function is a closure */  
2593 - ((U32 *)datum)[0] && /* and of permanent data */  
2594 - (!(--(((U32 *)datum)[0])))) /* and if counter becomes 0 */  
2595 - {  
2596 - /* call closure deletion code */  
2597 - *(MAM(m_SP)++) = (U32)(MAM(m_IP));  
2598 - *(MAM(m_SP)++) = datum;  
2599 - MAM(m_IP) = (U8 *)(((U32 *)datum)[2]); 2689 + if (datum) /* beware of 0 pseudo datum */
  2690 + {
  2691 + if (datum&1)
  2692 + { /* top level function */
  2693 + vdelete_module_ref((U8 *)datum,MAM(m_allocator));
2600 } 2694 }
  2695 + else
  2696 + { /* closure function */
  2697 + if (((U32 *)datum)[0] && /* and of permanent data */
  2698 + (!(--(((U32 *)datum)[0])))) /* and if counter becomes 0 */
  2699 + {
  2700 + /* call closure deletion code */
  2701 + *(MAM(m_SP)++) = (U32)(MAM(m_IP));
  2702 + *(MAM(m_SP)++) = datum;
  2703 + MAM(m_IP) = (U8 *)(((U32 *)datum)[2]);
  2704 + }
  2705 + }
  2706 + }
2601 /* else do nothing, but just execute this instruction again */ 2707 /* else do nothing, but just execute this instruction again */
2602 } 2708 }
2603 } 2709 }
@@ -3185,13 +3291,26 @@ ci_decl(copy_ptr) @@ -3185,13 +3291,26 @@ ci_decl(copy_ptr)
3185 Size: 1 3291 Size: 1
3186 3292
3187 This instruction is similar to i_copy_ptr. The sole difference is that it must not 3293 This instruction is similar to i_copy_ptr. The sole difference is that it must not
3188 - perform the copy when the pointer to the function is odd (top level function). */ 3294 + perform the copy when the pointer to the function is odd (top level function).
  3295 +
  3296 + Since version 1.13 all functions are counted, even top level functions. For a closure,
  3297 + the counter is in the closure itself, but for a top level function the counter is that of
  3298 + the corresponding module.
  3299 +
  3300 + */
3189 ci_decl(copy_function) 3301 ci_decl(copy_function)
3190 { 3302 {
3191 trace 3303 trace
3192 - if (!(MAM(m_R)&1))  
3193 - if (*((U32 *)(MAM(m_R))) != 0) 3304 + if (MAM(m_R)&1)
  3305 + { /* top level function */
  3306 + vcopy_module_ref((U8 *)(MAM(m_R)));
  3307 + }
  3308 + else
  3309 + { /* closure function */
  3310 + if (*((U32 *)(MAM(m_R))) != 0) /* avoid copying permanent functions
  3311 + (however, permanent closures do not exist until now) */
3194 (*((U32 *)(MAM(m_R))))++; 3312 (*((U32 *)(MAM(m_R))))++;
  3313 + }
3195 MAM(m_IP) += 1; 3314 MAM(m_IP) += 1;
3196 } 3315 }
3197 3316
@@ -3227,9 +3346,16 @@ ci_decl(vcopy_ptr) @@ -3227,9 +3346,16 @@ ci_decl(vcopy_ptr)
3227 ci_decl(vcopy_function) 3346 ci_decl(vcopy_function)
3228 { 3347 {
3229 trace 3348 trace
  3349 + if (MAM(m_R)&1)
  3350 + { /* top */
  3351 + multiple_vcopy_module_ref((U8 *)MAM(m_R),*(MAM(m_SP)-1));
  3352 + }
  3353 + else
  3354 + {
3230 if (*((U32 *)(MAM(m_R))) != 0) 3355 if (*((U32 *)(MAM(m_R))) != 0)
3231 (*((U32 *)(MAM(m_R)))) += *(MAM(m_SP)-1); 3356 (*((U32 *)(MAM(m_R)))) += *(MAM(m_SP)-1);
3232 - MAM(m_SP)--; 3357 + }
  3358 + MAM(m_SP)--; /* this was the number of copies required */
3233 MAM(m_IP) += 1; 3359 MAM(m_IP) += 1;
3234 } 3360 }
3235 3361
@@ -3618,17 +3744,25 @@ ci_decl(del_stack_function) @@ -3618,17 +3744,25 @@ ci_decl(del_stack_function)
3618 */ 3744 */
3619 3745
3620 /* virtual deletion of function */ 3746 /* virtual deletion of function */
3621 - if (aux && /* beware of NULL pointers */  
3622 - !(aux&1) && /* don't delete top level functions */  
3623 - *((U32 *)aux) && /* don't delete if permanent */  
3624 - !(--(*((U32 *)aux))))  
3625 - {  
3626 - /* call micro context deletion MAM(m_code_begin) */ 3747 + if (aux) /* beware of NULL pointers */
  3748 + {
  3749 + if (aux&1)
  3750 + { /* top level function */
  3751 + vdelete_module_ref((U8 *)aux,MAM(m_allocator));
  3752 + }
  3753 + else
  3754 + { /* closure function */
  3755 + if (*((U32 *)aux) && /* don't delete if permanent */
  3756 + !(--(*((U32 *)aux))))
  3757 + {
  3758 + /* call micro context deletion code */
3627 *(MAM(m_SP)++) = (U32)(MAM(m_IP)+1+4); 3759 *(MAM(m_SP)++) = (U32)(MAM(m_IP)+1+4);
3628 *(MAM(m_SP)++) = aux; 3760 *(MAM(m_SP)++) = aux;
3629 MAM(m_IP) = (U8 *)(((U32 *)aux)[2]); 3761 MAM(m_IP) = (U8 *)(((U32 *)aux)[2]);
3630 return; 3762 return;
  3763 + }
3631 } 3764 }
  3765 + }
3632 MAM(m_IP) += 1+4; 3766 MAM(m_IP) += 1+4;
3633 } 3767 }
3634 3768
@@ -4144,17 +4278,25 @@ ci_decl(indirect_del_function) @@ -4144,17 +4278,25 @@ ci_decl(indirect_del_function)
4144 { 4278 {
4145 trace 4279 trace
4146 U32 aux = *((U32 *)*(MAM(m_SP)-1)); /* pointer (manipulation word) to function */ 4280 U32 aux = *((U32 *)*(MAM(m_SP)-1)); /* pointer (manipulation word) to function */
4147 - if (aux &&  
4148 - !(aux&1) &&  
4149 - *((U32 *)aux) &&  
4150 - !(--(*((U32 *)aux))))  
4151 - {  
4152 - /* call closure deletion MAM(m_code_begin) */  
4153 - *(MAM(m_SP)++) = (U32)(MAM(m_IP)+1);  
4154 - *(MAM(m_SP)++) = aux;  
4155 - MAM(m_IP) = (U8 *)(((U32 *)aux)[2]);  
4156 - return; 4281 + if (aux)
  4282 + {
  4283 + if (aux&1)
  4284 + { /* top level function */
  4285 + vdelete_module_ref((U8 *)aux,MAM(m_allocator));
  4286 + }
  4287 + else
  4288 + { /* closure function */
  4289 + if (*((U32 *)aux) &&
  4290 + !(--(*((U32 *)aux))))
  4291 + {
  4292 + /* call closure deletion MAM(m_code_begin) */
  4293 + *(MAM(m_SP)++) = (U32)(MAM(m_IP)+1);
  4294 + *(MAM(m_SP)++) = aux;
  4295 + MAM(m_IP) = (U8 *)(((U32 *)aux)[2]);
  4296 + return;
  4297 + }
4157 } 4298 }
  4299 + }
4158 MAM(m_IP) += 1; 4300 MAM(m_IP) += 1;
4159 } 4301 }
4160 4302
@@ -4171,17 +4313,25 @@ ci_decl(incr_indirect_del_function) @@ -4171,17 +4313,25 @@ ci_decl(incr_indirect_del_function)
4171 ((*(MAM(m_SP)-1))) += get8(1); 4313 ((*(MAM(m_SP)-1))) += get8(1);
4172 4314
4173 U32 aux = *((U32 *)*(MAM(m_SP)-1)); /* pointer (manipulation word) to function */ 4315 U32 aux = *((U32 *)*(MAM(m_SP)-1)); /* pointer (manipulation word) to function */
4174 - if (aux &&  
4175 - !(aux&1) &&  
4176 - *((U32 *)aux) &&  
4177 - !(--(*((U32 *)aux))))  
4178 - { 4316 + if (aux)
  4317 + {
  4318 + if (aux&1)
  4319 + { /* top level function */
  4320 + vdelete_module_ref((U8 *)aux,MAM(m_allocator));
  4321 + }
  4322 + else
  4323 + { /* closure function */
  4324 + if (*((U32 *)aux) &&
  4325 + !(--(*((U32 *)aux))))
  4326 + {
4179 /* call closure deletion code */ 4327 /* call closure deletion code */
4180 *(MAM(m_SP)++) = (U32)(MAM(m_IP)+1+1); 4328 *(MAM(m_SP)++) = (U32)(MAM(m_IP)+1+1);
4181 *(MAM(m_SP)++) = aux; 4329 *(MAM(m_SP)++) = aux;
4182 MAM(m_IP) = (U8 *)(((U32 *)aux)[2]); 4330 MAM(m_IP) = (U8 *)(((U32 *)aux)[2]);
4183 return; 4331 return;
  4332 + }
4184 } 4333 }
  4334 + }
4185 MAM(m_IP) += 1+1; 4335 MAM(m_IP) += 1+1;
4186 } 4336 }
4187 4337
@@ -4245,17 +4395,25 @@ ci_decl(incr_indirect_del_int) @@ -4245,17 +4395,25 @@ ci_decl(incr_indirect_del_int)
4245 ci_decl(del_function) 4395 ci_decl(del_function)
4246 { 4396 {
4247 trace 4397 trace
4248 - if (MAM(m_R) &&  
4249 - !(MAM(m_R)&1) &&  
4250 - *((U32 *)MAM(m_R)) &&  
4251 - !(--(*((U32 *)MAM(m_R)))))  
4252 - {  
4253 - /* call closure deletion code */  
4254 - *(MAM(m_SP)++) = (U32)(MAM(m_IP)+1);  
4255 - *(MAM(m_SP)++) = MAM(m_R);  
4256 - MAM(m_IP) = (U8 *)(((U32 *)MAM(m_R))[2]);  
4257 - return; 4398 + if (MAM(m_R)) /* avoid pseudo-datum 0 */
  4399 + {
  4400 + if (MAM(m_R)&1)
  4401 + { /* top level function */
  4402 + vdelete_module_ref((U8 *)(MAM(m_R)),MAM(m_allocator));
4258 } 4403 }
  4404 + else
  4405 + { /* closure function */
  4406 + if (*((U32 *)MAM(m_R)) &&
  4407 + !(--(*((U32 *)MAM(m_R)))))
  4408 + {
  4409 + /* call closure deletion code */
  4410 + *(MAM(m_SP)++) = (U32)(MAM(m_IP)+1);
  4411 + *(MAM(m_SP)++) = MAM(m_R);
  4412 + MAM(m_IP) = (U8 *)(((U32 *)MAM(m_R))[2]);
  4413 + return;
  4414 + }
  4415 + }
  4416 + }
4259 MAM(m_IP) += 1; 4417 MAM(m_IP) += 1;
4260 } 4418 }
4261 4419
@@ -5115,7 +5273,9 @@ ci_decl(load_float) @@ -5115,7 +5273,9 @@ ci_decl(load_float)
5115 5273
5116 5274
5117 5275
5118 -/* Format: string (U32)length (U32)counter (U8)...(U8) (U8)0 5276 +/* Before version 1.13:
  5277 +
  5278 + Format: string (U32)length (U32)counter (U8)...(U8) (U8)0
5119 Size: 1+4+4+length+1 5279 Size: 1+4+4+length+1
5120 5280
5121 This instruction contains a character string. The first (U32) operand is the length of 5281 This instruction contains a character string. The first (U32) operand is the length of
@@ -5123,13 +5283,34 @@ ci_decl(load_float) @@ -5123,13 +5283,34 @@ ci_decl(load_float)
5123 value 0. This value will always remain 0, which means that the string is permanent. The 5283 value 0. This value will always remain 0, which means that the string is permanent. The
5124 string itself follows this operand, and is delimited by a 0. 5284 string itself follows this operand, and is delimited by a 0.
5125 5285
5126 - The action of the instruction is to put the address of the null counter into MAM(m_R). */ 5286 + The action of the instruction is to put the address of the null counter into MAM(m_R).
  5287 +
  5288 + Since version 1.13:
  5289 +
  5290 + Format: string (U32)length (U8)...(U8) (no trailing 0)
  5291 + Size: 1+4+length
  5292 +
  5293 + The instruction string allocates a segment and copies the string into it. Since version
  5294 + 1.13 there are no more permanent strings.
  5295 +
  5296 + */
5127 ci_decl(string) 5297 ci_decl(string)
5128 { 5298 {
5129 trace 5299 trace
5130 - MAM(m_R) = (U32)(MAM(m_IP)+1+4); /* address of null counter */  
5131 - assert(*((U32 *)(MAM(m_R))) == 0);  
5132 - MAM(m_IP) += 1+4+4+get32(1)+1; 5300 + int k;
  5301 + int len = get32(1);
  5302 +
  5303 + /* the two lines below replaced since version 1.13 */
  5304 + //MAM(m_R) = (U32)(MAM(m_IP)+1+4); /* address of null counter */
  5305 + //assert(*((U32 *)(MAM(m_R))) == 0);
  5306 +
  5307 + vm_alloc1(MAM(m_R),byte_size_to_word_size(4+len+1)); /* counter + string + trailing 0 */
  5308 + for (k = 0; k < len; k++) (((U8 *)(MAM(m_R)))+4)[k] = (((U8 *)(MAM(m_IP)))+5)[k];
  5309 + (((U8 *)(MAM(m_R)))+4)[k] = 0;
  5310 +
  5311 + /* the line below replaced since version 1.13 */
  5312 + //MAM(m_IP) += 1+4+4+get32(1)+1;
  5313 + MAM(m_IP) += 1+4+get32(1);
5133 } 5314 }
5134 5315
5135 5316
@@ -5137,8 +5318,17 @@ ci_decl(string) @@ -5137,8 +5318,17 @@ ci_decl(string)
5137 ci_decl(string_push) 5318 ci_decl(string_push)
5138 { 5319 {
5139 trace 5320 trace
5140 - MAM(m_R) = *(MAM(m_SP)++) = (U32)(MAM(m_IP)+1+4); /* address of null counter */  
5141 - MAM(m_IP) += 1+4+4+get32(1)+1; 5321 + int k;
  5322 + int len = get32(1);
  5323 +
  5324 + // the two lines below replaced since version 1.13 */
  5325 + //MAM(m_R) = *(MAM(m_SP)++) = (U32)(MAM(m_IP)+1+4); /* address of null counter */
  5326 + //MAM(m_IP) += 1+4+4+get32(1)+1;
  5327 + vm_alloc1(MAM(m_R),byte_size_to_word_size(4+len+1));
  5328 + for (k = 0; k < len; k++) (((U8 *)(MAM(m_R)))+4)[k] = (((U8 *)(MAM(m_IP)))+5)[k];
  5329 + (((U8 *)(MAM(m_R)))+4)[k] = 0;
  5330 + *(MAM(m_SP)++) = MAM(m_R);
  5331 + MAM(m_IP) += 1+4+get32(1);
5142 } 5332 }
5143 5333
5144 5334
@@ -5147,8 +5337,6 @@ ci_decl(string_push) @@ -5147,8 +5337,6 @@ ci_decl(string_push)
5147 5337
5148 5338
5149 5339
5150 -  
5151 -  
5152 /* Format: dec3 (U32)addr 5340 /* Format: dec3 (U32)addr
5153 Size: 1+4 5341 Size: 1+4
5154 5342
@@ -5163,364 +5351,7 @@ ci_decl(dec3) @@ -5163,364 +5351,7 @@ ci_decl(dec3)
5163 } 5351 }
5164 5352
5165 5353
5166 -  
5167 -  
5168 -#if 0  
5169 - the next 10 transformed into syscalls  
5170 -/* Format: connect_file_R  
5171 - connect_file_W  
5172 - connect_file_RW  
5173 - Size: 1  
5174 -  
5175 - This instruction receives a string at *(MAM(m_SP)-1), which is the name of a connection. The  
5176 - purpose is to open the connection, and return a datum of type Maybe(?Addr(T)) for some  
5177 - type T. However, the type T has no importance here, because it is used only statically  
5178 - by the compiler. A connection is always a pointer to a data segment. The function  
5179 - 'open_file_connection' returns 0 if the connection cannot be (immediately) opened, and  
5180 - 1 otherwise. */  
5181 -ci_decl(connect_file_R)  
5182 -{  
5183 - trace  
5184 - U32 conn_seg;  
5185 -  
5186 - vm_alloc2(MAM(m_R), 2,  
5187 - conn_seg, conn_word_size);  
5188 -  
5189 - /* open the connection */  
5190 - if (!open_file_connection(conn_seg,(((char *)(*(MAM(m_SP)-1)))+4),conn_read,0))  
5191 - {  
5192 - vm_free2(MAM(m_R),conn_seg);  
5193 - MAM(m_R) = 0; /* failure */  
5194 - }  
5195 - else  
5196 - {  
5197 - *(((U32 *)(MAM(m_R)))+1) = conn_seg;  
5198 - MAM(m_R) |= 1; /* mixed index 1 */  
5199 - }  
5200 - MAM(m_IP) += 1;  
5201 -}  
5202 -  
5203 -  
5204 -  
5205 -  
5206 -ci_decl(connect_file_W)  
5207 -{  
5208 - trace  
5209 - U32 conn_seg;  
5210 -  
5211 - vm_alloc2(MAM(m_R), 2,  
5212 - conn_seg, conn_word_size);  
5213 -  
5214 - /* open the connection */  
5215 - if (!open_file_connection(conn_seg,(((char *)(*(MAM(m_SP)-1)))+4),conn_write,0))  
5216 - {  
5217 - vm_free2(MAM(m_R),conn_seg);  
5218 - MAM(m_R) = 0; /* failure */  
5219 - }  
5220 - else  
5221 - {  
5222 - *(((U32 *)(MAM(m_R)))+1) = conn_seg;  
5223 - MAM(m_R) |= 1; /* mixed index 1 */  
5224 - }  
5225 - MAM(m_IP) += 1;  
5226 -}  
5227 -  
5228 -  
5229 -ci_decl(connect_file_RW)  
5230 -{  
5231 - trace  
5232 - U32 conn_seg;  
5233 -  
5234 - vm_alloc2(MAM(m_R), 2,  
5235 - conn_seg, conn_word_size);  
5236 -  
5237 - /* open the connection */  
5238 - if (!open_file_connection(conn_seg,(((char *)(*(MAM(m_SP)-1)))+4),conn_write,0))  
5239 - {  
5240 - vm_free2(MAM(m_R),conn_seg);  
5241 - MAM(m_R) = 0; /* failure */  
5242 - }  
5243 - else  
5244 - {  
5245 - *(((U32 *)(MAM(m_R)))+1) = conn_seg;  
5246 - MAM(m_R) |= 1; /* mixed index 1 */  
5247 - }  
5248 - MAM(m_IP) += 1;  
5249 -}  
5250 -  
5251 -  
5252 -/* Format: i_connect_IP_RW  
5253 - Size: 1  
5254 -  
5255 - This instruction is similar to i_connect_file_?, except that it receives two operands  
5256 - which are of type Word32:  
5257 -  
5258 - at *(MAM(m_SP)-1): ip address  
5259 - at *(MAM(m_SP)-2): ip port  
5260 -  
5261 - Opening a network connection may be non immediate. Hence, we open the connection using  
5262 - 'connect', but we test its availability using 'select'. Each time 'select' returns the  
5263 - answer that the connection is not yet established, we give up.  
5264 -  
5265 - So, we need to put our two segments in MAM(m_DUC1) and MAM(m_DUC2).  
5266 -  
5267 - The returned value has type Result(NetworkConnectError,?Addr(?)), hence is:  
5268 -  
5269 - 0 for error(cannot_create_the_socket)  
5270 - 4 for error(address_port_not_available)  
5271 - 8 for error(connection_refused)  
5272 - 12 for error(network_unreachable)  
5273 - 16 for error(address_port_already_in_use)  
5274 - 20 for error(out_of_time)  
5275 - ptr|1 for ok(conn)  
5276 -  
5277 - where ptr is a pointer to the connection data segment. */  
5278 -ci_decl(connect_IP_RW)  
5279 -{  
5280 - trace  
5281 - int i;  
5282 -  
5283 - if (!MAM(m_duc_non_empty))  
5284 - {  
5285 - vm_alloc2(MAM(m_DUC1), 2,  
5286 - MAM(m_DUC2), conn_word_size);  
5287 -  
5288 - /* open the connection without waiting or verifying (only once !) */  
5289 - if((i = open_IP_connection(MAM(m_DUC2),*(MAM(m_SP)-1),*(MAM(m_SP)-2),conn_read|conn_write)) != 0)  
5290 - {  
5291 - switch(i)  
5292 - {  
5293 - /* index bit width = 2 (mixed) */  
5294 - case 1: MAM(m_R) = 0; break; // cannot create the socket  
5295 - case 2: MAM(m_R) = 4; break; // address:port not available on remote machine  
5296 - case 3: MAM(m_R) = 8; break; // connection refused by server  
5297 - case 4: MAM(m_R) = 12; break; // network unreachable  
5298 - case 5: MAM(m_R) = 16; break; // address:port already in use  
5299 - default: MAM(m_R) = 0; break; // cannot create the socket  
5300 - }  
5301 - vm_free2(MAM(m_DUC1),MAM(m_DUC2));  
5302 - MAM(m_IP) += 1;  
5303 - return;  
5304 - }  
5305 -  
5306 - /* the socket handle has been put in the connection segment */  
5307 - MAM(m_duc_non_empty) = 1;  
5308 - }  
5309 -  
5310 - /* check if connection ready */  
5311 - i = is_IP_connection_ready(MAM(m_DUC2));  
5312 -  
5313 - if (i == 0) /* connection ready */  
5314 - {  
5315 - *(((U32 *)(MAM(m_DUC1)))+1) = MAM(m_DUC2);  
5316 - MAM(m_R) = MAM(m_DUC1);  
5317 - MAM(m_R) |= 1; /* mixed index 1 ('ok' of type 'Result') */  
5318 - MAM(m_duc_non_empty) = 0;  
5319 - //printf("Connection is ready\n"); fflush(stdout);  
5320 - }  
5321 - else if (i == 1) /* connection not yet ready */  
5322 - {  
5323 - /* wait until next try */  
5324 - //printf("Waiting for connection to be ready\n"); fflush(stdout);  
5325 - MAM(m_steps) = 0;  
5326 - return;  
5327 - }  
5328 - else if (i == 2)/* time is out */  
5329 - {  
5330 - vm_free2(MAM(m_DUC1),MAM(m_DUC2));  
5331 - MAM(m_duc_non_empty) = 0;  
5332 - //printf("Time is out(2)\n"); fflush(stdout);  
5333 - MAM(m_R) = 20; /* error(out_of_time) */  
5334 - }  
5335 - else if (i == 3)  
5336 - {  
5337 - vm_free2(MAM(m_DUC1),MAM(m_DUC2));  
5338 - MAM(m_duc_non_empty) = 0;  
5339 - MAM(m_R) = 4; /* address:port not available on remote machine */  
5340 - }  
5341 - else  
5342 - {  
5343 - //printf("i = %d\n",i); fflush(stdout);  
5344 - assert(0);  
5345 - }  
5346 - MAM(m_IP) += 1;  
5347 -}  
5348 -  
5349 -  
5350 -/* Format: read_Word8  
5351 - Size: 1  
5352 -  
5353 - This instruction reads a datum of type Word8 from the connection at *(MAM(m_SP)-1). The  
5354 - result is of type Maybe(Word8). */  
5355 -ci_decl(read_Word8)  
5356 -{  
5357 - trace  
5358 - int c;  
5359 -  
5360 - c = read_byte((U8 *)(*(MAM(m_SP)-1)));  
5361 -  
5362 - if (c == 2*EOF)  
5363 - {  
5364 - MAM(m_status) = waiting_for_event;  
5365 - MAM(m_steps) = 0; /* wait for input (network connection) */  
5366 - return;  
5367 - }  
5368 - else if (c == EOF)  
5369 - {  
5370 - //printf("connection closed by peer\n"); fflush(stdout);  
5371 - MAM(m_R) = 0; /* failure */  
5372 - }  
5373 - else  
5374 - {  
5375 - MAM(m_R) = (((U8)c)<<1)|1; /* index of width 1 (Maybe(Int8) has  
5376 - width 9) */  
5377 - }  
5378 - MAM(m_IP) += 1;  
5379 -}  
5380 -  
5381 -  
5382 -  
5383 -/* Format: write_Word8  
5384 - Size: 1  
5385 -  
5386 - This instruction writes a datum of type Word8 to the connection at *(MAM(m_SP)-2). The  
5387 - datum to be written is at *(MAM(m_SP)-1). The result is of type Maybe(One). */  
5388 -ci_decl(write_Word8)  
5389 -{  
5390 - trace  
5391 - MAM(m_R) = write_byte( (U8)(*(MAM(m_SP)-1)), /* Int8 to be written */  
5392 - (U8 *)(*(MAM(m_SP)-2))); /* connection */  
5393 - MAM(m_IP) += 1;  
5394 -}  
5395 -  
5396 -  
5397 -  
5398 -/* Format: implode  
5399 - Size: 1  
5400 -  
5401 - This instruction receives a datum of type List(Word8) at *(MAM(m_SP)-1) and constructs the  
5402 - corresponding string. */  
5403 -ci_decl(implode)  
5404 -{  
5405 - trace  
5406 - int n = 0;  
5407 - U32 l = *(MAM(m_SP)-1);  
5408 - U32 str;  
5409 -  
5410 - /* compute length of list */  
5411 - while (l&1) /* 0 is the empty List(Int8). */  
5412 - {  
5413 - n++;  
5414 - l = *((U32 *)(((U8 *)(l&pointer_mask))+4+1));  
5415 - }  
5416 -  
5417 - /* allocate 4+n+1 bytes for a string */  
5418 - n += 4+1;  
5419 - vm_alloc1(str,byte_size_to_word_size(n));  
5420 -  
5421 - /* initialize the string and copy its content */  
5422 - l = *(MAM(m_SP)-1);  
5423 - n = 4;  
5424 - while (l&1)  
5425 - {  
5426 - ((U8 *)str)[n++] = (U8)(*(((U8 *)(l&pointer_mask))+4));  
5427 - l = *((U32 *)(((U8 *)(l&pointer_mask))+4+1));  
5428 - }  
5429 - ((U8 *)str)[n] = 0;  
5430 - MAM(m_R) = str;  
5431 - MAM(m_IP) += 1;  
5432 -}  
5433 -  
5434 -  
5435 -  
5436 -/* Format: explode  
5437 - Size: 1  
5438 -  
5439 - This instruction receives a string at *(MAM(m_SP)-1) and constructs the list of its  
5440 - characters in the form of a List(Int8). */  
5441 -ci_decl(explode)  
5442 -{  
5443 - trace  
5444 - char *str = ((char *)(*(MAM(m_SP)-1)))+4;  
5445 - U32 aux;  
5446 -  
5447 - if (!MAM(m_duc_non_empty))  
5448 - {  
5449 - /* no datum under construction */  
5450 - if (str[0] == 0) /* the string is empty */  
5451 - {  
5452 - MAM(m_R) = 0; /* empty List(Int8) */  
5453 - MAM(m_IP) += 1;  
5454 - return;  
5455 - }  
5456 - else  
5457 - {  
5458 - MAM(m_DUC1) = 0; /* start with an empty list */  
5459 - MAM(m_DUC2) = 0; /* put the index of next character to be  
5460 - 'paired' in MAM(m_DUC2). */  
5461 - while (str[(MAM(m_DUC2))] != 0) MAM(m_DUC2)++;  
5462 - (MAM(m_DUC2))--; /* index of last character in string */  
5463 - MAM(m_duc_non_empty) = 1;  
5464 - /* continue with 'datum under construction' */  
5465 - }  
5466 - }  
5467 -  
5468 - /* Here, there is a datum under construction. The list constructed  
5469 - so far is in MAM(m_DUC1), and the index of the next character to be  
5470 - put in a pair is in MAM(m_DUC2) (it may be zero, but in any case there  
5471 - is still one character to be ''paired'').  
5472 -  
5473 - Note: the string is read from the end towards the beginning. */  
5474 -  
5475 - while (1)  
5476 - {  
5477 - vm_alloc1(aux,3);  
5478 -  
5479 - /* counter is already at 1 */  
5480 - *(((U8 *)aux)+4) = str[MAM(m_DUC2)]; /* store the character as the head */  
5481 - *((U32 *)(((U8 *)aux)+4+1)) = MAM(m_DUC1); /* store the tail of list */  
5482 - aux |= 1; /* glue mixed index */  
5483 -  
5484 - if (MAM(m_DUC2) == 0) /* this was the last character to store */  
5485 - {  
5486 - MAM(m_duc_non_empty) = 0;  
5487 - MAM(m_R) = aux;  
5488 - break;  
5489 - }  
5490 - else  
5491 - {  
5492 - MAM(m_DUC1) = aux; /* new list under construction */  
5493 - (MAM(m_DUC2))--; /* prepare for next character */  
5494 - }  
5495 - }  
5496 - MAM(m_IP) += 1;  
5497 -}  
5498 -  
5499 -  
5500 -  
5501 -  
5502 -/* Format: truncate_to_word8  
5503 - Size: 1  
5504 - */  
5505 -ci_decl(truncate_to_word8)  
5506 -{  
5507 - trace  
5508 - int i = (int)(*(MAM(m_SP)-1));  
5509 - if (i < 0)  
5510 - MAM(m_R) = 0;  
5511 - else if (i > 255)  
5512 - MAM(m_R) = 255;  
5513 - else  
5514 - MAM(m_R) = i;  
5515 - MAM(m_IP) += 1;  
5516 -}  
5517 -#endif  
5518 -  
5519 -  
5520 -  
5521 -  
5522 -  
5523 - 5354 +
5524 5355
5525 /* Format: alt_number_direct (U8)index_width 5356 /* Format: alt_number_direct (U8)index_width
5526 Size: 1+1 5357 Size: 1+1
@@ -5551,42 +5382,6 @@ ci_decl(alt_number_indirect) @@ -5551,42 +5382,6 @@ ci_decl(alt_number_indirect)
5551 5382
5552 5383
5553 5384
5554 -  
5555 -  
5556 -  
5557 -  
5558 -  
5559 -  
5560 -  
5561 -  
5562 -  
5563 -  
5564 -  
5565 -  
5566 -  
5567 -  
5568 -  
5569 -  
5570 -  
5571 -  
5572 -  
5573 -  
5574 -  
5575 -  
5576 -  
5577 -  
5578 -  
5579 -  
5580 -  
5581 -  
5582 -  
5583 -  
5584 -  
5585 -  
5586 -  
5587 -  
5588 -  
5589 -  
5590 5385
5591 /* Format: start (U8)depth (U32)addr 5386 /* Format: start (U8)depth (U32)addr
5592 Size: 6 5387 Size: 6
@@ -5710,11 +5505,15 @@ ci_decl(copy_stack_function) @@ -5710,11 +5505,15 @@ ci_decl(copy_stack_function)
5710 { 5505 {
5711 trace 5506 trace
5712 U32 f = (*(MAM(m_SP)-(1+get8(1)))); 5507 U32 f = (*(MAM(m_SP)-(1+get8(1))));
5713 - if (!(f&1))  
5714 - {  
5715 - assert(f);  
5716 - if (*((U32 *)f) != 0) (*((U32 *)f))++;  
5717 - } 5508 + if (f&1)
  5509 + { /* top level function */
  5510 + vcopy_module_ref((U8 *)f);
  5511 + }
  5512 + else
  5513 + { /* closure function */
  5514 + assert(f);
  5515 + if (*((U32 *)f) != 0) (*((U32 *)f))++;
  5516 + }
5718 MAM(m_IP) += 1+1; 5517 MAM(m_IP) += 1+1;
5719 } 5518 }
5720 5519
@@ -5893,92 +5692,6 @@ ci_decl(del_gv) @@ -5893,92 +5692,6 @@ ci_decl(del_gv)
5893 5692
5894 5693
5895 5694
5896 -#if 0  
5897 - transformed into a syscall  
5898 -  
5899 -  
5900 -static U8 vm_hex_digit(int b)  
5901 -{  
5902 - if (b < 10) return '0'+b;  
5903 - else return 'a'+b-10;  
5904 -}  
5905 -  
5906 -  
5907 -/* Format: byte_array_to_ascii  
5908 - Size: 1  
5909 -  
5910 - Expect a 'ByteArray' on top of stack, and produces a string with a pair of hexadecimal  
5911 - digits for each byte. */  
5912 -ci_decl(byte_array_to_ascii)  
5913 -{  
5914 - trace  
5915 - int i, j;  
5916 - char *dest;  
5917 - U8 *array = (U8 *)(*(MAM(m_SP)-1));  
5918 - U32 n = *((U32 *)(array+4)); /* number of bytes */  
5919 -  
5920 - vm_alloc1(MAM(m_R),byte_size_to_word_size(4+(2*n)+1));  
5921 -  
5922 - array += 8; /* point to first byte */  
5923 - dest = ((char *)MAM(m_R))+4; /* avoid counter in destination */  
5924 - j = 0;  
5925 -  
5926 - for (i = 0 ; i < (int)n; i++)  
5927 - {  
5928 - dest[j++] = vm_hex_digit(((array[i])>>4)&0xF);  
5929 - dest[j++] = vm_hex_digit((array[i])&0xF);  
5930 - }  
5931 - assert(j == (int)(2*n));  
5932 - dest[j] = 0; /* end of string */  
5933 - MAM(m_IP) += 1;  
5934 -}  
5935 -#endif  
5936 -  
5937 -  
5938 -  
5939 -  
5940 -  
5941 -  
5942 -  
5943 -  
5944 -#if 0  
5945 - transformed into a syscall  
5946 -/* Format: byte_array_to_string  
5947 - Size: 1  
5948 -  
5949 - Expects a byte array on the stack and produces the longuest string which is a prefix of  
5950 - it. */  
5951 -ci_decl(byte_array_to_string)  
5952 -{  
5953 - trace  
5954 - int i, l;  
5955 - U8 *array = (U8 *)(*(MAM(m_SP)-1));  
5956 - U32 n = *((U32 *)(array+4)); /* length of byte array */  
5957 -  
5958 - array += 8;  
5959 -  
5960 - /* compute length of string */  
5961 - for ( l = 0; l < (int)n; l++)  
5962 - if (array[l] == 0) break;  
5963 -  
5964 - /* the length of the string is l */  
5965 -  
5966 - vm_alloc1(MAM(m_R),byte_size_to_word_size(4+l+1));  
5967 -  
5968 - for (i = 0; i < l; i++)  
5969 - ((U8 *)MAM(m_R))[i+4] = array[i];  
5970 - ((U8 *)MAM(m_R))[i+4] = 0;  
5971 - MAM(m_IP) += 1;  
5972 -}  
5973 -  
5974 -#endif  
5975 -  
5976 -  
5977 -  
5978 -  
5979 -  
5980 -  
5981 -  
5982 /* Format: success (U8)bit_width 5695 /* Format: success (U8)bit_width
5983 Size: 1+1 5696 Size: 1+1
5984 5697
@@ -6104,10 +5817,6 @@ ci_decl(odd_align) /* this one is required but never executed */ @@ -6104,10 +5817,6 @@ ci_decl(odd_align) /* this one is required but never executed */
6104 trace 5817 trace
6105 } 5818 }
6106 5819
6107 -ci_decl(load_adm)  
6108 -{  
6109 - trace  
6110 -}  
6111 5820
6112 ci_decl(dummy) 5821 ci_decl(dummy)
6113 { 5822 {
@@ -6152,6 +5861,8 @@ ci_decl(begin_op) @@ -6152,6 +5861,8 @@ ci_decl(begin_op)
6152 function beginning followed by a single byte indicating if this call is terminal call 5861 function beginning followed by a single byte indicating if this call is terminal call
6153 or not. 5862 or not.
6154 */ 5863 */
  5864 +
  5865 +
6155 ci_decl(end_op) 5866 ci_decl(end_op)
6156 { 5867 {
6157 trace 5868 trace
@@ -6231,7 +5942,11 @@ U32 default_security_value = 0xffffffff; @@ -6231,7 +5942,11 @@ U32 default_security_value = 0xffffffff;
6231 U8* common_code_begin; 5942 U8* common_code_begin;
6232 U8* current_IP; 5943 U8* current_IP;
6233 #endif 5944 #endif
6234 - 5945 +
  5946 +
  5947 +
  5948 +
  5949 + /*** RunMachine (the function by which virtual machines work) ***/
6235 5950
6236 /* This function is independent */ 5951 /* This function is independent */
6237 int AnubisProcess::RunMachine(int steps) 5952 int AnubisProcess::RunMachine(int steps)
@@ -6281,8 +5996,7 @@ int AnubisProcess::RunMachine(int steps) @@ -6281,8 +5996,7 @@ int AnubisProcess::RunMachine(int steps)
6281 #ifdef WATCH_CODE 5996 #ifdef WATCH_CODE
6282 compare_watched_code(prev_IP-MAM(m_code_begin)); 5997 compare_watched_code(prev_IP-MAM(m_code_begin));
6283 #endif 5998 #endif
6284 -  
6285 - 5999 +
6286 m_steps--; 6000 m_steps--;
6287 } 6001 }
6288 #undef CARG 6002 #undef CARG
@@ -6292,5 +6006,4 @@ int AnubisProcess::RunMachine(int steps) @@ -6292,5 +6006,4 @@ int AnubisProcess::RunMachine(int steps)
6292 6006
6293 6007
6294 6008
6295 -  
6296 6009
anubis_dev/vm/src/vm.h
@@ -18,6 +18,7 @@ extern U8 *duplicate_code; @@ -18,6 +18,7 @@ extern U8 *duplicate_code;
18 extern U32 watched_code_size; 18 extern U32 watched_code_size;
19 #endif 19 #endif
20 20
  21 +#define debug_vm
21 22
22 #ifdef DEBUG 23 #ifdef DEBUG
23 // Only defines following macro on debug mode 24 // Only defines following macro on debug mode
@@ -206,6 +207,11 @@ extern void serialize_float(double d, U8 *dest); @@ -206,6 +207,11 @@ extern void serialize_float(double d, U8 *dest);
206 207
207 #define inf(x,y) ((x)<(y) ? (x) : (y)) 208 #define inf(x,y) ((x)<(y) ? (x) : (y))
208 #define sup(x,y) ((x)<(y) ? (y) : (x)) 209 #define sup(x,y) ((x)<(y) ? (y) : (x))
  210 +
  211 +
  212 +
  213 +
  214 +
209 215
210 struct Exec_Mod_struct { 216 struct Exec_Mod_struct {
211 U32 flags; /* also indicates is primary or secondary ('mf_secondary_adm' in 'bytecode.h') */ 217 U32 flags; /* also indicates is primary or secondary ('mf_secondary_adm' in 'bytecode.h') */
@@ -228,27 +234,39 @@ struct Exec_Mod_struct { @@ -228,27 +234,39 @@ struct Exec_Mod_struct {
228 }; 234 };
229 235
230 236
231 -extern int /* 0 = out of memory, 1 = ok */  
232 - add_module( U32 flags,  
233 - U8* byte_code,  
234 - int starting_point,  
235 - AnubisAllocator *allocator  
236 - );  
237 -  
238 -extern U32 number_of_modules;  
239 -  
240 -  
241 /*************************************************** 237 /***************************************************
242 * * 238 * *
243 * Dynamic modules stuff (added in version 1.13) * 239 * Dynamic modules stuff (added in version 1.13) *
244 * * 240 * *
245 ***************************************************/ 241 ***************************************************/
  242 +
  243 +extern U32 number_of_modules;
  244 +
246 /* Array of all modules, including the primary one ('the_primary_module' is kept anyway) */ 245 /* Array of all modules, including the primary one ('the_primary_module' is kept anyway) */
247 extern struct Exec_Mod_struct * modules; /* (in dynamic_module.c) */ 246 extern struct Exec_Mod_struct * modules; /* (in dynamic_module.c) */
248 /* Initializing/resizing this array */ 247 /* Initializing/resizing this array */
249 extern int resize_modules_array(void); /* 0 = out of memory, 1 = ok (initialization in anbexec.cpp) */ 248 extern int resize_modules_array(void); /* 0 = out of memory, 1 = ok (initialization in anbexec.cpp) */
250 249
251 250
  251 +extern int /* 0 = out of memory, 1 = ok */
  252 + add_module( U32 flags,
  253 + U8* byte_code,
  254 + int starting_point,
  255 + AnubisAllocator *allocator
  256 + );
  257 +
  258 +/* garbage-collector tools for modules */
  259 +extern void vcopy_module_ref(U8 *ref);
  260 +extern void multiple_vcopy_module_ref(U8 *ref,U32 n);
  261 +extern void vdelete_module_ref(U8 *ref, AnubisAllocator *allocator);
  262 +
  263 +
  264 +
  265 +
  266 +
  267 +
  268 +
  269 +
252 270
253 271
254 extern void check_module_integrity(void); 272 extern void check_module_integrity(void);
anubis_dev/vm/src/vmtools.cpp
@@ -1116,17 +1116,19 @@ void link_globals_and_relocate(U8* code, int size) @@ -1116,17 +1116,19 @@ void link_globals_and_relocate(U8* code, int size)
1116 case i_string_push: 1116 case i_string_push:
1117 if (nsc_file != NULL) 1117 if (nsc_file != NULL)
1118 { 1118 {
1119 - fprintf(nsc_file,"\n%8d | %s %ld %ld (\"",ptr-code,instr_names[*ptr],  
1120 - *((U32 *)(ptr+1)),*((U32 *)(ptr+5)));  
1121 - for (k = 0; k < (int)(*((U32 *)(ptr+5))); k++) 1119 + fprintf(nsc_file,"\n%8d | %s %ld (\"",ptr-code,instr_names[*ptr],
  1120 + *((U32 *)(ptr+1)));
  1121 + for (k = 0; k < (int)(*((U32 *)(ptr+1))); k++)
1122 { 1122 {
1123 - fprintf(nsc_file,"%c",(*(ptr+9+k))^172); 1123 + fprintf(nsc_file,"%c",(*(ptr+5+k))^172);
1124 } 1124 }
1125 fprintf(nsc_file,"\")"); 1125 fprintf(nsc_file,"\")");
1126 } 1126 }
1127 - ptr += 1+4+4;  
1128 - while (*ptr != 172) *(ptr++) ^= 172;  
1129 - *(ptr++) ^= 172; 1127 + for (k = 0; k < (int)(*((U32 *)(ptr+1))); k++)
  1128 + {
  1129 + *(ptr+k+5) ^= 172;
  1130 + }
  1131 + ptr += 5+(int)(*((U32 *)(ptr+1)));
1130 break; 1132 break;
1131 1133
1132 /* (U8)instr (U8)dec [dec align bytes] (U32)counter 1134 /* (U8)instr (U8)dec [dec align bytes] (U32)counter