Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
11e97f285712a490d277ca3a9f143294a614d68d
[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   XBT_DEBUG("%sData copied", sglua_get_spaces(indent));
238
239   sglua_stack_dump("src after copying a value (should be ... value): ", src);
240   sglua_stack_dump("dst after copying a value (should be ... value): ", dst);
241 }
242
243 /**
244  * @brief Copies the nil value on the top of src to the top of dst.
245  * @param src source state
246  * @param dst destination state
247  */
248 static void sglua_copy_nil(lua_State* src, lua_State* dst) {
249   lua_pushnil(dst);
250 }
251
252 /**
253  * @brief Copies the number value on the top of src to the top of dst.
254  * @param src source state
255  * @param dst destination state
256  */
257 static void sglua_copy_number(lua_State* src, lua_State* dst) {
258   lua_pushnumber(dst, lua_tonumber(src, -1));
259 }
260
261 /**
262  * @brief Copies the boolean value on the top of src to the top of dst.
263  * @param src source state
264  * @param dst destination state
265  */
266 static void sglua_copy_boolean(lua_State* src, lua_State* dst) {
267   lua_pushboolean(dst, lua_toboolean(src, -1));
268 }
269
270 /**
271  * @brief Copies the string value on the top of src to the top of dst.
272  * @param src source state
273  * @param dst destination state
274  */
275 static void sglua_copy_string(lua_State* src, lua_State* dst) {
276
277   /* no worries about memory: lua_pushstring makes a copy */
278   lua_pushstring(dst, lua_tostring(src, -1));
279 }
280
281 /**
282  * @brief Copies the table value on top of src to the top of dst.
283  *
284  * A deep copy of the table is made. If the table has a metatable, the
285  * metatable is also copied.
286  * If the table comes from maestro and is already known by the destination
287  * state, it is not copied again.
288  *
289  * @param src source state
290  * @param dst destination state
291  */
292 static void sglua_copy_table(lua_State* src, lua_State* dst) {
293
294                                   /* src: ... table
295                                      dst: ... */
296   int indent = lua_gettop(dst) * 6  + 2;
297
298   /* get from maestro the pointer that identifies this table */
299   void* table_ptr = sglua_get_maestro_table_ptr(src, -1);
300   int known_by_maestro = (table_ptr != NULL);
301
302   if (!known_by_maestro) {
303     /* the table didn't come from maestro: nevermind, use the pointer of src */
304     table_ptr = (void*) lua_topointer(src, -1);
305     XBT_DEBUG("%sMaestro does not know this table",
306         sglua_get_spaces(indent));
307   }
308
309   if (sglua_is_maestro(src)) {
310     /* register the table in maestro itself */
311     XBT_DEBUG("%sKeeping track of this table in maestro itself",
312         sglua_get_spaces(indent));
313     sglua_add_maestro_table(src, -1, table_ptr);
314     known_by_maestro = 1;
315     xbt_assert(sglua_get_maestro_table_ptr(src, -1) == table_ptr);
316   }
317
318   /* to avoid infinite recursion, see if this table is already known by dst */
319   sglua_get_table_by_ptr(dst, table_ptr);
320                                   /* dst: ... table/nil */
321   if (!lua_isnil(dst, -1)) {
322     XBT_DEBUG("%sNothing to do: table already known (%p)",
323         sglua_get_spaces(indent), table_ptr);
324                                   /* dst: ... table */
325   }
326   else {
327     XBT_DEBUG("%sFirst visit of this table (%p)", sglua_get_spaces(indent),
328         table_ptr);
329                                   /* dst: ... nil */
330     lua_pop(dst, 1);
331                                   /* dst: ... */
332
333     /* first visit: create the new table in dst */
334     lua_newtable(dst);
335                                   /* dst: ... table */
336
337     /* mark the table as known right now to avoid infinite recursion */
338     sglua_add_maestro_table(dst, -1, table_ptr);
339     /* we may have added a table with a non-maestro pointer, but if it was the
340      * case, we will remove it later */
341     XBT_DEBUG("%sTable marked as known", sglua_get_spaces(indent));
342     xbt_assert(sglua_get_maestro_table_ptr(dst, -1) == table_ptr);
343
344     sglua_stack_dump("dst after marking the table as known (should be ... table): ", dst);
345
346     /* copy the metatable if any */
347     int has_meta_table = lua_getmetatable(src, -1);
348                                   /* src: ... table mt? */
349     if (has_meta_table) {
350       XBT_DEBUG("%sCopying the metatable", sglua_get_spaces(indent));
351                                   /* src: ... table mt */
352       sglua_copy_table(src, dst);
353                                   /* dst: ... table mt */
354       lua_pop(src, 1);
355                                   /* src: ... table */
356       lua_setmetatable(dst, -2);
357                                   /* dst: ... table */
358     }
359     else {
360                                   /* src: ... table */
361       XBT_DEBUG("%sNo metatable", sglua_get_spaces(indent));
362     }
363
364     sglua_stack_dump("src before traversing the table (should be ... table): ", src);
365     sglua_stack_dump("dst before traversing the table (should be ... table): ", dst);
366
367     /* traverse the table of src and copy each element */
368     lua_pushnil(src);
369                                   /* src: ... table nil */
370     while (lua_next(src, -2) != 0) {
371                                   /* src: ... table key value */
372
373       XBT_DEBUG("%sCopying table element %s", sglua_get_spaces(indent),
374           sglua_keyvalue_tostring(src, -2, -1));
375
376       sglua_stack_dump("src before copying table element (should be ... table key value): ", src);
377       sglua_stack_dump("dst before copying table element (should be ... table): ", dst);
378
379       /* copy the key */
380       lua_pushvalue(src, -2);
381                                   /* src: ... table key value key */
382       indent += 2;
383       XBT_DEBUG("%sCopying the key part of the table element",
384           sglua_get_spaces(indent));
385       sglua_move_value(src, dst);
386                                   /* src: ... table key value
387                                      dst: ... table key */
388       XBT_DEBUG("%sCopied the key part of the table element",
389           sglua_get_spaces(indent));
390
391       /* copy the value */
392       XBT_DEBUG("%sCopying the value part of the table element",
393           sglua_get_spaces(indent));
394       sglua_move_value(src, dst);
395                                   /* src: ... table key
396                                      dst: ... table key value */
397       XBT_DEBUG("%sCopied the value part of the table element",
398           sglua_get_spaces(indent));
399       indent -= 2;
400
401       /* set the table element */
402       lua_settable(dst, -3);
403                                   /* dst: ... table */
404
405       /* the key stays on top of src for next iteration */
406       sglua_stack_dump("src before next iteration (should be ... table key): ", src);
407       sglua_stack_dump("dst before next iteration (should be ... table): ", dst);
408
409       XBT_DEBUG("%sTable element copied", sglua_get_spaces(indent));
410     }
411     XBT_DEBUG("%sFinished traversing the table", sglua_get_spaces(indent));
412   }
413
414   if (!known_by_maestro) {
415     /* actually,it was not a maestro table: forget the pointer */
416     sglua_remove_maestro_table(dst, -1, table_ptr);
417   }
418 }
419
420 /**
421  * @brief Copies the function on the top of src to the top of dst.
422  *
423  * It can be a Lua function or a C function.
424  * Copying upvalues is not implemented yet.
425  *
426  * @param src source state
427  * @param dst destination state
428  */
429 static void sglua_copy_function(lua_State* src, lua_State* dst) {
430
431   if (lua_iscfunction(src, -1)) {
432     /* it's a C function */
433
434     XBT_DEBUG("It's a C function");
435     sglua_stack_dump("src before copying upvalues: ", src);
436
437     /* get the function pointer */
438     int function_index = lua_gettop(src);
439     lua_CFunction f = lua_tocfunction(src, function_index);
440
441     /* copy the upvalues */
442     int i = 0;
443     const char* upvalue_name = NULL;
444     do {
445       i++;
446       upvalue_name = lua_getupvalue(src, function_index, i);
447
448       if (upvalue_name != NULL) {
449         XBT_DEBUG("Upvalue %s", upvalue_name);
450         sglua_move_value(src, dst);
451       }
452     } while (upvalue_name != NULL);
453
454     sglua_stack_dump("src before copying pointer: ", src);
455
456     /* set the function */
457     lua_pushcclosure(dst, f, i - 1);
458     XBT_DEBUG("Function pointer copied");
459   }
460   else {
461     /* it's a Lua function: dump it from src */
462
463     s_sglua_buffer_t buffer;
464     buffer.capacity = 128; /* an empty function uses 77 bytes */
465     buffer.size = 0;
466     buffer.data = xbt_new(char, buffer.capacity);
467
468     /* copy the binary chunk from src into a buffer */
469     _XBT_GNUC_UNUSED int error = lua_dump(src, sglua_memory_writer, &buffer);
470     xbt_assert(!error, "Failed to dump the function from the source state: error %d",
471         error);
472     XBT_DEBUG("Fonction dumped: %zu bytes", buffer.size);
473
474     /*
475     fwrite(buffer.data, buffer.size, buffer.size, stderr);
476     fprintf(stderr, "\n");
477     */
478
479     /* load the chunk into dst */
480     error = luaL_loadbuffer(dst, buffer.data, buffer.size, "(dumped function)");
481     xbt_assert(!error, "Failed to load the function into the destination state: %s",
482         lua_tostring(dst, -1));
483   }
484 }
485
486 /**
487  * @brief Copies the light userdata on the top of src to the top of dst.
488  * @param src source state
489  * @param dst destination state
490  */
491 static void sglua_copy_lightuserdata(lua_State* src, lua_State* dst) {
492   lua_pushlightuserdata(dst, lua_touserdata(src, -1));
493 }
494
495 /**
496  * @brief Copies the full userdata on the top of src to the top of dst.
497  *
498  * If the userdata has a metatable, the metatable is also copied.
499  *
500  * @param src source state
501  * @param dst destination state
502  */
503 static void sglua_copy_userdata(lua_State* src, lua_State* dst) {
504
505   int indent = lua_gettop(dst) * 6  + 2;
506
507   /* copy the data */
508                                   /* src: ... udata
509                                      dst: ... */
510   size_t size = lua_objlen(src, -1);
511   void* src_block = lua_touserdata(src, -1);
512   void* dst_block = lua_newuserdata(dst, size);
513                                   /* dst: ... udata */
514   memcpy(dst_block, src_block, size);
515
516   /* copy the metatable if any */
517   int has_meta_table = lua_getmetatable(src, -1);
518                                   /* src: ... udata mt? */
519   if (has_meta_table) {
520     XBT_DEBUG("%sCopying metatable of userdata (%p)",
521         sglua_get_spaces(indent), lua_topointer(src, -1));
522                                   /* src: ... udata mt */
523     sglua_copy_table(src, dst);
524                                   /* src: ... udata mt
525                                      dst: ... udata mt */
526     lua_pop(src, 1);
527                                   /* src: ... udata */
528     lua_setmetatable(dst, -2);
529                                   /* dst: ... udata */
530
531     XBT_DEBUG("%sMetatable of userdata copied", sglua_get_spaces(indent));
532   }
533   else {
534     XBT_DEBUG("%sNo metatable for this userdata",
535         sglua_get_spaces(indent));
536                                   /* src: ... udata */
537   }
538 }
539
540 /**
541  * @brief This operation is not supported (yet?) so it just pushes nil.
542  *
543  * @param src source state
544  * @param dst destination state
545  */
546 static void sglua_copy_thread(lua_State* src, lua_State* dst) {
547
548   XBT_WARN("Copying a thread from another state is not implemented (yet?).");
549   lua_pushnil(dst);
550 }
551
552 /**
553  * @brief Copies a global value or a registry value from the maestro state.
554  *
555  * The state L must have been created by sglua_clone_maestro_state().
556  * This function is meant to be an __index metamethod.
557  * Consequently, it assumes that the stack has two elements:
558  * a table (either the environment or the registry of L) and the string key of
559  * a value that does not exist yet in this table. It copies the corresponding
560  * value from maestro and pushes it on the stack of L.
561  * If the value does not exist in maestro state either, nil is pushed.
562  *
563  * TODO: make this function thread safe. If the simulation runs in parallel,
564  * several simulated processes may trigger this __index metamethod at the same
565  * time and get globals from maestro.
566  *
567  * @param L the current state
568  * @return number of return values pushed (always 1)
569  */
570 static int l_get_from_maestro(lua_State *L) {
571
572   /* check the arguments */
573   luaL_checktype(L, 1, LUA_TTABLE);
574   const char* key = luaL_checkstring(L, 2);
575                                   /* L:      table key */
576   XBT_DEBUG("__index of '%s' begins", key);
577
578   /* want a global or a registry value? */
579   int pseudo_index;
580   if (lua_equal(L, 1, LUA_REGISTRYINDEX)) {
581     /* registry */
582     pseudo_index = LUA_REGISTRYINDEX;
583     XBT_DEBUG("Will get the value from the registry of maestro");
584   }
585   else {
586     /* global */
587     pseudo_index = LUA_GLOBALSINDEX;
588     XBT_DEBUG("Will get the value from the globals of maestro");
589   }
590
591   /* get the father */
592   lua_State* maestro = sglua_get_maestro();
593
594                                   /* L:      table key */
595
596   /* get the value from maestro */
597   lua_getfield(maestro, pseudo_index, key);
598                                   /* maestro: ... value */
599
600   /* push the value onto the stack of L */
601   sglua_move_value(maestro, L);
602                                   /* maestro: ...
603                                      L:      table key value */
604
605   /* prepare the return value of __index */
606   lua_pushvalue(L, -1);
607                                   /* L:      table key value value */
608   lua_insert(L, 1);
609                                   /* L:      value table key value */
610
611   /* save the copied value in the table for subsequent accesses */
612   lua_settable(L, -3);
613                                   /* L:      value table */
614   lua_settop(L, 1);
615                                   /* L:      value */
616
617   XBT_DEBUG("__index of '%s' returns %s", key, sglua_tostring(L, -1));
618
619   return 1;
620 }
621
622 /**
623  * @brief Creates a new Lua state and get its environment from the maestro
624  * state.
625  *
626  * The state created is independent from maestro and has its own copies of
627  * global and registry values.
628  * However, the global and registry values are not copied right now from
629  * the original state; they are copied only the first time they are accessed.
630  * This behavior saves time and memory, and is okay for Simgrid's needs.
631  *
632  * TODO: if the simulation runs in parallel, copy everything right now?
633  *
634  * @return the state created
635  */
636 lua_State* sglua_clone_maestro(void) {
637
638   /* create the new state */
639   lua_State *L = luaL_newstate();
640
641   /* set its environment and its registry:
642    * - create a table newenv
643    * - create a metatable mt
644    * - set mt.__index = a function that copies the global from the father state
645    * - set mt as the metatable of the registry
646    * - set mt as the metatable of newenv
647    * - set newenv as the environment of the new state
648    */
649   lua_pushthread(L);                        /* thread */
650   lua_newtable(L);                          /* thread newenv */
651   lua_newtable(L);                          /* thread newenv mt */
652   lua_pushvalue(L, LUA_REGISTRYINDEX);      /* thread newenv mt reg */
653   lua_pushcfunction(L, l_get_from_maestro); /* thread newenv mt reg f */
654   lua_setfield(L, -3, "__index");           /* thread newenv mt reg */
655   lua_pushvalue(L, -2);                     /* thread newenv mt reg mt */
656   lua_setmetatable(L, -2);                  /* thread newenv mt reg */
657   lua_pop(L, 1);                            /* thread newenv mt */
658   lua_setmetatable(L, -2);                  /* thread newenv */
659   lua_setfenv(L, -2);                       /* thread */
660   lua_pop(L, 1);                            /* -- */
661
662   /* create the table of known tables from maestro */
663   lua_pushstring(L, "simgrid.maestro_tables");
664                                             /* "simgrid.maestro_tables" */
665   lua_newtable(L);                          /* "simgrid.maestro_tables" maestrotbs */
666   lua_rawset(L, LUA_REGISTRYINDEX);
667                                             /* -- */
668
669   /* opening the standard libs is not necessary as they are
670    * inherited like any global values */
671   /* luaL_openlibs(L); */
672
673   XBT_DEBUG("New state created");
674
675   return L;
676 }