2 Copyright (C) 2001-2010, Parrot Foundation.
7 src/pmc/eval.pmc - Dynamic code evaluation
11 C<Eval> extends C<Sub> to provide C<eval>-like dynamic code
12 evaluation and execution.
22 #include "pmc/pmc_sub.h"
24 /* HEADERIZER HFILE: none */
25 /* HEADERIZER BEGIN: static */
26 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
28 static void clear_fixups(PARROT_INTERP,
29 ARGIN(const Parrot_Sub_attributes *sub_data))
30 __attribute__nonnull__(1)
31 __attribute__nonnull__(2);
33 PARROT_WARN_UNUSED_RESULT
34 PARROT_CAN_RETURN_NULL
35 static PMC* get_sub(PARROT_INTERP, ARGIN(PMC *self), int idx)
36 __attribute__nonnull__(1)
37 __attribute__nonnull__(2);
39 static void mark_subs(PARROT_INTERP, ARGIN(PMC *self))
40 __attribute__nonnull__(1)
41 __attribute__nonnull__(2);
43 #define ASSERT_ARGS_clear_fixups __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
44 PARROT_ASSERT_ARG(interp) \
45 , PARROT_ASSERT_ARG(sub_data))
46 #define ASSERT_ARGS_get_sub __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
47 PARROT_ASSERT_ARG(interp) \
48 , PARROT_ASSERT_ARG(self))
49 #define ASSERT_ARGS_mark_subs __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
50 PARROT_ASSERT_ARG(interp) \
51 , PARROT_ASSERT_ARG(self))
52 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
53 /* HEADERIZER END: static */
56 clear_fixups(PARROT_INTERP, ARGIN(const Parrot_Sub_attributes *sub_data))
58 ASSERT_ARGS(clear_fixups)
61 PackFile_ByteCode * const seg = sub_data->seg;
62 PackFile_FixupTable *ft;
63 PackFile_ConstTable *ct;
72 ct = seg->const_table;
76 for (i = 0; i < ft->fixup_count; ++i) {
77 PackFile_FixupEntry * const e = ft->fixups + i;
79 if (e->type == enum_fixup_sub) {
80 opcode_t ci = e->offset;
82 ct->constants[ci]->u.key = NULL;
88 PARROT_WARN_UNUSED_RESULT
89 PARROT_CAN_RETURN_NULL
91 get_sub(PARROT_INTERP, ARGIN(PMC *self), int idx)
96 Parrot_Sub_attributes *sub;
97 PackFile_ByteCode *seg;
98 PackFile_FixupTable *ft;
99 PackFile_ConstTable *ct;
101 PMC_get_sub(interp, self, sub);
111 ct = seg->const_table;
115 for (i = n = 0; i < ft->fixup_count; ++i) {
116 const PackFile_FixupEntry * const e = ft->fixups + i;
118 if (e->type == enum_fixup_sub) {
119 opcode_t ci = e->offset;
122 return ct->constants[ci]->u.key;
130 mark_subs(PARROT_INTERP, ARGIN(PMC *self))
132 ASSERT_ARGS(mark_subs)
134 Parrot_Sub_attributes *sub;
135 PackFile_ByteCode *seg;
136 PackFile_FixupTable *ft;
137 PackFile_ConstTable *ct;
140 PMC_get_sub(interp, self, sub);
150 ct = seg->const_table;
154 for (i = 0; i < ft->fixup_count; ++i) {
155 const PackFile_FixupEntry * const e = ft->fixups + i;
157 if (e->type == enum_fixup_sub) {
158 opcode_t ci = e->offset;
159 PMC *sub = ct->constants[ci]->u.key;
161 Parrot_gc_mark_PMC_alive(interp, sub);
166 pmclass Eval extends Sub auto_attrs {
169 Parrot_Sub_attributes *sub_data;
172 PMC_get_sub(INTERP, SELF, sub_data);
173 sub_data->seg = NULL;
174 PObj_custom_mark_destroy_SETALL(SELF);
178 =item C<opcode_t *invoke(void *next)>
180 Invokes the first subroutine in the eval code.
186 VTABLE opcode_t *invoke(void *next) {
187 PMC *sub = SELF.get_pmc_keyed_int(0);
188 return VTABLE_invoke(INTERP, sub, next);
191 VTABLE void destroy() {
193 * If the compiled code contained any .sub (or .pcc.sub)
194 * subroutines, these subs got installed in the globals
195 * during compiling this bytecode segment.
197 * These globals still exist, calling them will segfault
198 * as the segment is destroyed now.
201 * Walk the fixups, locate globals and nullify the Sub PMC
202 * This probably needs a pointer into the globals.
204 * OTOH - if the global exists - this eval pmc ought
205 * to be alive and destroy isn't called.
207 PackFile_Segment *seg;
208 PackFile_ByteCode *cur_cs;
209 Parrot_Sub_attributes *sub_data;
211 PMC_get_sub(INTERP, SELF, sub_data);
218 clear_fixups(INTERP, sub_data);
219 cur_cs = sub_data->seg;
226 /* XXX Quick and dirty fix for TT #995 */
227 if ((struct PackFile *)cur_cs == INTERP->initial_pf
228 || cur_cs == INTERP->code) {
233 /* TT #1315 create PF API, move it there */
234 seg = (PackFile_Segment *)cur_cs->const_table;
236 PackFile_Segment_destroy(INTERP, seg);
237 cur_cs->const_table = NULL;
240 seg = (PackFile_Segment *)cur_cs->debugs;
242 PackFile_Segment_destroy(INTERP, seg);
243 cur_cs->debugs = NULL;
246 seg = (PackFile_Segment *)cur_cs->fixups;
248 PackFile_Segment_destroy(INTERP, seg);
249 cur_cs->fixups = NULL;
252 seg = (PackFile_Segment *)cur_cs;
254 PackFile_Segment_destroy(INTERP, seg);
256 sub_data->seg = NULL;
263 mark_subs(INTERP, SELF);
268 =item C<STRING *get_string>
270 Get a STRING representing the bytecode for this code segment, suitable
271 for writing to disc and later loading via C<load_bytecode>.
277 VTABLE STRING *get_string() {
278 Parrot_Sub_attributes *sub;
279 PackFile *pf = PackFile_new(INTERP, 0);
280 PackFile_ByteCode *seg;
282 size_t size, aligned_size;
284 PMC_get_sub(INTERP, SELF, sub);
287 PackFile_add_segment(INTERP, &pf->directory, (PackFile_Segment *)seg);
289 if (seg->const_table)
290 PackFile_add_segment(INTERP, &pf->directory,
291 (PackFile_Segment *)seg->const_table);
294 PackFile_add_segment(INTERP, &pf->directory,
295 (PackFile_Segment *)seg->debugs);
298 PackFile_add_segment(INTERP, &pf->directory,
299 (PackFile_Segment *)seg->fixups);
301 size = PackFile_pack_size(INTERP, pf) * sizeof (opcode_t);
304 * work around packfile bug:
305 * as far as I have checked it the story is:
306 * - PackFile_pack_size() assumes 16 byte alignment but doesn't
307 * have the actual start of the code (packed)
308 * - PackFile_pack() uses 16 bye alignment relative to the start
309 * of the code, which isn't really the same
310 * Therefore align code at 16, which should give the desired
313 aligned_size = size + 15;
314 res = Parrot_str_new_noinit(INTERP, enum_stringrep_one,
316 res->strlen = res->bufused = size;
318 if ((size_t)(res->strstart) & 0xf) {
319 char *adr = res->strstart;
320 adr += 16 - ((size_t)adr & 0xf);
324 /* We block GC while doing the packing, since GC run during a pack
325 has been observed to cause problems. There may be a Better Fix.
326 See http://rt.perl.org/rt3/Ticket/Display.html?id=40410
327 for example of the problem (note on line that
328 segfaults, it is *cursor that is pointing to dealloced memory). */
329 Parrot_block_GC_mark(INTERP);
330 PackFile_pack(INTERP, pf, (opcode_t *)res->strstart);
331 Parrot_unblock_GC_mark(INTERP);
333 /* now remove all segments from directory again and destroy
335 pf->directory.num_segments = 0;
336 PackFile_destroy(INTERP, pf);
343 =item C<PMC *get_pmc_keyed_int(INTVAL key)>
345 Returns the Sub PMC of the element at index C<key> or PMCNULL.
351 VTABLE PMC *get_pmc_keyed_int(INTVAL key) {
352 return get_sub(INTERP, SELF, key);
357 =item C<void freeze(PMC *info)>
359 Archives the evaled code
361 =item C<void thaw(PMC *info)>
369 VTABLE void freeze(PMC *info) {
370 STRING *packed = SELF.get_string();
371 VTABLE_push_string(INTERP, info, packed);
376 VTABLE void thaw(PMC *info) {
377 STRING *packed = VTABLE_shift_string(INTERP, info);
379 PackFile_Segment *seg;
380 Parrot_Sub_attributes *sub;
384 pf = PackFile_new(INTERP, 0);
386 if (!PackFile_unpack(INTERP, pf, (opcode_t *)packed->strstart,
388 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_EXTERNAL_ERROR,
389 "couldn't unpack packfile");
391 do_sub_pragmas(INTERP, pf->cur_cs, PBC_PBC, SELF);
393 for (i = 0; i < pf->directory.num_segments; ++i) {
394 seg = pf->directory.segments[i];
396 if (seg->type == PF_BYTEC_SEG) {
397 PMC_get_sub(INTERP, SELF, sub);
398 sub->seg = (PackFile_ByteCode *)seg;
403 pf->directory.num_segments = 0;
406 * TT #1292 this isn't ok - it seems that the packfile
407 * gets attached to INTERP->code and is
408 * destroyed again during interpreter destruction
410 /* PackFile_destroy(INTERP, pf); */
413 VTABLE INTVAL elements() {
415 Parrot_Sub_attributes *sub;
416 PackFile_ByteCode *seg;
417 PackFile_FixupTable *ft;
419 PMC_get_sub(INTERP, SELF, sub);
429 for (i = n = 0; i < ft->fixup_count; ++i) {
430 const PackFile_FixupEntry * const e = ft->fixups + i;
432 if (e->type == enum_fixup_sub)
446 Initial version by leo 2003/01/16.
454 * c-file-style: "parrot"
456 * vim: expandtab shiftwidth=4: