Skip to content
Find file
Fetching contributors…
Cannot retrieve contributors at this time
332 lines (229 sloc) 7.57 KB
/*
Copyright (C) 2010-2014, Parrot Foundation.
=head1 NAME
src/pmc/imageiosize.pmc - ImageIOSize PMC
=head1 DESCRIPTION
Gets the size of an ImageIO image without the allocation costs.
Part of the internal serializer.
=head1 STATIC FUNCTIONS
=over 4
=cut
*/
#define GROW_TO_16_BYTE_BOUNDARY(size) ((size) + ((size) % 16 ? 16 - (size) % 16 : 0))
/* HEADERIZER HFILE: none */
/* HEADERIZER BEGIN: static */
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
PARROT_INLINE
static int check_seen(PARROT_INTERP,
ARGIN(const PMC *self),
ARGIN(const PMC *v))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
__attribute__nonnull__(3);
#define ASSERT_ARGS_check_seen __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(self) \
, PARROT_ASSERT_ARG(v))
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
/* HEADERIZER END: static */
/*
=item C<static int check_seen(PARROT_INTERP, const PMC *self, const PMC *v)>
Check the seen hash to prevent duplicate serialization.
=cut
*/
PARROT_INLINE
static int
check_seen(PARROT_INTERP, ARGIN(const PMC *self), ARGIN(const PMC *v))
{
ASSERT_ARGS(check_seen)
const Hash * const seen =
(Hash *)VTABLE_get_pointer(interp, PARROT_IMAGEIOSIZE(self)->seen);
const HashBucket * const b = Parrot_hash_get_bucket(interp, seen, v);
if (b)
return 1;
else
return 0;
}
pmclass ImageIOSize auto_attrs {
ATTR PMC *seen; /* seen hash */
ATTR PMC *todo; /* todo list */
ATTR struct PackFile_ConstTable *pf_ct;
ATTR INTVAL size;
/*
=back
=head1 VTABLES
=over 4
=cut
*/
/*
=item C<void init()>
Initializes the PMC.
=cut
*/
VTABLE void init() {
PARROT_IMAGEIOSIZE(SELF)->todo = Parrot_pmc_new(INTERP, enum_class_ResizablePMCArray);
PARROT_IMAGEIOSIZE(SELF)->pf_ct = NULL;
PARROT_IMAGEIOSIZE(SELF)->size = 0;
PARROT_IMAGEIOSIZE(SELF)->seen = Parrot_pmc_new(INTERP, enum_class_Hash);
VTABLE_set_pointer(INTERP, PARROT_IMAGEIOSIZE(SELF)->seen,
Parrot_hash_new_intval_hash(INTERP));
PObj_flag_CLEAR(private1, SELF);
PObj_custom_mark_SET(SELF);
}
/*
=item C<void init_pmc()>
Initializes the PMC with a pre-existing C<PackFile_ConstTable>.
=cut
*/
VTABLE void init_pmc(PMC *pf_ct) {
PARROT_IMAGEIOSIZE(SELF)->todo = Parrot_pmc_new(INTERP, enum_class_ResizablePMCArray);
PARROT_IMAGEIOSIZE(SELF)->pf_ct =
(PackFile_ConstTable *)VTABLE_get_pointer(INTERP, pf_ct);
PARROT_IMAGEIOSIZE(SELF)->size = 0;
PARROT_IMAGEIOSIZE(SELF)->seen = Parrot_pmc_new(INTERP, enum_class_Hash);
VTABLE_set_pointer(INTERP, PARROT_IMAGEIOSIZE(SELF)->seen,
Parrot_hash_new_intval_hash(INTERP));
PObj_flag_SET(private1, SELF);
PObj_custom_mark_SET(SELF);
}
/*
=item C<void mark()>
Marks the PMC as alive.
=cut
*/
VTABLE void mark() :no_wb {
Parrot_gc_mark_PMC_alive(INTERP, PARROT_IMAGEIOSIZE(SELF)->todo);
Parrot_gc_mark_PMC_alive(INTERP, PARROT_IMAGEIOSIZE(SELF)->seen);
}
/*
=item C<VTABLE PMC *get_pmc()>
Gets the result PMC after a thaw.
=cut
*/
VTABLE PMC *get_pmc() :no_wb {
PMC * const ret = Parrot_pmc_new_init_int(INTERP, enum_class_Integer,
PARROT_IMAGEIOSIZE(SELF)->size);
return ret;
}
/*
=item C<VTABLE INTVAL get_integer()>
Returns the flags describing the visit action
=cut
*/
VTABLE INTVAL get_integer() :no_wb {
UNUSED(INTERP)
UNUSED(SELF)
return VISIT_FREEZE_NORMAL;
}
/*
=item C<VTABLE void push_integer(INTVAL v)>
Pushes the integer C<v> onto the end of the image.
The argument C<v> is currently ignored.
=cut
*/
VTABLE void push_integer(INTVAL v) {
const size_t len = PF_size_integer() * sizeof (opcode_t);
UNUSED(v)
PARROT_IMAGEIOSIZE(SELF)->size += len;
}
/*
=item C<VTABLE void push_float(FLOATVAL v)>
Pushes the float C<v> onto the end of the image.
The argument C<v> is currently ignored.
=cut
*/
VTABLE void push_float(FLOATVAL v) {
const size_t len = PF_size_number() * sizeof (opcode_t);
UNUSED(v)
PARROT_IMAGEIOSIZE(SELF)->size += len;
}
/*
=item C<VTABLE void push_string(STRING *v)>
Pushes the string C<*v> onto the end of the image.
=cut
*/
VTABLE void push_string(STRING *v) :manual_wb {
if (PObj_flag_TEST(private1, SELF)) {
/* store a reference to constant table entry of string */
const PackFile_ConstTable * const table = PARROT_IMAGEIOSIZE(SELF)->pf_ct;
const int idx = Parrot_pf_ConstTable_rlookup_str(INTERP, table, v);
if (idx >= 0) {
STATICSELF.push_integer(idx);
return;
}
/* XXX
* handle cases where the PMC has changed after Parrot_freeze_strings was called
* eg: :immediate subs
*/
STATICSELF.push_integer(-1);
/* TODO
* should really be:
* PANIC(INTERP, "string not previously in constant table when freezing to packfile");
*/
}
{
const size_t len = PF_size_string(v) * sizeof (opcode_t);
PARROT_IMAGEIOSIZE(SELF)->size += len;
PARROT_GC_WRITE_BARRIER(INTERP, SELF);
}
}
/*
=item C<VTABLE void push_pmc(PMC *v)>
Pushes a reference to pmc C<*v> onto the end of the image. If C<*v>
hasn't been seen yet, it is also pushed onto the todo list.
=cut
*/
VTABLE void push_pmc(PMC *v) :manual_wb {
if (PMC_IS_NULL(v)
|| check_seen(INTERP, SELF, v))
SELF.push_integer(0);
else {
INTVAL cno, idx;
PackFile_ConstTable * const ct = PARROT_IMAGEIOSIZE(SELF)->pf_ct;
Hash * const seen = (Hash *)VTABLE_get_pointer(INTERP,
PARROT_IMAGEIOSIZE(SELF)->seen);
if (PObj_flag_TEST(private1, SELF)
&& Parrot_pf_ConstTable_rlookup_pmc(INTERP, ct, v, &cno, &idx)) {
SELF.push_integer(0);
SELF.push_integer(cno);
SELF.push_integer(idx);
}
else {
SELF.push_integer(0);
VTABLE_push_integer(INTERP, SELF, v->vtable->base_type);
VTABLE_push_pmc(INTERP, PARROT_IMAGEIOSIZE(SELF)->todo, v);
PARROT_GC_WRITE_BARRIER(INTERP, SELF);
}
Parrot_hash_put(INTERP, seen, v, v);
}
}
VTABLE void *get_pointer() :no_wb {
return VTABLE_get_pointer(INTERP, PARROT_IMAGEIOSIZE(SELF)->seen);
}
VTABLE void set_pmc(PMC *p) :manual_wb {
if (!PObj_flag_TEST(private1, SELF)) {
const UINTVAL header_length = GROW_TO_16_BYTE_BOUNDARY(PACKFILE_HEADER_BYTES);
PARROT_IMAGEIOSIZE(SELF)->size += header_length;
}
STATICSELF.push_pmc(p);
{
PMC * const todo = PARROT_IMAGEIOSIZE(SELF)->todo;
while (VTABLE_elements(INTERP, todo)) {
PMC * const current = VTABLE_shift_pmc(INTERP, todo);
VTABLE_freeze(INTERP, current, SELF);
VTABLE_visit(INTERP, current, SELF);
SELF.push_pmc(PMC_metadata(current));
}
}
}
/*
=back
=cut
*/
}
/*
* Local variables:
* c-file-style: "parrot"
* End:
* vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
*/
Something went wrong with that request. Please try again.