changeset 111:13dfe8214254

Merge
author Mike Pavone <pavone@retrodev.com>
date Mon, 11 Oct 2010 20:04:48 -0400
parents a7add4db4a25 (current diff) 439db471f595 (diff)
children fd23ab2c1a73
files string.rhope
diffstat 14 files changed, 271 insertions(+), 672 deletions(-) [+]
line wrap: on
line diff
--- a/array.rhope	Wed Oct 06 23:46:47 2010 +0000
+++ b/array.rhope	Mon Oct 11 20:04:48 2010 -0400
@@ -20,6 +20,7 @@
 {
 	_internal_array_copyout[array(Array), index(Int32,Naked), dest(Any Type,Boxed,Mutable):dest]
 	_internal_array_copyin[array(Array,Boxed,Mutable), index(Int32,Naked), val:array]
+	_internal_array_copychunk[source(Array), sindex(Int32,Naked), dest(Array,Boxed,Mutable), dindex(Int32,Naked), len(Int32,Naked):dest]
 	_internal_array_getboxed[array(Boxed Array), index(Int32,Naked):out]
 	_internal_array_setboxed[array(Boxed Array,Boxed,Mutable), index(Int32,Naked), val:array]
 	_internal_array_allocboxed[size(Int32,Naked):out(Boxed Array)]
--- a/cbackend.rhope	Wed Oct 06 23:46:47 2010 +0000
+++ b/cbackend.rhope	Mon Oct 11 20:04:48 2010 -0400
@@ -1181,6 +1181,11 @@
 	out <- [text]Append[ [["object * _const_"]Append[Escape Rhope Name[name]]]Append[";\n"] ]
 }
 
+_Consts C Release[text,value,name:out]
+{
+	out <- [text]Append[ [["\trelease_ref(_const_"]Append[Escape Rhope Name[name]]]Append[");\n"] ]
+}
+
 _List Literal El[text,val,index,type reg:out]
 {
 	out <- [[[[text
@@ -1467,8 +1472,9 @@
 #include \"blueprint.h\"
 #include \"array.h\"
 #include \"worker.h\"
-#include \"bool.h\"\n\n"
-	out <- [[[[[[[[[[[[[[[headers
+#include \"bool.h\"
+#include <sys/time.h>\n\n"
+	out <- [[[[[[[[[[[[[[[[[headers
 		]Append[[program]Dispatch[all methods]]
 		]Append[[[program]Type Registry >>]Type Defs]
 		]Append[Fold["_Consts C Program", 
@@ -1476,8 +1482,17 @@
 					constants]]
 		]Append[Fold[["_Text C Program"]Set Input[2, [program]Type Registry >>], "", Filter[[program]Functions >>, "Not Native"]]]
 		]Append["\n
+#ifdef ENABLE_PROFILING
+uint64_t profile_counts[END];
+uint64_t profile_totals[END];
+uint64_t profile_selftotals[END];
+#endif
+
 int32_t rhope(uint32_t func, object ** params, uint16_t numparams, uint16_t callspace)
 {
+#ifdef ENABLE_PROFILING
+	struct timeval time;
+#endif
 	uint16_t resume,idx, vcparam_offset, last_vcparam;
 	context * ct;
 	calldata * cdata, *temp_cdata, *my_cdata;
@@ -1587,7 +1602,20 @@
 		inout[1] = make_String(argv[idx]);
 		rhope(FUNC_Append, inout, 2, 2);
 	}
-	numret = rhope(FUNC_Main, inout, 1, 1);
+	numret = rhope(FUNC_Main, inout, 1, 1);"]
+		]Append[Fold["_Consts C Release", "", constants]]
+		]Append[
+	"
+	print_mem_info(manager);
+	print_live_object_types(manager);
+	
+#ifdef ENABLE_PROFILING
+	for (idx = 0; idx < END; ++idx)
+	{
+		if(profile_counts[idx])
+			printf(\"Func: %d\tCount: %llu\tTime: %llu\tAvg: %f\tSelf: %llu\tAvg: %f\n\", idx, profile_counts[idx], profile_totals[idx], ((double)profile_totals[idx])/((double)profile_counts[idx]), profile_selftotals[idx], ((double)profile_selftotals[idx])/((double)profile_counts[idx]));
+	}
+#endif
 	if (!numret)
 		return 0;
 	if (numret < 0)
--- a/ctobin	Wed Oct 06 23:46:47 2010 +0000
+++ b/ctobin	Mon Oct 11 20:04:48 2010 -0400
@@ -18,6 +18,7 @@
 	CC="gcc"
 fi
 
+echo "$CC -o $bin $2 $1.c blueprint.c context.c fixed_alloc.c object.c"
 $CC -o $bin $2 "$1.c" blueprint.c context.c fixed_alloc.c object.c
 
 cd ..
--- a/genasm.rhope	Wed Oct 06 23:46:47 2010 +0000
+++ b/genasm.rhope	Mon Oct 11 20:04:48 2010 -0400
@@ -1,5 +1,3 @@
-//Import extendlib.rhope
-Import backendutils.rhope
 
 Blueprint Registers
 {
@@ -317,20 +315,6 @@
 	out <- [pointer]Target Size >>
 }
 
-Blueprint X86 Instruction
-{
-	Name
-	Op1
-	Op2
-	Width
-	Extra Offset
-}
-
-X86 Instruction[name, op1, op2, width:out]
-{
-	out <- [[[[[Build["X86 Instruction"]]Name << [name]]Op1 << [op1]]Op2 <<[op2]]Width <<[width]]Extra Offset <<[0]
-}
-
 CAppend[left,right:out]
 {
 	If[[right] = [""]]
@@ -341,589 +325,3 @@
 	}
 }
 
-Inst ASM@X86 Instruction[inst,func:out]
-{
-	If[[[inst]Width >>] = [4]]
-	{
-		regs <- ("eax","ecx","edx","ebx","esi","edi","esp")
-	}{
-		If[[[inst]Width >>] = [2]]
-		{
-			regs <- ("ax","cx","dx","bx","si","di")
-		}{
-			regs <- ("al","cl","dl","bl","si","di")
-		}
-	}
-	out <- [[[inst]Name >>
-	]Append[ [" "]CAppend[[[inst]Op1>>]Op ASM[func, regs, [inst]Extra Offset >>]] ]
-	]Append[ [", "]CAppend[[[inst]Op2>>]Op ASM[func, regs, [inst]Extra Offset >>]] ]
-}
-
-Blueprint X86 Function
-{
-	Name
-	Registers
-	Variables
-	Scratch
-	Need Save
-	Free Stack Locations
-	Stack Size
-	Param Size
-	Temp Stack
-	Convention
-	Instructions
-}
-
-X86 Function[name,params,convention:out]
-{
-	[[[[[[[[[Build["X86 Function"]
-	]Name << [name]
-	]Registers << [Registers[("eax","ecx","edx","ebx","esi","edi"), (0,1,2,3,4,5), (0,1,2,3,4,5), (3,4,5), 4]]
-	]Variables  <<[New@Dictionary[]]
-	]Need Save <<[()]
-	]Free Stack Locations <<[()]
-	]Stack Size <<[0]
-	]Instructions <<[()]
-	]Convention <<[convention]
-	]Alloc Params[params, convention]
-	{
-		out <- [~]Param Size <<[ [~]Stack Size >> ]
-	}
-}
-
-Pointer Size@X86 Function[func:out]
-{
-	out <- 4
-}
-
-Param Helper@X86 Function[func, param:out]
-{
-	,loc <- [func]Allocate Stack[4]
-	{
-		out <- [~]Variables << [ [[~]Variables >>]Set[param, loc] ]
-	}
-}
-
-Alloc Params@X86 Function[func,params,convention:out]
-{
-	If[[convention] = ["fastcall"]]
-	{
-		[params]Index[0]
-		{
-				next func <- [[func]Registers <<[ [[func]Registers >>]Available? <<[ [[[func]Registers >>]Available? >>]Set[1, No] ]]
-				]Variables <<[ [[func]Variables >>]Set[~, Register[1,4]] ]
-				[params]Index[1]
-				{
-					next func2 <- [[next func]Registers <<[ [[next func]Registers >>]Available? <<[ [[[next func]Registers >>]Available? >>]Set[2, No] ]]
-					]Variables <<[ [[next func]Variables >>]Set[~, Register[2,4]] ]
-					[params]Index[2]
-					{
-						out <- _Fold[params, 2, next func2, "Param Helper"]
-					}{
-						out <- Val[next func2]
-					}
-				}{
-					out <- Val[next func]
-				}
-		}{
-			out <- func
-		}
-	}{
-		out <- Fold["Param Helper", func, params]
-	}
-}
-
-Add Instruction@X86 Function[func, inst:out]
-{
-	out <- [func]Instructions << [ [[func]Instructions >>]Append[ [inst]Extra Offset <<[[func]Temp Stack >>] ] ]
-}
-
-Allocate Stack@X86 Function[func,size:func out,out]
-{
-	out <- Stack Location[[func]Stack Size >>, size]
-	func out <- [func]Stack Size <<[ [[func]Stack Size >>]+[size] ]
-}
-
-Allocate Var@X86 Function[func,name,size,type:out func,out]
-{
-	out func, out <- Processor Allocate[func,name,size,type]
-}
-
-Resolve@X86 Function[func,op:out,out func]
-{
-	If[[Type Of[op]] = ["String"]]
-	{
-		out <- [[func]Variables >>]Index[op]
-	}{
-		out <- op
-	}
-}
-
-Allocate Scratch@X86 Function[func,size:out func,scratch]
-{
-	out func,scratch <- Processor Reg[func,"data"] {} {}
-	{
-		//FIXME: need to use a reg that's not involved in the current op
-		//FIXME: Also, might need two scratch regs and both might be in use
-		,stack inc <- [func]Save Reg[0]
-		{
-			out func <- [~]Scratch << [ [[~]Scratch >>]Set[0, Yes] ]
-		}
-	}
-}
-
-Free Scratch@X86 Function[func,scratch:out func]
-{
-	[[func]Scratch >>]Index[scratch]
-	{
-		[func]Restore Reg[scratch]
-		{
-			out func <- [~]Scratch << [ [[~]Scratch >>]Remove[scratch] ]
-		}
-	}{
-		out func <- Processor Free Reg[func, scratch]
-	}
-	If[[scratch]Index[1]]
-	{
-		
-	}{
-		
-	}
-}
-
-Classify Op@X86 Function[func,op:class]
-{
-	If[[op]In Memory?]
-	{
-		If[[Type Of[op]] = ["Pointer"]]
-		{
-			If[[[[op]Base >>]In Memory?] Or [[[op]Offset >>]In Memory?]]
-			{
-				class <- "u"
-			}{
-				class <- "m"
-			}
-		}{
-			class <- "m"
-		}
-	}{
-		class <- "r"
-	}
-}
-
-RegMem2Op@X86 Function[func,dest,notdest,op,size:out]
-{
-	out <- [func]Add Instruction[X86 Instruction[op, dest, notdest, size]]
-}
-
-MemPointer2Op@X86 Function[func,dest,notdest,op,size:out]
-{
-	,scratch <- [func]Allocate Scratch[size]
-	{
-		out <- [[[~]Fetch[notdest,scratch]
-			]Add Instruction[X86 Instruction[op, dest, scratch, size]]
-			]Free Scratch[scratch]
-	}
-}
-
-//Make sure to map this to both r, (m or r) -> m and r, (m or r) -> r
-RegMemToNotPointer@X86 Function[func,source1,source2,dest,op,size:out]
-{
-	out <- [[func]Move[source2,dest]
-		]Add Instruction[X86 Instruction[op, dest, source1, size]]
-}
-
-RegMemToPointer@X86 Function[func,source1,source2,dest,op,size:out]
-{
-	,scratch <- [func]Allocate Scratch[size]
-	{
-		spointer <- Pointer[scratch, None[], size]
-		out <- [[[[~]Calculate Address[dest, scratch]
-			]Move[source2, spointer]
-			]Add Instruction[X86 Instruction[op, spointer, source1, size]]
-			]Free Scratch[scratch]
-	}
-}
-
-RegPointerToMem@X86 Function[func,source1,source2,dest,op,size:out]
-{
-	,scratch <- [func]Allocate Scratch[size]
-	{
-		spointer <- Pointer[scratch, None[], size]
-		out <- [[[[~]Calculate Address[source2, scratch]
-			]Move[spointer, dest]
-			]Add Instruction[X86 Instruction[op, dest, source1, size]]
-			]Free Scratch[scratch]
-	}
-}
-
-RegPointerReg2Op@X86 Function[func,dest,notdest,op,size:out]
-{
-	,scratch <- [func]Allocate Scratch[size]
-	{
-		spointer <- Pointer[scratch, None[], size]
-		out <- [[[~]Calculate Address[notdest, scratch]
-			]Add Instruction[X86 Instruction[op, dest, spointer, size]]
-			]Free Scratch[scratch]
-	}
-}
-
-RegPointerPointer2Op@X86 Function[func,dest,notdest,op,size:out]
-{
-	,scratch <- [func]Allocate Scratch[size]
-	{
-		spointer <- Pointer[scratch, None[], size]
-		out <- [[[~]Calculate Address[dest, scratch]
-			]Add Instruction[X86 Instruction[op, spointer, notdest, size]]
-			]Free Scratch[scratch]
-	}
-}
-
-RegPointerToPointer@X86 Function[func,source1,source2,dest,op,size:out]
-{
-	,scratch <- [func]Allocate Scratch[size]
-	{
-		spointer <- Pointer[scratch, None[], size]
-		,scratch2 <- [~]Allocate Scratch[size]
-		{
-			spointer2 <- Pointer[scratch2, None[], size]
-			out <- [[[[[[~]Calculate Address[source2, scratch]
-				]Calculate Address[dest, scratch2]
-				]Move[spointer2, spointer]
-				]Add Instruction[X86 Instruction[op, spointer2, source1, size]]
-				]Free Scratch[scratch2]
-				]Free Scratch[scratch]
-		}
-	}
-}
-
-//If source1, source2 and dest are all pointers with register offsets, allocating a scratch register could
-//become a problem unless I let ebp be used as a scratch register. Should be doable as long as thread local
-//variables properly report ebp as a used register. Alternatively, one register could be reserved for scratch
-//usage
-MemPointerToMem@X86 Function[func,source1,source2,dest,op,size:out]
-{
-	,scratch <- [func]Allocate Scratch[size]
-	{
-		out <- [[[[~]Fetch[source2, scratch]
-			]Add Instruction[X86 Instruction[op, scratch, source1, size]]
-			]Move[scratch, dest]
-			]Free Scratch[scratch]
-	}
-}
-
-MemPointerToPointer@X86 Function[func,source1,source2,dest,op,size:out]
-{
-	,scratch <- [func]Allocate Scratch[size]
-	{
-		,scratch2 <- [~]Allocate Scratch[size]
-		{
-			spointer2 <- Pointer[scratch2, None[], size]
-			out <- [[[[[[~]Fetch[source2, scratch]
-				]Add Instruction[X86 Instruction[op, scratch, source1, size]]
-				]Calculate Address[dest, scratch2]
-				]Move[scratch, spointer2]
-				]Free Scratch[scratch2]
-				]Free Scratch[scratch]
-		}
-	}
-}
-
-//This does almost the same thing as RegMemToNotPointer, depending on how I do the pattern matching I could maybe combine them
-PointerMemToReg@X86 Function[func,source1,source2,dest,op,size:out]
-{
-	out <- [[func]Fetch[source1,dest]
-		]Add Instruction[X86 Instruction[op, dest, source2, size]]
-}
-
-PointerPointer2Op@X86 Function[func,dest,notdest,op,size:out]
-{
-	,scratch <- [func]Allocate Scratch[size]
-	{
-		spointer <- Pointer[scratch, None[], size]
-		,scratch2 <- [~]Allocate Scratch[size]
-		{
-			out <- [[[[[[[~]Calculate Address[dest, scratch]
-				]Fetch[notdest, scratch2]
-				]Add Instruction[X86 Instruction[op, scratch, scratch2, size]]
-				]Calculate Address[dest, scratch2]
-				]Move[scratch, spointer2]
-				]Free Scratch[scratch2]
-				]Free Scratch[scratch]
-		}
-	}
-}
-
-PointerPointerToPointer@X86 Function[func,source1,source2,dest,op,size:out]
-{
-	,scratch <- [func]Allocate Scratch[size]
-	{
-		,scratch2 <- [~]Allocate Scratch[size]
-		{
-			spointer2 <- Pointer[scratch2, None[], size]
-			out <- [[[[[[[~]Fetch[source1, scratch]
-				]Calculate Address[source2, scratch2]
-				]Add Instruction[X86 Instruction[op, scratch, spointer2, size]]
-				]Calculate Address[dest, scratch2]
-				]Move[scratch, spointer2]
-				]Free Scratch[scratch2]
-				]Free Scratch[scratch]
-		}
-	}
-}
-
-PointerPointerToMem@X86 Function[func,source1,souce2,dest,op,size:out]
-{
-	,scratch <- [func]Allocate Scratch[size]
-	{
-		spointer <- Pointer[scratch, None[], size]
-		out <- [[[[[~]Calculate Address[source1, scratch]
-			]Move[dest, spointer]
-			]Fetch[source2, scratch]
-			]Add Instruction[X86 Instruction[op, dest, scratch, size]]
-			]Free Scratch[scratch]
-	}
-}
-
-PointerPointerToReg@X86 Function[func,source1,souce2,dest,op,size:out]
-{
-	,scratch <- [func]Allocate Scratch[size]
-	{
-		spointer <- Pointer[scratch, None[], size]
-		out <- [[[[~]Fetch[source1, dest]
-			]Calculate Address[source2, scratch]
-			]Add Instruction[X86 Instruction[op, dest, scratch, size]]
-			]Free Scratch[scratch]
-	}
-}
-
-2Op Associative@X86 Function[func,psource1,psource2,pdest,name:out func]
-{
-	source1 <- [func]Resolve[psource1]
-	source2 <- [func]Resolve[psource2]
-	dest <- [func]Resolve[pdest]
-	dest class <- [func]Classify Op[dest]
-	width <- Min[Min[Min[[source1]Size,[source2]Size], [dest]Size], 4]
-	swapper <- (1,0)
-	sources <- [[()]Append[source1]Append[source2]
-	[sources]Find[dest]
-	{
-		source <- [swapper]Index[~]
-		source class <- [func]Classify Op[source]
-		If[[dest class] = ["u"]]
-		{
-			If[[source class] = ["r"]]
-			{
-				out func <- [func]RegPointerPointer2Op[dest,source,name,width]
-			}{
-				out func <- [func]PointerPointer2Op[dest,source,name,width]
-			}
-		}{
-			If[[dest class] = ["r"]]
-			{
-				If[[source class] = ["u"]]
-				{
-					out func <- [func]RegPointerReg2Op[dest,source,name,width]
-				}{
-					out func <- [func]RegMem2Op[dest,source,name,width]
-				}
-			}{
-				If[[source class] = ["r"]]
-				{
-					out func <- [func]RegMem2Op[dest,source,name,width]
-				}{
-					out func <- [func]MemPointer2Op[dest,source,name,width]
-				}
-			}
-		}
-	}{
-		sclasses <- Map[sources, ["Classify Op"]Set Input[0, func]]
-		first <- [sources]Index[found index]
-		other index <- [swapper]Index[found index]
-		other <- [sources]Index[other index]
-		other class <- [sclasses]Index[other index]
-		found index <- [sclasses]Find["r"]
-		{
-			If[[other class] = ["u"]]
-			{
-				If[[dest class] = ["m"]]
-				{
-					out func <- [func]RegPointerToMem[first,other,dest,name,width]
-				}{
-					If[[dest class] = ["u"]]
-					{
-						out func <- [func]RegPointerToPointer[first,other,dest,name,width]
-					}{
-						out func <- [func]PointerMemToReg[other,first,dest,name,width]
-					}
-				}
-			}{
-				If[[dest class] = ["u"]]
-				{
-					out func <- [func]RegMemToPointer[first,other,dest,name,width]
-				}{
-					out func <- [func]RegMemToNotPointer[first,other,dest,name,width]
-				}
-			}
-		}{
-			found index <- [sclasses]Find["m"]
-			{
-				If[[dest class] = ["r"]]
-				{
-					out func <- [func]PointerMemToReg[other,first,dest,name,width]
-				}{
-					If[[dest class] = ["m"]]
-					{
-						out func <- [func]MemPointerToMem[first,other,dest,name,width]	
-					}{
-						out func <- [func]MemPointerToPointer[first,other,dest,name,width]
-					}
-				}
-			}{
-				If[[dest class] = ["r"]]
-				{
-					out func <- [func]PointerPointerToReg[first,other,dest,name,width]
-				}{
-					If[[dest class] = ["m"]]
-					{
-						out func <- [func]PointerPointerToMem[first,other,dest,name,width]
-					}{
-						out func <- [func]PointerPointerToPointer[first,other,dest,name,width]
-					}
-				}
-			}
-		}
-	}
-}
-
-2Op@X86 Function[func,psource1,psource2,pdest,name:out func]
-{
-	source1 <- [func]Resolve[psource1]
-	source2 <- [func]Resolve[psource2]
-	dest <- [func]Resolve[pdest]
-	width <- Min[Min[Min[[source1]Size,[source2]Size], [dest]Size], 4]
-	If[[source1] = [dest]]
-	{
-		If[[[source1]In Memory?] And [[source2]In Memory?]]
-		{
-			,scratch, stack inc <- [func]Allocate Scratch[width]
-			{
-				out func <- [[[~]Add Instruction[X86 Instruction["mov", [scratch]Index[0], source2, width, stack inc]]
-				]Add Instruction[X86 Instruction[name, source1, [scratch]Index[0], width, stack inc]]
-				]Free Scratch[scratch]
-			}
-		}{
-			out func <- [func]Add Instruction[X86 Instruction[name, dest, source2, width, 0]]
-		}
-	}{
-		If[[dest]In Memory?]
-		{
-			If[[source2]In Memory?]
-			{
-				,scratch, stack inc <- [func]Allocate Scratch[width]
-				{
-					out func <- [[[[~]Add Instruction[X86 Instruction["mov", [scratch]Index[0], source1, width, stack inc]]
-					]Add Instruction[X86 Instruction[name, [scratch]Index[0], source2, width, stack inc]]
-					]Add Instruction[X86 Instruction["mov", dest, [scratch]Index[0], width, stack inc]]
-					]Free Scratch[scratch]
-				}
-			}{
-				out func <- [[func]Move[source1,dest]
-				]Add Instruction[X86 Instruction[name, dest, source2, width, 0]]
-			}
-		}{
-			out func <- [[func]Move[source1,dest]
-			]Add Instruction[X86 Instruction[name, dest, source2, width, 0]]
-		}
-	}
-}
-
-Add@X86 Function[func,source1,source2,dest:out func]
-{
-	out func <- [func]2Op Associative[source1,source2,dest,"add"]
-}
-
-Sub@X86 Function[func,source1,source2,dest:out func]
-{
-	out func <- [func]2Op[source1,source2,dest,"sub"]
-}
-
-Move@X86 Function[func,psource,pdest:out func]
-{
-	source <- [func]Resolve[psource]
-	dest <- [func]Resolve[pdest]
-	out func <- [func]Add Instruction[X86 Instruction["mov", dest, source, 4]]
-}
-
-Instruction ASM[current,instruction,func:out]
-{
-	out <- [[[current]Append["\t"]]Append[ [instruction]Inst ASM[func] ]]Append["\n"]
-}
-
-Save Reg@X86 Function[func,reg:out]
-{
-	out <- [[func]Add Instruction[X86 Instruction["push", Register[reg, 4], None[], 4]]
-	]Temp Stack << [ [[func]Temp Stack >>]+[4] ]
-}
-
-Prolog Save@X86 Function[func,junk,reg:out]
-{
-	out <- [[func]Add Instruction[X86 Instruction["push", Register[reg, 4], None[], 4]]
-	]Stack Size << [ [[func]Stack Size >>]+[4] ]
-}
-
-Restore Reg@X86 Function[func,reg:out]
-{
-	out <- [[func]Add Instruction[X86 Instruction["pop", Register[reg, 4], None[], 4]]
-	]Temp Stack << [ [[func]Temp Stack >>]-[4] ]
-}
-
-Epilogue Restore@X86 Function[func,junk,reg:out]
-{
-	out <- [func]Add Instruction[X86 Instruction["pop", Register[reg, 4], None[], 4]]
-}
-
-Finalize@X86 Function[func:out]
-{
-	alloc stack <- [[func]Stack Size >>] - [[func]Param Size >>]
-	
-	oldstream <- [func]Instructions >>
-	
-	If[[alloc stack] > [0]]
-	{
-		start <- [()]Append[X86 Instruction["sub", Register[6, 4],Immediate[alloc stack], Register[6, 4], 4], func]
-	}{
-		start <- ()
-	}
-	
-	If[[[func]Convention >>] = ["cdecl"]]
-	{
-		If[ [alloc stack] > [0] ]
-		{
-			retparam <- Immediate[alloc stack]
-		}{
-			retparam <- None[]
-		}
-	}{
-		retparam <- Immediate[[func]Stack Size >>]
-	}
-	
-	[[func]Need Save >>]First
-	{
-		prolog <- Fold["Prolog Save", [func]Instructions << [start], [func]Need Save >>]
-		out <- [Reverse Fold["Epilogue Restore", body, [func]Need Save >>]]Add Instruction[X86 Instruction["ret", retparam, None[], 4]]
-	}{
-		prolog <- [func]Instructions <<[start]
-		out <- [body]Add Instruction[X86 Instruction["ret", retparam, None[], 4]]
-	}
-	
-	body <- Fold["Add Instruction", prolog, oldstream]
-}
-
-Text@X86 Function[func:out]
-{
-	name line <- [Escape Rhope Name[[func]Name >>]
-	]Append[":\n"]
-	
-	out <- Fold[["Instruction ASM"]Set Input[2, func], name line, [func]Instructions >>]
-}
--- a/hello.rhope	Wed Oct 06 23:46:47 2010 +0000
+++ b/hello.rhope	Mon Oct 11 20:04:48 2010 -0400
@@ -4,8 +4,8 @@
 
 //All programs in Rhope must have a Main worker
 //This is where execution of a Rhope program begins
-Main[]
+Main[:out]
 {
 	//The Print worker prints a line of text to the terminal
-	Print["Hello Rhope Programming!"]
-}
\ No newline at end of file
+	out <- Print["Hello Rhope Programming!"]
+}
--- a/nworker.rhope	Wed Oct 06 23:46:47 2010 +0000
+++ b/nworker.rhope	Mon Oct 11 20:04:48 2010 -0400
@@ -492,9 +492,27 @@
 	out,node index <- [worker]Add Typed Input[name,number,Type Instance["Any Type"]]
 }
 
+Add Anon Input@NWorker[worker,number:out]
+{
+	If[[number]>[Length[[worker]Inputs >>]]]
+	{
+		prepped <- [worker]Add Anon Input[[number]-[1]]
+	}{
+		prepped <- Val[worker]
+	}
+	out <- out <- [[prepped]Inputs <<[[[prepped]Inputs >>]Set[number,[" unnamed"]Append[number]]]
+		]Input Types <<[[[prepped]Input Types >>]Set[number,Type Instance["Any Type"]]]
+}
+
 Add Typed Input@NWorker[worker,name,number,type:out,node index]
 {
-	,node index <- [worker]Add Node["input",number,0,1]
+	If[[number]>[Length[[worker]Inputs >>]]]
+	{
+		prepped <- [worker]Add Anon Input[[number]-[1]]
+	}{
+		prepped <- Val[worker]
+	}
+	,node index <- [prepped]Add Node["input",number,0,1]
 	{ 
 		out <- [[~]Inputs <<[[[~]Inputs >>]Set[number,name]]
 		]Input Types <<[[[~]Input Types >>]Set[number,type]]
@@ -873,7 +891,7 @@
 				[conditions]For Backend
 				{
 					stream <- [[withconst]Instruction Stream
-						]Move[Constant[constname], [[["__result_"]Append[node index]]Append["_"]]Append[0]]
+						]Move[Strip Addref[Constant[constname]], [[["__result_"]Append[node index]]Append["_"]]Append[0]]
 					nfunc <- [withconst]Do If[~, stream]
 				}{
 					nfunc <- Val[withconst]
@@ -943,8 +961,7 @@
 
 Release Var@NWorker[worker,func,name:out]
 {
-	//_result_index_ionum
-	Print[["Release Var@NWorker: "]Append[name]]
+	//__result_index_ionum
 	parts <- [name]Split["_"]
 	index <- <String@Whole Number[ [parts]Index[3] ]
 	io num <- <String@Whole Number[ [parts]Index[4] ]
@@ -954,25 +971,27 @@
 		Print["oops"]
 		{ Pretty Print[node, ""] 
 		{ Pretty Print[parts, ""]}} }
-	If[[[dests]Length] = [1]]
-	{
-		Print["Single dest, maybe release"]
-		{ Print[["Dest index: "]Append[dest index]] }
-		dest index <- [[dests]Index[0]]Index >>
-		dest node <- [[worker]Nodes >>]Index[dest index]
-		{ Print["got dest node"] }
-		
-		[[dest node]Conditions >>]For Backend
+	,normal <- If[[[dests]Length] = [1]]
+	{	
+		dest ionum <- [[dests]Index[0]]IO Num >>
+		If[[[[dests]Index[0]]IO Num >>]=[-1]]
 		{
-			Print["dest has conditions"]
-			out <- [func]Do If[AndCond[NotCond[~], name],  [[func]Instruction Stream]Release[name]]
-			{ Print["got output"] }
+			normal <- Yes
 		}{
-			Print["No conditions on dest, no release needed"]
-			out <- func
+			dest index <- [[dests]Index[0]]Index >>
+			dest node <- [[worker]Nodes >>]Index[dest index]
+		
+			[[dest node]Conditions >>]For Backend
+			{
+				out <- [func]Do If[AndCond[NotCond[~], name],  [[func]Instruction Stream]Release[name]]
+			}{
+				out <- func
+			}
 		}
-	}{
-		Print["Multiple (or zero) dests, definitely release"]
+	}
+	
+	Val[normal]
+	{
 		do if <- If[[[node]Outputs >>] > [1]] {}
 		{
 			do if <- [[node]Conditions >>]Empty? {}
@@ -1079,6 +1098,27 @@
 	}
 }
 
+Release Raw Inputs[func,input type,index,inputs,outputs:out]
+{
+	If[[[input type]Variant >>] = ["Raw Pointer"]]
+	{
+		name <- [inputs]Index[index]
+		If[[input type]Mutable? >>]
+		{
+			[outputs]Find[[inputs]Index[index]]
+			{
+				out <- func
+			}{
+				out <- [func]Release[name]	
+			}
+		}{
+			out <- [func]Release[name]
+		}
+	}{
+		out <- func
+	}
+}
+
 FParams[input:out]
 {
 	iname <- [input]Index[0]
@@ -1161,8 +1201,9 @@
 	
 	Fold[["FInputs"]Set Input[3, [worker]Inputs >>], rfunc, [worker]Input Types >>]
 	{ [~]Call Foreign[name, [worker]Convention >>, Map[Zip[[worker]Inputs >>, [worker]Input Types >>], "FParams"], rparam]
+	{ Fold[[["Release Raw Inputs"]Set Input[3, [worker]Inputs >>]]Set Input[4, [worker]Outputs >>], ~, [worker]Input Types >>]
 	{ Fold[[[["Save Foreign Result"]Set Input[3, [worker]Output Types >>]]Set Input[4, [worker]Inputs >>]]Set Input[5, [worker]Input Types >>], ~, [worker]Outputs >>]
-	{ out <- [program]Store Function[~] }}}
+	{ out <- [program]Store Function[~] }}}}
 }		
 
 Compile Worker@NWorker[worker,program,name:out]
--- a/runtime/array.c	Wed Oct 06 23:46:47 2010 +0000
+++ b/runtime/array.c	Mon Oct 11 20:04:48 2010 -0400
@@ -18,6 +18,23 @@
 	release_ref(val);
 }
 
+void _internal_array_copychunk(object * src, int32_t srcidx, object * dest, int32_t destidx, int32_t len)
+{
+	int32_t idx;
+	object * cur;
+	t_Array *sarr,*darr;
+	sarr = (t_Array *)src;
+	darr = (t_Array *)dest;
+	memcpy((char *)(darr+1) + darr->payload.Eltype->bp->size * destidx, (char *)(sarr+1) + sarr->payload.Eltype->bp->size * srcidx, len*sarr->payload.Eltype->bp->size);
+	cur = (object *)((char *)(darr+1) + darr->payload.Eltype->bp->size * destidx - sizeof(object));
+	for (idx = 0; idx < len; ++idx)
+	{
+		darr->payload.Eltype->bp->copy(cur);
+		cur++;
+	}
+	release_ref(src);
+}
+
 object * _internal_array_getboxed(object * array, int32_t index)
 {
 	object * ret;
--- a/runtime/array.h	Wed Oct 06 23:46:47 2010 +0000
+++ b/runtime/array.h	Mon Oct 11 20:04:48 2010 -0400
@@ -7,6 +7,7 @@
 
 void _internal_array_copyout(object * array, int32_t index, object * dest);
 void _internal_array_copyin(object * array, int32_t index, object * val);
+void _internal_array_copychunk(object * src, int32_t srcidx, object * dest, int32_t destidx, int32_t len);
 object * _internal_array_getboxed(object * array, int32_t index);
 void _internal_array_setboxed(object *, int32_t index, object * val);
 object *_internal_array_allocboxed(int32_t size);
--- a/runtime/blueprint.c	Wed Oct 06 23:46:47 2010 +0000
+++ b/runtime/blueprint.c	Mon Oct 11 20:04:48 2010 -0400
@@ -21,6 +21,8 @@
 {
 	t_Blueprint * l = (t_Blueprint *)left;
 	t_Blueprint * r = (t_Blueprint *)right;
+	release_ref(left);
+	release_ref(right);
 	return l->bp == r->bp;
 }
 
--- a/runtime/fixed_alloc.c	Wed Oct 06 23:46:47 2010 +0000
+++ b/runtime/fixed_alloc.c	Mon Oct 11 20:04:48 2010 -0400
@@ -1,4 +1,5 @@
 #include "fixed_alloc.h"
+#include "object.h"
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
@@ -24,8 +25,9 @@
 {
 	int i,count,freeobjs;
 	mem_block * cur;
-	printf("Free blocks: %d\n", manager->freecount);
-	printf("Full Blocks: %d\n", manager->fullcount);
+	//printf("Free blocks: %d\n", manager->freecount);
+	if (manager->fullcount)
+		printf("Full Blocks: %d\n", manager->fullcount);
 	for (i = 0; i < (MAX_SIZE-MIN_SIZE)/STRIDE; i++)
 	{
 		count = 0;
@@ -37,11 +39,47 @@
 			freeobjs += ((int)cur->numfree);
 			cur = cur->next;
 		}
-		printf("Bucket %d(size: %d) has %d blocks in use with %d total free slots\n", i, i*STRIDE+MIN_SIZE,count, freeobjs);
+		if (freeobjs)
+			printf("Bucket %d(size: %d) has %d blocks in use with %d free slots out of %d\n", i, i*STRIDE+MIN_SIZE,count, freeobjs, max_free[i]*count);
 	}
 	fflush(stdout);
 }
 
+void print_live_object_types(mem_manager * manager)
+{
+	object * obj;
+	mem_block * cur;
+	int32_t i,j,bitslots,bit,*counts = malloc(sizeof(int32_t)*max_registered_type);
+	memset(counts, 0, sizeof(int32_t)*max_registered_type);
+	for (i = 0; i < (MAX_SIZE-MIN_SIZE)/STRIDE; i++)
+	{
+		cur = manager->inuse[i];
+		while(cur)
+		{
+			bitslots = max_free[i]/8;
+			if(max_free[i]&7)
+				++bitslots;
+			for(j = 0; j < bitslots; ++j)
+				if(cur->bitmap[j] != 0xFF)
+				{
+					for (bit = 0; bit < 8; ++bit)
+					{
+						if (!(cur->bitmap[j] & (1 << bit)))
+						{
+							obj = (object *)(((char *)cur)+BLOCK_SIZE-(((j*8+bit)+1)*(i*STRIDE+MIN_SIZE)));
+							counts[obj->bprint->type_id]++;
+						}
+					}
+				}
+			cur = cur->next;
+		}
+	}
+	for (i = 0; i < max_registered_type; ++i)
+		if(counts[i])
+			printf("%d live objects of type %d\n", counts[i], i);
+	fflush(stdout);
+}
+
 void * falloc(size_t size, mem_manager * manager)
 {
 	uint16_t i,bit;
--- a/runtime/fixed_alloc.h	Wed Oct 06 23:46:47 2010 +0000
+++ b/runtime/fixed_alloc.h	Mon Oct 11 20:04:48 2010 -0400
@@ -44,5 +44,6 @@
 void * falloc(size_t size, mem_manager * manager);
 void ffree(void * ptr, size_t size, mem_manager * manager);
 void print_mem_info(mem_manager * manager);
+void print_live_object_types(mem_manager * manager);
 
 #endif //FIXED_ALLOC_H_
--- a/runtime/func.h	Wed Oct 06 23:46:47 2010 +0000
+++ b/runtime/func.h	Mon Oct 11 20:04:48 2010 -0400
@@ -33,12 +33,58 @@
 
 #define MethodName(name,type) f_ ## name ## AT_ ## type
 
+#ifdef ENABLE_PROFILING
+
+#define START_PROFILE \
+		gettimeofday(&time, NULL);\
+		cdata->accum = cdata->self_accum = 0;\
+		cdata->self_start = cdata->start = ((uint64_t)time.tv_sec) * 1000000ULL + ((uint64_t)time.tv_usec);
+
+#define PAUSE_SELF \
+		gettimeofday(&time, NULL);\
+		my_cdata->self_accum += ((uint64_t)time.tv_sec) * 1000000ULL + ((uint64_t)time.tv_usec) - my_cdata->self_start;
+		
+#define AND_TOTAL \
+		my_cdata->accum += ((uint64_t)time.tv_sec) * 1000000ULL + ((uint64_t)time.tv_usec) - my_cdata->start;
+
+#define RESUME_SELF \
+		gettimeofday(&time, NULL);\
+		my_cdata->self_start = ((uint64_t)time.tv_sec) * 1000000ULL + ((uint64_t)time.tv_usec);
+		
+#define AND_RESUME_TOTAL my_cdata->start = my_cdata->self_start;
+		
+#define EndFunc(name)	\
+		free_stack(ct, lv_ ## name);\
+		func = cdata->func;\
+		gettimeofday(&time, NULL);\
+		profile_counts[FUNC_ ## name]++;\
+		profile_totals[FUNC_ ## name] += ((uint64_t)time.tv_sec) * 1000000ULL + ((uint64_t)time.tv_usec) - cdata->start + cdata->accum;\
+		profile_selftotals[FUNC_ ## name] +=  ((uint64_t)time.tv_sec) * 1000000ULL + ((uint64_t)time.tv_usec) - cdata->self_start + cdata->self_accum;
+
+#else
+
+#define START_PROFILE
+#define PAUSE_SELF
+#define RESUME_SELF
+#define AND_TOTAL
+#define AND_RESUME_TOTAL
+
+#define EndFunc(name)	\
+		free_stack(ct, lv_ ## name);\
+		func = cdata->func;
+
+
+#endif
+
+#define EndFuncNoLocals	\
+		func = cdata->func;
 
 #define Func(name,numparams) \
 f_ ## name:\
 		for(idx = numparams; idx < cdata->num_params; ++idx)\
 			release_ref(cdata->params[idx]); cdata->num_params = numparams;\
 sf_ ## name:\
+		START_PROFILE\
 		lv_ ## name = alloc_stack(ct, sizeof(lt_ ## name));\
 		my_cdata = cdata;
 
@@ -50,32 +96,6 @@
 sf_ ## name:\
 		my_cdata = cdata;		
 
-#define EndFunc(name)	\
-		free_stack(ct, lv_ ## name);\
-		func = cdata->func;
-	
-#define EndFuncNoLocals	\
-		func = cdata->func;
-
-#define Method(name) \
-f_ ## name:\
-sf_ ## name:\
-		switch(get_blueprint(cdata->params[0])->type_id)\
-		{
-			
-#define EndMethod(name) \
-		default:\
-			printf("Type %d does not implement method %s\n", get_blueprint(cdata->params[0])->type_id, #name);\
-			cdata = alloc_cdata(ct, cdata, 0);\
-			cdata->func = FUNC_ ## name;\
-			goto _exception;\
-		}
-			
-			
-#define MethodDispatch(type_id,name,type_name) \
-		case type_id:\
-			goto m_ ## name ## AT_ ## type_name;
-			
 #define MethodImpl(name,type_name,mytype_id,numparams) \
 f_ ## name ## AT_ ## type_name:\
 sf_ ## name ## AT_ ## type_name:\
@@ -91,6 +111,7 @@
 			exit(1);\
 		}\
 m_ ## name ## AT_ ## type_name:\
+		START_PROFILE\
 		for(idx = numparams; idx < cdata->num_params; ++idx)\
 			release_ref(cdata->params[idx]); cdata->num_params = numparams;\
 		lv_ ## name ## AT_ ## type_name = alloc_stack(ct, sizeof(lt_ ## name ## AT_ ## type_name));\
@@ -113,6 +134,26 @@
 		for(idx = numparams; idx < cdata->num_params; ++idx)\
 			release_ref(cdata->params[idx]); cdata->num_params = numparams;\
 		my_cdata = cdata;
+
+		
+#define Method(name) \
+f_ ## name:\
+sf_ ## name:\
+		switch(get_blueprint(cdata->params[0])->type_id)\
+		{
+			
+#define EndMethod(name) \
+		default:\
+			printf("Type %d does not implement method %s\n", get_blueprint(cdata->params[0])->type_id, #name);\
+			cdata = alloc_cdata(ct, cdata, 0);\
+			cdata->func = FUNC_ ## name;\
+			goto _exception;\
+		}
+			
+			
+#define MethodDispatch(type_id,name,type_name) \
+		case type_id:\
+			goto m_ ## name ## AT_ ## type_name;
 			
 #define NumParams
 #define CallSpace
@@ -175,11 +216,13 @@
 	cdata->func = RES_  ## resumeto ## _ ## myname;\
 	cdata->num_params = numparams + ((t_Worker *)tocall)->payload.Count;\
 	cdata->vars = lv_ ## myname;\
-	func = ((t_Worker *)tocall)->payload.Index;
+	func = ((t_Worker *)tocall)->payload.Index;\
+	PAUSE_SELF
 
 #define ValCallPostlude(resumeto,myname)\
 r ## resumeto ## _ ## myname:\
 	my_cdata = cdata->lastframe;\
+	RESUME_SELF\
 	lv_ ## myname = cdata->vars;
 
 
@@ -187,9 +230,21 @@
 			cdata->func = RES_  ## resumeto ## _ ## myname;\
 			cdata->num_params = numparams;\
 			cdata->vars = lv_ ## myname;\
+			if(FUNC_ ## tocall == FUNC_ ## myname) {\
+				PAUSE_SELF\
+				AND_TOTAL\
+			} else if (FUNC_ ## tocall != FUNC_PL_ && FUNC_ ## tocall != FUNC_MN_ && FUNC_ ## tocall != FUNC_TM_ && FUNC_ ## tocall != FUNC_DV_ && FUNC_ ## tocall != FUNC_If) {\
+				PAUSE_SELF\
+			}\
 			goto sf_ ## tocall;\
 r ## resumeto ## _ ## myname:\
 			my_cdata = cdata->lastframe;\
+			if(FUNC_ ## tocall == FUNC_ ## myname) {\
+				RESUME_SELF\
+				AND_RESUME_TOTAL\
+			} else if (FUNC_ ## tocall != FUNC_PL_ && FUNC_ ## tocall != FUNC_MN_ && FUNC_ ## tocall != FUNC_TM_ && FUNC_ ## tocall != FUNC_DV_ && FUNC_ ## tocall != FUNC_If) {\
+				RESUME_SELF\
+			}\
 			lv_ ## myname = cdata->vars;
 			
 	
--- a/runtime/object.h	Wed Oct 06 23:46:47 2010 +0000
+++ b/runtime/object.h	Mon Oct 11 20:04:48 2010 -0400
@@ -45,10 +45,16 @@
 struct calldata {
 	struct calldata	*lastframe;
 	void            *vars;
-	uint32_t 		func;
-	uint16_t 		num_params;
-	uint16_t		callspace;
-	object 			*params[1];
+#ifdef ENABLE_PROFILING
+	uint64_t        start;
+	uint64_t        accum;
+	uint64_t        self_start;
+	uint64_t        self_accum;
+#endif
+	uint32_t        func;
+	uint16_t        num_params;
+	uint16_t        callspace;
+	object 	        *params[1];
 };
 #pragma pack(pop)
 
--- a/string.rhope	Wed Oct 06 23:46:47 2010 +0000
+++ b/string.rhope	Mon Oct 11 20:04:48 2010 -0400
@@ -596,7 +596,7 @@
 {
 	If[count]
 	{
-		out <- [string]_Flatten[[dest]Append[ [[string]Buffer >>]Index[offset] ], [offset]+[1i32], [count]-[1i32]]
+		out <- [_internal_array_copychunk[[string]Buffer >>, offset, dest, [dest]Length, count]]Length <<[[[dest]Length]+[count]]
 	}{
 		out <- dest
 	}
@@ -614,8 +614,13 @@
 
 Flatten@String Slice[string:out]
 {
-	out <- [[Build[String()]]Buffer <<[ [[string]Source >>]_Flatten[Array[], [string]Offset >>, [string]ByteLen >>] ]
-		]Length <<[[string]Length >>]
+	If[[string]ByteLen >>]
+	{
+		out <- [[Build[String()]]Buffer <<[ [[string]Source >>]_Flatten[_internal_array_allocnaked[[string]ByteLen >>, UInt8()], [string]Offset >>, [string]ByteLen >>] ]
+			]Length <<[[string]Length >>]
+	}{
+		out <- ""
+	}
 }
 
 Print@String Slice[string:out]
@@ -718,12 +723,17 @@
 
 Flatten@String Cat[string:out]
 {
-	out <- [[Build[String()]
-		]Buffer << [
-			[[string]Right >>]_Flatten[
-				[[string]Left >>]_Flatten[Array[], 0i32, [[string]Left >>]Byte Length],
-				0i32, [[string]Right >>]Byte Length]]
-		]Length << [[string]Length >>]
+	If[[string]ByteLen >>]
+	{
+		out <- [[Build[String()]
+			]Buffer << [
+				[[string]Right >>]_Flatten[
+					[[string]Left >>]_Flatten[_internal_array_allocnaked[[string]ByteLen >>, UInt8()], 0i32, [[string]Left >>]Byte Length],
+					0i32, [[string]Right >>]Byte Length]]
+			]Length << [[string]Length >>]
+	}{
+		out <- ""
+	}
 }
 
 Print@String Cat[string:out]