Skip to content
This repository
Browse code

Merge branch 'master' into kill-useless-defaults

Conflicts:
	src/PAST/NQP.pir
	tools/build/PARROT_REVISION
  • Loading branch information...
commit 9ed74283d144c326ef70796b938f09b57f0c41dd 2 parents 2ea19fd + 76afaff
Brian Gernhardt Benabik authored
1  src/6model/reprs/HashAttrStore.c
@@ -174,6 +174,7 @@ static storage_spec get_storage_spec(PARROT_INTERP, STable *st) {
174 174 storage_spec spec;
175 175 spec.inlineable = STORAGE_SPEC_REFERENCE;
176 176 spec.boxed_primitive = STORAGE_SPEC_BP_NONE;
  177 + spec.can_box = 0;
177 178 return spec;
178 179 }
179 180
1  src/6model/reprs/KnowHOWREPR.c
@@ -165,6 +165,7 @@ static storage_spec get_storage_spec(PARROT_INTERP, STable *st) {
165 165 storage_spec spec;
166 166 spec.inlineable = STORAGE_SPEC_REFERENCE;
167 167 spec.boxed_primitive = STORAGE_SPEC_BP_NONE;
  168 + spec.can_box = 0;
168 169 return spec;
169 170 }
170 171
1  src/6model/reprs/P6int.c
@@ -156,6 +156,7 @@ static storage_spec get_storage_spec(PARROT_INTERP, STable *st) {
156 156 spec.inlineable = STORAGE_SPEC_INLINED;
157 157 spec.bits = sizeof(INTVAL) * 8;
158 158 spec.boxed_primitive = STORAGE_SPEC_BP_INT;
  159 + spec.can_box = STORAGE_SPEC_CAN_BOX_INT;
159 160 return spec;
160 161 }
161 162
1  src/6model/reprs/P6num.c
@@ -156,6 +156,7 @@ static storage_spec get_storage_spec(PARROT_INTERP, STable *st) {
156 156 spec.inlineable = STORAGE_SPEC_INLINED;
157 157 spec.bits = sizeof(FLOATVAL) * 8;
158 158 spec.boxed_primitive = STORAGE_SPEC_BP_NUM;
  159 + spec.can_box = STORAGE_SPEC_CAN_BOX_NUM;
159 160 return spec;
160 161 }
161 162
9 src/6model/reprs/P6opaque.c
@@ -382,7 +382,6 @@ static PMC * instance_of(PARROT_INTERP, PMC *WHAT) {
382 382 /* Checks if a given object is defined (from the point of view of the
383 383 * representation). */
384 384 static INTVAL defined(PARROT_INTERP, PMC *obj) {
385   - P6opaqueInstance *instance = (P6opaqueInstance *)PMC_data(obj);
386 385 return !PObj_flag_TEST(private0, obj);
387 386 }
388 387
@@ -800,9 +799,17 @@ static void gc_free_repr(PARROT_INTERP, STable *st) {
800 799
801 800 /* Gets the storage specification for this representation. */
802 801 static storage_spec get_storage_spec(PARROT_INTERP, STable *st) {
  802 + P6opaqueREPRData *repr_data = (P6opaqueREPRData *)st->REPR_data;
803 803 storage_spec spec;
804 804 spec.inlineable = STORAGE_SPEC_REFERENCE;
805 805 spec.boxed_primitive = STORAGE_SPEC_BP_NONE;
  806 + spec.can_box = 0;
  807 + if (repr_data->unbox_int_offset)
  808 + spec.can_box += STORAGE_SPEC_CAN_BOX_INT;
  809 + if (repr_data->unbox_num_offset)
  810 + spec.can_box += STORAGE_SPEC_CAN_BOX_NUM;
  811 + if (repr_data->unbox_str_offset)
  812 + spec.can_box += STORAGE_SPEC_CAN_BOX_STR;
806 813 return spec;
807 814 }
808 815
1  src/6model/reprs/P6str.c
@@ -158,6 +158,7 @@ static storage_spec get_storage_spec(PARROT_INTERP, STable *st) {
158 158 spec.inlineable = STORAGE_SPEC_INLINED;
159 159 spec.bits = sizeof(STRING *) * 8;
160 160 spec.boxed_primitive = STORAGE_SPEC_BP_STR;
  161 + spec.can_box = STORAGE_SPEC_CAN_BOX_STR;
161 162 return spec;
162 163 }
163 164
1  src/6model/reprs/Uninstantiable.c
@@ -154,6 +154,7 @@ static storage_spec get_storage_spec(PARROT_INTERP, STable *st) {
154 154 storage_spec spec;
155 155 spec.inlineable = STORAGE_SPEC_REFERENCE;
156 156 spec.boxed_primitive = STORAGE_SPEC_BP_NONE;
  157 + spec.can_box = 0;
157 158 return spec;
158 159 }
159 160
8 src/6model/storage_spec.h
@@ -19,6 +19,9 @@ typedef struct {
19 19 * primitive type and can unbox, this says what primitive type
20 20 * that they unbox to. */
21 21 INTVAL boxed_primitive;
  22 +
  23 + /* The types that this one can box/unbox to. */
  24 + INTVAL can_box;
22 25 } storage_spec;
23 26
24 27 /* Inlined or not. */
@@ -31,4 +34,9 @@ typedef struct {
31 34 #define STORAGE_SPEC_BP_NUM 2
32 35 #define STORAGE_SPEC_BP_STR 3
33 36
  37 +/* can_box bit field values. */
  38 +#define STORAGE_SPEC_CAN_BOX_INT 1
  39 +#define STORAGE_SPEC_CAN_BOX_NUM 2
  40 +#define STORAGE_SPEC_CAN_BOX_STR 4
  41 +
34 42 #endif
148 src/NCI/CallBuilder.pm
... ... @@ -0,0 +1,148 @@
  1 +# This exposes the NQP NCI call builder interface and implements it in
  2 +# terms of the Parrot VM's Native Call Interface. It works in terms of
  3 +# argument descriptor hashes, which can have the following keys/values:
  4 +#
  5 +# type (the type of the argument)
  6 +# int8
  7 +# int16
  8 +# int32
  9 +# int
  10 +# num32
  11 +# num64
  12 +# str (A VM string we'll convert to null-terminated C string)
  13 +# ptr (Just any old pointer.)
  14 +# struct (Expects a CStruct representation; NYI)
  15 +# array (Expects elemtype; NYI)
  16 +# void (Valid for returns only)
  17 +#
  18 +# elemtype (only applicable for array)
  19 +# NYI
  20 +#
  21 +# The thunk it returns will be able to do some basic work on the arguments,
  22 +# but not everything. In general, it expects the following:
  23 +#
  24 +# int8 Something it can unbox_i
  25 +# int16 Something it can unbox_i
  26 +# int32 Something it can unbox_i
  27 +# int Something it can unbox_i
  28 +# num32 Something it can unbox_n
  29 +# num64 Something it can unbox_n
  30 +# str Something it can unbox_s
  31 +# ptr Pointer handle (which we will have returned in the past)
  32 +# struct A 6model object with CStruct representation (NYI)
  33 +# array NYI
  34 +#
  35 +# Since the language may not work directly in terms of those, we give it a
  36 +# chance to do some mapping of its own too for the arguments by passing an
  37 +# optional arg_mapper code ref.
  38 +#
  39 +# For returns, the return descriptor describes what to do. For all the numeric
  40 +# types and str, this is done by the language passing a "box_to" key with the
  41 +# type object of the target box type as the value. This also applies to ptr,
  42 +# but 'box_attr_name' must be supplied to say which attribute to stash the
  43 +# VM-level pointer object in. Currently, struct and array are NYI in this case.
  44 +
  45 +class NCI::CallBuilder {
  46 +
  47 + # Creates a thunk.
  48 + # $libname is the library to load from
  49 + # $funcname is the function to look up.
  50 + # @arg_descriptors - array of hashes describing arguments
  51 + # $return_descriptor - hash describing what's returned
  52 + method create_thunk($libname, $funcname, @arg_descriptors, $return_descriptor,
  53 + :$arg_mapper) {
  54 + # Look up thing to call.
  55 + my $lib := pir::loadlib__Ps($libname);
  56 + unless $lib {
  57 + pir::die("Could not locate native library '$libname'");
  58 + }
  59 + my $sig := sig_from(@arg_descriptors, $return_descriptor);
  60 + my $fun := pir::dlfunc__PPss($lib, $funcname, $sig);
  61 + unless $fun {
  62 + pir::die("Could not locate function '$funcname' in native library '$libname'");
  63 + }
  64 +
  65 + # Create call thunk.
  66 + -> *@pos_args, *%forbidden {
  67 + # Check and pre-process the args.
  68 + if %forbidden {
  69 + pir::die("Cannot pass named arguments to a native call")
  70 + }
  71 + if +@pos_args != +@arg_descriptors {
  72 + pir::die("Wrong number of arguments for native call; expected " ~
  73 + @arg_descriptors ~ " but got " ~ +@pos_args);
  74 + }
  75 + my @args := $arg_mapper ?? $arg_mapper(@pos_args) !! @pos_args;
  76 +
  77 + # Do our processing on them.
  78 + my @to_pass;
  79 + my @free_cstrings;
  80 + my $i := 0;
  81 + while $i < +@arg_descriptors {
  82 + my $type := pir::substr(@arg_descriptors[$i]<type>, 0, 3);
  83 + if $type eq 'int' {
  84 + @to_pass[$i] := nqp::unbox_i(@args[$i]);
  85 + }
  86 + elsif $type eq 'num' {
  87 + @to_pass[$i] := nqp::unbox_n(@args[$i]);
  88 + }
  89 + elsif $type eq 'ptr' {
  90 + @to_pass[$i] := @args[$i];
  91 + }
  92 + else {
  93 + pir::die("Cannot yet process " ~ @arg_descriptors[$i]<type>);
  94 + }
  95 + $i := $i + 1;
  96 + }
  97 +
  98 + # Make call.
  99 + my $result := $fun(|@to_pass);
  100 +
  101 + # Pre-process result.
  102 + my $ret_type := pir::substr($return_descriptor<type>, 0, 3);
  103 + if $ret_type eq 'int' {
  104 + return nqp::box_i($result, $return_descriptor<box_type>);
  105 + }
  106 + elsif $ret_type eq 'num' {
  107 + return nqp::box_n($result, $return_descriptor<box_type>);
  108 + }
  109 + elsif $ret_type eq 'ptr' {
  110 + my $wrap := nqp::create($return_descriptor<box_type>);
  111 + nqp::bindattr($wrap, $return_descriptor<box_type>,
  112 + $return_descriptor<attr_name>, $wrap);
  113 + return $wrap;
  114 + }
  115 + else {
  116 + pir::die("Cannot yet process " ~ $return_descriptor<type>);
  117 + }
  118 + }
  119 + }
  120 +
  121 + # Creates the Parrot signature from the descriptors.
  122 + my %sig_char := nqp::hash(
  123 + 'int8', 'c',
  124 + 'int16', 's',
  125 + 'int32', 'i',
  126 + 'int', 'l',
  127 + 'num32', 'f',
  128 + 'num64', 'd',
  129 + 'str', 'p',
  130 + 'ptr', 'p',
  131 + 'struct', 'p',
  132 + 'array', 'p'
  133 + );
  134 + sub sig_from(@arg_descriptors, $return_descriptor) {
  135 + my @chars;
  136 + unless pir::exists(%sig_char, $return_descriptor<type>) {
  137 + pir::die("Native call return type '" ~ $return_descriptor<type> ~ "' not handled");
  138 + }
  139 + @chars.push(%sig_char{$return_descriptor<type>});
  140 + for @arg_descriptors {
  141 + unless pir::exists(%sig_char, $_<type>) {
  142 + pir::die("Native call argument type '" ~ $_<type> ~ "' not handled");
  143 + }
  144 + @chars.push(%sig_char{$_<type>});
  145 + }
  146 + pir::join('', @chars)
  147 + }
  148 +}
3  src/PAST/NQP.pir
@@ -560,6 +560,9 @@ entry to produce the node to be returned.
560 560 maphash['unbox_i'] = 'repr_unbox_int__IP'
561 561 maphash['unbox_n'] = 'repr_unbox_num__NP'
562 562 maphash['unbox_s'] = 'repr_unbox_str__SP'
  563 + maphash['box_i'] = 'repr_box_int__PiP'
  564 + maphash['box_n'] = 'repr_box_num__PnP'
  565 + maphash['box_s'] = 'repr_box_str__PsP'
563 566 maphash['where'] = 'get_id__IP'
564 567
565 568 # control opcodes
10 src/pmc/stable.pmc
@@ -5,16 +5,16 @@
5 5 #include "../6model/sixmodelobject.h"
6 6
7 7 /* This is a source of type cache IDs (see notes below about them).
8   - * The lowest one is 4. This is to make the lower two bits available for
9   - * defined/undefined flags for the multi dispatch cache, which is the
10   - * main reason these IDs exist at all. */
  8 + * The lowest one is 8. This is to make the lower three bits available for
  9 + * defined/undefined flag and native type flags for the multi dispatch cache,
  10 + * which is the main reason these IDs exist at all. */
11 11 static INTVAL TypeCacheIDSource = 0;
12 12 static INTVAL get_next_type_cache_id(void) {
13 13 /* XXX The C# original is doing:
14   - * return Interlocked.Add(ref TypeCacheIDSource, 4);
  14 + * return Interlocked.Add(ref TypeCacheIDSource, 8);
15 15 * But we don't yet have an abstraction layer for an atomic addition
16 16 * so this is not yet threadsafe. */
17   - TypeCacheIDSource += 4;
  17 + TypeCacheIDSource += 8;
18 18 return TypeCacheIDSource;
19 19 }
20 20
13 tools/build/Makefile.in
@@ -115,7 +115,7 @@ STAGE0_SOURCES = \
115 115 src/stage0/NQPMO-s0.pir \
116 116 src/stage0/NQP-s0.pir \
117 117 src/stage0/NQPCORE.setting-s0.pir \
118   -
  118 +
119 119 STAGE0 = src/stage0
120 120 STAGE1 = src/stage1
121 121 STAGE2 = src/stage2
@@ -139,6 +139,9 @@ NQP_COMBINED_PIR = gen/NQP.pir
139 139 NQP_PBC = nqp.pbc
140 140 NQP_EXE = nqp$(EXE)
141 141
  142 +NCI_SOURCE = src/NCI/CallBuilder.pm
  143 +NCI_PBC = CallBuilder.pbc
  144 +
142 145 NQP_MO_SOURCES = src/how/Archetypes.pm src/how/RoleToRoleApplier.pm \
143 146 src/how/NQPConcreteRoleHOW.pm src/how/RoleToClassApplier.pm \
144 147 src/how/NQPParametricRoleHOW.pm src/how/NQPClassHOW.pm \
@@ -231,13 +234,14 @@ CLEANUPS = \
231 234 $(OPS_DIR)/*$(LOAD_EXT) \
232 235 $(DYNEXT_DIR)/*$(LOAD_EXT) \
233 236
234   -all: $(NQP_EXE) qregex
  237 +all: $(NQP_EXE) qregex $(NCI_PBC)
235 238
236 239 install: all
237 240 $(MKPATH) $(DESTDIR)$(PARROT_LIBRARY_DIR)
238 241 $(CP) $(MODULE_LOADER_PBC) $(DESTDIR)$(PARROT_LIBRARY_DIR)/$(MODULE_LOADER_PBC)
239 242 $(CP) $(PAST_PBC) $(DESTDIR)$(PARROT_LIBRARY_DIR)/$(PAST_PBC)
240 243 $(MKPATH) $(DESTDIR)$(NQP_LANG_DIR)/lib
  244 + $(MKPATH) $(DESTDIR)$(NQP_LANG_DIR)/lib/NCI
241 245 $(CP) $(P6REGEX_PBC) $(DESTDIR)$(NQP_LANG_DIR)/lib/$(P6REGEX_PBC)
242 246 $(CP) $(REGEX_PBC) $(DESTDIR)$(NQP_LANG_DIR)/lib/$(REGEX_PBC)
243 247 $(CP) $(HLL_PBC) $(DESTDIR)$(NQP_LANG_DIR)/lib/$(HLL_PBC)
@@ -245,6 +249,7 @@ install: all
245 249 $(CP) $(NQP_MO_PBC) $(DESTDIR)$(NQP_LANG_DIR)/lib/$(NQP_MO_PBC)
246 250 $(CP) $(NQP_PBC) $(DESTDIR)$(NQP_LANG_DIR)/lib/$(NQP_PBC)
247 251 $(CP) $(QREGEX_PBC) $(DESTDIR)$(NQP_LANG_DIR)/lib/$(QREGEX_PBC)
  252 + $(CP) $(NCI_PBC) $(DESTDIR)$(NQP_LANG_DIR)/lib/NCI/$(NCI_PBC)
248 253 $(MKPATH) $(DESTDIR)$(PARROT_BIN_DIR)
249 254 $(CP) $(NQP_EXE) $(DESTDIR)$(PARROT_BIN_DIR)/nqp$(EXE)
250 255 $(CHMOD) 755 $(DESTDIR)$(PARROT_BIN_DIR)/nqp$(EXE)
@@ -395,6 +400,10 @@ $(ALL_PBCS): $(STAGE2_PBCS)
395 400 $(NQP_EXE): $(NQP_PBC)
396 401 $(PBC_TO_EXE) $(NQP_PBC)
397 402
  403 +$(NCI_PBC): $(NQP_EXE)
  404 + ./$(NQP_EXE) --target=pir --output=src/gen/CallBuilder.pir $(NCI_SOURCE)
  405 + $(PARROT) -o $(NCI_PBC) src/gen/CallBuilder.pir
  406 +
398 407 $(DYNEXT_TARGET): $(DYNPMC) $(DYNOPS)
399 408 $(CP) $(DYNPMC) $(DYNEXT_DIR)
400 409 $(CP) $(DYNOPS) $(DYNEXT_DIR)

0 comments on commit 9ed7428

Please sign in to comment.
Something went wrong with that request. Please try again.