Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

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
@Benabik Benabik authored
View
1  src/6model/reprs/HashAttrStore.c
@@ -174,6 +174,7 @@ static storage_spec get_storage_spec(PARROT_INTERP, STable *st) {
storage_spec spec;
spec.inlineable = STORAGE_SPEC_REFERENCE;
spec.boxed_primitive = STORAGE_SPEC_BP_NONE;
+ spec.can_box = 0;
return spec;
}
View
1  src/6model/reprs/KnowHOWREPR.c
@@ -165,6 +165,7 @@ static storage_spec get_storage_spec(PARROT_INTERP, STable *st) {
storage_spec spec;
spec.inlineable = STORAGE_SPEC_REFERENCE;
spec.boxed_primitive = STORAGE_SPEC_BP_NONE;
+ spec.can_box = 0;
return spec;
}
View
1  src/6model/reprs/P6int.c
@@ -156,6 +156,7 @@ static storage_spec get_storage_spec(PARROT_INTERP, STable *st) {
spec.inlineable = STORAGE_SPEC_INLINED;
spec.bits = sizeof(INTVAL) * 8;
spec.boxed_primitive = STORAGE_SPEC_BP_INT;
+ spec.can_box = STORAGE_SPEC_CAN_BOX_INT;
return spec;
}
View
1  src/6model/reprs/P6num.c
@@ -156,6 +156,7 @@ static storage_spec get_storage_spec(PARROT_INTERP, STable *st) {
spec.inlineable = STORAGE_SPEC_INLINED;
spec.bits = sizeof(FLOATVAL) * 8;
spec.boxed_primitive = STORAGE_SPEC_BP_NUM;
+ spec.can_box = STORAGE_SPEC_CAN_BOX_NUM;
return spec;
}
View
9 src/6model/reprs/P6opaque.c
@@ -382,7 +382,6 @@ static PMC * instance_of(PARROT_INTERP, PMC *WHAT) {
/* Checks if a given object is defined (from the point of view of the
* representation). */
static INTVAL defined(PARROT_INTERP, PMC *obj) {
- P6opaqueInstance *instance = (P6opaqueInstance *)PMC_data(obj);
return !PObj_flag_TEST(private0, obj);
}
@@ -800,9 +799,17 @@ static void gc_free_repr(PARROT_INTERP, STable *st) {
/* Gets the storage specification for this representation. */
static storage_spec get_storage_spec(PARROT_INTERP, STable *st) {
+ P6opaqueREPRData *repr_data = (P6opaqueREPRData *)st->REPR_data;
storage_spec spec;
spec.inlineable = STORAGE_SPEC_REFERENCE;
spec.boxed_primitive = STORAGE_SPEC_BP_NONE;
+ spec.can_box = 0;
+ if (repr_data->unbox_int_offset)
+ spec.can_box += STORAGE_SPEC_CAN_BOX_INT;
+ if (repr_data->unbox_num_offset)
+ spec.can_box += STORAGE_SPEC_CAN_BOX_NUM;
+ if (repr_data->unbox_str_offset)
+ spec.can_box += STORAGE_SPEC_CAN_BOX_STR;
return spec;
}
View
1  src/6model/reprs/P6str.c
@@ -158,6 +158,7 @@ static storage_spec get_storage_spec(PARROT_INTERP, STable *st) {
spec.inlineable = STORAGE_SPEC_INLINED;
spec.bits = sizeof(STRING *) * 8;
spec.boxed_primitive = STORAGE_SPEC_BP_STR;
+ spec.can_box = STORAGE_SPEC_CAN_BOX_STR;
return spec;
}
View
1  src/6model/reprs/Uninstantiable.c
@@ -154,6 +154,7 @@ static storage_spec get_storage_spec(PARROT_INTERP, STable *st) {
storage_spec spec;
spec.inlineable = STORAGE_SPEC_REFERENCE;
spec.boxed_primitive = STORAGE_SPEC_BP_NONE;
+ spec.can_box = 0;
return spec;
}
View
8 src/6model/storage_spec.h
@@ -19,6 +19,9 @@ typedef struct {
* primitive type and can unbox, this says what primitive type
* that they unbox to. */
INTVAL boxed_primitive;
+
+ /* The types that this one can box/unbox to. */
+ INTVAL can_box;
} storage_spec;
/* Inlined or not. */
@@ -31,4 +34,9 @@ typedef struct {
#define STORAGE_SPEC_BP_NUM 2
#define STORAGE_SPEC_BP_STR 3
+/* can_box bit field values. */
+#define STORAGE_SPEC_CAN_BOX_INT 1
+#define STORAGE_SPEC_CAN_BOX_NUM 2
+#define STORAGE_SPEC_CAN_BOX_STR 4
+
#endif
View
148 src/NCI/CallBuilder.pm
@@ -0,0 +1,148 @@
+# This exposes the NQP NCI call builder interface and implements it in
+# terms of the Parrot VM's Native Call Interface. It works in terms of
+# argument descriptor hashes, which can have the following keys/values:
+#
+# type (the type of the argument)
+# int8
+# int16
+# int32
+# int
+# num32
+# num64
+# str (A VM string we'll convert to null-terminated C string)
+# ptr (Just any old pointer.)
+# struct (Expects a CStruct representation; NYI)
+# array (Expects elemtype; NYI)
+# void (Valid for returns only)
+#
+# elemtype (only applicable for array)
+# NYI
+#
+# The thunk it returns will be able to do some basic work on the arguments,
+# but not everything. In general, it expects the following:
+#
+# int8 Something it can unbox_i
+# int16 Something it can unbox_i
+# int32 Something it can unbox_i
+# int Something it can unbox_i
+# num32 Something it can unbox_n
+# num64 Something it can unbox_n
+# str Something it can unbox_s
+# ptr Pointer handle (which we will have returned in the past)
+# struct A 6model object with CStruct representation (NYI)
+# array NYI
+#
+# Since the language may not work directly in terms of those, we give it a
+# chance to do some mapping of its own too for the arguments by passing an
+# optional arg_mapper code ref.
+#
+# For returns, the return descriptor describes what to do. For all the numeric
+# types and str, this is done by the language passing a "box_to" key with the
+# type object of the target box type as the value. This also applies to ptr,
+# but 'box_attr_name' must be supplied to say which attribute to stash the
+# VM-level pointer object in. Currently, struct and array are NYI in this case.
+
+class NCI::CallBuilder {
+
+ # Creates a thunk.
+ # $libname is the library to load from
+ # $funcname is the function to look up.
+ # @arg_descriptors - array of hashes describing arguments
+ # $return_descriptor - hash describing what's returned
+ method create_thunk($libname, $funcname, @arg_descriptors, $return_descriptor,
+ :$arg_mapper) {
+ # Look up thing to call.
+ my $lib := pir::loadlib__Ps($libname);
+ unless $lib {
+ pir::die("Could not locate native library '$libname'");
+ }
+ my $sig := sig_from(@arg_descriptors, $return_descriptor);
+ my $fun := pir::dlfunc__PPss($lib, $funcname, $sig);
+ unless $fun {
+ pir::die("Could not locate function '$funcname' in native library '$libname'");
+ }
+
+ # Create call thunk.
+ -> *@pos_args, *%forbidden {
+ # Check and pre-process the args.
+ if %forbidden {
+ pir::die("Cannot pass named arguments to a native call")
+ }
+ if +@pos_args != +@arg_descriptors {
+ pir::die("Wrong number of arguments for native call; expected " ~
+ @arg_descriptors ~ " but got " ~ +@pos_args);
+ }
+ my @args := $arg_mapper ?? $arg_mapper(@pos_args) !! @pos_args;
+
+ # Do our processing on them.
+ my @to_pass;
+ my @free_cstrings;
+ my $i := 0;
+ while $i < +@arg_descriptors {
+ my $type := pir::substr(@arg_descriptors[$i]<type>, 0, 3);
+ if $type eq 'int' {
+ @to_pass[$i] := nqp::unbox_i(@args[$i]);
+ }
+ elsif $type eq 'num' {
+ @to_pass[$i] := nqp::unbox_n(@args[$i]);
+ }
+ elsif $type eq 'ptr' {
+ @to_pass[$i] := @args[$i];
+ }
+ else {
+ pir::die("Cannot yet process " ~ @arg_descriptors[$i]<type>);
+ }
+ $i := $i + 1;
+ }
+
+ # Make call.
+ my $result := $fun(|@to_pass);
+
+ # Pre-process result.
+ my $ret_type := pir::substr($return_descriptor<type>, 0, 3);
+ if $ret_type eq 'int' {
+ return nqp::box_i($result, $return_descriptor<box_type>);
+ }
+ elsif $ret_type eq 'num' {
+ return nqp::box_n($result, $return_descriptor<box_type>);
+ }
+ elsif $ret_type eq 'ptr' {
+ my $wrap := nqp::create($return_descriptor<box_type>);
+ nqp::bindattr($wrap, $return_descriptor<box_type>,
+ $return_descriptor<attr_name>, $wrap);
+ return $wrap;
+ }
+ else {
+ pir::die("Cannot yet process " ~ $return_descriptor<type>);
+ }
+ }
+ }
+
+ # Creates the Parrot signature from the descriptors.
+ my %sig_char := nqp::hash(
+ 'int8', 'c',
+ 'int16', 's',
+ 'int32', 'i',
+ 'int', 'l',
+ 'num32', 'f',
+ 'num64', 'd',
+ 'str', 'p',
+ 'ptr', 'p',
+ 'struct', 'p',
+ 'array', 'p'
+ );
+ sub sig_from(@arg_descriptors, $return_descriptor) {
+ my @chars;
+ unless pir::exists(%sig_char, $return_descriptor<type>) {
+ pir::die("Native call return type '" ~ $return_descriptor<type> ~ "' not handled");
+ }
+ @chars.push(%sig_char{$return_descriptor<type>});
+ for @arg_descriptors {
+ unless pir::exists(%sig_char, $_<type>) {
+ pir::die("Native call argument type '" ~ $_<type> ~ "' not handled");
+ }
+ @chars.push(%sig_char{$_<type>});
+ }
+ pir::join('', @chars)
+ }
+}
View
3  src/PAST/NQP.pir
@@ -560,6 +560,9 @@ entry to produce the node to be returned.
maphash['unbox_i'] = 'repr_unbox_int__IP'
maphash['unbox_n'] = 'repr_unbox_num__NP'
maphash['unbox_s'] = 'repr_unbox_str__SP'
+ maphash['box_i'] = 'repr_box_int__PiP'
+ maphash['box_n'] = 'repr_box_num__PnP'
+ maphash['box_s'] = 'repr_box_str__PsP'
maphash['where'] = 'get_id__IP'
# control opcodes
View
10 src/pmc/stable.pmc
@@ -5,16 +5,16 @@
#include "../6model/sixmodelobject.h"
/* This is a source of type cache IDs (see notes below about them).
- * The lowest one is 4. This is to make the lower two bits available for
- * defined/undefined flags for the multi dispatch cache, which is the
- * main reason these IDs exist at all. */
+ * The lowest one is 8. This is to make the lower three bits available for
+ * defined/undefined flag and native type flags for the multi dispatch cache,
+ * which is the main reason these IDs exist at all. */
static INTVAL TypeCacheIDSource = 0;
static INTVAL get_next_type_cache_id(void) {
/* XXX The C# original is doing:
- * return Interlocked.Add(ref TypeCacheIDSource, 4);
+ * return Interlocked.Add(ref TypeCacheIDSource, 8);
* But we don't yet have an abstraction layer for an atomic addition
* so this is not yet threadsafe. */
- TypeCacheIDSource += 4;
+ TypeCacheIDSource += 8;
return TypeCacheIDSource;
}
View
13 tools/build/Makefile.in
@@ -115,7 +115,7 @@ STAGE0_SOURCES = \
src/stage0/NQPMO-s0.pir \
src/stage0/NQP-s0.pir \
src/stage0/NQPCORE.setting-s0.pir \
-
+
STAGE0 = src/stage0
STAGE1 = src/stage1
STAGE2 = src/stage2
@@ -139,6 +139,9 @@ NQP_COMBINED_PIR = gen/NQP.pir
NQP_PBC = nqp.pbc
NQP_EXE = nqp$(EXE)
+NCI_SOURCE = src/NCI/CallBuilder.pm
+NCI_PBC = CallBuilder.pbc
+
NQP_MO_SOURCES = src/how/Archetypes.pm src/how/RoleToRoleApplier.pm \
src/how/NQPConcreteRoleHOW.pm src/how/RoleToClassApplier.pm \
src/how/NQPParametricRoleHOW.pm src/how/NQPClassHOW.pm \
@@ -231,13 +234,14 @@ CLEANUPS = \
$(OPS_DIR)/*$(LOAD_EXT) \
$(DYNEXT_DIR)/*$(LOAD_EXT) \
-all: $(NQP_EXE) qregex
+all: $(NQP_EXE) qregex $(NCI_PBC)
install: all
$(MKPATH) $(DESTDIR)$(PARROT_LIBRARY_DIR)
$(CP) $(MODULE_LOADER_PBC) $(DESTDIR)$(PARROT_LIBRARY_DIR)/$(MODULE_LOADER_PBC)
$(CP) $(PAST_PBC) $(DESTDIR)$(PARROT_LIBRARY_DIR)/$(PAST_PBC)
$(MKPATH) $(DESTDIR)$(NQP_LANG_DIR)/lib
+ $(MKPATH) $(DESTDIR)$(NQP_LANG_DIR)/lib/NCI
$(CP) $(P6REGEX_PBC) $(DESTDIR)$(NQP_LANG_DIR)/lib/$(P6REGEX_PBC)
$(CP) $(REGEX_PBC) $(DESTDIR)$(NQP_LANG_DIR)/lib/$(REGEX_PBC)
$(CP) $(HLL_PBC) $(DESTDIR)$(NQP_LANG_DIR)/lib/$(HLL_PBC)
@@ -245,6 +249,7 @@ install: all
$(CP) $(NQP_MO_PBC) $(DESTDIR)$(NQP_LANG_DIR)/lib/$(NQP_MO_PBC)
$(CP) $(NQP_PBC) $(DESTDIR)$(NQP_LANG_DIR)/lib/$(NQP_PBC)
$(CP) $(QREGEX_PBC) $(DESTDIR)$(NQP_LANG_DIR)/lib/$(QREGEX_PBC)
+ $(CP) $(NCI_PBC) $(DESTDIR)$(NQP_LANG_DIR)/lib/NCI/$(NCI_PBC)
$(MKPATH) $(DESTDIR)$(PARROT_BIN_DIR)
$(CP) $(NQP_EXE) $(DESTDIR)$(PARROT_BIN_DIR)/nqp$(EXE)
$(CHMOD) 755 $(DESTDIR)$(PARROT_BIN_DIR)/nqp$(EXE)
@@ -395,6 +400,10 @@ $(ALL_PBCS): $(STAGE2_PBCS)
$(NQP_EXE): $(NQP_PBC)
$(PBC_TO_EXE) $(NQP_PBC)
+$(NCI_PBC): $(NQP_EXE)
+ ./$(NQP_EXE) --target=pir --output=src/gen/CallBuilder.pir $(NCI_SOURCE)
+ $(PARROT) -o $(NCI_PBC) src/gen/CallBuilder.pir
+
$(DYNEXT_TARGET): $(DYNPMC) $(DYNOPS)
$(CP) $(DYNPMC) $(DYNEXT_DIR)
$(CP) $(DYNOPS) $(DYNEXT_DIR)
Please sign in to comment.
Something went wrong with that request. Please try again.