Author: jonathan
Date: Fri Jan 16 09:33:50 2009
New Revision: 35636
Modified:
trunk/include/parrot/sub.h
trunk/src/pic_jit.c
trunk/src/sub.c
trunk/src/thread.c
Log:
[core] PMC_sub could not check that we actually had something that was a sub underneath, nor did it handle the case where the Sub PMC had been subclassed by a high level class. Lots of code wanted a Parrot_Sub to be handed back by this, and not getting one could lead to segfaults. So this patch plugs those, and also makes it OK to subclass Sub in a high level class and use those subclasses with, e.g. capture_lex and elsewhere. The couple of other seemingly unreated changes in this patch are a result of needing to have an interp variable around to use PMC_sub now. All core tests pass.
Modified: trunk/include/parrot/sub.h
==============================================================================
--- trunk/include/parrot/sub.h (original)
+++ trunk/include/parrot/sub.h Fri Jan 16 09:33:50 2009
@@ -171,7 +171,12 @@
struct Parrot_Context *outer_ctx; /* outer context, if a closure */
} Parrot_sub;
-#define PMC_sub(pmc) ((Parrot_sub *)PMC_struct_val(pmc))
+#define PMC_sub(pmc) (pmc->vtable->base_type == enum_class_Sub || \
+ pmc->vtable->base_type == enum_class_Coroutine || \
+ pmc->vtable->base_type == enum_class_Eval || \
+ pmc->vtable->base_type == enum_class_Closure ? \
+ (Parrot_sub *)PMC_struct_val(pmc) : \
+ Parrot_get_sub_pmc_from_subclass(interp, pmc))
/* the first entries must match Parrot_sub, so we can cast
* these two to the other type
@@ -272,6 +277,11 @@
PARROT_EXPORT
PARROT_CANNOT_RETURN_NULL
+Parrot_sub * Parrot_get_sub_pmc_from_subclass(PARROT_INTERP, PMC *subclass)
+ __attribute__nonnull__(1);
+
+PARROT_EXPORT
+PARROT_CANNOT_RETURN_NULL
PARROT_WARN_UNUSED_RESULT
PMC* parrot_new_closure(PARROT_INTERP, ARGIN(PMC *sub_pmc))
__attribute__nonnull__(1)
@@ -352,6 +362,9 @@
|| PARROT_ASSERT_ARG(ctx)
#define ASSERT_ARGS_Parrot_full_sub_name __attribute__unused__ int _ASSERT_ARGS_CHECK = \
PARROT_ASSERT_ARG(interp)
+#define ASSERT_ARGS_Parrot_get_sub_pmc_from_subclass \
+ __attribute__unused__ int _ASSERT_ARGS_CHECK = \
+ PARROT_ASSERT_ARG(interp)
#define ASSERT_ARGS_parrot_new_closure __attribute__unused__ int _ASSERT_ARGS_CHECK = \
PARROT_ASSERT_ARG(interp) \
|| PARROT_ASSERT_ARG(sub_pmc)
Modified: trunk/src/pic_jit.c
==============================================================================
--- trunk/src/pic_jit.c (original)
+++ trunk/src/pic_jit.c Fri Jan 16 09:33:50 2009
@@ -49,9 +49,12 @@
__attribute__nonnull__(3);
PARROT_WARN_UNUSED_RESULT
-static int call_is_safe(ARGIN(const PMC *sub), ARGMOD(opcode_t **set_args))
+static int call_is_safe(PARROT_INTERP,
+ ARGIN(const PMC *sub),
+ ARGMOD(opcode_t **set_args))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
+ __attribute__nonnull__(3)
FUNC_MODIFIES(*set_args);
PARROT_WARN_UNUSED_RESULT
@@ -97,7 +100,8 @@
|| PARROT_ASSERT_ARG(seg) \
|| PARROT_ASSERT_ARG(start)
#define ASSERT_ARGS_call_is_safe __attribute__unused__ int _ASSERT_ARGS_CHECK = \
- PARROT_ASSERT_ARG(sub) \
+ PARROT_ASSERT_ARG(interp) \
+ || PARROT_ASSERT_ARG(sub) \
|| PARROT_ASSERT_ARG(set_args)
#define ASSERT_ARGS_jit_can_compile_sub __attribute__unused__ int _ASSERT_ARGS_CHECK = \
PARROT_ASSERT_ARG(interp) \
@@ -328,7 +332,7 @@
PARROT_WARN_UNUSED_RESULT
static int
-call_is_safe(ARGIN(const PMC *sub), ARGMOD(opcode_t **set_args))
+call_is_safe(PARROT_INTERP, ARGIN(const PMC *sub), ARGMOD(opcode_t **set_args))
{
ASSERT_ARGS(call_is_safe)
PMC *called, *sig_results;
@@ -407,7 +411,7 @@
break;
case PARROT_OP_set_args_pc:
/* verify call, return address after the call */
- if (!call_is_safe(sub, &pc))
+ if (!call_is_safe(interp, sub, &pc))
return 0;
*flags |= JIT_CODE_RECURSIVE;
continue;
Modified: trunk/src/sub.c
==============================================================================
--- trunk/src/sub.c (original)
+++ trunk/src/sub.c Fri Jan 16 09:33:50 2009
@@ -570,7 +570,7 @@
ASSERT_ARGS(Parrot_capture_lex)
Parrot_Context * const ctx = CONTEXT(interp);
Parrot_sub * const current_sub = PMC_sub(ctx->current_sub);
- Parrot_sub * const sub = PMC_sub(sub_pmc);
+ Parrot_sub *sub;
Parrot_Context *old;
/* MultiSub gets special treatment */
@@ -592,6 +592,7 @@
}
/* the sub_pmc has to have an outer_sub that is the caller */
+ sub = PMC_sub(sub_pmc);
if (PMC_IS_NULL(sub->outer_sub))
return;
@@ -704,6 +705,43 @@
interp->ctx.bp_ps = to_ctx->bp_ps;
}
+
+/*
+
+=item C<Parrot_sub * Parrot_get_sub_pmc_from_subclass>
+
+Gets a Parrot_sub structure from something that isn't a Sub PMC, but rather a
+subclass.
+
+=cut
+
+*/
+
+PARROT_EXPORT
+PARROT_CANNOT_RETURN_NULL
+Parrot_sub *
+Parrot_get_sub_pmc_from_subclass(PARROT_INTERP, ARGIN(PMC *subclass)) {
+ ASSERT_ARGS(Parrot_get_sub_pmc_from_subclass)
+ PMC *key, *sub_pmc;
+
+ /* Ensure we really do have a subclass of sub. */
+ if (VTABLE_isa(interp, subclass, CONST_STRING(interp, "Sub"))) {
+ /* If it's actually a PMC still, probably does the same structure
+ * underneath. */
+ if (!PObj_is_object_TEST(subclass))
+ return (Parrot_sub *)PMC_struct_val(subclass);
+
+ /* Get the Sub PMC itself. */
+ key = pmc_new(interp, enum_class_String);
+ VTABLE_set_string_native(interp, key, CONST_STRING(interp, "Sub"));
+ sub_pmc = VTABLE_get_attr_keyed(interp, subclass, key, CONST_STRING(interp, "proxy"));
+ if (sub_pmc->vtable->base_type == enum_class_Sub)
+ return (Parrot_sub *)PMC_struct_val(sub_pmc);
+ }
+ Parrot_ex_throw_from_op_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
+ "Attempting to do sub operation on non-Sub.");
+}
+
/*
=back
Modified: trunk/src/thread.c
==============================================================================
--- trunk/src/thread.c (original)
+++ trunk/src/thread.c Fri Jan 16 09:33:50 2009
@@ -68,7 +68,7 @@
static void pt_gc_wakeup_check(PARROT_INTERP)
__attribute__nonnull__(1);
-static void pt_ns_clone(
+static void pt_ns_clone(PARROT_INTERP,
ARGOUT(Parrot_Interp d),
ARGOUT(PMC *dest_ns),
ARGIN(Parrot_Interp s),
@@ -77,6 +77,7 @@
__attribute__nonnull__(2)
__attribute__nonnull__(3)
__attribute__nonnull__(4)
+ __attribute__nonnull__(5)
FUNC_MODIFIES(d)
FUNC_MODIFIES(*dest_ns);
@@ -123,7 +124,8 @@
#define ASSERT_ARGS_pt_gc_wakeup_check __attribute__unused__ int _ASSERT_ARGS_CHECK = \
PARROT_ASSERT_ARG(interp)
#define ASSERT_ARGS_pt_ns_clone __attribute__unused__ int _ASSERT_ARGS_CHECK = \
- PARROT_ASSERT_ARG(d) \
+ PARROT_ASSERT_ARG(interp) \
+ || PARROT_ASSERT_ARG(d) \
|| PARROT_ASSERT_ARG(dest_ns) \
|| PARROT_ASSERT_ARG(s) \
|| PARROT_ASSERT_ARG(source_ns)
@@ -593,7 +595,7 @@
*/
static void
-pt_ns_clone(ARGOUT(Parrot_Interp d), ARGOUT(PMC *dest_ns),
+pt_ns_clone(PARROT_INTERP, ARGOUT(Parrot_Interp d), ARGOUT(PMC *dest_ns),
ARGIN(Parrot_Interp s), ARGIN(PMC *source_ns))
{
ASSERT_ARGS(pt_ns_clone)
@@ -613,7 +615,7 @@
sub_ns = pmc_new(d, enum_class_NameSpace);
VTABLE_set_pmc_keyed_str(d, dest_ns, key, sub_ns);
}
- pt_ns_clone(d, sub_ns, s, val);
+ pt_ns_clone(s, d, sub_ns, s, val);
}
else {
PMC * const dval = VTABLE_get_pmc_keyed_str(d, dest_ns, key);
@@ -647,7 +649,7 @@
{
ASSERT_ARGS(pt_clone_globals)
Parrot_block_GC_mark(d);
- pt_ns_clone(d, d->root_namespace, s, s->root_namespace);
+ pt_ns_clone(s, d, d->root_namespace, s, s->root_namespace);
Parrot_unblock_GC_mark(d);
}
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.