changeset 62:b218af069da7

merge
author Mike Pavone <pavone@retrodev.com>
date Sat, 10 Oct 2009 16:43:37 -0400
parents fa24ef3b026f (current diff) 1b86a1ee500a (diff)
children 04baa003de5a
files runtime/object.c runtime/object.h
diffstat 8 files changed, 385 insertions(+), 39 deletions(-) [+]
line wrap: on
line diff
--- a/cbackend.rhope	Thu Oct 08 23:16:26 2009 -0400
+++ b/cbackend.rhope	Sat Oct 10 16:43:37 2009 -0400
@@ -154,13 +154,36 @@
 			}{
 				typename <- "Array"
 			}
+			primitive <- No
 		}{
-			typename <- [type]Name >>
+			,regulartype <- [("Naked","Raw Pointer")]Find[variant]
+			{
+				[("Int32","Int16","Int8")]Find[[type]Name >>]
+				{
+					primitive <- Yes
+					[[type]Name >>]Slice[3] {}
+					{ typename <- [["int"]Append[~]]Append["_t"] }
+				}{
+					,regulartype <- [("UInt32","UInt16","UInt8")]Find[[type]Name >>]
+					{
+						primitive <- Yes
+						[[type]Name >>]Slice[4] {}
+						{ typename <- [["uint"]Append[~]]Append["_t"] }
+					}
+				}
+			}
+			
+			Val[regulartype]
+			{
+				typename <- [type]Name >>
+				primitive <- No
+			}
 		}
 	}{
 		typename <- type
 		param <- "Any Type"
 		variant <- "boxed"
+		primitive <- No
 	}
 	Val[typename]
 	{ array <- "" }
@@ -170,7 +193,12 @@
 	}{
 		[("Naked","Raw Pointer")]Find[variant]
 		{
-			prefix <- "nt_"
+			If[primitive]
+			{
+				prefix <- ""
+			}{
+				prefix <- "nt_"
+			}
 		}{
 			prefix <- "t_"
 		}
@@ -182,7 +210,13 @@
 			postfix <- " *"
 		}
 	}
-	out <- [[prefix]Append[Escape Rhope Name[typename]]]Append[postfix]
+	If[primitive]
+	{
+		escaped <- Val[typename]	
+	}{
+		escaped <- Escape Rhope Name[typename]
+	}
+	out <- [[prefix]Append[escaped]]Append[postfix]
 }
 
 _Type Def C Type[text,field:out]
@@ -484,6 +518,31 @@
 	out <- [func]Add Statement[ [dest]Append[[[" = copy_object("]Append[dest]]Append[")"]] ]
 }
 
+Box@C Function[func,pdest,psource,type:out]
+{
+	dest <- [pdest]Make Op[func]
+	source <- [psource]Make Op[func]
+	out <- [func]Add Statement[ 
+		[[[[[dest
+		]Append[" = naked_to_boxed("]
+		]Append[ [[func]Type Registry >>]Type ID[[type]Name >>] ]
+		]Append[", &"]
+		]Append[source]
+		]Append[")"] ]
+}
+
+Unbox@C Function[func,pdest,psource:out]
+{
+	dest <- [pdest]Make Op[func]
+	source <- [psource]Make Op[func]
+	out <- [func]Add Statement[ 
+		[[[["boxed_to_naked("
+		]Append[source]
+		]Append[", &"]
+		]Append[dest]
+		]Append[")"] ]
+}
+
 _Function Arg C[func,val,inputnum:out]
 {
 	out <- [func]Add Statement[
--- a/nworker.rhope	Thu Oct 08 23:16:26 2009 -0400
+++ b/nworker.rhope	Sat Oct 10 16:43:37 2009 -0400
@@ -766,28 +766,46 @@
 Make Init[func,field:out]
 {
 	name <- [field]Index[0]
-	out <- [func]Set Field Null["obj", name]
+	variant <- [[field]Index[1]]Variant >>
+	If[[variant] = ["Boxed"]]
+	{
+		out <- [func]Set Field Null["obj", name]
+	}{
+		out <- func
+	}
 }
 
 Make Copy[func,field:out]
 {
 	name <- [field]Index[0]
-	got <- [func]Read Field["obj", name] {}
-	{ 
-		stream <- [[got]Instruction Stream
-			]AddRef No Dest[~] 
-		out <- [got]Do If[~, stream]
+	variant <- [[field]Index[1]]Variant >>
+	If[[variant] = ["Boxed"]]
+	{
+		got <- [func]Read Field["obj", name] {}
+		{ 
+			stream <- [[got]Instruction Stream
+				]AddRef No Dest[~] 
+			out <- [got]Do If[~, stream]
+		}
+	}{
+		out <- func
 	}
 }
 
 Make Cleanup[func,field:out]
 {
 	name <- [field]Index[0]
-	got <- [func]Read Field["obj", name] {}
-	{ 
-		stream <- [[got]Instruction Stream
-			]Release[~] 
-		out <- [got]Do If[~, stream]
+	variant <- [[field]Index[1]]Variant >>
+	If[[variant] = ["Boxed"]]
+	{
+		got <- [func]Read Field["obj", name] {}
+		{ 
+			stream <- [[got]Instruction Stream
+				]Release[~] 
+			out <- [got]Do If[~, stream]
+		}
+	}{
+		out <- func
 	}
 }
 
--- a/parser_old.rhope	Thu Oct 08 23:16:26 2009 -0400
+++ b/parser_old.rhope	Sat Oct 10 16:43:37 2009 -0400
@@ -666,14 +666,39 @@
 	out <- [[Build["Blueprint Field"]]Name <<[name]]Type <<[type]
 }
 
-Process Blueprint Field[list,field,delim:out]
+Process Blueprint Field[list,field,params:out]
 {
-	parts <- [field]Split[delim]
-	If[[[parts]Length] > [1]]
+	,name <- [field]Get DString[[params]List Begin >>]
 	{
-		out <- [list]Append[New@Blueprint Field[[parts]Index[1], [parts]Index[0]]]
-	}{
-		out <- [list]Append[New@Blueprint Field[[parts]Index[0], "Any Type"]]
+		type info <- Parse List[~,params,()]
+		type <- [type info]Index[0]
+		{
+			If[[Type Of[~]] = ["Named Pipe Node"]]
+			{
+				before variant <- Type Instance[[type]Name >>]
+			}{
+				before variant <-  [type]Params <<[ Map[[type]Params >>, "Remove Named Pipe Node"] ]
+			}
+			variant <- [type info]Index[1]
+			{
+				,warn <- If[[Type Of[~]] = ["Named Pipe Node"]]
+				{
+					fieldtype,warn <- [before variant]Set Variant[[variant]Name >>]
+				}
+				Val[warn]
+				{
+					Print[[[["Warning: Invalid variant for type "]Append[[before variant]Name >>]]Append[" on field "]]Append[name]]
+					fieldtype <- Val[before variant]
+				}
+			}{
+				fieldtype <- Val[before variant]
+			}
+		}{
+			fieldtype <- Type Instance["Any Type"]
+		}
+		out <- [list]Append[New@Blueprint Field[name, fieldtype]]
+	} {} {} {
+		out <- [list]Append[New@Blueprint Field[name, Type Instance["Any Type"]]]
 	}
 }
 
@@ -779,7 +804,7 @@
 		{
 			body lines <- [body]Split["\n"]
 			more lines <- [[[body lines]Length] - [1]] + [name lines]
-			fields <- Fold[["Process Blueprint Field"]Set Input[2, [params]Blueprint Type Delim >>], New@List[], Filter[Map[body lines, ["Trim"]Set Input[1,"\n\r\t "]], "Filter Empty"]]
+			fields <- Fold[["Process Blueprint Field"]Set Input[2, params], New@List[], Filter[Map[body lines, ["Trim"]Set Input[1,"\n\r\t "]], "Filter Empty"]]
 			new tree <- [tree]Blueprints << [ [[tree]Blueprints >>]Set[name, New@Blueprint Definition[name, fields]] ]
 			out <- Null[~, params, new tree, [lines] + [more lines]]
 		} {} {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runtime/block_alloc.h	Sat Oct 10 16:43:37 2009 -0400
@@ -0,0 +1,13 @@
+#ifndef BLOCK_ALLOC_H_
+#define BLOCK_ALLOC_H_
+
+#ifdef _WIN32
+#define BLOCK_SIZE 1024*16
+#include <windows.h>
+
+#define block_alloc(size)      VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
+#define block_free(block,size) VirtualFree(block, size, MEM_RELEASE)
+
+#endif
+
+#endif //BLOCK_ALLOC_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runtime/fixed_alloc.c	Sat Oct 10 16:43:37 2009 -0400
@@ -0,0 +1,153 @@
+#include "fixed_alloc.h"
+#include <stdlib.h>
+
+uint16_t max_free[(MAX_SIZE-MIN_SIZE)/STRIDE];
+
+void fixed_alloc_init()
+{
+	int i;
+	for(i = 0; i < (MAX_SIZE-MIN_SIZE)/STRIDE; ++i)
+		max_free[i] = (BLOCK_SIZE - sizeof(mem_block)+1)*8/((i*STRIDE+MIN_SIZE)*8+1);
+}
+
+mem_manager * new_mem_manager()
+{
+	int i;
+	mem_manager * ret = malloc(sizeof(mem_manager));
+	memset(ret, 0, sizeof(mem_manager));
+	return ret;
+}
+
+void * falloc(size_t size, mem_manager * manager)
+{
+	uint16_t i,bit;
+	uint16_t bucket;
+	mem_block * block,*temp;
+	if(size > MAX_SIZE)
+		return malloc(size);
+	//puts("falloc");
+	size = ADJUST_SIZE(size);
+	bucket = (size-MIN_SIZE)/STRIDE;
+	block = manager->inuse[bucket];
+	if(!block)
+	{
+		block = manager->freelist;
+		if(block)
+		{
+			--manager->freecount;
+			manager->freelist = block->next;
+		}
+		else
+		{
+			block = block_alloc(BLOCK_SIZE);
+		}
+		manager->inuse[bucket] = block;
+		block->next = NULL;
+		block->last = NULL;
+		block->numfree = max_free[bucket];
+		block->firstfree = 0;
+		memset(block->bitmap, 0xFF, max_free[bucket]/8+1);
+	}
+	//printf("block: %X,numfree: %d, firstfree: %d, maxfree: %d\n", block, block->numfree, block->firstfree, max_free[bucket]);
+	/*if(block->numfree > max_free[bucket])
+	{
+		puts("uh oh!");
+		exit(1);
+	}*/
+	//find first free 
+	i = block->firstfree;
+	while(!block->bitmap[i])
+		++i;
+	//printf("i:%d,bitmap:%X\n", i, block->bitmap[i]);
+	bit = 0;
+	while(!((1 << bit) & block->bitmap[i]))
+		++bit;
+	//update free bitmask
+	block->bitmap[i] ^= 1 << bit;
+	//If current bitmap has no more free elements, set firstfree to the next bitmap
+	if(!block->bitmap[i])
+		block->firstfree = i+1;
+	else
+		block->firstfree = i;
+	--block->numfree;
+	if(!block->numfree)
+	{
+		//Remove from linked list if there are no more free elements
+		manager->inuse[bucket] = block->next;
+		if(block->next)
+			block->next->last = block->last;
+	}
+	i = i*8+bit;
+	//printf("%X\n", ((char *)block)+BLOCK_SIZE-((i+1)*size));
+	return (void *)(((char *)block)+BLOCK_SIZE-((i+1)*size));
+}
+
+void ffree(void * ptr, size_t size, mem_manager * manager)
+{
+	mem_block * block,*temp;
+	uint16_t i,bit,bucket;
+	if(size > MAX_SIZE)
+	{
+		free(ptr);
+		return;
+	}
+	//puts("ffree");
+	size = ADJUST_SIZE(size);
+	block = GET_BLOCK(ptr);
+	i = (((((char *)block) + BLOCK_SIZE) - ((char *)ptr))/size)-1;
+	bit = i & 0x7;
+	i = (i&0xFFFFFFF8) >> 3;
+	//printf("ptr:%X,block:%X,i:%d,bit:%d\n", ptr,block,bit,i);
+	block->bitmap[i] |= 1 << bit;
+	if(i < block->firstfree)
+		block->firstfree = i;
+	++block->numfree;
+	bucket = (size-MIN_SIZE)/STRIDE;
+	//printf("numfree:%d,max_free:%d,last:%X,next:%X\n", block->numfree, max_free[bucket], block->last, block->next);
+	/*if(block->numfree > max_free[bucket])
+	{
+		puts("uh oh!");
+		exit(1);
+	}*/
+	if(block->numfree == max_free[bucket])
+	{
+		//Block is now unused, remove it from the inuse list
+		if(block->last)
+			block->last->next = block->next;
+		else
+			manager->inuse[bucket] = block->next;
+		if(block->next)
+			block->next->last = block->last;
+		if(manager->freecount == MAX_FREE)
+			block_free(block, BLOCK_SIZE);
+		else
+		{
+			block->next = manager->freelist;
+			manager->freelist = block;
+			++manager->freecount;
+		}
+	} else if(block->numfree == 1) {
+		//Block was previously full, add it to the inuse list
+		block->next = manager->inuse[bucket];
+		block->last = NULL;
+		manager->inuse[bucket] = block;
+		if(block->next)
+			block->next->last = block;
+	} else if(block->next && block->next->numfree < block->numfree) {
+		//We want to use more filled blockes before less filled ones
+		//so we can return empty ones to the OS more often
+		//so if we now have more free nodes in this block than the 
+		//next one swap them
+		temp = block->next;
+		block->next = temp->next;
+		temp->last = block->last;
+		block->last = temp;
+		temp->next = block;
+		if(block->next)
+			block->next->last = block;
+		if(temp->last)
+			temp->last->next = temp;
+		else
+			manager->inuse[bucket] = temp;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runtime/fixed_alloc.h	Sat Oct 10 16:43:37 2009 -0400
@@ -0,0 +1,40 @@
+#ifndef FIXED_ALLOC_H_
+#define FIXED_ALLOC_H_
+
+#include <stddef.h>
+#include "plat_types.h"
+#include "block_alloc.h"
+
+#define GET_BLOCK(ptr) ((void*)(((uint32_t)(ptr))&(~(BLOCK_SIZE-1))))
+
+#define MAX_SIZE   (BLOCK_SIZE/32)
+#define STRIDE     (BLOCK_SIZE/1024)
+#define MIN_SIZE   (BLOCK_SIZE/1024)
+#define MAX_FREE   16
+
+#define ADJUST_SIZE(requested) (((requested)+(STRIDE-1)) & (~(STRIDE-1)))
+
+
+#pragma pack(push,1)
+typedef struct mem_block {
+	struct mem_block *next;
+	struct mem_block *last;
+	uint16_t         numfree;
+	uint16_t          firstfree;
+	uint8_t          bitmap[1];
+} mem_block;
+#pragma pack(pop)
+
+//num_elements = (BLOCK_SIZE - sizeof(mem_block)+1)*8/(sizeof(element)*8+1)
+typedef struct {
+	mem_block *freelist;
+	mem_block *inuse[(MAX_SIZE-MIN_SIZE)/STRIDE];
+	uint32_t freecount;
+} mem_manager;
+
+void fixed_alloc_init();
+mem_manager * new_mem_manager();
+void * falloc(size_t size, mem_manager * manager);
+void ffree(void * ptr, size_t size, mem_manager * manager);
+
+#endif //FIXED_ALLOC_H_
--- a/runtime/object.c	Thu Oct 08 23:16:26 2009 -0400
+++ b/runtime/object.c	Sat Oct 10 16:43:37 2009 -0400
@@ -3,12 +3,15 @@
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
+#include "fixed_alloc.h"
 
 blueprint ** registered_types = NULL;
 uint32_t max_registered_type = 0;
 uint32_t type_storage = 0;
 
+mem_manager * manager = NULL;
 /*
+
 returntype call_method(uint32_t methodid, calldata * params)
 {
 	int i;
@@ -126,19 +129,13 @@
 
 object * alloc_object(blueprint * bp)
 {
-	//TODO: Replace with something more performant
-	return malloc(bp->boxed_size);
-}
-
-void * alloc_variable(uint32_t size)
-{
-	return malloc(size);
+	return falloc(bp->boxed_size, manager);
+	//return malloc(bp->boxed_size);
 }
 
 void dealloc_object(blueprint * bp, object * obj)
 {
-	//TODO: Replace with something more performant
-	free(obj);
+	ffree(obj, bp->boxed_size, manager);
 }
 
 object * new_object(uint32_t type)
@@ -173,7 +170,7 @@
 	multisize * ret;
 	if(type >= max_registered_type || !registered_types[type])
 		return NULL;
-	ret = alloc_variable(sizeof(multisize) + type);
+	ret = falloc(sizeof(multisize) + size, manager);
 	if(ret)
 	{
 		bp = registered_types[type];
@@ -196,7 +193,7 @@
 	bp = get_blueprint(tocopy);
 	if(bp->size < 0) {
 		mtocopy = (multisize *)tocopy;
-		mcopy = alloc_variable(sizeof(multisize) + mtocopy->size);
+		mcopy = falloc(sizeof(multisize) + mtocopy->size, manager);
 		mcopy->size = mtocopy->size;
 		memcpy(((char *)mcopy)+sizeof(multisize), ((char *)mtocopy)+sizeof(multisize), mtocopy->size);
 		copy = (object *)mcopy;
@@ -211,18 +208,33 @@
 	return copy;
 }
 
-void free_object(object * obj)
+object * naked_to_boxed(uint32_t type, void * rawdata)
 {
-	blueprint * bp = get_blueprint(obj);
-	if(bp->cleanup)
-		bp->cleanup(obj);
-	dealloc_object(bp, obj);
+	object * dest;
+	blueprint * bp = get_blueprint_byid(type);
+	if(!bp->boxed_size)
+		return NULL; //We don't know how big a naked multi-size object is so we can't do anything with it
+	dest = alloc_object(bp);
+	memcpy(((char *)dest) + sizeof(object), rawdata, bp->size);
+	dest->bprint = bp;
+	rh_atomic_set(dest, refcount, 1);
+	bp->copy(dest);
+	return dest;
+}
+
+void boxed_to_naked(object * src, void * dest)
+{
+	blueprint * bp = get_blueprint(src);
+	if(!bp->boxed_size)
+		return; //We don't know how big a naked multi-size object is so we can't do anything with it
+	memcpy(dest, ((char *)src) + sizeof(object), bp->size);
+	bp->copy(src);
 }
 
 void release_ref(object * obj)
 {
 	if(rh_atomic_sub_testzero(obj, refcount, 1))
-		free_object(obj);
+		get_blueprint(obj)->free(obj);
 }
 
 void check_type_storage(type)
@@ -268,18 +280,41 @@
 {
 }
 
+void normal_free(object * obj)
+{
+	blueprint * bp = get_blueprint(obj);
+	if(bp->cleanup)
+		bp->cleanup(obj);
+	ffree(obj, bp->boxed_size, manager);
+}
+
+void multi_free(object * obj)
+{
+	multisize * multi = (multisize *)obj;
+	blueprint * bp = get_blueprint(obj);
+	if(bp->cleanup)
+		bp->cleanup(obj);
+	ffree(multi, sizeof(multi) + multi->size, manager);
+}
+
 blueprint * new_blueprint(uint32_t type, uint32_t size, special_func init, special_func copy, special_func cleanup)
 {
 	blueprint * bp = malloc(sizeof(blueprint));
+	//dirty hack!, move elsewhere
+	if (!manager) {
+		fixed_alloc_init();
+		manager = new_mem_manager();
+	}
 	if(bp)
 	{
 		bp->size = size;
-		bp->boxed_size = size >= 0 ? size + sizeof(object) : size;
+		bp->boxed_size = size >= 0 ? size + sizeof(object) : 0;
 		bp->method_lookup = bp->getter_lookup = bp->setter_lookup = bp->convert_to = bp->convert_from = NULL;
 		bp->type_id = type;
 		bp->init = init ? init : default_action;
 		bp->copy = copy ? copy : default_action;
 		bp->cleanup = cleanup ? cleanup : default_action;
+		bp->free = size >= 0 ? normal_free : multi_free;
 		bp->first_methodid = bp->last_methodid = bp->first_getfieldid = bp->last_getfieldid = bp->first_setfieldid = bp->last_setfieldid = bp->first_convertto = bp->last_convertto = bp->first_convertfrom = bp->last_convertfrom = 0;
 		//TODO: Handle names
 		bp->name = NULL;
--- a/runtime/object.h	Thu Oct 08 23:16:26 2009 -0400
+++ b/runtime/object.h	Sat Oct 10 16:43:37 2009 -0400
@@ -14,6 +14,7 @@
 	special_func   init;
 	special_func   copy;
 	special_func   cleanup;
+	special_func   free;
 	struct object  *name;
 	uint32_t       type_id;
 	uint32_t       first_methodid;
@@ -76,6 +77,8 @@
 returntype convert_to(uint32_t convertto, calldata * params);
 returntype convert_from(uint32_t convertfrom, calldata * params);
 object * copy_object(object * tocopy);
+object * naked_to_boxed(uint32_t type, void * rawdata);
+void boxed_to_naked(object * src, void * dest);
 returntype coerce_value(uint32_t type, calldata * params);
 blueprint * get_blueprint_byid(uint32_t type);