[t][TT #1119] Convert t/op/bitwise.t to PIR
[parrot.git] / src / pmc.c
blob22ed49fb4c58e617cf7845b0a4f76043c87926e9
1 /*
2 Copyright (C) 2001-2009, Parrot Foundation.
3 $Id$
5 =head1 NAME
7 src/pmc.c - The base vtable calling functions
9 =head1 DESCRIPTION
11 =head2 Functions
13 =over 4
15 =cut
19 #include "parrot/parrot.h"
20 #include "pmc.str"
21 #include "pmc/pmc_class.h"
22 #include "pmc/pmc_context.h"
24 /* HEADERIZER HFILE: include/parrot/pmc.h */
26 /* HEADERIZER BEGIN: static */
27 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
29 static void check_pmc_reuse_flags(PARROT_INTERP,
30 UINTVAL srcflags,
31 UINTVAL destflags)
32 __attribute__nonnull__(1);
34 PARROT_WARN_UNUSED_RESULT
35 PARROT_CANNOT_RETURN_NULL
36 static PMC * create_class_pmc(PARROT_INTERP, INTVAL type)
37 __attribute__nonnull__(1);
39 PARROT_WARN_UNUSED_RESULT
40 PARROT_CANNOT_RETURN_NULL
41 static PMC * get_new_pmc_header(PARROT_INTERP,
42 INTVAL base_type,
43 UINTVAL flags)
44 __attribute__nonnull__(1);
46 PARROT_CANNOT_RETURN_NULL
47 static PMC* pmc_reuse_no_init(PARROT_INTERP,
48 ARGIN(PMC *pmc),
49 INTVAL new_type,
50 SHIM(UINTVAL flags))
51 __attribute__nonnull__(1)
52 __attribute__nonnull__(2);
54 #define ASSERT_ARGS_check_pmc_reuse_flags __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
55 PARROT_ASSERT_ARG(interp))
56 #define ASSERT_ARGS_create_class_pmc __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
57 PARROT_ASSERT_ARG(interp))
58 #define ASSERT_ARGS_get_new_pmc_header __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
59 PARROT_ASSERT_ARG(interp))
60 #define ASSERT_ARGS_pmc_reuse_no_init __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
61 PARROT_ASSERT_ARG(interp) \
62 , PARROT_ASSERT_ARG(pmc))
63 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
64 /* HEADERIZER END: static */
67 #if PARROT_CATCH_NULL
68 PMC * PMCNULL;
69 #endif
73 =item C<INTVAL PMC_is_null(PARROT_INTERP, const PMC *pmc)>
75 Tests if the given pmc is null.
77 =cut
81 PARROT_EXPORT
82 INTVAL
83 PMC_is_null(SHIM_INTERP, ARGIN_NULLOK(const PMC *pmc))
85 ASSERT_ARGS(PMC_is_null)
86 #if PARROT_CATCH_NULL
87 return pmc == PMCNULL || pmc == NULL;
88 #else
89 return pmc == NULL;
90 #endif
95 =item C<void Parrot_pmc_destroy(PARROT_INTERP, PMC *pmc)>
97 Destroy a PMC. Call his destroy vtable function if needed, and deallocate
98 his attributes if they are automatically allocated.
100 For internal usage of the PMC handling functions and garbage collection
101 subsystem.
103 =cut
107 PARROT_EXPORT
108 void
109 Parrot_pmc_destroy(PARROT_INTERP, ARGMOD(PMC *pmc))
111 ASSERT_ARGS(Parrot_pmc_destroy)
113 if (PObj_custom_destroy_TEST(pmc)) {
114 VTABLE_destroy(interp, pmc);
115 /* Prevent repeated calls. */
116 PObj_custom_destroy_CLEAR(pmc);
119 PObj_custom_mark_CLEAR(pmc);
120 PObj_live_CLEAR(pmc);
122 if (PObj_is_PMC_shared_TEST(pmc) && PMC_sync(pmc))
123 Parrot_gc_free_pmc_sync(interp, pmc);
125 if (pmc->vtable->attr_size)
126 Parrot_gc_free_pmc_attributes(interp, pmc);
127 else
128 PMC_data(pmc) = NULL;
130 #ifndef NDEBUG
132 pmc->vtable = (VTABLE *)0xdeadbeef;
134 #endif
140 =item C<PMC * pmc_new(PARROT_INTERP, INTVAL base_type)>
142 Creates a new PMC of type C<base_type> (which is an index into the list of PMC
143 types declared in C<vtables> in F<include/parrot/pmc.h>). Once the PMC has been
144 successfully created and its vtable pointer initialized, we call its C<init>
145 method to perform any other necessary initialization.
147 =cut
151 PARROT_EXPORT
152 PARROT_CANNOT_RETURN_NULL
153 PARROT_WARN_UNUSED_RESULT
154 PMC *
155 pmc_new(PARROT_INTERP, INTVAL base_type)
157 ASSERT_ARGS(pmc_new)
158 PARROT_ASSERT(interp->vtables[base_type]);
160 PMC *const classobj = interp->vtables[base_type]->pmc_class;
162 if (!PMC_IS_NULL(classobj) && PObj_is_class_TEST(classobj))
163 return VTABLE_instantiate(interp, classobj, PMCNULL);
164 else {
165 PMC * const pmc = get_new_pmc_header(interp, base_type, 0);
166 VTABLE_init(interp, pmc);
167 return pmc;
174 =item C<PMC * pmc_reuse(PARROT_INTERP, PMC *pmc, INTVAL new_type, UINTVAL
175 flags)>
177 Reuse an existing PMC, turning it into an empty PMC of the new type. Any
178 required internal structure will be put in place (such as the extension area)
179 and the PMC will be ready to go.
181 Cannot currently handle converting a non-Object PMC into an Object. Use
182 C<pmc_reuse_by_class> for that.
185 =cut
189 PARROT_EXPORT
190 PARROT_CANNOT_RETURN_NULL
191 PARROT_IGNORABLE_RESULT
192 PMC *
193 pmc_reuse(PARROT_INTERP, ARGIN(PMC *pmc), INTVAL new_type,
194 UINTVAL flags)
196 ASSERT_ARGS(pmc_reuse)
197 pmc = pmc_reuse_no_init(interp, pmc, new_type, flags);
199 /* Call the base init for the redone pmc. Warning, this should not
200 be called on Object PMCs. */
201 VTABLE_init(interp, pmc);
203 return pmc;
208 =item C<PMC * pmc_reuse_init(PARROT_INTERP, PMC *pmc, INTVAL new_type, PMC
209 *init, UINTVAL flags)>
211 Reuse an existing PMC, turning it into an PMC of the new type. Any
212 required internal structure will be put in place (such as the extension area)
213 and the PMC will be inited.
215 Cannot currently handle converting a non-Object PMC into an Object. Use
216 C<pmc_reuse_by_class> for that.
219 =cut
223 PARROT_EXPORT
224 PARROT_CANNOT_RETURN_NULL
225 PARROT_IGNORABLE_RESULT
226 PMC *
227 pmc_reuse_init(PARROT_INTERP, ARGIN(PMC *pmc), INTVAL new_type, ARGIN(PMC *init),
228 UINTVAL flags)
230 ASSERT_ARGS(pmc_reuse_init)
231 pmc = pmc_reuse_no_init(interp, pmc, new_type, flags);
233 /* Call the base init for the redone pmc. Warning, this should not
234 be called on Object PMCs. */
235 VTABLE_init_pmc(interp, pmc, init);
237 return pmc;
242 =item C<static PMC* pmc_reuse_no_init(PARROT_INTERP, PMC *pmc, INTVAL new_type,
243 UINTVAL flags)>
245 Prepare pmc for reuse. Do all scuffolding except initing.
247 =cut
250 PARROT_CANNOT_RETURN_NULL
251 static PMC*
252 pmc_reuse_no_init(PARROT_INTERP, ARGIN(PMC *pmc), INTVAL new_type,
253 SHIM(UINTVAL flags)) {
255 ASSERT_ARGS(pmc_reuse_no_init)
256 VTABLE *new_vtable;
257 INTVAL has_ext, new_flags = 0;
259 if (pmc->vtable->base_type == new_type)
260 return pmc;
262 new_vtable = interp->vtables[new_type];
264 /* Singleton/const PMCs/types are not eligible */
265 check_pmc_reuse_flags(interp, pmc->vtable->flags, new_vtable->flags);
267 /* Free the old PMC resources. */
268 Parrot_pmc_destroy(interp, pmc);
270 PObj_flags_SETTO(pmc, PObj_is_PMC_FLAG | new_flags);
272 /* Set the right vtable */
273 pmc->vtable = new_vtable;
275 if (new_vtable->attr_size)
276 Parrot_gc_allocate_pmc_attributes(interp, pmc);
278 else
279 PMC_data(pmc) = NULL;
281 return pmc;
286 =item C<PMC * pmc_reuse_by_class(PARROT_INTERP, PMC *pmc, PMC *class_, UINTVAL
287 flags)>
289 Reuse an existing PMC. Convert it to the type specified by the given Class
290 PMC. At the moment, this means we can only use this function to reuse PMCs
291 into types with Classes (not built-in PMCs). Use C<pmc_reuse> if you need
292 to convert to a built-in PMC type.
294 =cut
298 PARROT_EXPORT
299 PARROT_CANNOT_RETURN_NULL
300 PARROT_IGNORABLE_RESULT
301 PMC *
302 pmc_reuse_by_class(PARROT_INTERP, ARGMOD(PMC *pmc), ARGIN(PMC *class_),
303 UINTVAL flags)
305 ASSERT_ARGS(pmc_reuse_by_class)
306 const INTVAL new_type = PARROT_CLASS(class_)->id;
307 VTABLE * const new_vtable = interp->vtables[new_type];
308 INTVAL new_flags = flags;
310 if (pmc->vtable->base_type == new_type)
311 return pmc;
313 /* Singleton/const PMCs/types are not eligible */
314 check_pmc_reuse_flags(interp, pmc->vtable->flags, new_vtable->flags);
316 Parrot_pmc_destroy(interp, pmc);
318 PObj_flags_SETTO(pmc, PObj_is_PMC_FLAG | new_flags);
320 /* Set the right vtable */
321 pmc->vtable = new_vtable;
323 if (new_vtable->attr_size)
324 Parrot_gc_allocate_pmc_attributes(interp, pmc);
325 else
326 PMC_data(pmc) = NULL;
328 return pmc;
334 =item C<static void check_pmc_reuse_flags(PARROT_INTERP, UINTVAL srcflags,
335 UINTVAL destflags)>
337 We're converting one PMC type to another, either in C<pmc_reuse> or
338 C<pmc_reuse_by_class>. Check to make sure that neither the existing PMC
339 or the intended target PMC type are singletons or constants. We throw an
340 exception if we are attempting an illegal operation.
342 =cut
346 static void
347 check_pmc_reuse_flags(PARROT_INTERP, UINTVAL srcflags, UINTVAL destflags)
349 ASSERT_ARGS(check_pmc_reuse_flags)
350 if ((srcflags | destflags) & (VTABLE_PMC_IS_SINGLETON | VTABLE_IS_CONST_FLAG))
352 /* First, is the destination a singleton? No joy for us there */
353 if (destflags & VTABLE_PMC_IS_SINGLETON)
354 Parrot_ex_throw_from_c_args(interp, NULL,
355 EXCEPTION_ALLOCATION_ERROR,
356 "Parrot VM: Can't turn to a singleton type!\n");
358 /* Is the destination a constant? No joy for us there */
359 if (destflags & VTABLE_IS_CONST_FLAG)
360 Parrot_ex_throw_from_c_args(interp, NULL,
361 EXCEPTION_ALLOCATION_ERROR,
362 "Parrot VM: Can't turn to a constant type!\n");
364 /* Is the source a singleton? */
365 if (srcflags & VTABLE_PMC_IS_SINGLETON)
366 Parrot_ex_throw_from_c_args(interp, NULL,
367 EXCEPTION_ALLOCATION_ERROR,
368 "Parrot VM: Can't modify a singleton\n");
370 /* Is the source constant? */
371 if (srcflags & VTABLE_IS_CONST_FLAG)
372 Parrot_ex_throw_from_c_args(interp, NULL,
373 EXCEPTION_ALLOCATION_ERROR,
374 "Parrot VM: Can't modify a constant\n");
380 =item C<static PMC * get_new_pmc_header(PARROT_INTERP, INTVAL base_type, UINTVAL
381 flags)>
383 Gets a new PMC header of the given integer type. Initialize the pmc if
384 necessary. In the case of singleton PMC types, get the existing singleton
385 instead of allocating a new one.
387 =cut
391 PARROT_WARN_UNUSED_RESULT
392 PARROT_CANNOT_RETURN_NULL
393 static PMC *
394 get_new_pmc_header(PARROT_INTERP, INTVAL base_type, UINTVAL flags)
396 ASSERT_ARGS(get_new_pmc_header)
397 PMC *pmc;
398 VTABLE *vtable = interp->vtables[base_type];
399 UINTVAL vtable_flags;
401 /* This is usually because you either didn't call init_world early enough,
402 * you added a new PMC class without adding Parrot_(classname)_class_init
403 * to init_world, or you forgot to run 'make realclean' after adding a new
404 * PMC class. */
405 if (!vtable)
406 PANIC(interp, "Null vtable used; did you add a new PMC?");
408 vtable_flags = vtable->flags;
410 /* we only have one global Env object, living in the interp */
411 if (vtable_flags & VTABLE_PMC_IS_SINGLETON) {
413 * singletons (monadic objects) exist only once
414 * the interface * with the class is:
415 * - get_pointer: return NULL or a pointer to the single instance
416 * - set_pointer: set the only instance once
418 * - singletons are created in the constant pmc pool
420 PMC *pmc = (PMC *)(vtable->get_pointer)(interp, NULL);
422 /* LOCK */
423 if (!pmc) {
424 pmc = Parrot_gc_new_pmc_header(interp, PObj_constant_FLAG);
425 PARROT_ASSERT(pmc);
427 pmc->vtable = vtable;
428 VTABLE_set_pointer(interp, pmc, pmc);
431 return pmc;
434 if (vtable_flags & VTABLE_IS_CONST_PMC_FLAG)
435 flags |= PObj_constant_FLAG;
436 else if (vtable_flags & VTABLE_IS_CONST_FLAG) {
437 /* put the normal vtable in, so that the pmc can be initialized first
438 * parrot or user code has to set the _ro property then,
439 * to morph the PMC to the const variant
440 * This assumes that a constant PMC enum is one bigger then
441 * the normal one.
445 * XXX not yet we can't assure that all contents in the
446 * const PMC is const too
447 * see e.g. t/pmc/sarray_13.pir
449 #if 0
450 flags |= PObj_constant_FLAG;
451 #endif
452 --base_type;
453 vtable = interp->vtables[base_type];
456 if (vtable_flags & VTABLE_IS_SHARED_FLAG)
457 flags |= PObj_is_PMC_shared_FLAG;
459 pmc = Parrot_gc_new_pmc_header(interp, flags);
460 pmc->vtable = vtable;
462 if (vtable->attr_size)
463 Parrot_gc_allocate_pmc_attributes(interp, pmc);
465 #if GC_VERBOSE
466 if (Interp_flags_TEST(interp, PARROT_TRACE_FLAG)) {
467 /* XXX make a more verbose trace flag */
468 fprintf(stderr, "\t=> new %p type %d\n", pmc, (int)base_type);
470 #endif
472 return pmc;
478 =item C<PMC * pmc_new_noinit(PARROT_INTERP, INTVAL base_type)>
480 Creates a new PMC of type C<base_type> (which is an index into the list of PMC
481 types declared in C<vtables> in F<include/parrot/pmc.h>). Unlike C<pmc_new()>,
482 C<pmc_new_noinit()> does not call its C<init> method. This allows separate
483 allocation and initialization for continuations.
485 =cut
489 PARROT_EXPORT
490 PARROT_CANNOT_RETURN_NULL
491 PMC *
492 pmc_new_noinit(PARROT_INTERP, INTVAL base_type)
494 ASSERT_ARGS(pmc_new_noinit)
495 PMC *const classobj = interp->vtables[base_type]->pmc_class;
497 if (!PMC_IS_NULL(classobj) && PObj_is_class_TEST(classobj))
498 return VTABLE_instantiate(interp, classobj, PMCNULL);
500 return get_new_pmc_header(interp, base_type, 0);
506 =item C<PMC * constant_pmc_new_noinit(PARROT_INTERP, INTVAL base_type)>
508 Creates a new constant PMC of type C<base_type>.
510 =cut
514 PARROT_EXPORT
515 PARROT_CANNOT_RETURN_NULL
516 PMC *
517 constant_pmc_new_noinit(PARROT_INTERP, INTVAL base_type)
519 ASSERT_ARGS(constant_pmc_new_noinit)
520 return get_new_pmc_header(interp, base_type, PObj_constant_FLAG);
526 =item C<PMC * constant_pmc_new(PARROT_INTERP, INTVAL base_type)>
528 Creates a new constant PMC of type C<base_type>, then calls its C<init>.
530 =cut
534 PARROT_EXPORT
535 PARROT_CANNOT_RETURN_NULL
536 PMC *
537 constant_pmc_new(PARROT_INTERP, INTVAL base_type)
539 ASSERT_ARGS(constant_pmc_new)
540 PMC * const pmc = get_new_pmc_header(interp, base_type, PObj_constant_FLAG);
541 VTABLE_init(interp, pmc);
542 return pmc;
548 =item C<PMC * pmc_new_init(PARROT_INTERP, INTVAL base_type, PMC *init)>
550 As C<pmc_new()>, but passes C<init> to the PMC's C<init_pmc()> vtable entry.
552 =cut
556 PARROT_EXPORT
557 PARROT_CANNOT_RETURN_NULL
558 PMC *
559 pmc_new_init(PARROT_INTERP, INTVAL base_type, ARGOUT(PMC *init))
561 ASSERT_ARGS(pmc_new_init)
562 PMC *const classobj = interp->vtables[base_type]->pmc_class;
564 if (!PMC_IS_NULL(classobj) && PObj_is_class_TEST(classobj))
565 return VTABLE_instantiate(interp, classobj, init);
566 else {
567 PMC * const pmc = get_new_pmc_header(interp, base_type, 0);
568 VTABLE_init_pmc(interp, pmc, init);
569 return pmc;
576 =item C<PMC * constant_pmc_new_init(PARROT_INTERP, INTVAL base_type, PMC *init)>
578 As C<constant_pmc_new>, but passes C<init> to the PMC's C<init_pmc> vtable
579 entry.
581 =cut
585 PARROT_EXPORT
586 PARROT_CANNOT_RETURN_NULL
587 PMC *
588 constant_pmc_new_init(PARROT_INTERP, INTVAL base_type, ARGIN_NULLOK(PMC *init))
590 ASSERT_ARGS(constant_pmc_new_init)
591 PMC * const pmc = get_new_pmc_header(interp, base_type, PObj_constant_FLAG);
592 VTABLE_init_pmc(interp, pmc, init);
593 return pmc;
599 =item C<PMC * temporary_pmc_new(PARROT_INTERP, INTVAL base_type)>
601 Creates a new temporary PMC of type C<base_type>, then call C<init>. Cannot
602 be used to create PMC Objects which have been defined from PIR.
604 B<You> are responsible for freeing this PMC when it goes out of scope with
605 C<free_temporary_pmc()>. B<Do not> store this PMC in any other PMCs, or
606 allow it to be stored. B<Do not> store any regular PMC in this PMC, or
607 allow the storage of any regular PMC in this PMC. Temporary PMCs do not
608 participate in garbage collection, and mixing them with PMCs that are
609 garbage-collected will cause bugs.
611 If you don't know what this means means, or you can't tell if either case
612 will happen as the result of any call you make on or with this PMC,
613 B<DO NOT> use this function, lest you cause weird crashes and memory errors.
614 Use C<pmc_new()> instead.
616 (Why do these functions even exist? Used judiciously, they can reduce GC
617 pressure in hotspots tremendously. If you haven't audited the code carefully
618 -- including profiling and benchmarking -- then use C<pmc_new()> instead, and
619 never B<ever> add C<PARROT_EXPORT> to either function.)
621 =cut
625 PARROT_CANNOT_RETURN_NULL
626 PMC *
627 temporary_pmc_new(PARROT_INTERP, INTVAL base_type)
629 ASSERT_ARGS(temporary_pmc_new)
630 PMC * const pmc = get_new_pmc_header(interp, base_type, PObj_constant_FLAG);
631 VTABLE_init(interp, pmc);
632 return pmc;
638 =item C<void temporary_pmc_free(PARROT_INTERP, PMC *pmc)>
640 Frees a new temporary PMC created by C<temporary_pmc_new()>. Do not call
641 this with any other type of PMC. Do not forget to call this (or you'll leak
642 PMCs). Read and I<understand> the warnings for C<temporary_pmc_new()> before
643 you're tempted to use this.
645 =cut
649 void
650 temporary_pmc_free(PARROT_INTERP, ARGMOD(PMC *pmc))
652 ASSERT_ARGS(temporary_pmc_free)
653 Parrot_gc_free_pmc_header(interp, pmc);
659 =item C<INTVAL get_new_vtable_index(PARROT_INTERP)>
661 Get a new unique identifier number and allocate a new vtable structure for a
662 new PMC type.
664 =cut
668 INTVAL
669 get_new_vtable_index(PARROT_INTERP)
671 ASSERT_ARGS(get_new_vtable_index)
672 const INTVAL type_id = interp->n_vtable_max++;
674 /* Have we overflowed the table? */
675 if (type_id >= interp->n_vtable_alloced)
676 parrot_realloc_vtables(interp);
678 return type_id;
683 =item C<INTVAL pmc_register(PARROT_INTERP, STRING *name)>
685 Registers the name of a new PMC type with Parrot, returning the INTVAL
686 representing that type.
688 =cut
692 PARROT_EXPORT
693 INTVAL
694 pmc_register(PARROT_INTERP, ARGIN(STRING *name))
696 ASSERT_ARGS(pmc_register)
697 /* If they're looking to register an existing class, return that
698 class' type number */
699 INTVAL type = pmc_type(interp, name);
701 if (type > enum_type_undef)
702 return type;
704 if (type < enum_type_undef)
705 Parrot_ex_throw_from_c_args(interp, NULL, 1,
706 "undefined type already exists - can't register PMC");
708 type = get_new_vtable_index(interp);
710 /* set entry in name->type hash */
711 VTABLE_set_integer_keyed_str(interp, interp->class_hash, name, type);
713 return type;
719 =item C<INTVAL pmc_type(PARROT_INTERP, STRING *name)>
721 Returns the PMC type for C<name>.
723 =cut
727 PARROT_EXPORT
728 PARROT_WARN_UNUSED_RESULT
729 INTVAL
730 pmc_type(PARROT_INTERP, ARGIN_NULLOK(STRING *name))
732 ASSERT_ARGS(pmc_type)
733 if (!name)
734 return enum_type_undef;
735 else {
736 PMC * const classname_hash = interp->class_hash;
737 PMC * const item =
738 (PMC *)VTABLE_get_pointer_keyed_str(interp, classname_hash, name);
740 if (!PMC_IS_NULL(item)) {
741 /* nested namespace with same name */
742 if (item->vtable->base_type == enum_class_NameSpace)
743 return enum_type_undef;
744 else
745 return VTABLE_get_integer(interp, item);
747 else
748 return Parrot_get_datatype_enum(interp, name);
755 =item C<INTVAL pmc_type_p(PARROT_INTERP, PMC *name)>
757 Returns the PMC type for C<name>.
759 =cut
763 PARROT_EXPORT
764 INTVAL
765 pmc_type_p(PARROT_INTERP, ARGIN(PMC *name))
767 ASSERT_ARGS(pmc_type_p)
768 PMC * const classname_hash = interp->class_hash;
769 PMC * item;
771 item = (PMC *)VTABLE_get_pointer_keyed(interp, classname_hash, name);
773 if (!PMC_IS_NULL(item))
774 return VTABLE_get_integer(interp, item);
776 return 0;
782 =item C<static PMC * create_class_pmc(PARROT_INTERP, INTVAL type)>
784 Create a class object for this interpreter. Takes an interpreter name and type
785 as arguments. Returns a pointer to the class object.
787 =cut
791 PARROT_WARN_UNUSED_RESULT
792 PARROT_CANNOT_RETURN_NULL
793 static PMC *
794 create_class_pmc(PARROT_INTERP, INTVAL type)
796 ASSERT_ARGS(create_class_pmc)
798 * class interface - a PMC is its own class
799 * put an instance of this PMC into class
801 * create a constant PMC
803 PMC * const _class = get_new_pmc_header(interp, type,
804 PObj_constant_FLAG);
806 /* If we are a second thread, we may get the same object as the
807 * original because we have a singleton. Just set the singleton to
808 * be our class object, but don't mess with its vtable. */
809 if ((interp->vtables[type]->flags & VTABLE_PMC_IS_SINGLETON)
810 && (_class == _class->vtable->pmc_class))
811 interp->vtables[type]->pmc_class = _class;
812 else {
813 Parrot_gc_free_pmc_sync(interp, _class);
814 gc_flag_CLEAR(is_special_PMC, _class);
815 PObj_is_PMC_shared_CLEAR(_class);
816 interp->vtables[type]->pmc_class = _class;
819 return _class;
825 =item C<void Parrot_create_mro(PARROT_INTERP, INTVAL type)>
827 Create the MRO (method resolution order) array for this type.
829 =cut
833 PARROT_EXPORT
834 void
835 Parrot_create_mro(PARROT_INTERP, INTVAL type)
837 ASSERT_ARGS(Parrot_create_mro)
838 PMC *_class, *mro;
839 VTABLE *vtable = interp->vtables[type];
840 PMC *mro_list = vtable->mro;
841 INTVAL i, count;
843 /* this should never be PMCNULL */
844 PARROT_ASSERT(!PMC_IS_NULL(mro_list));
846 /* multithreaded: has already mro */
847 if (mro_list->vtable->base_type != enum_class_ResizableStringArray)
848 return;
850 mro = pmc_new(interp, enum_class_ResizablePMCArray);
851 vtable->mro = mro;
853 if (vtable->ro_variant_vtable)
854 vtable->ro_variant_vtable->mro = mro;
856 count = VTABLE_elements(interp, mro_list);
858 for (i = 0; i < count; ++i) {
859 STRING *class_name = VTABLE_get_string_keyed_int(interp, mro_list, i);
860 INTVAL parent_type = pmc_type(interp, class_name);
862 /* abstract classes don't have a vtable */
863 if (!parent_type)
864 break;
866 vtable = interp->vtables[parent_type];
868 if (!vtable->_namespace) {
869 /* need a namespace Hash, anchor at parent, name it */
870 PMC * const ns = pmc_new(interp,
871 Parrot_get_ctx_HLL_type(interp, enum_class_NameSpace));
872 vtable->_namespace = ns;
874 /* anchor at parent, aka current_namespace, that is 'parrot' */
875 VTABLE_set_pmc_keyed_str(interp,
876 Parrot_pcc_get_namespace(interp, CURRENT_CONTEXT(interp)), class_name, ns);
879 _class = vtable->pmc_class;
880 if (!_class)
881 _class = create_class_pmc(interp, parent_type);
883 VTABLE_push_pmc(interp, mro, _class);
890 =back
892 =head2 GC registry interface
894 =over 4
896 =item C<void gc_register_pmc(PARROT_INTERP, PMC *pmc)>
898 Registers the PMC with the interpreter's GC registry.
900 =cut
904 PARROT_EXPORT
905 void
906 gc_register_pmc(PARROT_INTERP, ARGIN(PMC *pmc))
908 ASSERT_ARGS(gc_register_pmc)
909 /* Better not trigger a GC run with a potentially unanchored PMC */
910 Parrot_block_GC_mark(interp);
912 PARROT_ASSERT(interp->gc_registry);
914 VTABLE_set_pmc_keyed(interp, interp->gc_registry, pmc, PMCNULL);
915 Parrot_unblock_GC_mark(interp);
921 =item C<void gc_unregister_pmc(PARROT_INTERP, PMC *pmc)>
923 Unregisters the PMC from the interpreter's GC registry.
925 =cut
929 PARROT_EXPORT
930 void
931 gc_unregister_pmc(PARROT_INTERP, ARGIN(PMC *pmc))
933 ASSERT_ARGS(gc_unregister_pmc)
934 PARROT_ASSERT(interp->gc_registry);
936 VTABLE_delete_keyed(interp, interp->gc_registry, pmc);
942 =back
944 =head1 SEE ALSO
946 F<include/parrot/vtable.h>.
948 C<5.1.0.14.2.20011008152120.02158148@pop.sidhe.org>
949 (http://www.nntp.perl.org/group/perl.perl6.internals/5516).
951 =head1 HISTORY
953 Initial version by Simon on 2001.10.20.
955 =cut
961 * Local variables:
962 * c-file-style: "parrot"
963 * End:
964 * vim: expandtab shiftwidth=4: