[t][cage] Remove PGE-dependence from t/op/inf_nan.t since it is part of 'make coretest'
[parrot.git] / src / pmc.c
blob1808351cb765a9db8d650efda3ca574200510824
1 /*
2 Copyright (C) 2001-2009, Parrot Foundation.
3 $Id$
5 =head1 NAME
7 src/pmc.c
9 =head1 DESCRIPTION
11 The base vtable calling functions
13 =head1 FUNCTIONS
15 =over 4
17 =cut
21 #include "parrot/parrot.h"
22 #include "pmc.str"
23 #include "pmc/pmc_class.h"
24 #include "pmc/pmc_context.h"
26 /* HEADERIZER HFILE: include/parrot/pmc.h */
28 /* HEADERIZER BEGIN: static */
29 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
31 static void check_pmc_reuse_flags(PARROT_INTERP,
32 UINTVAL srcflags,
33 UINTVAL destflags)
34 __attribute__nonnull__(1);
36 PARROT_WARN_UNUSED_RESULT
37 PARROT_CANNOT_RETURN_NULL
38 static PMC * create_class_pmc(PARROT_INTERP, INTVAL type)
39 __attribute__nonnull__(1);
41 PARROT_WARN_UNUSED_RESULT
42 PARROT_CANNOT_RETURN_NULL
43 static PMC * get_new_pmc_header(PARROT_INTERP,
44 INTVAL base_type,
45 UINTVAL flags)
46 __attribute__nonnull__(1);
48 PARROT_CANNOT_RETURN_NULL
49 static PMC* pmc_reuse_no_init(PARROT_INTERP,
50 ARGIN(PMC *pmc),
51 INTVAL new_type,
52 SHIM(UINTVAL flags))
53 __attribute__nonnull__(1)
54 __attribute__nonnull__(2);
56 #define ASSERT_ARGS_check_pmc_reuse_flags __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
57 PARROT_ASSERT_ARG(interp))
58 #define ASSERT_ARGS_create_class_pmc __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
59 PARROT_ASSERT_ARG(interp))
60 #define ASSERT_ARGS_get_new_pmc_header __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
61 PARROT_ASSERT_ARG(interp))
62 #define ASSERT_ARGS_pmc_reuse_no_init __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
63 PARROT_ASSERT_ARG(interp) \
64 , PARROT_ASSERT_ARG(pmc))
65 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
66 /* HEADERIZER END: static */
69 #if PARROT_CATCH_NULL
70 PMC * PMCNULL;
71 #endif
75 =item C<INTVAL PMC_is_null(PARROT_INTERP, const PMC *pmc)>
77 Tests if the given pmc is null.
79 =cut
83 PARROT_EXPORT
84 INTVAL
85 PMC_is_null(SHIM_INTERP, ARGIN_NULLOK(const PMC *pmc))
87 ASSERT_ARGS(PMC_is_null)
88 #if PARROT_CATCH_NULL
89 return pmc == PMCNULL || pmc == NULL;
90 #else
91 return pmc == NULL;
92 #endif
97 =item C<void Parrot_pmc_destroy(PARROT_INTERP, PMC *pmc)>
99 Destroy a PMC. Call his destroy vtable function if needed, and deallocate
100 his attributes if they are automatically allocated.
102 For internal usage of the PMC handling functions and garbage collection
103 subsystem.
105 =cut
109 PARROT_EXPORT
110 void
111 Parrot_pmc_destroy(PARROT_INTERP, ARGMOD(PMC *pmc))
113 ASSERT_ARGS(Parrot_pmc_destroy)
115 if (PObj_custom_destroy_TEST(pmc)) {
116 VTABLE_destroy(interp, pmc);
117 /* Prevent repeated calls. */
118 PObj_custom_destroy_CLEAR(pmc);
121 PObj_custom_mark_CLEAR(pmc);
122 PObj_live_CLEAR(pmc);
124 if (PObj_is_PMC_shared_TEST(pmc) && PMC_sync(pmc))
125 Parrot_gc_free_pmc_sync(interp, pmc);
127 if (pmc->vtable->attr_size)
128 Parrot_gc_free_pmc_attributes(interp, pmc);
129 else
130 PMC_data(pmc) = NULL;
132 #ifndef NDEBUG
134 pmc->vtable = (VTABLE *)0xdeadbeef;
136 #endif
142 =item C<PMC * pmc_new(PARROT_INTERP, INTVAL base_type)>
144 Creates a new PMC of type C<base_type> (which is an index into the list of PMC
145 types declared in C<vtables> in F<include/parrot/pmc.h>). Once the PMC has been
146 successfully created and its vtable pointer initialized, we call its C<init>
147 method to perform any other necessary initialization.
149 =cut
153 PARROT_EXPORT
154 PARROT_CANNOT_RETURN_NULL
155 PARROT_WARN_UNUSED_RESULT
156 PMC *
157 pmc_new(PARROT_INTERP, INTVAL base_type)
159 ASSERT_ARGS(pmc_new)
160 PARROT_ASSERT(interp->vtables[base_type]);
162 PMC *const classobj = interp->vtables[base_type]->pmc_class;
164 if (!PMC_IS_NULL(classobj) && PObj_is_class_TEST(classobj))
165 return VTABLE_instantiate(interp, classobj, PMCNULL);
166 else {
167 PMC * const pmc = get_new_pmc_header(interp, base_type, 0);
168 VTABLE_init(interp, pmc);
169 return pmc;
176 =item C<PMC * pmc_reuse(PARROT_INTERP, PMC *pmc, INTVAL new_type, UINTVAL
177 flags)>
179 Reuse an existing PMC, turning it into an empty PMC of the new type. Any
180 required internal structure will be put in place (such as the extension area)
181 and the PMC will be ready to go.
183 Cannot currently handle converting a non-Object PMC into an Object. Use
184 C<pmc_reuse_by_class> for that.
187 =cut
191 PARROT_EXPORT
192 PARROT_CANNOT_RETURN_NULL
193 PARROT_IGNORABLE_RESULT
194 PMC *
195 pmc_reuse(PARROT_INTERP, ARGIN(PMC *pmc), INTVAL new_type,
196 UINTVAL flags)
198 ASSERT_ARGS(pmc_reuse)
199 pmc = pmc_reuse_no_init(interp, pmc, new_type, flags);
201 /* Call the base init for the redone pmc. Warning, this should not
202 be called on Object PMCs. */
203 VTABLE_init(interp, pmc);
205 return pmc;
210 =item C<PMC * pmc_reuse_init(PARROT_INTERP, PMC *pmc, INTVAL new_type, PMC
211 *init, UINTVAL flags)>
213 Reuse an existing PMC, turning it into an PMC of the new type. Any
214 required internal structure will be put in place (such as the extension area)
215 and the PMC will be inited.
217 Cannot currently handle converting a non-Object PMC into an Object. Use
218 C<pmc_reuse_by_class> for that.
221 =cut
225 PARROT_EXPORT
226 PARROT_CANNOT_RETURN_NULL
227 PARROT_IGNORABLE_RESULT
228 PMC *
229 pmc_reuse_init(PARROT_INTERP, ARGIN(PMC *pmc), INTVAL new_type, ARGIN(PMC *init),
230 UINTVAL flags)
232 ASSERT_ARGS(pmc_reuse_init)
233 pmc = pmc_reuse_no_init(interp, pmc, new_type, flags);
235 /* Call the base init for the redone pmc. Warning, this should not
236 be called on Object PMCs. */
237 VTABLE_init_pmc(interp, pmc, init);
239 return pmc;
244 =item C<static PMC* pmc_reuse_no_init(PARROT_INTERP, PMC *pmc, INTVAL new_type,
245 UINTVAL flags)>
247 Prepare pmc for reuse. Do all scuffolding except initing.
249 =cut
252 PARROT_CANNOT_RETURN_NULL
253 static PMC*
254 pmc_reuse_no_init(PARROT_INTERP, ARGIN(PMC *pmc), INTVAL new_type,
255 SHIM(UINTVAL flags)) {
257 ASSERT_ARGS(pmc_reuse_no_init)
258 VTABLE *new_vtable;
259 INTVAL has_ext, new_flags = 0;
261 if (pmc->vtable->base_type == new_type)
262 return pmc;
264 new_vtable = interp->vtables[new_type];
266 /* Singleton/const PMCs/types are not eligible */
267 check_pmc_reuse_flags(interp, pmc->vtable->flags, new_vtable->flags);
269 /* Free the old PMC resources. */
270 Parrot_pmc_destroy(interp, pmc);
272 PObj_flags_SETTO(pmc, PObj_is_PMC_FLAG | new_flags);
274 /* Set the right vtable */
275 pmc->vtable = new_vtable;
277 if (new_vtable->attr_size)
278 Parrot_gc_allocate_pmc_attributes(interp, pmc);
280 else
281 PMC_data(pmc) = NULL;
283 return pmc;
288 =item C<PMC * pmc_reuse_by_class(PARROT_INTERP, PMC *pmc, PMC *class_, UINTVAL
289 flags)>
291 Reuse an existing PMC. Convert it to the type specified by the given Class
292 PMC. At the moment, this means we can only use this function to reuse PMCs
293 into types with Classes (not built-in PMCs). Use C<pmc_reuse> if you need
294 to convert to a built-in PMC type.
296 =cut
300 PARROT_EXPORT
301 PARROT_CANNOT_RETURN_NULL
302 PARROT_IGNORABLE_RESULT
303 PMC *
304 pmc_reuse_by_class(PARROT_INTERP, ARGMOD(PMC *pmc), ARGIN(PMC *class_),
305 UINTVAL flags)
307 ASSERT_ARGS(pmc_reuse_by_class)
308 const INTVAL new_type = PARROT_CLASS(class_)->id;
309 VTABLE * const new_vtable = interp->vtables[new_type];
310 INTVAL new_flags = flags;
312 if (pmc->vtable->base_type == new_type)
313 return pmc;
315 /* Singleton/const PMCs/types are not eligible */
316 check_pmc_reuse_flags(interp, pmc->vtable->flags, new_vtable->flags);
318 Parrot_pmc_destroy(interp, pmc);
320 PObj_flags_SETTO(pmc, PObj_is_PMC_FLAG | new_flags);
322 /* Set the right vtable */
323 pmc->vtable = new_vtable;
325 if (new_vtable->attr_size)
326 Parrot_gc_allocate_pmc_attributes(interp, pmc);
327 else
328 PMC_data(pmc) = NULL;
330 return pmc;
336 =item C<static void check_pmc_reuse_flags(PARROT_INTERP, UINTVAL srcflags,
337 UINTVAL destflags)>
339 We're converting one PMC type to another, either in C<pmc_reuse> or
340 C<pmc_reuse_by_class>. Check to make sure that neither the existing PMC
341 or the intended target PMC type are singletons or constants. We throw an
342 exception if we are attempting an illegal operation.
344 =cut
348 static void
349 check_pmc_reuse_flags(PARROT_INTERP, UINTVAL srcflags, UINTVAL destflags)
351 ASSERT_ARGS(check_pmc_reuse_flags)
352 if ((srcflags | destflags) & (VTABLE_PMC_IS_SINGLETON | VTABLE_IS_CONST_FLAG))
354 /* First, is the destination a singleton? No joy for us there */
355 if (destflags & VTABLE_PMC_IS_SINGLETON)
356 Parrot_ex_throw_from_c_args(interp, NULL,
357 EXCEPTION_ALLOCATION_ERROR,
358 "Parrot VM: Can't turn to a singleton type!\n");
360 /* Is the destination a constant? No joy for us there */
361 if (destflags & VTABLE_IS_CONST_FLAG)
362 Parrot_ex_throw_from_c_args(interp, NULL,
363 EXCEPTION_ALLOCATION_ERROR,
364 "Parrot VM: Can't turn to a constant type!\n");
366 /* Is the source a singleton? */
367 if (srcflags & VTABLE_PMC_IS_SINGLETON)
368 Parrot_ex_throw_from_c_args(interp, NULL,
369 EXCEPTION_ALLOCATION_ERROR,
370 "Parrot VM: Can't modify a singleton\n");
372 /* Is the source constant? */
373 if (srcflags & VTABLE_IS_CONST_FLAG)
374 Parrot_ex_throw_from_c_args(interp, NULL,
375 EXCEPTION_ALLOCATION_ERROR,
376 "Parrot VM: Can't modify a constant\n");
382 =item C<static PMC * get_new_pmc_header(PARROT_INTERP, INTVAL base_type, UINTVAL
383 flags)>
385 Gets a new PMC header of the given integer type. Initialize the pmc if
386 necessary. In the case of singleton PMC types, get the existing singleton
387 instead of allocating a new one.
389 =cut
393 PARROT_WARN_UNUSED_RESULT
394 PARROT_CANNOT_RETURN_NULL
395 static PMC *
396 get_new_pmc_header(PARROT_INTERP, INTVAL base_type, UINTVAL flags)
398 ASSERT_ARGS(get_new_pmc_header)
399 PMC *pmc;
400 VTABLE *vtable = interp->vtables[base_type];
401 UINTVAL vtable_flags;
403 /* This is usually because you either didn't call init_world early enough,
404 * you added a new PMC class without adding Parrot_(classname)_class_init
405 * to init_world, or you forgot to run 'make realclean' after adding a new
406 * PMC class. */
407 if (!vtable)
408 PANIC(interp, "Null vtable used; did you add a new PMC?");
410 vtable_flags = vtable->flags;
412 /* we only have one global Env object, living in the interp */
413 if (vtable_flags & VTABLE_PMC_IS_SINGLETON) {
415 * singletons (monadic objects) exist only once
416 * the interface * with the class is:
417 * - get_pointer: return NULL or a pointer to the single instance
418 * - set_pointer: set the only instance once
420 * - singletons are created in the constant pmc pool
422 PMC *pmc = (PMC *)(vtable->get_pointer)(interp, NULL);
424 /* LOCK */
425 if (!pmc) {
426 pmc = Parrot_gc_new_pmc_header(interp, PObj_constant_FLAG);
427 PARROT_ASSERT(pmc);
429 pmc->vtable = vtable;
430 VTABLE_set_pointer(interp, pmc, pmc);
433 return pmc;
436 if (vtable_flags & VTABLE_IS_CONST_PMC_FLAG)
437 flags |= PObj_constant_FLAG;
438 else if (vtable_flags & VTABLE_IS_CONST_FLAG) {
439 /* put the normal vtable in, so that the pmc can be initialized first
440 * parrot or user code has to set the _ro property then,
441 * to morph the PMC to the const variant
442 * This assumes that a constant PMC enum is one bigger then
443 * the normal one.
447 * XXX not yet we can't assure that all contents in the
448 * const PMC is const too
449 * see e.g. t/pmc/sarray_13.pir
451 #if 0
452 flags |= PObj_constant_FLAG;
453 #endif
454 --base_type;
455 vtable = interp->vtables[base_type];
458 if (vtable_flags & VTABLE_IS_SHARED_FLAG)
459 flags |= PObj_is_PMC_shared_FLAG;
461 pmc = Parrot_gc_new_pmc_header(interp, flags);
462 pmc->vtable = vtable;
464 if (vtable->attr_size)
465 Parrot_gc_allocate_pmc_attributes(interp, pmc);
467 #if GC_VERBOSE
468 if (Interp_flags_TEST(interp, PARROT_TRACE_FLAG)) {
469 /* XXX make a more verbose trace flag */
470 fprintf(stderr, "\t=> new %p type %d\n", pmc, (int)base_type);
472 #endif
474 return pmc;
480 =item C<PMC * pmc_new_noinit(PARROT_INTERP, INTVAL base_type)>
482 Creates a new PMC of type C<base_type> (which is an index into the list of PMC
483 types declared in C<vtables> in F<include/parrot/pmc.h>). Unlike C<pmc_new()>,
484 C<pmc_new_noinit()> does not call its C<init> method. This allows separate
485 allocation and initialization for continuations.
487 =cut
491 PARROT_EXPORT
492 PARROT_CANNOT_RETURN_NULL
493 PMC *
494 pmc_new_noinit(PARROT_INTERP, INTVAL base_type)
496 ASSERT_ARGS(pmc_new_noinit)
497 PMC *const classobj = interp->vtables[base_type]->pmc_class;
499 if (!PMC_IS_NULL(classobj) && PObj_is_class_TEST(classobj))
500 return VTABLE_instantiate(interp, classobj, PMCNULL);
502 return get_new_pmc_header(interp, base_type, 0);
508 =item C<PMC * constant_pmc_new_noinit(PARROT_INTERP, INTVAL base_type)>
510 Creates a new constant PMC of type C<base_type>.
512 =cut
516 PARROT_EXPORT
517 PARROT_CANNOT_RETURN_NULL
518 PMC *
519 constant_pmc_new_noinit(PARROT_INTERP, INTVAL base_type)
521 ASSERT_ARGS(constant_pmc_new_noinit)
522 return get_new_pmc_header(interp, base_type, PObj_constant_FLAG);
528 =item C<PMC * constant_pmc_new(PARROT_INTERP, INTVAL base_type)>
530 Creates a new constant PMC of type C<base_type>, then calls its C<init>.
532 =cut
536 PARROT_EXPORT
537 PARROT_CANNOT_RETURN_NULL
538 PMC *
539 constant_pmc_new(PARROT_INTERP, INTVAL base_type)
541 ASSERT_ARGS(constant_pmc_new)
542 PMC * const pmc = get_new_pmc_header(interp, base_type, PObj_constant_FLAG);
543 VTABLE_init(interp, pmc);
544 return pmc;
550 =item C<PMC * pmc_new_init(PARROT_INTERP, INTVAL base_type, PMC *init)>
552 As C<pmc_new()>, but passes C<init> to the PMC's C<init_pmc()> vtable entry.
554 =cut
558 PARROT_EXPORT
559 PARROT_CANNOT_RETURN_NULL
560 PMC *
561 pmc_new_init(PARROT_INTERP, INTVAL base_type, ARGOUT(PMC *init))
563 ASSERT_ARGS(pmc_new_init)
564 PMC *const classobj = interp->vtables[base_type]->pmc_class;
566 if (!PMC_IS_NULL(classobj) && PObj_is_class_TEST(classobj))
567 return VTABLE_instantiate(interp, classobj, init);
568 else {
569 PMC * const pmc = get_new_pmc_header(interp, base_type, 0);
570 VTABLE_init_pmc(interp, pmc, init);
571 return pmc;
578 =item C<PMC * constant_pmc_new_init(PARROT_INTERP, INTVAL base_type, PMC *init)>
580 As C<constant_pmc_new>, but passes C<init> to the PMC's C<init_pmc> vtable
581 entry.
583 =cut
587 PARROT_EXPORT
588 PARROT_CANNOT_RETURN_NULL
589 PMC *
590 constant_pmc_new_init(PARROT_INTERP, INTVAL base_type, ARGIN_NULLOK(PMC *init))
592 ASSERT_ARGS(constant_pmc_new_init)
593 PMC * const pmc = get_new_pmc_header(interp, base_type, PObj_constant_FLAG);
594 VTABLE_init_pmc(interp, pmc, init);
595 return pmc;
601 =item C<PMC * temporary_pmc_new(PARROT_INTERP, INTVAL base_type)>
603 Creates a new temporary PMC of type C<base_type>, then call C<init>. Cannot
604 be used to create PMC Objects which have been defined from PIR.
606 B<You> are responsible for freeing this PMC when it goes out of scope with
607 C<free_temporary_pmc()>. B<Do not> store this PMC in any other PMCs, or
608 allow it to be stored. B<Do not> store any regular PMC in this PMC, or
609 allow the storage of any regular PMC in this PMC. Temporary PMCs do not
610 participate in garbage collection, and mixing them with PMCs that are
611 garbage-collected will cause bugs.
613 If you don't know what this means means, or you can't tell if either case
614 will happen as the result of any call you make on or with this PMC,
615 B<DO NOT> use this function, lest you cause weird crashes and memory errors.
616 Use C<pmc_new()> instead.
618 (Why do these functions even exist? Used judiciously, they can reduce GC
619 pressure in hotspots tremendously. If you haven't audited the code carefully
620 -- including profiling and benchmarking -- then use C<pmc_new()> instead, and
621 never B<ever> add C<PARROT_EXPORT> to either function.)
623 =cut
627 PARROT_CANNOT_RETURN_NULL
628 PMC *
629 temporary_pmc_new(PARROT_INTERP, INTVAL base_type)
631 ASSERT_ARGS(temporary_pmc_new)
632 PMC * const pmc = get_new_pmc_header(interp, base_type, PObj_constant_FLAG);
633 VTABLE_init(interp, pmc);
634 return pmc;
640 =item C<void temporary_pmc_free(PARROT_INTERP, PMC *pmc)>
642 Frees a new temporary PMC created by C<temporary_pmc_new()>. Do not call
643 this with any other type of PMC. Do not forget to call this (or you'll leak
644 PMCs). Read and I<understand> the warnings for C<temporary_pmc_new()> before
645 you're tempted to use this.
647 =cut
651 void
652 temporary_pmc_free(PARROT_INTERP, ARGMOD(PMC *pmc))
654 ASSERT_ARGS(temporary_pmc_free)
655 Parrot_gc_free_pmc_header(interp, pmc);
661 =item C<INTVAL get_new_vtable_index(PARROT_INTERP)>
663 Get a new unique identifier number and allocate a new vtable structure for a
664 new PMC type.
666 =cut
670 INTVAL
671 get_new_vtable_index(PARROT_INTERP)
673 ASSERT_ARGS(get_new_vtable_index)
674 const INTVAL type_id = interp->n_vtable_max++;
676 /* Have we overflowed the table? */
677 if (type_id >= interp->n_vtable_alloced)
678 parrot_realloc_vtables(interp);
680 return type_id;
685 =item C<INTVAL pmc_register(PARROT_INTERP, STRING *name)>
687 Registers the name of a new PMC type with Parrot, returning the INTVAL
688 representing that type.
690 =cut
694 PARROT_EXPORT
695 INTVAL
696 pmc_register(PARROT_INTERP, ARGIN(STRING *name))
698 ASSERT_ARGS(pmc_register)
699 /* If they're looking to register an existing class, return that
700 class' type number */
701 INTVAL type = pmc_type(interp, name);
703 if (type > enum_type_undef)
704 return type;
706 if (type < enum_type_undef)
707 Parrot_ex_throw_from_c_args(interp, NULL, 1,
708 "undefined type already exists - can't register PMC");
710 type = get_new_vtable_index(interp);
712 /* set entry in name->type hash */
713 VTABLE_set_integer_keyed_str(interp, interp->class_hash, name, type);
715 return type;
721 =item C<INTVAL pmc_type(PARROT_INTERP, STRING *name)>
723 Returns the PMC type for C<name>.
725 =cut
729 PARROT_EXPORT
730 PARROT_WARN_UNUSED_RESULT
731 INTVAL
732 pmc_type(PARROT_INTERP, ARGIN_NULLOK(STRING *name))
734 ASSERT_ARGS(pmc_type)
735 if (!name)
736 return enum_type_undef;
737 else {
738 PMC * const classname_hash = interp->class_hash;
739 PMC * const item =
740 (PMC *)VTABLE_get_pointer_keyed_str(interp, classname_hash, name);
742 if (!PMC_IS_NULL(item)) {
743 /* nested namespace with same name */
744 if (item->vtable->base_type == enum_class_NameSpace)
745 return enum_type_undef;
746 else
747 return VTABLE_get_integer(interp, item);
749 else
750 return Parrot_get_datatype_enum(interp, name);
757 =item C<INTVAL pmc_type_p(PARROT_INTERP, PMC *name)>
759 Returns the PMC type for C<name>.
761 =cut
765 PARROT_EXPORT
766 INTVAL
767 pmc_type_p(PARROT_INTERP, ARGIN(PMC *name))
769 ASSERT_ARGS(pmc_type_p)
770 PMC * const classname_hash = interp->class_hash;
771 PMC * item;
773 item = (PMC *)VTABLE_get_pointer_keyed(interp, classname_hash, name);
775 if (!PMC_IS_NULL(item))
776 return VTABLE_get_integer(interp, item);
778 return 0;
784 =item C<static PMC * create_class_pmc(PARROT_INTERP, INTVAL type)>
786 Create a class object for this interpreter. Takes an interpreter name and type
787 as arguments. Returns a pointer to the class object.
789 =cut
793 PARROT_WARN_UNUSED_RESULT
794 PARROT_CANNOT_RETURN_NULL
795 static PMC *
796 create_class_pmc(PARROT_INTERP, INTVAL type)
798 ASSERT_ARGS(create_class_pmc)
800 * class interface - a PMC is its own class
801 * put an instance of this PMC into class
803 * create a constant PMC
805 PMC * const _class = get_new_pmc_header(interp, type,
806 PObj_constant_FLAG);
808 /* If we are a second thread, we may get the same object as the
809 * original because we have a singleton. Just set the singleton to
810 * be our class object, but don't mess with its vtable. */
811 if ((interp->vtables[type]->flags & VTABLE_PMC_IS_SINGLETON)
812 && (_class == _class->vtable->pmc_class))
813 interp->vtables[type]->pmc_class = _class;
814 else {
815 Parrot_gc_free_pmc_sync(interp, _class);
816 gc_flag_CLEAR(is_special_PMC, _class);
817 PObj_is_PMC_shared_CLEAR(_class);
818 interp->vtables[type]->pmc_class = _class;
821 return _class;
827 =item C<void Parrot_create_mro(PARROT_INTERP, INTVAL type)>
829 Create the MRO (method resolution order) array for this type.
831 =cut
835 PARROT_EXPORT
836 void
837 Parrot_create_mro(PARROT_INTERP, INTVAL type)
839 ASSERT_ARGS(Parrot_create_mro)
840 PMC *_class, *mro;
841 VTABLE *vtable = interp->vtables[type];
842 PMC *mro_list = vtable->mro;
843 INTVAL i, count;
845 /* this should never be PMCNULL */
846 PARROT_ASSERT(!PMC_IS_NULL(mro_list));
848 /* multithreaded: has already mro */
849 if (mro_list->vtable->base_type != enum_class_ResizableStringArray)
850 return;
852 mro = pmc_new(interp, enum_class_ResizablePMCArray);
853 vtable->mro = mro;
855 if (vtable->ro_variant_vtable)
856 vtable->ro_variant_vtable->mro = mro;
858 count = VTABLE_elements(interp, mro_list);
860 for (i = 0; i < count; ++i) {
861 STRING *class_name = VTABLE_get_string_keyed_int(interp, mro_list, i);
862 INTVAL parent_type = pmc_type(interp, class_name);
864 /* abstract classes don't have a vtable */
865 if (!parent_type)
866 break;
868 vtable = interp->vtables[parent_type];
870 if (!vtable->_namespace) {
871 /* need a namespace Hash, anchor at parent, name it */
872 PMC * const ns = pmc_new(interp,
873 Parrot_get_ctx_HLL_type(interp, enum_class_NameSpace));
874 vtable->_namespace = ns;
876 /* anchor at parent, aka current_namespace, that is 'parrot' */
877 VTABLE_set_pmc_keyed_str(interp,
878 Parrot_pcc_get_namespace(interp, CURRENT_CONTEXT(interp)), class_name, ns);
881 _class = vtable->pmc_class;
882 if (!_class)
883 _class = create_class_pmc(interp, parent_type);
885 VTABLE_push_pmc(interp, mro, _class);
892 =back
894 =head2 GC registry interface
896 =over 4
898 =item C<void gc_register_pmc(PARROT_INTERP, PMC *pmc)>
900 Registers the PMC with the interpreter's GC registry.
902 =cut
906 PARROT_EXPORT
907 void
908 gc_register_pmc(PARROT_INTERP, ARGIN(PMC *pmc))
910 ASSERT_ARGS(gc_register_pmc)
911 /* Better not trigger a GC run with a potentially unanchored PMC */
912 Parrot_block_GC_mark(interp);
914 PARROT_ASSERT(interp->gc_registry);
916 VTABLE_set_pmc_keyed(interp, interp->gc_registry, pmc, PMCNULL);
917 Parrot_unblock_GC_mark(interp);
923 =item C<void gc_unregister_pmc(PARROT_INTERP, PMC *pmc)>
925 Unregisters the PMC from the interpreter's GC registry.
927 =cut
931 PARROT_EXPORT
932 void
933 gc_unregister_pmc(PARROT_INTERP, ARGIN(PMC *pmc))
935 ASSERT_ARGS(gc_unregister_pmc)
936 PARROT_ASSERT(interp->gc_registry);
938 VTABLE_delete_keyed(interp, interp->gc_registry, pmc);
944 =back
946 =head1 SEE ALSO
948 F<include/parrot/vtable.h>.
950 C<5.1.0.14.2.20011008152120.02158148@pop.sidhe.org>
951 (http://www.nntp.perl.org/group/perl.perl6.internals/5516).
953 =head1 HISTORY
955 Initial version by Simon on 2001.10.20.
957 =cut
963 * Local variables:
964 * c-file-style: "parrot"
965 * End:
966 * vim: expandtab shiftwidth=4: