Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
e33aebb3ba0d2c3d80f95198082b1d5c968c98c2
[simgrid.git] / src / bindings / lua / lua_state_cloner.c
1 /* Copyright (c) 2010. The SimGrid Team.
2  * All rights reserved.                                                     */
3
4 /* This program is free software; you can redistribute it and/or modify it
5  * under the terms of the license (GNU LGPL) which comes with this package. */
6
7 /* SimGrid Lua state management                                             */
8
9 #include "lua_state_cloner.h"
10 #include "lua_utils.h"
11 #include "xbt.h"
12 #include "xbt/log.h"
13 #include <lauxlib.h>
14 #include <lualib.h>
15
16 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(lua_state_cloner, bindings, "Lua state management");
17
18 static void sglua_add_maestro_table(lua_State* L, int index, void* maestro_table_ptr);
19 static void sglua_remove_maestro_table(lua_State* L, int index, void* maestro_table_ptr);
20 static void* sglua_get_maestro_table_ptr(lua_State* L, int index);
21 static void sglua_get_table_by_ptr(lua_State* L, void* table_ptr);
22 static int l_get_from_maestro(lua_State* L);
23
24 static void sglua_copy_nil(lua_State* src, lua_State* dst);
25 static void sglua_copy_number(lua_State* src, lua_State* dst);
26 static void sglua_copy_boolean(lua_State* src, lua_State* dst);
27 static void sglua_copy_string(lua_State* src, lua_State* dst);
28 static void sglua_copy_table(lua_State* src, lua_State* dst);
29 static void sglua_copy_function(lua_State* src, lua_State* dst);
30 static void sglua_copy_lightuserdata(lua_State* src, lua_State* dst);
31 static void sglua_copy_userdata(lua_State* src, lua_State* dst);
32 static void sglua_copy_thread(lua_State* src, lua_State* dst);
33
34 /**
35  * @brief Adds a reference to a maestro table to the list of known maestro
36  * tables of a state.
37  *
38  * TODO identify maestro's tables with my own IDs instead of pointers
39  * to Lua internals
40  *
41  * @param L a state (can be maestro itself)
42  * @param index index of the copy of the maestro table in the stack of L
43  * @param maestro_table_ptr pointer to the original table in maestro's world
44  */
45 static void sglua_add_maestro_table(lua_State* L, int index, void* maestro_table_ptr) {
46
47   /* we will set both [ptr] -> table and [table] -> ptr */
48
49                                   /* ... */
50   lua_pushvalue(L, index);
51                                   /* ... table */
52   lua_pushstring(L, "simgrid.maestro_tables");
53                                   /* ... table "simgrid.maestro_tables" */
54   lua_rawget(L, LUA_REGISTRYINDEX);
55                                   /* ... table maestrotbs */
56   lua_pushvalue(L, -2);
57                                   /* ... table maestrotbs table */
58   lua_pushlightuserdata(L, maestro_table_ptr);
59                                   /* ... table maestrotbs table tableptr */
60   lua_pushvalue(L, -1);
61                                   /* ... table maestrotbs table tableptr tableptr */
62   lua_pushvalue(L, -3);
63                                   /* ... table maestrotbs table tableptr tableptr table */
64   lua_settable(L, -5);
65                                   /* ... table maestrotbs table tableptr */
66   lua_settable(L, -3);
67                                   /* ... table maestrotbs */
68   lua_pop(L, 2);
69                                   /* ... */
70 }
71
72 /**
73  * @brief Removes a reference to a maestro table to the list of known maestro
74  * tables of a state.
75  *
76  * @param L a state (can be maestro itself)
77  * @param index index of the copy of the maestro table in the stack of L
78  * @param maestro_table_ptr pointer to the original table in maestro's world
79  */
80 static void sglua_remove_maestro_table(lua_State* L, int index, void* maestro_table_ptr) {
81
82   /* we will unset both [ptr] -> table and [table] -> ptr */
83
84                                   /* ... */
85   lua_pushvalue(L, index);
86                                   /* ... table */
87   lua_pushstring(L, "simgrid.maestro_tables");
88                                   /* ... table "simgrid.maestro_tables" */
89   lua_rawget(L, LUA_REGISTRYINDEX);
90                                   /* ... table maestrotbs */
91   lua_pushvalue(L, -2);
92                                   /* ... table maestrotbs table */
93   lua_pushnil(L);
94                                   /* ... table maestrotbs table nil */
95   lua_pushlightuserdata(L, maestro_table_ptr);
96                                   /* ... table maestrotbs table nil tableptr */
97   lua_pushnil(L);
98                                   /* ... table maestrotbs table nil tableptr nil*/
99   lua_settable(L, -5);
100                                   /* ... table maestrotbs table nil */
101   lua_settable(L, -3);
102                                   /* ... table maestrotbs */
103   lua_pop(L, 2);
104                                   /* ... */
105 }
106
107 /**
108  * @brief For a table in the stack of L, returns a pointer that identifies the
109  * same table in in maestro's world.
110  * @param L a Lua state
111  * @param index index of a table in the stack of L
112  * @return a pointer to maestro's copy of this table, or NULL if this table
113  * did not come from maestro
114  */
115 static void* sglua_get_maestro_table_ptr(lua_State* L, int index) {
116
117   void* maestro_table_ptr = NULL;
118                                   /* ... */
119   lua_pushvalue(L, index);
120                                   /* ... table */
121   lua_pushstring(L, "simgrid.maestro_tables");
122                                   /* ... table "simgrid.maestro_tables" */
123   lua_rawget(L, LUA_REGISTRYINDEX);
124                                   /* ... table maestrotbs */
125   lua_pushvalue(L, -2);
126                                   /* ... table maestrotbs table */
127   lua_gettable(L, -2);
128                                   /* ... table maestrotbs tableptr/nil */
129   if (!lua_isnil(L, -1)) {
130                                   /* ... table maestrotbs tableptr */
131     maestro_table_ptr = (void*) lua_topointer(L, -1);
132   }
133
134   lua_pop(L, 3);
135                                   /* ... */
136   return maestro_table_ptr;
137 }
138
139 /**
140  * @brief Pushes a table knowing a pointer to maestro's copy of this table.
141  *
142  * Pushes nil if L does not know this table in maestro.
143  *
144  * @param L a Lua state
145  * @param maestro_table_ptr pointer that identifies a table in maestro's world
146  */
147 static void sglua_get_table_by_ptr(lua_State* L, void* maestro_table_ptr) {
148
149                                   /* ... */
150   lua_pushstring(L, "simgrid.maestro_tables");
151                                   /* ... "simgrid.maestro_tables" */
152   lua_rawget(L, LUA_REGISTRYINDEX);
153                                   /* ... maestrotbs */
154   lua_pushlightuserdata(L, maestro_table_ptr);
155                                   /* ... maestrotbs tableptr */
156   lua_gettable(L, -2);
157                                   /* ... maestrotbs table/nil */
158   lua_remove(L, -2);
159                                   /* ... table/nil */
160 }
161
162 /**
163  * @brief Pops a value from the stack of a source state and pushes it on the
164  * stack of another state.
165  * If the value is a table, its content is copied recursively.
166  *
167  * This function is similar to lua_xmove() but it allows to move a value
168  * between two different global states.
169  *
170  * @param src the source state (not necessarily maestro)
171  * @param dst the destination state
172  */
173 void sglua_move_value(lua_State* src, lua_State* dst) {
174
175   sglua_copy_value(src, dst);
176   lua_pop(src, 1);
177 }
178
179 /**
180  * @brief Pushes onto the stack a copy of the value on top another stack.
181  * If the value is a table, its content is copied recursively.
182  *
183  * This function allows to move a value between two different global states.
184  *
185  * @param src the source state (not necessarily maestro)
186  * @param dst the destination state
187  */
188 void sglua_copy_value(lua_State* src, lua_State* dst) {
189
190   luaL_checkany(src, -1);                  /* check the value to copy */
191
192   int indent = (lua_gettop(dst) - 1) * 6;
193   XBT_DEBUG("%sCopying data %s", sglua_get_spaces(indent), sglua_tostring(src, -1));
194
195   sglua_stack_dump("src before copying a value (should be ... value): ", src);
196   sglua_stack_dump("dst before copying a value (should be ...): ", dst);
197
198   switch (lua_type(src, -1)) {
199
200     case LUA_TNIL:
201       sglua_copy_nil(src, dst);
202       break;
203
204     case LUA_TNUMBER:
205       sglua_copy_number(src, dst);
206       break;
207
208     case LUA_TBOOLEAN:
209       sglua_copy_boolean(src, dst);
210       break;
211
212     case LUA_TSTRING:
213       sglua_copy_string(src, dst);
214       break;
215
216     case LUA_TFUNCTION:
217       sglua_copy_function(src, dst);
218       break;
219
220     case LUA_TTABLE:
221       sglua_copy_table(src, dst);
222       break;
223
224     case LUA_TLIGHTUSERDATA:
225       sglua_copy_lightuserdata(src, dst);
226       break;
227
228     case LUA_TUSERDATA:
229       sglua_copy_userdata(src, dst);
230       break;
231
232     case LUA_TTHREAD:
233       sglua_copy_thread(src, dst);
234       break;
235   }
236
237   indent -= 2;
238   XBT_DEBUG("%sData copied", sglua_get_spaces(indent));
239
240   sglua_stack_dump("src after copying a value (should be ... value): ", src);
241   sglua_stack_dump("dst after copying a value (should be ... value): ", dst);
242 }
243
244 /**
245  * @brief Copies the nil value on the top of src to the top of dst.
246  * @param src source state
247  * @param dst destination state
248  */
249 static void sglua_copy_nil(lua_State* src, lua_State* dst) {
250   lua_pushnil(dst);
251 }
252
253 /**
254  * @brief Copies the number value on the top of src to the top of dst.
255  * @param src source state
256  * @param dst destination state
257  */
258 static void sglua_copy_number(lua_State* src, lua_State* dst) {
259   lua_pushnumber(dst, lua_tonumber(src, -1));
260 }
261
262 /**
263  * @brief Copies the boolean value on the top of src to the top of dst.
264  * @param src source state
265  * @param dst destination state
266  */
267 static void sglua_copy_boolean(lua_State* src, lua_State* dst) {
268   lua_pushboolean(dst, lua_toboolean(src, -1));
269 }
270
271 /**
272  * @brief Copies the string value on the top of src to the top of dst.
273  * @param src source state
274  * @param dst destination state
275  */
276 static void sglua_copy_string(lua_State* src, lua_State* dst) {
277
278   /* no worries about memory: lua_pushstring makes a copy */
279   lua_pushstring(dst, lua_tostring(src, -1));
280 }
281
282 /**
283  * @brief Copies the table value on top of src to the top of dst.
284  *
285  * A deep copy of the table is made. If the table has a metatable, the
286  * metatable is also copied.
287  * If the table comes from maestro and is already known by the destination
288  * state, it is not copied again.
289  *
290  * @param src source state
291  * @param dst destination state
292  */
293 static void sglua_copy_table(lua_State* src, lua_State* dst) {
294
295                                   /* src: ... table
296                                      dst: ... */
297   int indent = lua_gettop(dst) * 6  + 2;
298
299   /* get from maestro the pointer that identifies this table */
300   void* table_ptr = sglua_get_maestro_table_ptr(src, -1);
301   int known_by_maestro = (table_ptr != NULL);
302
303   if (!known_by_maestro) {
304     /* the table didn't come from maestro: nevermind, use the pointer of src */
305     table_ptr = (void*) lua_topointer(src, -1);
306     XBT_DEBUG("%sMaestro does not know this table",
307         sglua_get_spaces(indent));
308   }
309
310   if (sglua_is_maestro(src)) {
311     /* register the table in maestro itself */
312     XBT_DEBUG("%sKeeping track of this table in maestro itself",
313         sglua_get_spaces(indent));
314     sglua_add_maestro_table(src, -1, table_ptr);
315     known_by_maestro = 1;
316     xbt_assert(sglua_get_maestro_table_ptr(src, -1) == table_ptr);
317   }
318
319   /* to avoid infinite recursion, see if this table is already known by dst */
320   sglua_get_table_by_ptr(dst, table_ptr);
321                                   /* dst: ... table/nil */
322   if (!lua_isnil(dst, -1)) {
323     XBT_DEBUG("%sNothing to do: table already known (%p)",
324         sglua_get_spaces(indent), table_ptr);
325                                   /* dst: ... table */
326   }
327   else {
328     XBT_DEBUG("%sFirst visit of this table (%p)", sglua_get_spaces(indent),
329         table_ptr);
330                                   /* dst: ... nil */
331     lua_pop(dst, 1);
332                                   /* dst: ... */
333
334     /* first visit: create the new table in dst */
335     lua_newtable(dst);
336                                   /* dst: ... table */
337
338     /* mark the table as known right now to avoid infinite recursion */
339     sglua_add_maestro_table(dst, -1, table_ptr);
340     /* we may have added a table with a non-maestro pointer, but if it was the
341      * case, we will remove it later */
342     XBT_DEBUG("%sTable marked as known", sglua_get_spaces(indent));
343     xbt_assert(sglua_get_maestro_table_ptr(dst, -1) == table_ptr);
344
345     sglua_stack_dump("dst after marking the table as known (should be ... table): ", dst);
346
347     /* copy the metatable if any */
348     int has_meta_table = lua_getmetatable(src, -1);
349                                   /* src: ... table mt? */
350     if (has_meta_table) {
351       XBT_DEBUG("%sCopying the metatable", sglua_get_spaces(indent));
352                                   /* src: ... table mt */
353       sglua_copy_table(src, dst);
354                                   /* dst: ... table mt */
355       lua_pop(src, 1);
356                                   /* src: ... table */
357       lua_setmetatable(dst, -2);
358                                   /* dst: ... table */
359     }
360     else {
361                                   /* src: ... table */
362       XBT_DEBUG("%sNo metatable", sglua_get_spaces(indent));
363     }
364
365     sglua_stack_dump("src before traversing the table (should be ... table): ", src);
366     sglua_stack_dump("dst before traversing the table (should be ... table): ", dst);
367
368     /* traverse the table of src and copy each element */
369     lua_pushnil(src);
370                                   /* src: ... table nil */
371     while (lua_next(src, -2) != 0) {
372                                   /* src: ... table key value */
373
374       XBT_DEBUG("%sCopying table element %s", sglua_get_spaces(indent),
375           sglua_keyvalue_tostring(src, -2, -1));
376
377       sglua_stack_dump("src before copying table element (should be ... table key value): ", src);
378       sglua_stack_dump("dst before copying table element (should be ... table): ", dst);
379
380       /* copy the key */
381       lua_pushvalue(src, -2);
382                                   /* src: ... table key value key */
383       indent += 2;
384       XBT_DEBUG("%sCopying the key part of the table element",
385           sglua_get_spaces(indent));
386       sglua_move_value(src, dst);
387                                   /* src: ... table key value
388                                      dst: ... table key */
389       XBT_DEBUG("%sCopied the key part of the table element",
390           sglua_get_spaces(indent));
391
392       /* copy the value */
393       XBT_DEBUG("%sCopying the value part of the table element",
394           sglua_get_spaces(indent));
395       sglua_move_value(src, dst);
396                                   /* src: ... table key
397                                      dst: ... table key value */
398       XBT_DEBUG("%sCopied the value part of the table element",
399           sglua_get_spaces(indent));
400       indent -= 2;
401
402       /* set the table element */
403       lua_settable(dst, -3);
404                                   /* dst: ... table */
405
406       /* the key stays on top of src for next iteration */
407       sglua_stack_dump("src before next iteration (should be ... table key): ", src);
408       sglua_stack_dump("dst before next iteration (should be ... table): ", dst);
409
410       XBT_DEBUG("%sTable element copied", sglua_get_spaces(indent));
411     }
412     XBT_DEBUG("%sFinished traversing the table", sglua_get_spaces(indent));
413   }
414
415   if (!known_by_maestro) {
416     /* actually,it was not a maestro table: forget the pointer */
417     sglua_remove_maestro_table(dst, -1, table_ptr);
418   }
419 }
420
421 /**
422  * @brief Copies the function on the top of src to the top of dst.
423  *
424  * It can be a Lua function or a C function.
425  * Copying upvalues is not implemented yet.
426  *
427  * @param src source state
428  * @param dst destination state
429  */
430 static void sglua_copy_function(lua_State* src, lua_State* dst) {
431
432   if (lua_iscfunction(src, -1)) {
433     /* it's a C function */
434
435     XBT_DEBUG("It's a C function");
436     sglua_stack_dump("src before copying upvalues: ", src);
437
438     /* get the function pointer */
439     int function_index = lua_gettop(src);
440     lua_CFunction f = lua_tocfunction(src, function_index);
441
442     /* copy the upvalues */
443     int i = 0;
444     const char* upvalue_name = NULL;
445     do {
446       i++;
447       upvalue_name = lua_getupvalue(src, function_index, i);
448
449       if (upvalue_name != NULL) {
450         XBT_DEBUG("Upvalue %s", upvalue_name);
451         sglua_move_value(src, dst);
452       }
453     } while (upvalue_name != NULL);
454
455     sglua_stack_dump("src before copying pointer: ", src);
456
457     /* set the function */
458     lua_pushcclosure(dst, f, i - 1);
459     XBT_DEBUG("Function pointer copied");
460   }
461   else {
462     /* it's a Lua function: dump it from src */
463
464     s_sglua_buffer_t buffer;
465     buffer.capacity = 128; /* an empty function uses 77 bytes */
466     buffer.size = 0;
467     buffer.data = xbt_new(char, buffer.capacity);
468
469     /* copy the binary chunk from src into a buffer */
470     _XBT_GNUC_UNUSED int error = lua_dump(src, sglua_memory_writer, &buffer);
471     xbt_assert(!error, "Failed to dump the function from the source state: error %d",
472         error);
473     XBT_DEBUG("Fonction dumped: %zu bytes", buffer.size);
474
475     /*
476     fwrite(buffer.data, buffer.size, buffer.size, stderr);
477     fprintf(stderr, "\n");
478     */
479
480     /* load the chunk into dst */
481     error = luaL_loadbuffer(dst, buffer.data, buffer.size, "(dumped function)");
482     xbt_assert(!error, "Failed to load the function into the destination state: %s",
483         lua_tostring(dst, -1));
484   }
485 }
486
487 /**
488  * @brief Copies the light userdata on the top of src to the top of dst.
489  * @param src source state
490  * @param dst destination state
491  */
492 static void sglua_copy_lightuserdata(lua_State* src, lua_State* dst) {
493   lua_pushlightuserdata(dst, lua_touserdata(src, -1));
494 }
495
496 /**
497  * @brief Copies the full userdata on the top of src to the top of dst.
498  *
499  * If the userdata has a metatable, the metatable is also copied.
500  *
501  * @param src source state
502  * @param dst destination state
503  */
504 static void sglua_copy_userdata(lua_State* src, lua_State* dst) {
505
506   int indent = lua_gettop(dst) * 6  + 2;
507
508   /* copy the data */
509                                   /* src: ... udata
510                                      dst: ... */
511   size_t size = lua_objlen(src, -1);
512   void* src_block = lua_touserdata(src, -1);
513   void* dst_block = lua_newuserdata(dst, size);
514                                   /* dst: ... udata */
515   memcpy(dst_block, src_block, size);
516
517   /* copy the metatable if any */
518   int has_meta_table = lua_getmetatable(src, -1);
519                                   /* src: ... udata mt? */
520   if (has_meta_table) {
521     XBT_DEBUG("%sCopying metatable of userdata (%p)",
522         sglua_get_spaces(indent), lua_topointer(src, -1));
523                                   /* src: ... udata mt */
524     sglua_copy_table(src, dst);
525                                   /* src: ... udata mt
526                                      dst: ... udata mt */
527     lua_pop(src, 1);
528                                   /* src: ... udata */
529     lua_setmetatable(dst, -2);
530                                   /* dst: ... udata */
531
532     XBT_DEBUG("%sMetatable of userdata copied", sglua_get_spaces(indent));
533   }
534   else {
535     XBT_DEBUG("%sNo metatable for this userdata",
536         sglua_get_spaces(indent));
537                                   /* src: ... udata */
538   }
539 }
540
541 /**
542  * @brief This operation is not supported (yet?) so it just pushes nil.
543  *
544  * @param src source state
545  * @param dst destination state
546  */
547 static void sglua_copy_thread(lua_State* src, lua_State* dst) {
548
549   XBT_WARN("Copying a thread from another state is not implemented (yet?).");
550   lua_pushnil(dst);
551 }
552
553 /**
554  * @brief Copies a global value or a registry value from the maestro state.
555  *
556  * The state L must have been created by sglua_clone_maestro_state().
557  * This function is meant to be an __index metamethod.
558  * Consequently, it assumes that the stack has two elements:
559  * a table (either the environment or the registry of L) and the string key of
560  * a value that does not exist yet in this table. It copies the corresponding
561  * value from maestro and pushes it on the stack of L.
562  * If the value does not exist in maestro state either, nil is pushed.
563  *
564  * TODO: make this function thread safe. If the simulation runs in parallel,
565  * several simulated processes may trigger this __index metamethod at the same
566  * time and get globals from maestro.
567  *
568  * @param L the current state
569  * @return number of return values pushed (always 1)
570  */
571 static int l_get_from_maestro(lua_State *L) {
572
573   /* check the arguments */
574   luaL_checktype(L, 1, LUA_TTABLE);
575   const char* key = luaL_checkstring(L, 2);
576                                   /* L:      table key */
577   XBT_DEBUG("__index of '%s' begins", key);
578
579   /* want a global or a registry value? */
580   int pseudo_index;
581   if (lua_equal(L, 1, LUA_REGISTRYINDEX)) {
582     /* registry */
583     pseudo_index = LUA_REGISTRYINDEX;
584     XBT_DEBUG("Will get the value from the registry of maestro");
585   }
586   else {
587     /* global */
588     pseudo_index = LUA_GLOBALSINDEX;
589     XBT_DEBUG("Will get the value from the globals of maestro");
590   }
591
592   /* get the father */
593   lua_State* maestro = sglua_get_maestro();
594
595                                   /* L:      table key */
596
597   /* get the value from maestro */
598   lua_getfield(maestro, pseudo_index, key);
599                                   /* maestro: ... value */
600
601   /* push the value onto the stack of L */
602   sglua_move_value(maestro, L);
603                                   /* maestro: ...
604                                      L:      table key value */
605
606   /* prepare the return value of __index */
607   lua_pushvalue(L, -1);
608                                   /* L:      table key value value */
609   lua_insert(L, 1);
610                                   /* L:      value table key value */
611
612   /* save the copied value in the table for subsequent accesses */
613   lua_settable(L, -3);
614                                   /* L:      value table */
615   lua_settop(L, 1);
616                                   /* L:      value */
617
618   XBT_DEBUG("__index of '%s' returns %s", key, sglua_tostring(L, -1));
619
620   return 1;
621 }
622
623 /**
624  * @brief Creates a new Lua state and get its environment from the maestro
625  * state.
626  *
627  * The state created is independent from maestro and has its own copies of
628  * global and registry values.
629  * However, the global and registry values are not copied right now from
630  * the original state; they are copied only the first time they are accessed.
631  * This behavior saves time and memory, and is okay for Simgrid's needs.
632  *
633  * TODO: if the simulation runs in parallel, copy everything right now?
634  *
635  * @return the state created
636  */
637 lua_State* sglua_clone_maestro(void) {
638
639   /* create the new state */
640   lua_State *L = luaL_newstate();
641
642   /* set its environment and its registry:
643    * - create a table newenv
644    * - create a metatable mt
645    * - set mt.__index = a function that copies the global from the father state
646    * - set mt as the metatable of the registry
647    * - set mt as the metatable of newenv
648    * - set newenv as the environment of the new state
649    */
650   lua_pushthread(L);                        /* thread */
651   lua_newtable(L);                          /* thread newenv */
652   lua_newtable(L);                          /* thread newenv mt */
653   lua_pushvalue(L, LUA_REGISTRYINDEX);      /* thread newenv mt reg */
654   lua_pushcfunction(L, l_get_from_maestro); /* thread newenv mt reg f */
655   lua_setfield(L, -3, "__index");           /* thread newenv mt reg */
656   lua_pushvalue(L, -2);                     /* thread newenv mt reg mt */
657   lua_setmetatable(L, -2);                  /* thread newenv mt reg */
658   lua_pop(L, 1);                            /* thread newenv mt */
659   lua_setmetatable(L, -2);                  /* thread newenv */
660   lua_setfenv(L, -2);                       /* thread */
661   lua_pop(L, 1);                            /* -- */
662
663   /* create the table of known tables from maestro */
664   lua_pushstring(L, "simgrid.maestro_tables");
665                                             /* "simgrid.maestro_tables" */
666   lua_newtable(L);                          /* "simgrid.maestro_tables" maestrotbs */
667   lua_rawset(L, LUA_REGISTRYINDEX);
668                                             /* -- */
669
670   /* opening the standard libs is not necessary as they are
671    * inherited like any global values */
672   /* luaL_openlibs(L); */
673
674   XBT_DEBUG("New state created");
675
676   return L;
677 }