2 Copyright (C) 2001-2006, The Perl Foundation.
7 src/pmc.c - The base vtable calling functions
19 #include "parrot/parrot.h"
23 static PMC
* get_new_pmc_header(Interp
*, INTVAL base_type
, UINTVAL flags
);
31 pmc_new(Interp *interp, INTVAL base_type)>
33 Creates a new PMC of type C<base_type> (which is an index into the list
34 of PMC types declared in C<vtables> in
35 F<include/parrot/pmc.h>). Once the PMC has been successfully created and
36 its vtable pointer initialized, we call its C<init> method to perform
37 any other necessary initialization.
44 pmc_new(Interp
*interp
, INTVAL base_type
)
46 PMC
* const pmc
= pmc_new_noinit(interp
, base_type
);
47 VTABLE_init(interp
, pmc
);
54 pmc_reuse(Interp *interp, PMC *pmc, INTVAL new_type,
57 Reuse an existing PMC, turning it into an empty PMC of the new
58 type. Any required internal structure will be put in place (such as
59 the extension area) and the PMC will be ready to go. This will throw
60 an exception if the PMC is constant or of a singleton type (such as
61 the environment PMC) or is being turned into a PMC of a singleton
69 pmc_reuse(Interp
*interp
, PMC
*pmc
, INTVAL new_type
,
72 INTVAL has_ext
, new_flags
;
75 if (pmc
->vtable
->base_type
== new_type
)
78 new_vtable
= interp
->vtables
[new_type
];
80 /* Singleton/const PMCs/types are not eligible */
82 if ((pmc
->vtable
->flags
| new_vtable
->flags
)
83 & (VTABLE_PMC_IS_SINGLETON
| VTABLE_IS_CONST_FLAG
))
85 /* First, is the destination a singleton? No joy for us there */
86 if (new_vtable
->flags
& VTABLE_PMC_IS_SINGLETON
) {
87 internal_exception(ALLOCATION_ERROR
,
88 "Parrot VM: Can't turn to a singleton type!\n");
92 /* First, is the destination a constant? No joy for us there */
93 if (new_vtable
->flags
& VTABLE_IS_CONST_FLAG
) {
94 internal_exception(ALLOCATION_ERROR
,
95 "Parrot VM: Can't turn to a constant type!\n");
99 /* Is the source a singleton? */
100 if (pmc
->vtable
->flags
& VTABLE_PMC_IS_SINGLETON
) {
101 internal_exception(ALLOCATION_ERROR
,
102 "Parrot VM: Can't modify a singleton\n");
106 /* Is the source constant? */
107 if (pmc
->vtable
->flags
& VTABLE_IS_CONST_FLAG
) {
108 internal_exception(ALLOCATION_ERROR
,
109 "Parrot VM: Can't modify a constant\n");
114 /* Do we have an extension area? */
115 has_ext
= (PObj_is_PMC_EXT_TEST(pmc
) && pmc
->pmc_ext
);
117 /* Do we need one? */
118 if (new_vtable
->flags
& VTABLE_PMC_NEEDS_EXT
) {
120 /* If we need an ext area, go allocate one */
121 add_pmc_ext(interp
, pmc
);
123 new_flags
= PObj_is_PMC_EXT_FLAG
;
127 /* if the PMC has a PMC_EXT structure,
128 * return it to the pool/arena
130 Small_Object_Pool
* const ext_pool
=
131 interp
->arena_base
->pmc_ext_pool
;
132 if (PObj_is_PMC_shared_TEST(pmc
) && PMC_sync(pmc
)) {
133 MUTEX_DESTROY(PMC_sync(pmc
)->pmc_lock
);
134 mem_internal_free(PMC_sync(pmc
));
135 PMC_sync(pmc
) = NULL
;
137 ext_pool
->add_free_object(interp
, ext_pool
, pmc
->pmc_ext
);
140 #if ! PMC_DATA_IN_EXT
141 PMC_data(pmc
) = NULL
;
146 /* we are a PMC + maybe is_PMC_EXT */
147 PObj_flags_SETTO(pmc
, PObj_is_PMC_FLAG
| new_flags
);
149 /* Set the right vtable */
150 pmc
->vtable
= new_vtable
;
152 /* Call the base init for the redone pmc */
153 VTABLE_init(interp
, pmc
);
161 get_new_pmc_header(Interp *interp, INTVAL base_type, UINTVAL flags)>
163 Gets a new PMC header.
170 get_new_pmc_header(Interp
*interp
, INTVAL base_type
, UINTVAL flags
)
173 VTABLE
*vtable
= interp
->vtables
[base_type
];
176 /* This is usually because you either didn't call init_world early
177 * enough, you added a new PMC class without adding
178 * Parrot_(classname)_class_init to init_world, or you forgot
179 * to run 'make realclean' after adding a new PMC class.
181 PANIC("Null vtable used");
184 /* we only have one global Env object, living in the interp */
185 if (vtable
->flags
& VTABLE_PMC_IS_SINGLETON
) {
187 * singletons (monadic objects) exist only once, the interface
189 * - get_pointer: return NULL or a pointer to the single instance
190 * - set_pointer: set the only instance once
192 * - singletons are created in the constant pmc pool
194 pmc
= (PMC
*)(vtable
->get_pointer
)(interp
, NULL
);
197 pmc
= new_pmc_header(interp
, PObj_constant_FLAG
);
198 pmc
->vtable
= vtable
;
199 VTABLE_set_pointer(interp
, pmc
, pmc
);
203 if (vtable
->flags
& VTABLE_IS_CONST_PMC_FLAG
) {
204 flags
= PObj_constant_FLAG
;
206 else if (vtable
->flags
& VTABLE_IS_CONST_FLAG
) {
207 /* put the normal vtable in, so that the pmc can be initialized first
208 * parrot or user code has to set the _ro property then,
209 * to morph the PMC to the const variant
210 * This assumes that a constant PMC enum is one bigger then
215 * XXX not yet we can't assure that all contents in the
216 * const PMC is const too
217 * see e.g. t/pmc/sarray_13.pir
220 flags
= PObj_constant_FLAG
;
223 vtable
= interp
->vtables
[base_type
];
225 if (vtable
->flags
& VTABLE_PMC_NEEDS_EXT
) {
226 flags
|= PObj_is_PMC_EXT_FLAG
;
227 if (vtable
->flags
& VTABLE_IS_SHARED_FLAG
)
228 flags
|= PObj_is_PMC_shared_FLAG
;
231 pmc
= new_pmc_header(interp
, flags
);
233 internal_exception(ALLOCATION_ERROR
,
234 "Parrot VM: PMC allocation failed!\n");
238 pmc
->vtable
= vtable
;
241 if (Interp_flags_TEST(interp
, PARROT_TRACE_FLAG
)) {
242 /* XXX make a more verbose trace flag */
243 fprintf(stderr
, "\t=> new %p type %d\n", pmc
, (int)base_type
);
253 pmc_new_noinit(Interp *interp, INTVAL base_type)>
255 Creates a new PMC of type C<base_type> (which is an index into the list
256 of PMC types declared in C<vtables> in
257 F<include/parrot/pmc.h>). Unlike C<pmc_new()>, C<pmc_new_noinit()> does
258 not call its C<init> method. This allows separate allocation and
259 initialization for continuations.
266 pmc_new_noinit(Interp
*interp
, INTVAL base_type
)
268 PMC
* const pmc
= get_new_pmc_header(interp
, base_type
, 0);
276 constant_pmc_new_noinit(Interp *interp, INTVAL base_type)>
278 Creates a new constant PMC of type C<base_type>.
285 constant_pmc_new_noinit(Interp
*interp
, INTVAL base_type
)
287 PMC
* const pmc
= get_new_pmc_header(interp
, base_type
,
295 constant_pmc_new(Interp *interp, INTVAL base_type)>
297 Creates a new constant PMC of type C<base_type>, the call C<init>.
304 constant_pmc_new(Interp
*interp
, INTVAL base_type
)
306 PMC
* const pmc
= get_new_pmc_header(interp
, base_type
,
308 VTABLE_init(interp
, pmc
);
315 pmc_new_init(Interp *interp, INTVAL base_type, PMC *init)>
317 As C<pmc_new()>, but passes C<init> to the PMC's C<init_pmc()> method.
324 pmc_new_init(Interp
*interp
, INTVAL base_type
, PMC
*init
)
326 PMC
* const pmc
= pmc_new_noinit(interp
, base_type
);
328 VTABLE_init_pmc(interp
, pmc
, init
);
336 constant_pmc_new_init(Interp *interp, INTVAL base_type, PMC *init)>
338 As C<constant_pmc_new>, but passes C<init> to the PMC's C<init_pmc> method.
345 constant_pmc_new_init(Interp
*interp
, INTVAL base_type
, PMC
*init
)
347 PMC
* const pmc
= get_new_pmc_header(interp
, base_type
, 1);
348 VTABLE_init_pmc(interp
, pmc
, init
);
355 pmc_register(Interp* interp, STRING *name)>
357 This segment handles PMC registration and such.
364 pmc_register(Interp
* interp
, STRING
*name
)
368 /* If they're looking to register an existing class, return that
369 class' type number */
370 if ((type
= pmc_type(interp
, name
)) > enum_type_undef
) {
373 if (type
< enum_type_undef
) {
374 internal_exception(1, "native type with name '%s' already exists - "
375 "can't register PMC", data_types
[type
].name
);
379 classname_hash
= interp
->class_hash
;
380 type
= interp
->n_vtable_max
++;
381 /* Have we overflowed the table? */
382 if (type
>= interp
->n_vtable_alloced
) {
383 parrot_realloc_vtables(interp
);
385 /* set entry in name->type hash */
386 VTABLE_set_integer_keyed_str(interp
, classname_hash
, name
, type
);
393 pmc_type(Interp* interp, STRING *name)>
395 Returns the PMC type for C<name>.
402 pmc_type(Interp
* interp
, const STRING
*name
)
404 PMC
* const classname_hash
= interp
->class_hash
;
405 const PMC
* const item
= (PMC
*)VTABLE_get_pointer_keyed_str(interp
, classname_hash
, name
);
407 /* nested namespace with same name */
408 if (item
->vtable
->base_type
== enum_class_NameSpace
)
410 if (!PMC_IS_NULL(item
))
411 return PMC_int_val((PMC
*) item
);
412 return Parrot_get_datatype_enum(interp
, name
);
416 pmc_type_p(Interp
* interp
, const PMC
*name
)
418 PMC
* const classname_hash
= interp
->class_hash
;
419 PMC
*item
= (PMC
*)VTABLE_get_pointer_keyed(interp
, classname_hash
, name
);
421 if (!PMC_IS_NULL(item
))
422 return PMC_int_val((PMC
*) item
);
427 create_class_pmc(Interp
*interp
, INTVAL type
)
430 * class interface - a PMC is its own class
431 * put an instance of this PMC into class
433 * create a constant PMC
435 PMC
* const _class
= get_new_pmc_header(interp
, type
,
437 /* If we are a second thread, we may get the same object as the
438 * original because we have a singleton. Just set the singleton to
439 * be our class object, but don't mess with its vtable.
441 if ((interp
->vtables
[type
]->flags
& VTABLE_PMC_IS_SINGLETON
)
442 && (_class
== _class
->vtable
->pmc_class
)) {
443 interp
->vtables
[type
]->pmc_class
= _class
;
446 if (PObj_is_PMC_EXT_TEST(_class
)) {
447 /* if the PMC has a PMC_EXT structure,
448 * return it to the pool/arena
449 * we don't need it - basically only the vtable is important
451 Small_Object_Pool
* const ext_pool
=
452 interp
->arena_base
->pmc_ext_pool
;
453 if (PMC_sync(_class
))
454 mem_internal_free(PMC_sync(_class
));
455 ext_pool
->add_free_object(interp
, ext_pool
, _class
->pmc_ext
);
457 _class
->pmc_ext
= NULL
;
458 DOD_flag_CLEAR(is_special_PMC
, _class
);
459 PMC_pmc_val(_class
) = (PMC
*)0xdeadbeef;
460 PMC_struct_val(_class
)= (void*)0xdeadbeef;
462 PObj_is_PMC_shared_CLEAR(_class
);
464 interp
->vtables
[type
]->pmc_class
= _class
;
471 =item C<void Parrot_create_mro(Interp *interp, INTVAL type)>
473 Create the MRO (method resolution order) array for this type.
480 Parrot_create_mro(Interp
*interp
, INTVAL type
)
483 STRING
*class_name
, *isa
;
484 INTVAL pos
, parent_type
, total
;
488 vtable
= interp
->vtables
[type
];
489 /* multithreaded: has already mro */
492 mro
= pmc_new(interp
, enum_class_ResizablePMCArray
);
494 if (vtable
->ro_variant_vtable
) {
495 vtable
->ro_variant_vtable
->mro
= mro
;
497 class_name
= vtable
->whoami
;
498 isa
= vtable
->isa_str
;
499 total
= (INTVAL
)string_length(interp
, isa
);
501 INTVAL len
= string_length(interp
, class_name
);
503 parent_type
= pmc_type(interp
, class_name
);
504 if (!parent_type
) /* abstract classes don't have a vtable */
506 vtable
= interp
->vtables
[parent_type
];
507 if (!vtable
->_namespace
) {
508 /* need a namespace Hash, anchor at parent, name it */
510 Parrot_get_ctx_HLL_type(interp
, enum_class_NameSpace
));
511 vtable
->_namespace
= ns
;
512 /* anchor at parent, aka current_namespace, that is 'parrot' */
513 VTABLE_set_pmc_keyed_str(interp
,
514 CONTEXT(interp
->ctx
)->current_namespace
,
517 _class
= vtable
->pmc_class
;
519 _class
= create_class_pmc(interp
, parent_type
);
521 VTABLE_push_pmc(interp
, mro
, _class
);
524 len
= string_str_index(interp
, isa
,
525 CONST_STRING(interp
, " "), pos
);
528 class_name
= string_substr(interp
, isa
, pos
,
537 =head2 DOD registry interface
542 dod_register_pmc(Interp* interp, PMC* pmc)>
544 Registers the PMC with the interpreter's DOD registery.
551 dod_register_pmc(Interp
* interp
, PMC
* pmc
)
554 /* Better not trigger a DOD run with a potentially unanchored PMC */
555 Parrot_block_DOD(interp
);
557 if (!interp
->DOD_registry
) {
558 registry
= interp
->DOD_registry
=
559 pmc_new(interp
, enum_class_AddrRegistry
);
562 registry
= interp
->DOD_registry
;
563 VTABLE_set_pmc_keyed(interp
, registry
, pmc
, NULL
);
564 Parrot_unblock_DOD(interp
);
571 dod_unregister_pmc(Interp* interp, PMC* pmc)>
573 Unregisters the PMC from the interpreter's DOD registery.
580 dod_unregister_pmc(Interp
* interp
, PMC
* pmc
)
582 if (!interp
->DOD_registry
)
583 return; /* XXX or signal exception? */
584 VTABLE_delete_keyed(interp
, interp
->DOD_registry
, pmc
);
593 F<include/parrot/vtable.h>.
595 C<5.1.0.14.2.20011008152120.02158148@pop.sidhe.org>
596 (http://www.nntp.perl.org/group/perl.perl6.internals/5516).
600 Initial version by Simon on 2001.10.20.
609 * c-file-style: "parrot"
611 * vim: expandtab shiftwidth=4: