Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Fix errors caught by java -Xcheck:jni.
[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  *
425  * @param src source state
426  * @param dst destination state
427  */
428 static void sglua_copy_function(lua_State* src, lua_State* dst) {
429
430   if (lua_iscfunction(src, -1)) {
431     /* it's a C function */
432
433     XBT_DEBUG("It's a C function");
434     sglua_stack_dump("src before copying upvalues: ", src);
435
436     /* get the function pointer */
437     int function_index = lua_gettop(src);
438     lua_CFunction f = lua_tocfunction(src, function_index);
439
440     /* copy the upvalues */
441     int i = 0;
442     const char* upvalue_name = NULL;
443     do {
444       i++;
445       upvalue_name = lua_getupvalue(src, function_index, i);
446
447       if (upvalue_name != NULL) {
448         XBT_DEBUG("Upvalue %s", upvalue_name);
449         sglua_move_value(src, dst);
450       }
451     } while (upvalue_name != NULL);
452
453     sglua_stack_dump("src before copying pointer: ", src);
454
455     /* set the function */
456     lua_pushcclosure(dst, f, i - 1);
457     XBT_DEBUG("Function pointer copied");
458   }
459   else {
460     /* it's a Lua function: dump it from src */
461
462     s_sglua_buffer_t buffer;
463     buffer.capacity = 128; /* an empty function uses 77 bytes */
464     buffer.size = 0;
465     buffer.data = xbt_new(char, buffer.capacity);
466
467     /* copy the binary chunk from src into a buffer */
468     _XBT_GNUC_UNUSED int error = lua_dump(src, sglua_memory_writer, &buffer);
469     xbt_assert(!error, "Failed to dump the function from the source state: error %d",
470         error);
471     XBT_DEBUG("Fonction dumped: %zu bytes", buffer.size);
472
473     /*
474     fwrite(buffer.data, buffer.size, buffer.size, stderr);
475     fprintf(stderr, "\n");
476     */
477
478     /* load the chunk into dst */
479     error = luaL_loadbuffer(dst, buffer.data, buffer.size, "(dumped function)");
480     xbt_assert(!error, "Failed to load the function into the destination state: %s",
481         lua_tostring(dst, -1));
482   }
483 }
484
485 /**
486  * @brief Copies the light userdata on the top of src to the top of dst.
487  * @param src source state
488  * @param dst destination state
489  */
490 static void sglua_copy_lightuserdata(lua_State* src, lua_State* dst) {
491   lua_pushlightuserdata(dst, lua_touserdata(src, -1));
492 }
493
494 /**
495  * @brief Copies the full userdata on the top of src to the top of dst.
496  *
497  * If the userdata has a metatable, the metatable is also copied.
498  *
499  * @param src source state
500  * @param dst destination state
501  */
502 static void sglua_copy_userdata(lua_State* src, lua_State* dst) {
503
504   int indent = lua_gettop(dst) * 6  + 2;
505
506   /* copy the data */
507                                   /* src: ... udata
508                                      dst: ... */
509   size_t size = lua_objlen(src, -1);
510   void* src_block = lua_touserdata(src, -1);
511   void* dst_block = lua_newuserdata(dst, size);
512                                   /* dst: ... udata */
513   memcpy(dst_block, src_block, size);
514
515   /* copy the metatable if any */
516   int has_meta_table = lua_getmetatable(src, -1);
517                                   /* src: ... udata mt? */
518   if (has_meta_table) {
519     XBT_DEBUG("%sCopying metatable of userdata (%p)",
520         sglua_get_spaces(indent), lua_topointer(src, -1));
521                                   /* src: ... udata mt */
522     sglua_copy_table(src, dst);
523                                   /* src: ... udata mt
524                                      dst: ... udata mt */
525     lua_pop(src, 1);
526                                   /* src: ... udata */
527     lua_setmetatable(dst, -2);
528                                   /* dst: ... udata */
529
530     XBT_DEBUG("%sMetatable of userdata copied", sglua_get_spaces(indent));
531   }
532   else {
533     XBT_DEBUG("%sNo metatable for this userdata",
534         sglua_get_spaces(indent));
535                                   /* src: ... udata */
536   }
537 }
538
539 /**
540  * @brief This operation is not supported (yet?) so it just pushes nil.
541  *
542  * @param src source state
543  * @param dst destination state
544  */
545 static void sglua_copy_thread(lua_State* src, lua_State* dst) {
546
547   XBT_WARN("Copying a thread from another state is not implemented (yet?).");
548   lua_pushnil(dst);
549 }
550
551 /**
552  * @brief Copies a global value or a registry value from the maestro state.
553  *
554  * The state L must have been created by sglua_clone_maestro_state().
555  * This function is meant to be an __index metamethod.
556  * Consequently, it assumes that the stack has two elements:
557  * a table (either the environment or the registry of L) and the string key of
558  * a value that does not exist yet in this table. It copies the corresponding
559  * value from maestro and pushes it on the stack of L.
560  * If the value does not exist in maestro state either, nil is pushed.
561  *
562  * TODO: make this function thread safe. If the simulation runs in parallel,
563  * several simulated processes may trigger this __index metamethod at the same
564  * time and get globals from maestro.
565  *
566  * @param L the current state
567  * @return number of return values pushed (always 1)
568  */
569 static int l_get_from_maestro(lua_State *L) {
570
571   /* check the arguments */
572   luaL_checktype(L, 1, LUA_TTABLE);
573   const char* key = luaL_checkstring(L, 2);
574                                   /* L:      table key */
575   XBT_DEBUG("__index of '%s' begins", key);
576
577   /* want a global or a registry value? */
578   int pseudo_index;
579   if (lua_equal(L, 1, LUA_REGISTRYINDEX)) {
580     /* registry */
581     pseudo_index = LUA_REGISTRYINDEX;
582     XBT_DEBUG("Will get the value from the registry of maestro");
583   }
584   else {
585     /* global */
586     pseudo_index = LUA_GLOBALSINDEX;
587     XBT_DEBUG("Will get the value from the globals of maestro");
588   }
589
590   /* get the father */
591   lua_State* maestro = sglua_get_maestro();
592
593                                   /* L:      table key */
594
595   /* get the value from maestro */
596   lua_getfield(maestro, pseudo_index, key);
597                                   /* maestro: ... value */
598
599   /* push the value onto the stack of L */
600   sglua_move_value(maestro, L);
601                                   /* maestro: ...
602                                      L:      table key value */
603
604   /* prepare the return value of __index */
605   lua_pushvalue(L, -1);
606                                   /* L:      table key value value */
607   lua_insert(L, 1);
608                                   /* L:      value table key value */
609
610   /* save the copied value in the table for subsequent accesses */
611   lua_settable(L, -3);
612                                   /* L:      value table */
613   lua_settop(L, 1);
614                                   /* L:      value */
615
616   XBT_DEBUG("__index of '%s' returns %s", key, sglua_tostring(L, -1));
617
618   return 1;
619 }
620
621 /**
622  * @brief Creates a new Lua state and get its environment from the maestro
623  * state.
624  *
625  * The state created is independent from maestro and has its own copies of
626  * global and registry values.
627  * However, the global and registry values are not copied right now from
628  * the original state; they are copied only the first time they are accessed.
629  * This behavior saves time and memory, and is okay for Simgrid's needs.
630  *
631  * TODO: if the simulation runs in parallel, copy everything right now?
632  *
633  * @return the state created
634  */
635 lua_State* sglua_clone_maestro(void) {
636
637   /* create the new state */
638   lua_State *L = luaL_newstate();
639
640   /* set its environment and its registry:
641    * - create a table newenv
642    * - create a metatable mt
643    * - set mt.__index = a function that copies the global from the father state
644    * - set mt as the metatable of the registry
645    * - set mt as the metatable of newenv
646    * - set newenv as the environment of the new state
647    */
648   lua_pushthread(L);                        /* thread */
649   lua_newtable(L);                          /* thread newenv */
650   lua_newtable(L);                          /* thread newenv mt */
651   lua_pushvalue(L, LUA_REGISTRYINDEX);      /* thread newenv mt reg */
652   lua_pushcfunction(L, l_get_from_maestro); /* thread newenv mt reg f */
653   lua_setfield(L, -3, "__index");           /* thread newenv mt reg */
654   lua_pushvalue(L, -2);                     /* thread newenv mt reg mt */
655   lua_setmetatable(L, -2);                  /* thread newenv mt reg */
656   lua_pop(L, 1);                            /* thread newenv mt */
657   lua_setmetatable(L, -2);                  /* thread newenv */
658   lua_setfenv(L, -2);                       /* thread */
659   lua_pop(L, 1);                            /* -- */
660
661   /* create the table of known tables from maestro */
662   lua_pushstring(L, "simgrid.maestro_tables");
663                                             /* "simgrid.maestro_tables" */
664   lua_newtable(L);                          /* "simgrid.maestro_tables" maestrotbs */
665   lua_rawset(L, LUA_REGISTRYINDEX);
666                                             /* -- */
667
668   /* opening the standard libs is not necessary as they are
669    * inherited like any global values */
670   /* luaL_openlibs(L); */
671
672   XBT_DEBUG("New state created");
673
674   return L;
675 }