Commit 4a191c2c authored by Jan Ziak's avatar Jan Ziak Committed by Russ Cox

runtime: store types of allocated objects

R=rsc
CC=golang-dev
https://golang.org/cl/6569057
parent 4545dc6a
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
#include "runtime.h" #include "runtime.h"
#include "arch_GOARCH.h"
#include "malloc.h"
#include "hashmap.h" #include "hashmap.h"
#include "type.h" #include "type.h"
#include "race.h" #include "race.h"
...@@ -748,6 +750,13 @@ runtime·makemap_c(MapType *typ, int64 hint) ...@@ -748,6 +750,13 @@ runtime·makemap_c(MapType *typ, int64 hint)
h = runtime·mal(sizeof(*h)); h = runtime·mal(sizeof(*h));
h->flag |= CanFreeTable; /* until reflect gets involved, free is okay */ h->flag |= CanFreeTable; /* until reflect gets involved, free is okay */
if(UseSpanType) {
if(false) {
runtime·printf("makemap %S: %p\n", *typ->string, h);
}
runtime·settype(h, (uintptr)typ | TypeInfo_Map);
}
ksize = ROUND(key->size, sizeof(void*)); ksize = ROUND(key->size, sizeof(void*));
vsize = ROUND(val->size, sizeof(void*)); vsize = ROUND(val->size, sizeof(void*));
if(ksize > MaxData || vsize > MaxData || ksize+vsize > MaxData) { if(ksize > MaxData || vsize > MaxData || ksize+vsize > MaxData) {
......
...@@ -688,6 +688,7 @@ void ...@@ -688,6 +688,7 @@ void
reflect·unsafe_New(Eface typ, void *ret) reflect·unsafe_New(Eface typ, void *ret)
{ {
Type *t; Type *t;
uint32 flag;
// Reflect library has reinterpreted typ // Reflect library has reinterpreted typ
// as its own kind of type structure. // as its own kind of type structure.
...@@ -695,10 +696,16 @@ reflect·unsafe_New(Eface typ, void *ret) ...@@ -695,10 +696,16 @@ reflect·unsafe_New(Eface typ, void *ret)
// type structure sits before the data pointer. // type structure sits before the data pointer.
t = (Type*)((Eface*)typ.data-1); t = (Type*)((Eface*)typ.data-1);
if(t->kind&KindNoPointers) flag = t->kind&KindNoPointers ? FlagNoPointers : 0;
ret = runtime·mallocgc(t->size, FlagNoPointers, 1, 1); ret = runtime·mallocgc(t->size, flag, 1, 1);
else
ret = runtime·mal(t->size); if(UseSpanType && !flag) {
if(false) {
runtime·printf("unsafe_New %S: %p\n", *t->string, ret);
}
runtime·settype(ret, (uintptr)t | TypeInfo_SingleObject);
}
FLUSH(&ret); FLUSH(&ret);
} }
...@@ -715,9 +722,20 @@ reflect·unsafe_NewArray(Eface typ, intgo n, void *ret) ...@@ -715,9 +722,20 @@ reflect·unsafe_NewArray(Eface typ, intgo n, void *ret)
t = (Type*)((Eface*)typ.data-1); t = (Type*)((Eface*)typ.data-1);
size = n*t->size; size = n*t->size;
if(t->kind&KindNoPointers) if(size == 0)
ret = (byte*)&runtime·zerobase;
else if(t->kind&KindNoPointers)
ret = runtime·mallocgc(size, FlagNoPointers, 1, 1); ret = runtime·mallocgc(size, FlagNoPointers, 1, 1);
else else {
ret = runtime·mal(size); ret = runtime·mallocgc(size, 0, 1, 1);
if(UseSpanType) {
if(false) {
runtime·printf("unsafe_NewArray [%D]%S: %p\n", (int64)n, *t->string, ret);
}
runtime·settype(ret, (uintptr)t | TypeInfo_Array);
}
}
FLUSH(&ret); FLUSH(&ret);
} }
...@@ -708,6 +708,26 @@ runtime·new(Type *typ, uint8 *ret) ...@@ -708,6 +708,26 @@ runtime·new(Type *typ, uint8 *ret)
FLUSH(&ret); FLUSH(&ret);
} }
// same as runtime·new, but callable from C
void*
runtime·cnew(Type *typ)
{
uint32 flag;
void *ret;
m->racepc = runtime·getcallerpc(&typ);
flag = typ->kind&KindNoPointers ? FlagNoPointers : 0;
ret = runtime·mallocgc(typ->size, flag, 1, 1);
if(UseSpanType && !flag) {
if(false) {
runtime·printf("new %S: %p\n", *typ->string, ret);
}
runtime·settype(ret, (uintptr)typ | TypeInfo_SingleObject);
}
return ret;
}
void* void*
runtime·stackalloc(uint32 n) runtime·stackalloc(uint32 n)
{ {
......
...@@ -452,6 +452,7 @@ void runtime·unmarkspan(void *v, uintptr size); ...@@ -452,6 +452,7 @@ void runtime·unmarkspan(void *v, uintptr size);
bool runtime·blockspecial(void*); bool runtime·blockspecial(void*);
void runtime·setblockspecial(void*, bool); void runtime·setblockspecial(void*, bool);
void runtime·purgecachedstats(MCache*); void runtime·purgecachedstats(MCache*);
void* runtime·cnew(Type*);
void runtime·settype(void*, uintptr); void runtime·settype(void*, uintptr);
void runtime·settype_flush(M*, bool); void runtime·settype_flush(M*, bool);
...@@ -485,3 +486,6 @@ enum ...@@ -485,3 +486,6 @@ enum
// Enables type information at the end of blocks allocated from heap // Enables type information at the end of blocks allocated from heap
DebugTypeAtBlockEnd = 0, DebugTypeAtBlockEnd = 0,
}; };
// defined in mgc0.go
void runtime·gc_m_ptr(Eface*);
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package runtime
// Called from C. Returns the Go type *m.
func gc_m_ptr(ret *interface{}) {
*ret = (*m)(nil)
}
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "os_GOOS.h" #include "os_GOOS.h"
#include "stack.h" #include "stack.h"
#include "race.h" #include "race.h"
#include "type.h"
bool runtime·iscgo; bool runtime·iscgo;
...@@ -833,8 +834,15 @@ M* ...@@ -833,8 +834,15 @@ M*
runtime·newm(void) runtime·newm(void)
{ {
M *mp; M *mp;
static Type *mtype; // The Go type M
mp = runtime·malloc(sizeof(M)); if(mtype == nil) {
Eface e;
runtime·gc_m_ptr(&e);
mtype = ((PtrType*)e.type)->elem;
}
mp = runtime·cnew(mtype);
mcommoninit(mp); mcommoninit(mp);
if(runtime·iscgo) { if(runtime·iscgo) {
......
...@@ -517,6 +517,7 @@ struct Panic ...@@ -517,6 +517,7 @@ struct Panic
* external data * external data
*/ */
extern String runtime·emptystring; extern String runtime·emptystring;
extern uintptr runtime·zerobase;
G* runtime·allg; G* runtime·allg;
G* runtime·lastg; G* runtime·lastg;
M* runtime·allm; M* runtime·allm;
......
...@@ -38,7 +38,7 @@ runtime·makeslice(SliceType *t, int64 len, int64 cap, Slice ret) ...@@ -38,7 +38,7 @@ runtime·makeslice(SliceType *t, int64 len, int64 cap, Slice ret)
// Dummy word to use as base pointer for make([]T, 0). // Dummy word to use as base pointer for make([]T, 0).
// Since you cannot take the address of such a slice, // Since you cannot take the address of such a slice,
// you can't tell that they all have the same base pointer. // you can't tell that they all have the same base pointer.
static uintptr zerobase; uintptr runtime·zerobase;
static void static void
makeslice1(SliceType *t, intgo len, intgo cap, Slice *ret) makeslice1(SliceType *t, intgo len, intgo cap, Slice *ret)
...@@ -50,12 +50,20 @@ makeslice1(SliceType *t, intgo len, intgo cap, Slice *ret) ...@@ -50,12 +50,20 @@ makeslice1(SliceType *t, intgo len, intgo cap, Slice *ret)
ret->len = len; ret->len = len;
ret->cap = cap; ret->cap = cap;
if(cap == 0) if(size == 0)
ret->array = (byte*)&zerobase; ret->array = (byte*)&runtime·zerobase;
else if((t->elem->kind&KindNoPointers)) else if((t->elem->kind&KindNoPointers))
ret->array = runtime·mallocgc(size, FlagNoPointers, 1, 1); ret->array = runtime·mallocgc(size, FlagNoPointers, 1, 1);
else else {
ret->array = runtime·mal(size); ret->array = runtime·mallocgc(size, 0, 1, 1);
if(UseSpanType) {
if(false) {
runtime·printf("new slice [%D]%S: %p\n", (int64)cap, *t->elem->string, ret->array);
}
runtime·settype(ret->array, (uintptr)t->elem | TypeInfo_Array);
}
}
} }
// appendslice(type *Type, x, y, []T) []T // appendslice(type *Type, x, y, []T) []T
......
...@@ -18,6 +18,7 @@ typedef struct Method Method; ...@@ -18,6 +18,7 @@ typedef struct Method Method;
typedef struct IMethod IMethod; typedef struct IMethod IMethod;
typedef struct SliceType SliceType; typedef struct SliceType SliceType;
typedef struct FuncType FuncType; typedef struct FuncType FuncType;
typedef struct PtrType PtrType;
// Needs to be in sync with typekind.h/CommonSize // Needs to be in sync with typekind.h/CommonSize
struct CommonType struct CommonType
...@@ -101,3 +102,9 @@ struct FuncType ...@@ -101,3 +102,9 @@ struct FuncType
Slice in; Slice in;
Slice out; Slice out;
}; };
struct PtrType
{
Type;
Type *elem;
};
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment