slices

R=rsc
DELTA=59  (44 added, 13 deleted, 2 changed)
OCL=31105
CL=31105
diff --git a/src/pkg/gob/decode.go b/src/pkg/gob/decode.go
index 8a7440b..80d772f 100644
--- a/src/pkg/gob/decode.go
+++ b/src/pkg/gob/decode.go
@@ -313,21 +313,8 @@
 	return state.err
 }
 
-func decodeArray(atyp reflect.ArrayType, state *DecState, p uintptr, elemOp decOp, elemWid int, length int, indir, elemIndir int) os.Error {
-	if indir > 0 {
-		up := unsafe.Pointer(p);
-		if *(*unsafe.Pointer)(up) == nil {
-			// Allocate the structure by making a slice of bytes and recording the
-			// address of the beginning of the array. TODO(rsc).
-			b := make([]byte, atyp.Size());
-			*(*unsafe.Pointer)(up) = unsafe.Pointer(&b[0]);
-		}
-		p = *(*uintptr)(up);
-	}
+func decodeArrayHelper(state *DecState, p uintptr, elemOp decOp, elemWid, length, elemIndir int) os.Error {
 	instr := &decInstr{elemOp, 0, elemIndir, 0};
-	if DecodeUint(state) != uint64(length) {
-		state.err = os.ErrorString("length mismatch in decodeArray");
-	}
 	for i := 0; i < length && state.err == nil; i++ {
 		up := unsafe.Pointer(p);
 		if elemIndir > 1 {
@@ -339,6 +326,43 @@
 	return state.err
 }
 
+func decodeArray(atyp reflect.ArrayType, state *DecState, p uintptr, elemOp decOp, elemWid, length, indir, elemIndir int) os.Error {
+	if indir > 0 {
+		up := unsafe.Pointer(p);
+		if *(*unsafe.Pointer)(up) == nil {
+			// Allocate the array by making a slice of bytes of the correct size
+			// and taking the address of the beginning of the array. TODO(rsc).
+			b := make([]byte, atyp.Size());
+			*(**byte)(up) = &b[0];
+		}
+		p = *(*uintptr)(up);
+	}
+	if DecodeUint(state) != uint64(length) {
+		return os.ErrorString("length mismatch in decodeArray");
+	}
+	return decodeArrayHelper(state, p, elemOp, elemWid, length, elemIndir);
+}
+
+func decodeSlice(atyp reflect.ArrayType, state *DecState, p uintptr, elemOp decOp, elemWid, indir, elemIndir int) os.Error {
+	length := int(DecodeUint(state));
+	if indir > 0 {
+		up := unsafe.Pointer(p);
+		if *(*unsafe.Pointer)(up) == nil {
+			// Allocate the slice header.
+			*(*unsafe.Pointer)(up) = unsafe.Pointer(new(reflect.SliceHeader));
+		}
+		p = *(*uintptr)(up);
+	}
+	// Allocate storage for the slice elements, that is, the underlying array.
+	data := make([]byte, length*atyp.Elem().Size());
+	// Always write a header at p.
+	hdrp := (*reflect.SliceHeader)(unsafe.Pointer(p));
+	hdrp.Data = uintptr(unsafe.Pointer(&data[0]));
+	hdrp.Len = uint32(length);
+	hdrp.Cap = uint32(length);
+	return decodeArrayHelper(state, hdrp.Data, elemOp, elemWid, length, elemIndir);
+}
+
 var decEngineMap = make(map[reflect.Type] *decEngine)
 var decOpMap = map[int] decOp {
 	 reflect.BoolKind: decBool,
@@ -370,6 +394,11 @@
 			case atyp.Elem().Kind() == reflect.Uint8Kind:
 				op = decUint8Array
 			case atyp.IsSlice():
+				elemOp := decOpFor(atyp.Elem());
+				_, elemIndir := indirect(atyp.Elem());
+				op = func(i *decInstr, state *DecState, p unsafe.Pointer) {
+					state.err = decodeSlice(atyp, state, uintptr(p), elemOp, atyp.Elem().Size(), i.indir, elemIndir);
+				};
 			case !atyp.IsSlice():
 				elemOp := decOpFor(atyp.Elem());
 				_, elemIndir := indirect(atyp.Elem());