Obtain abstract forms from a module loaded using code:load_binary/3

Previous Topic Next Topic
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view

Obtain abstract forms from a module loaded using code:load_binary/3

Edmond Begumisa
Hello all,

Is there a way to obtain the abstract forms back from a module loaded with  
code:load_binary/3? Are the abstract forms not kept somewhere for the  

To elaborate, I'm doing some metaprogramming where a module evolves over  
time after being initially loaded from disk. For a simplified contrived  
example [1], say I have a module...


     get(foo) -> 1.

dynamic.beam is compiled with debug_info and distributed as part of my OTP  
app. Then, at runtime, I have code I call once in a while which  
conceptually resembles the following...

     update_get(Incr) when is_integer(Incr) ->
         {_,PrevObjCode,_} = code:get_get_object_code(dynamic),
                                % ^^^ NOPE! Gets original obj code from disk
         {ok,{_,[{abstract_code,{_,Forms0}}]}} =
             beam_lib:chunks(PrevObjCode, [abstract_code]),
         Forms1 =
             merl code to replace get return literal in Forms0
             with the value incremented by Incr
         {ok,_,UpdObjCode} = compile:forms(Forms1, [binary,debug_info]),
                                                        % ^^^ What happens to  
these after loading?
         {module,_} = code:load_binary(dynamic, code:which(dynamic),  

update_get/1 won't work when called multiple times because PrevObjCode  
always contains 1 as the return value of dynamic:get/1.

One solution is to keep UpdObjCode somewhere as state and use that the  
next time update_get/1 is called instead of calling  
code:get_object_code/1. However, I can't do that because my use case is  
such that I can't really keep track of what's supposed to be the current  
code. update_get/1 needs to only use knowledge from whatever the current  
version is of the module it's updating.

The solution I'm currently using is to store the Forms1 in the updated  
module by compiling it in when calling compile:forms/2. I'm using a module  
attribute for this. I'm trying to see if there's an alternative to abusing  
module attributes to store code.

- Edmond -

[1] My actual use case is code that performs infrequent write transactions  
on frequently read data stored in the constant pool so that it's and  
accessible from thousands of processes in a concurrency-friendly manner.

Using Opera's mail client: http://www.opera.com/mail/
erlang-questions mailing list
[hidden email]