2 Copyright (C) 2001-2008, The Perl Foundation.
7 src/pmc.c - The base vtable calling functions
19 #include "parrot/parrot.h"
22 /* HEADERIZER HFILE: include/parrot/pmc.h */
24 /* HEADERIZER BEGIN: static */
25 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
27 PARROT_WARN_UNUSED_RESULT
28 PARROT_CANNOT_RETURN_NULL
29 static PMC
* create_class_pmc(PARROT_INTERP
, INTVAL type
)
30 __attribute__nonnull__(1);
32 PARROT_WARN_UNUSED_RESULT
33 PARROT_CANNOT_RETURN_NULL
34 static PMC
* get_new_pmc_header(PARROT_INTERP
,
37 __attribute__nonnull__(1);
39 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
40 /* HEADERIZER END: static */
49 =item C<INTVAL PMC_is_null>
51 Tests if the given pmc is null.
59 PMC_is_null(SHIM_INTERP
, NULLOK(const PMC
*pmc
))
62 return pmc
== PMCNULL
|| pmc
== NULL
;
70 =item C<PMC * pmc_new>
72 Creates a new PMC of type C<base_type> (which is an index into the list of PMC
73 types declared in C<vtables> in F<include/parrot/pmc.h>). Once the PMC has been
74 successfully created and its vtable pointer initialized, we call its C<init>
75 method to perform any other necessary initialization.
82 PARROT_CANNOT_RETURN_NULL
83 PARROT_WARN_UNUSED_RESULT
85 pmc_new(PARROT_INTERP
, INTVAL base_type
)
87 PMC
*const classobj
= interp
->vtables
[base_type
]->pmc_class
;
89 if (!PMC_IS_NULL(classobj
) && PObj_is_class_TEST(classobj
))
90 return VTABLE_instantiate(interp
, classobj
, PMCNULL
);
92 PMC
* const pmc
= get_new_pmc_header(interp
, base_type
, 0);
93 VTABLE_init(interp
, pmc
);
100 =item C<PMC* pmc_reuse>
102 Reuse an existing PMC, turning it into an empty PMC of the new type. Any
103 required internal structure will be put in place (such as the extension area)
104 and the PMC will be ready to go. This will throw an exception if the PMC is
105 constant or of a singleton type (such as the environment PMC) or is being
106 turned into a PMC of a singleton type.
113 PARROT_CANNOT_RETURN_NULL
115 pmc_reuse(PARROT_INTERP
, ARGIN(PMC
*pmc
), INTVAL new_type
,
118 INTVAL has_ext
, new_flags
;
121 if (pmc
->vtable
->base_type
== new_type
)
124 new_vtable
= interp
->vtables
[new_type
];
126 /* Singleton/const PMCs/types are not eligible */
128 if ((pmc
->vtable
->flags
| new_vtable
->flags
)
129 & (VTABLE_PMC_IS_SINGLETON
| VTABLE_IS_CONST_FLAG
))
131 /* First, is the destination a singleton? No joy for us there */
132 if (new_vtable
->flags
& VTABLE_PMC_IS_SINGLETON
)
133 real_exception(interp
, NULL
, ALLOCATION_ERROR
,
134 "Parrot VM: Can't turn to a singleton type!\n");
136 /* First, is the destination a constant? No joy for us there */
137 if (new_vtable
->flags
& VTABLE_IS_CONST_FLAG
)
138 real_exception(interp
, NULL
, ALLOCATION_ERROR
,
139 "Parrot VM: Can't turn to a constant type!\n");
141 /* Is the source a singleton? */
142 if (pmc
->vtable
->flags
& VTABLE_PMC_IS_SINGLETON
)
143 real_exception(interp
, NULL
, ALLOCATION_ERROR
,
144 "Parrot VM: Can't modify a singleton\n");
146 /* Is the source constant? */
147 if (pmc
->vtable
->flags
& VTABLE_IS_CONST_FLAG
)
148 real_exception(interp
, NULL
, ALLOCATION_ERROR
,
149 "Parrot VM: Can't modify a constant\n");
152 /* Do we have an extension area? */
153 has_ext
= (PObj_is_PMC_EXT_TEST(pmc
) && pmc
->pmc_ext
);
155 /* Do we need one? */
156 if (new_vtable
->flags
& VTABLE_PMC_NEEDS_EXT
) {
158 /* If we need an ext area, go allocate one */
159 add_pmc_ext(interp
, pmc
);
161 new_flags
= PObj_is_PMC_EXT_FLAG
;
165 Parrot_free_pmc_ext(interp
, pmc
);
167 #if ! PMC_DATA_IN_EXT
168 PMC_data(pmc
) = NULL
;
173 /* we are a PMC + maybe is_PMC_EXT */
174 PObj_flags_SETTO(pmc
, PObj_is_PMC_FLAG
| new_flags
);
176 /* Set the right vtable */
177 pmc
->vtable
= new_vtable
;
179 /* Call the base init for the redone pmc */
180 VTABLE_init(interp
, pmc
);
187 =item C<static PMC* get_new_pmc_header>
189 Gets a new PMC header.
195 PARROT_WARN_UNUSED_RESULT
196 PARROT_CANNOT_RETURN_NULL
198 get_new_pmc_header(PARROT_INTERP
, INTVAL base_type
, UINTVAL flags
)
201 VTABLE
*vtable
= interp
->vtables
[base_type
];
202 UINTVAL vtable_flags
;
204 /* This is usually because you either didn't call init_world early enough,
205 * you added a new PMC class without adding Parrot_(classname)_class_init
206 * to init_world, or you forgot to run 'make realclean' after adding a new
209 PANIC(interp
, "Null vtable used; did you add a new PMC?");
211 vtable_flags
= vtable
->flags
;
213 /* we only have one global Env object, living in the interp */
214 if (vtable_flags
& VTABLE_PMC_IS_SINGLETON
) {
216 * singletons (monadic objects) exist only once, the interface
218 * - get_pointer: return NULL or a pointer to the single instance
219 * - set_pointer: set the only instance once
221 * - singletons are created in the constant pmc pool
223 PMC
*pmc
= (PMC
*)(vtable
->get_pointer
)(interp
, NULL
);
227 pmc
= new_pmc_header(interp
, PObj_constant_FLAG
);
230 pmc
->vtable
= vtable
;
231 pmc
->real_self
= pmc
;
232 VTABLE_set_pointer(interp
, pmc
, pmc
);
238 if (vtable_flags
& VTABLE_IS_CONST_PMC_FLAG
) {
239 flags
|= PObj_constant_FLAG
;
241 else if (vtable_flags
& VTABLE_IS_CONST_FLAG
) {
242 /* put the normal vtable in, so that the pmc can be initialized first
243 * parrot or user code has to set the _ro property then,
244 * to morph the PMC to the const variant
245 * This assumes that a constant PMC enum is one bigger then
250 * XXX not yet we can't assure that all contents in the
251 * const PMC is const too
252 * see e.g. t/pmc/sarray_13.pir
255 flags
|= PObj_constant_FLAG
;
258 vtable
= interp
->vtables
[base_type
];
261 if (vtable_flags
& VTABLE_PMC_NEEDS_EXT
) {
262 flags
|= PObj_is_PMC_EXT_FLAG
;
263 if (vtable_flags
& VTABLE_IS_SHARED_FLAG
)
264 flags
|= PObj_is_PMC_shared_FLAG
;
267 pmc
= new_pmc_header(interp
, flags
);
268 pmc
->vtable
= vtable
;
269 pmc
->real_self
= pmc
;
272 if (Interp_flags_TEST(interp
, PARROT_TRACE_FLAG
)) {
273 /* XXX make a more verbose trace flag */
274 fprintf(stderr
, "\t=> new %p type %d\n", pmc
, (int)base_type
);
284 =item C<PMC * pmc_new_noinit>
286 Creates a new PMC of type C<base_type> (which is an index into the list of PMC
287 types declared in C<vtables> in F<include/parrot/pmc.h>). Unlike C<pmc_new()>,
288 C<pmc_new_noinit()> does not call its C<init> method. This allows separate
289 allocation and initialization for continuations.
296 PARROT_CANNOT_RETURN_NULL
298 pmc_new_noinit(PARROT_INTERP
, INTVAL base_type
)
300 PMC
*const classobj
= interp
->vtables
[base_type
]->pmc_class
;
302 if (!PMC_IS_NULL(classobj
) && PObj_is_class_TEST(classobj
))
303 return VTABLE_instantiate(interp
, classobj
, PMCNULL
);
305 return get_new_pmc_header(interp
, base_type
, 0);
310 =item C<PMC * constant_pmc_new_noinit>
312 Creates a new constant PMC of type C<base_type>.
319 PARROT_CANNOT_RETURN_NULL
321 constant_pmc_new_noinit(PARROT_INTERP
, INTVAL base_type
)
323 return get_new_pmc_header(interp
, base_type
, PObj_constant_FLAG
);
328 =item C<PMC * constant_pmc_new>
330 Creates a new constant PMC of type C<base_type>, the call C<init>.
337 PARROT_CANNOT_RETURN_NULL
339 constant_pmc_new(PARROT_INTERP
, INTVAL base_type
)
341 PMC
* const pmc
= get_new_pmc_header(interp
, base_type
,
343 VTABLE_init(interp
, pmc
);
349 =item C<PMC * pmc_new_init>
351 As C<pmc_new()>, but passes C<init> to the PMC's C<init_pmc()> method.
358 PARROT_CANNOT_RETURN_NULL
360 pmc_new_init(PARROT_INTERP
, INTVAL base_type
, ARGOUT(PMC
*init
))
362 PMC
*const classobj
= interp
->vtables
[base_type
]->pmc_class
;
364 if (!PMC_IS_NULL(classobj
) && PObj_is_class_TEST(classobj
))
365 return VTABLE_instantiate(interp
, classobj
, init
);
367 PMC
* const pmc
= get_new_pmc_header(interp
, base_type
, 0);
368 VTABLE_init_pmc(interp
, pmc
, init
);
375 =item C<PMC * constant_pmc_new_init>
377 As C<constant_pmc_new>, but passes C<init> to the PMC's C<init_pmc> method.
384 PARROT_CANNOT_RETURN_NULL
386 constant_pmc_new_init(PARROT_INTERP
, INTVAL base_type
, ARGIN_NULLOK(PMC
*init
))
388 PMC
* const pmc
= get_new_pmc_header(interp
, base_type
, PObj_constant_FLAG
);
389 VTABLE_init_pmc(interp
, pmc
, init
);
395 =item C<INTVAL pmc_register>
397 This segment handles PMC registration and such.
405 pmc_register(PARROT_INTERP
, ARGIN(STRING
*name
))
409 /* If they're looking to register an existing class, return that
410 class' type number */
411 INTVAL type
= pmc_type(interp
, name
);
413 if (type
> enum_type_undef
)
416 if (type
< enum_type_undef
)
417 real_exception(interp
, NULL
, 1,
418 "undefined type already exists - can't register PMC");
420 classname_hash
= interp
->class_hash
;
421 type
= interp
->n_vtable_max
++;
423 /* Have we overflowed the table? */
424 if (type
>= interp
->n_vtable_alloced
)
425 parrot_realloc_vtables(interp
);
427 /* set entry in name->type hash */
428 VTABLE_set_integer_keyed_str(interp
, classname_hash
, name
, type
);
435 =item C<INTVAL pmc_type>
437 Returns the PMC type for C<name>.
444 PARROT_WARN_UNUSED_RESULT
446 pmc_type(PARROT_INTERP
, ARGIN_NULLOK(STRING
*name
))
449 return enum_type_undef
;
451 PMC
* const classname_hash
= interp
->class_hash
;
453 (PMC
*)VTABLE_get_pointer_keyed_str(interp
, classname_hash
, name
);
455 /* nested namespace with same name */
456 if (item
->vtable
->base_type
== enum_class_NameSpace
)
457 return enum_type_undef
;
459 if (!PMC_IS_NULL(item
))
460 return VTABLE_get_integer(interp
, item
);
462 return Parrot_get_datatype_enum(interp
, name
);
468 =item C<INTVAL pmc_type_p>
470 Returns the PMC type for C<name>.
478 pmc_type_p(PARROT_INTERP
, ARGIN(PMC
*name
))
480 PMC
* const classname_hash
= interp
->class_hash
;
482 (PMC
*)VTABLE_get_pointer_keyed(interp
, classname_hash
, name
);
484 if (!PMC_IS_NULL(item
))
485 return VTABLE_get_integer(interp
, item
);
492 =item C<static PMC* create_class_pmc>
494 Create a class object for this interpreter. Takes an interpreter
495 name and type as arguments. Returns a pointer to the class object.
501 PARROT_WARN_UNUSED_RESULT
502 PARROT_CANNOT_RETURN_NULL
504 create_class_pmc(PARROT_INTERP
, INTVAL type
)
507 * class interface - a PMC is its own class
508 * put an instance of this PMC into class
510 * create a constant PMC
512 PMC
* const _class
= get_new_pmc_header(interp
, type
,
515 /* If we are a second thread, we may get the same object as the
516 * original because we have a singleton. Just set the singleton to
517 * be our class object, but don't mess with its vtable.
519 if ((interp
->vtables
[type
]->flags
& VTABLE_PMC_IS_SINGLETON
)
520 && (_class
== _class
->vtable
->pmc_class
)) {
521 interp
->vtables
[type
]->pmc_class
= _class
;
524 if (PObj_is_PMC_EXT_TEST(_class
))
525 Parrot_free_pmc_ext(interp
, _class
);
527 DOD_flag_CLEAR(is_special_PMC
, _class
);
529 PMC_pmc_val(_class
) = (PMC
*)0xdeadbeef;
530 PMC_struct_val(_class
) = (void *)0xdeadbeef;
532 PObj_is_PMC_shared_CLEAR(_class
);
534 interp
->vtables
[type
]->pmc_class
= _class
;
542 =item C<void Parrot_create_mro>
544 Create the MRO (method resolution order) array for this type.
552 Parrot_create_mro(PARROT_INTERP
, INTVAL type
)
557 VTABLE
*vtable
= interp
->vtables
[type
];
558 PMC
*mro_list
= vtable
->mro
;
560 /* multithreaded: has already mro */
561 if (mro_list
&& mro_list
->vtable
->base_type
!= enum_class_ResizableStringArray
)
564 mro
= pmc_new(interp
, enum_class_ResizablePMCArray
);
567 if (vtable
->ro_variant_vtable
)
568 vtable
->ro_variant_vtable
->mro
= mro
;
570 count
= VTABLE_elements(interp
, mro_list
);
572 for (i
= 0; i
< count
; ++i
) {
573 STRING
*class_name
= VTABLE_get_string_keyed_int(interp
, mro_list
, i
);
574 INTVAL parent_type
= pmc_type(interp
, class_name
);
576 /* abstract classes don't have a vtable */
580 vtable
= interp
->vtables
[parent_type
];
582 if (!vtable
->_namespace
) {
583 /* need a namespace Hash, anchor at parent, name it */
584 PMC
* const ns
= pmc_new(interp
,
585 Parrot_get_ctx_HLL_type(interp
, enum_class_NameSpace
));
586 vtable
->_namespace
= ns
;
588 /* anchor at parent, aka current_namespace, that is 'parrot' */
589 VTABLE_set_pmc_keyed_str(interp
,
590 CONTEXT(interp
)->current_namespace
, class_name
, ns
);
593 _class
= vtable
->pmc_class
;
595 _class
= create_class_pmc(interp
, parent_type
);
597 VTABLE_push_pmc(interp
, mro
, _class
);
605 =head2 DOD registry interface
609 =item C<void dod_register_pmc>
611 Registers the PMC with the interpreter's DOD registery.
619 dod_register_pmc(PARROT_INTERP
, ARGIN(PMC
* pmc
))
621 /* Better not trigger a DOD run with a potentially unanchored PMC */
622 Parrot_block_GC_mark(interp
);
624 PARROT_ASSERT(interp
->DOD_registry
);
626 VTABLE_set_pmc_keyed(interp
, interp
->DOD_registry
, pmc
, PMCNULL
);
627 Parrot_unblock_GC_mark(interp
);
632 =item C<void dod_unregister_pmc>
634 Unregisters the PMC from the interpreter's DOD registry.
641 dod_unregister_pmc(PARROT_INTERP
, ARGIN(PMC
* pmc
))
643 PARROT_ASSERT(interp
->DOD_registry
);
645 VTABLE_delete_keyed(interp
, interp
->DOD_registry
, pmc
);
656 F<include/parrot/vtable.h>.
658 C<5.1.0.14.2.20011008152120.02158148@pop.sidhe.org>
659 (http://www.nntp.perl.org/group/perl.perl6.internals/5516).
663 Initial version by Simon on 2001.10.20.
672 * c-file-style: "parrot"
674 * vim: expandtab shiftwidth=4: