Skip to content

Commit 89c34b4

Browse files
committed
Bring the work on compile time meta-object support so far in line with my latest thinking on how stuff will work. Quite a few little changes.
1 parent 1516bd2 commit 89c34b4

File tree

6 files changed

+91
-85
lines changed

6 files changed

+91
-85
lines changed

src/HLL/SerializationContextBuilder.pm

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,13 @@ class HLL::Compiler::SerializationContextBuilder::Event {
3737
}
3838

3939
class HLL::Compiler::SerializationContextBuilder {
40-
# The objects that live in or should be built by this context.
41-
has @!root_objects;
40+
# The serialization context that we're building.
41+
has $!sc;
4242

43-
# Address => slot mapping, we we can quickly look up existing objects
43+
# The handle for the context.
44+
has $!handle;
45+
46+
# Address => slot mapping, so we can quickly look up existing objects
4447
# in the context.
4548
has %!addr_to_slot;
4649
sub addr($obj) {
@@ -51,14 +54,15 @@ class HLL::Compiler::SerializationContextBuilder {
5154
has @!event_stream;
5255

5356
# XXX Fix BUILD...
54-
method new() {
57+
method new(:$handle!) {
5558
my $obj := self.CREATE();
56-
$obj.BUILD();
59+
$obj.BUILD(:handle($handle));
5760
$obj
5861
}
5962

60-
method BUILD() {
61-
@!root_objects := pir::new('ResizablePMCArray');
63+
method BUILD(:$handle) {
64+
$!sc := pir::nqp_create_sc__PS($handle);
65+
$!handle := $handle;
6266
%!addr_to_slot := pir::new('Hash');
6367
@!event_stream := pir::new('ResizablePMCArray');
6468
}
@@ -78,18 +82,18 @@ class HLL::Compiler::SerializationContextBuilder {
7882
# a constant and we're using the SC as a constants table).
7983
method get_slot_past_for_object($obj) {
8084
my $slot := self.slot_for_object($obj);
81-
return PAST::Op.new( :pirop('nqp_get_sc_object Pi'), $slot );
85+
return PAST::Op.new( :pirop('nqp_get_sc_object Psi'), $!handle, $slot );
8286
}
8387

8488
# Utility sub to wrap PAST with slot setting.
85-
sub set_slot_past($slot, $past_to_set) {
86-
return PAST::Op.new( :pirop('nqp_set_sc_object viP'), $slot, $past_to_set );
89+
method set_slot_past($slot, $past_to_set) {
90+
return PAST::Op.new( :pirop('nqp_set_sc_object vsiP'), $!handle, $slot, $past_to_set );
8791
}
8892

8993
# Adds an object to the root set, along with a mapping.
9094
method add_object($obj) {
91-
my $idx := +@!root_objects;
92-
@!root_objects[$idx] := $obj;
95+
my $idx := $!sc.elems();
96+
$!sc[$idx] := $obj;
9397
%!addr_to_slot{addr($obj)} := $idx;
9498
$idx
9599
}
@@ -125,7 +129,7 @@ class HLL::Compiler::SerializationContextBuilder {
125129
if pir::defined($repr) {
126130
$setup_call.push(PAST::Val.new( :value($repr), :named('repr') ));
127131
}
128-
self.add_event(:deserialize_past(set_slot_past($slot, $setup_call)));
132+
self.add_event(:deserialize_past(self.set_slot_past($slot, $setup_call)));
129133

130134
# Result is just the object.
131135
return $mo;
@@ -154,10 +158,9 @@ class HLL::Compiler::SerializationContextBuilder {
154158
$obj
155159
}
156160

157-
# Gets the root object graph for the serialization context, which can
158-
# be attached to the compiled output.
159-
method root_objects() {
160-
@!root_objects
161+
# Gets the built serialization context.
162+
method sc() {
163+
@!sc
161164
}
162165

163166
# Generates a series of PAST operations that will build this context if

src/NQP/Grammar.pm

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ method TOP() {
2626
# Serialization context builder - keeps track of objects that
2727
# cross the compile-time/run-time boundary that are associated
2828
# with this compilation unit.
29-
my $*SC := HLL::Compiler::SerializationContextBuilder.new();
29+
my $*SC := HLL::Compiler::SerializationContextBuilder.new(
30+
# XXX Need to hash the source, or something.
31+
:handle(~pir::time__N()));
3032

3133
my $*SCOPE := '';
3234
my $*MULTINESS := '';

src/metamodel/rakudoobject.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ typedef struct {
156156
/* Various handy macros for getting at important stuff. */
157157
#define STABLE_PMC(o) (((RakudoObjectCommonalities *)PMC_data(o))->stable)
158158
#define STABLE(o) ((STable *)PMC_data(STABLE_PMC(o)))
159+
#define SC_PMC(o) (((RakudoObjectCommonalities *)PMC_data(o))->sc)
159160
#define STABLE_STRUCT(p) ((STable *)PMC_data(p))
160161
#define REPR_PMC(o) (STABLE(o)->REPR)
161162
#define REPR(o) ((REPRCommonalities *)PMC_data(REPR_PMC(o)))

src/metamodel/serialization_context.c

Lines changed: 16 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,31 @@
11
/* This implements a little bit of support for serialization contexts.
2-
* At the moment, its main role is to let us have a PMC array of objects
3-
* per Parrot bytecode segment. This gives fast access to them. Note
4-
* that if this ever made it into core Parrot, we'd hang it off the
5-
* packfile data structure, or maybe consider whether there's a kind of
6-
* unification with the "constants" segment. */
2+
* At the moment, its main role is to just be a global lookup table for
3+
* serialization contexts; it'll need to get much smarter. */
74

85
#define PARROT_IN_EXTENSION
96
#include "parrot/parrot.h"
107
#include "parrot/extend.h"
118

12-
/* Array of root object arrays, one per SC. */
13-
static PMC *sc_root_objects = NULL;
9+
/* Hash of serialization context objects */
10+
static PMC *scs = NULL;
1411

15-
/* Array of bytecode segment locations. Related to the above array.
16-
* Just an array of integers. Can be array of bytecode PMCs later. */
17-
static PMC *sc_index_lookup = NULL;
18-
19-
/* Initializes the stores and register them with the GC. */
12+
/* Initializes the store and register with the GC. */
2013
static void setup_sc_stores(PARROT_INTERP) {
21-
sc_root_objects = pmc_new(interp, enum_class_ResizablePMCArray);
22-
sc_index_lookup = pmc_new(interp, enum_class_ResizableIntegerArray);
23-
Parrot_pmc_gc_register(interp, sc_root_objects);
24-
Parrot_pmc_gc_register(interp, sc_index_lookup);
14+
scs = pmc_new(interp, enum_class_Hash);
15+
Parrot_pmc_gc_register(interp, scs);
2516
}
2617

27-
/* Gets an object from the serialization context associated with the
28-
* current bytecode segment. */
29-
PMC * SC_get_sc_object(PARROT_INTERP, INTVAL idx) {
30-
/* Locate the SC root list for this bytecode segment. */
31-
INTVAL addr = (INTVAL)interp->code;
32-
INTVAL scs, i;
33-
if (!sc_index_lookup)
18+
/* Gets the serialization context - if any - associated with the
19+
* specified handle. */
20+
PMC * SC_get_sc(PARROT_INTERP, STRING *handle) {
21+
if (!scs)
3422
setup_sc_stores(interp);
35-
scs = VTABLE_elements(interp, sc_index_lookup);
36-
for (i = 0; i < scs; i++) {
37-
if (VTABLE_get_integer_keyed_int(interp, sc_index_lookup, i) == addr) {
38-
/* Found it; grab object we're looking for. */
39-
PMC *sc_root = VTABLE_get_pmc_keyed_int(interp, sc_root_objects, i);
40-
return VTABLE_get_pmc_keyed_int(interp, sc_root, idx);
41-
}
42-
}
43-
44-
/* None found, just return PMCNULL. */
45-
return PMCNULL;
23+
return VTABLE_get_pmc_keyed_str(interp, scs, handle);
4624
}
4725

48-
/* Puts an object into the serialization context associated with the
49-
* current bytecode segment. */
50-
void SC_set_sc_object(PARROT_INTERP, INTVAL idx, PMC *object) {
51-
/* Locate the SC root list for this bytecode segment. */
52-
INTVAL addr = (INTVAL)interp->code;
53-
PMC * sc_root = PMCNULL;
54-
INTVAL scs, i;
55-
if (!sc_index_lookup)
26+
/* Stashes a serialization context with the specified handle. */
27+
void SC_set_sc(PARROT_INTERP, STRING *handle, PMC *sc) {
28+
if (!scs)
5629
setup_sc_stores(interp);
57-
scs = VTABLE_elements(interp, sc_index_lookup);
58-
for (i = 0; i < scs; i++) {
59-
if (VTABLE_get_integer_keyed_int(interp, sc_index_lookup, i) == addr) {
60-
sc_root = VTABLE_get_pmc_keyed_int(interp, sc_root_objects, i);
61-
break;
62-
}
63-
}
64-
65-
/* If we found none, add it. */
66-
if (PMC_IS_NULL(sc_root)) {
67-
sc_root = pmc_new(interp, enum_class_ResizablePMCArray);
68-
VTABLE_set_pmc_keyed_int(interp, sc_root_objects, scs, sc_root);
69-
VTABLE_set_integer_keyed_int(interp, sc_index_lookup, scs, addr);
70-
}
71-
72-
/* Stash the value in the the SC. */
73-
VTABLE_set_pmc_keyed_int(interp, sc_root, idx, object);
30+
VTABLE_set_pmc_keyed_str(interp, scs, handle, sc);
7431
}

src/metamodel/serialization_context.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#ifndef SERIALIZATIONCONTEXT_H_GUARD
22
#define SERIALIZATIONCONTEXT_H_GUARD
33

4-
PMC * SC_get_sc_object(PARROT_INTERP, INTVAL idx);
5-
void SC_set_sc_object(PARROT_INTERP, INTVAL idx, PMC *object);
4+
PMC * SC_get_sc(PARROT_INTERP, STRING *handle);
5+
void SC_set_sc(PARROT_INTERP, STRING *handle, PMC *sc);
66

77
#endif

src/ops/nqp.ops

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -642,24 +642,67 @@ inline op stable_publish_vtable_mapping(in PMC, in PMC) :base_core {
642642

643643
=item nqp_get_sc_object()
644644

645-
Fetches an object from the current segment's serialization context.
645+
Fetches an object from the serialization context keyed by handle and index.
646646

647647
=cut
648648

649649
*/
650-
inline op nqp_get_sc_object(out PMC, in INT) :base_core {
651-
$1 = SC_get_sc_object(interp, $2);
650+
inline op nqp_get_sc_object(out PMC, in STR, in INT) :base_core {
651+
PMC *sc = SC_get_sc(interp, $2);
652+
if (!PMC_IS_NULL(sc))
653+
$1 = VTABLE_get_pmc_keyed_int(interp, sc, $3);
654+
else
655+
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
656+
"Cannot fetch object from non-existance serialization context %Ss",
657+
$2);
658+
}
659+
660+
/*
661+
662+
=item nqp_get_sc()
663+
664+
Gets the serialization context with the specified handle. Returns
665+
NULL if it does not exist.
666+
667+
=cut
668+
669+
*/
670+
inline op nqp_get_sc(out PMC, in STR) {
671+
$1 = SC_get_sc(interp, $2);
672+
}
673+
674+
/*
675+
676+
=item nqp_create_sc()
677+
678+
Creates a serialization context with the specified handle, adds it
679+
to the registry and returns it.
680+
681+
=cut
682+
683+
*/
684+
inline op nqp_create_sc(out PMC, in STR) {
685+
$1 = pmc_new(interp, pmc_type(interp,
686+
Parrot_str_new(interp, "SerializationContext", 0)));
687+
VTABLE_set_string_native(interp, $1, $2);
688+
SC_set_sc(interp, $2, $1);
652689
}
653690

654691
/*
655692

656693
=item nqp_set_sc_object()
657694

658-
Stores an object in the current segment's serialization context.
695+
Stores an object in the serialization context keyed by handle and index.
659696

660697
=cut
661698

662699
*/
663-
inline op nqp_set_sc_object(in INT, in PMC) :base_core {
664-
SC_set_sc_object(interp, $1, $2);
700+
inline op nqp_set_sc_object(in STR, in INT, in PMC) :base_core {
701+
PMC *sc = SC_get_sc(interp, $1);
702+
if (!PMC_IS_NULL(sc))
703+
VTABLE_set_pmc_keyed_int(interp, sc, $2, $3);
704+
else
705+
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
706+
"Cannot fetch object from non-existance serialization context %Ss",
707+
$1);
665708
}

0 commit comments

Comments
 (0)