mirror of https://github.com/m-labs/artiq.git
Remove selective attribute writeback; always synchronize all attributes.
The reasons are: 1. Shadow memory manipulation added ~12 instructions to TTLOut.pulse (without inlining), and it's already barely fast enough. 2. More importantly, code such as self.ts[1] did not trigger attribute writeback, and there seems to be no easy way to fix that.
This commit is contained in:
parent
e41b9db787
commit
81427af506
|
@ -418,17 +418,9 @@ class LLVMIRGenerator:
|
||||||
return self.llmodule
|
return self.llmodule
|
||||||
|
|
||||||
def emit_attribute_writeback(self):
|
def emit_attribute_writeback(self):
|
||||||
llobjects = []
|
llobjects = defaultdict(lambda: [])
|
||||||
shadow_memory_dim = defaultdict(lambda: 0)
|
|
||||||
|
|
||||||
for obj_id in self.object_map:
|
for obj_id in self.object_map:
|
||||||
while len(llobjects) <= obj_id:
|
|
||||||
llobjects.append(ll.Constant(llptr, None))
|
|
||||||
|
|
||||||
llobject = self.llmodule.get_global("object.{}".format(obj_id))
|
|
||||||
if llobject is not None:
|
|
||||||
llobjects[obj_id] = llobject.bitcast(llptr)
|
|
||||||
|
|
||||||
obj_ref = self.object_map.retrieve(obj_id)
|
obj_ref = self.object_map.retrieve(obj_id)
|
||||||
if isinstance(obj_ref, (pytypes.FunctionType, pytypes.MethodType)):
|
if isinstance(obj_ref, (pytypes.FunctionType, pytypes.MethodType)):
|
||||||
continue
|
continue
|
||||||
|
@ -437,19 +429,20 @@ class LLVMIRGenerator:
|
||||||
else:
|
else:
|
||||||
typ, _ = self.type_map[type(obj_ref)]
|
typ, _ = self.type_map[type(obj_ref)]
|
||||||
|
|
||||||
if shadow_memory_dim[typ] <= obj_id:
|
llobject = self.llmodule.get_global("object.{}".format(obj_id))
|
||||||
shadow_memory_dim[typ] = obj_id + 1
|
if llobject is not None:
|
||||||
|
llobjects[typ].append(llobject.bitcast(llptr))
|
||||||
|
|
||||||
lldatalayout = llvm.create_target_data(self.llmodule.data_layout)
|
lldatalayout = llvm.create_target_data(self.llmodule.data_layout)
|
||||||
|
|
||||||
llrpcattrty = self.llcontext.get_identified_type("shadow.attr")
|
llrpcattrty = self.llcontext.get_identified_type("attr_desc")
|
||||||
llrpcattrty.elements = [lli32, llptr, llptr]
|
llrpcattrty.elements = [lli32, llptr, llptr]
|
||||||
|
|
||||||
lldescty = self.llcontext.get_identified_type("shadow.desc")
|
lldescty = self.llcontext.get_identified_type("type_desc")
|
||||||
lldescty.elements = [llrpcattrty.as_pointer().as_pointer(), lli32, llptr]
|
lldescty.elements = [llrpcattrty.as_pointer().as_pointer(), llptr.as_pointer()]
|
||||||
|
|
||||||
lldescs = []
|
lldescs = []
|
||||||
for typ in shadow_memory_dim:
|
for typ in llobjects:
|
||||||
if "__objectid__" not in typ.attributes:
|
if "__objectid__" not in typ.attributes:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
@ -458,44 +451,25 @@ class LLVMIRGenerator:
|
||||||
else:
|
else:
|
||||||
type_name = "instance.{}".format(typ.name)
|
type_name = "instance.{}".format(typ.name)
|
||||||
|
|
||||||
shadowname = "shadow.{}".format(type_name)
|
|
||||||
llshadow = self.llmodule.get_global(shadowname)
|
|
||||||
if llshadow is None:
|
|
||||||
continue
|
|
||||||
|
|
||||||
llshadowlen = shadow_memory_dim[typ] * len(typ.attributes)
|
|
||||||
llshadowty = ll.ArrayType(lli8, llshadowlen)
|
|
||||||
llshadow.gtype = llshadowty
|
|
||||||
llshadow.type = llshadowty.as_pointer()
|
|
||||||
llshadow.initializer = ll.Constant(llshadowty, None)
|
|
||||||
|
|
||||||
def llrpcattr_of_attr(name, typ):
|
def llrpcattr_of_attr(name, typ):
|
||||||
llty = self.llty_of_type(typ)
|
size = self.llty_of_type(typ).get_abi_size(lldatalayout, context=self.llcontext)
|
||||||
if isinstance(llty, ll.PointerType):
|
|
||||||
# Work around llvmlite bug where it is unable to get a C++
|
|
||||||
# object for a type if it includes an identified type in a context
|
|
||||||
# other than the default.
|
|
||||||
size = llptr.get_abi_size(lldatalayout)
|
|
||||||
else:
|
|
||||||
size = llty.get_abi_size(lldatalayout)
|
|
||||||
|
|
||||||
def rpc_tag_error(typ):
|
def rpc_tag_error(typ):
|
||||||
print(typ)
|
print(typ)
|
||||||
assert False
|
assert False
|
||||||
|
|
||||||
rpctag = b"Os"
|
if not (types.is_function(typ) or types.is_method(typ) or
|
||||||
if not (types.is_function(typ) or types.is_method(typ)):
|
name == "__objectid__"):
|
||||||
rpctag += self._rpc_tag(typ, error_handler=rpc_tag_error)
|
rpctag = b"Os" + self._rpc_tag(typ, error_handler=rpc_tag_error) + b":n\x00"
|
||||||
|
llrpctag = self.llstr_of_str(rpctag)
|
||||||
else:
|
else:
|
||||||
rpctag += b""
|
llrpctag = ll.Constant(llptr, None)
|
||||||
rpctag += b":n\x00"
|
|
||||||
llrpctag = self.llstr_of_str(rpctag)
|
|
||||||
|
|
||||||
llrpcattr = ll.GlobalVariable(self.llmodule, llrpcattrty,
|
llrpcattr = ll.GlobalVariable(self.llmodule, llrpcattrty,
|
||||||
name="shadow.attr.{}.{}".format(type_name, name))
|
name="attr.{}.{}".format(type_name, name))
|
||||||
llrpcattr.initializer = ll.Constant(llrpcattrty, [
|
llrpcattr.initializer = ll.Constant(llrpcattrty, [
|
||||||
ll.Constant(lli32, size),
|
ll.Constant(lli32, size),
|
||||||
self.llstr_of_str(rpctag),
|
llrpctag,
|
||||||
self.llstr_of_str(name)
|
self.llstr_of_str(name)
|
||||||
])
|
])
|
||||||
llrpcattr.global_constant = True
|
llrpcattr.global_constant = True
|
||||||
|
@ -509,33 +483,36 @@ class LLVMIRGenerator:
|
||||||
|
|
||||||
llrpcattraryty = ll.ArrayType(llrpcattrty.as_pointer(), len(llrpcattrs) + 1)
|
llrpcattraryty = ll.ArrayType(llrpcattrty.as_pointer(), len(llrpcattrs) + 1)
|
||||||
llrpcattrary = ll.GlobalVariable(self.llmodule, llrpcattraryty,
|
llrpcattrary = ll.GlobalVariable(self.llmodule, llrpcattraryty,
|
||||||
name="shadow.attrs.{}".format(type_name))
|
name="attrs.{}".format(type_name))
|
||||||
llrpcattrary.initializer = ll.Constant(llrpcattraryty,
|
llrpcattrary.initializer = ll.Constant(llrpcattraryty,
|
||||||
llrpcattrs + [ll.Constant(llrpcattrty.as_pointer(), None)])
|
llrpcattrs + [ll.Constant(llrpcattrty.as_pointer(), None)])
|
||||||
llrpcattrary.global_constant = True
|
llrpcattrary.global_constant = True
|
||||||
llrpcattrary.unnamed_addr = True
|
llrpcattrary.unnamed_addr = True
|
||||||
llrpcattrary.linkage = 'internal'
|
llrpcattrary.linkage = 'internal'
|
||||||
|
|
||||||
|
llobjectaryty = ll.ArrayType(llptr, len(llobjects[typ]) + 1)
|
||||||
|
llobjectary = ll.GlobalVariable(self.llmodule, llobjectaryty,
|
||||||
|
name="objects.{}".format(type_name))
|
||||||
|
llobjectary.initializer = ll.Constant(llobjectaryty,
|
||||||
|
llobjects[typ] + [ll.Constant(llptr, None)])
|
||||||
|
llobjectary.linkage = 'internal'
|
||||||
|
|
||||||
lldesc = ll.GlobalVariable(self.llmodule, lldescty,
|
lldesc = ll.GlobalVariable(self.llmodule, lldescty,
|
||||||
name="shadow.desc.{}".format(type_name))
|
name="desc.{}".format(type_name))
|
||||||
lldesc.initializer = ll.Constant(lldescty, [
|
lldesc.initializer = ll.Constant(lldescty, [
|
||||||
llrpcattrary.bitcast(llrpcattrty.as_pointer().as_pointer()),
|
llrpcattrary.bitcast(llrpcattrty.as_pointer().as_pointer()),
|
||||||
ll.Constant(lli32, shadow_memory_dim[typ]),
|
llobjectary.bitcast(llptr.as_pointer())
|
||||||
llshadow.bitcast(llptr)
|
|
||||||
])
|
])
|
||||||
lldesc.global_constant = True
|
lldesc.global_constant = True
|
||||||
lldesc.linkage = 'internal'
|
lldesc.linkage = 'internal'
|
||||||
lldescs.append(lldesc)
|
lldescs.append(lldesc)
|
||||||
|
|
||||||
llglobaldescty = ll.ArrayType(lldescty.as_pointer(), len(lldescs) + 1)
|
llglobaldescty = ll.ArrayType(lldescty.as_pointer(), len(lldescs) + 1)
|
||||||
llglobaldesc = ll.GlobalVariable(self.llmodule, llglobaldescty, name="shadow")
|
llglobaldesc = ll.GlobalVariable(self.llmodule, llglobaldescty,
|
||||||
|
name="typeinfo")
|
||||||
llglobaldesc.initializer = ll.Constant(llglobaldescty,
|
llglobaldesc.initializer = ll.Constant(llglobaldescty,
|
||||||
lldescs + [ll.Constant(lldescty.as_pointer(), None)])
|
lldescs + [ll.Constant(lldescty.as_pointer(), None)])
|
||||||
|
|
||||||
llobjectaryty = ll.ArrayType(llptr, len(llobjects))
|
|
||||||
llobjectary = ll.GlobalVariable(self.llmodule, llobjectaryty, name="objects")
|
|
||||||
llobjectary.initializer = ll.Constant(llobjectaryty, llobjects)
|
|
||||||
|
|
||||||
def process_function(self, func):
|
def process_function(self, func):
|
||||||
try:
|
try:
|
||||||
self.llfunction = self.llmodule.get_global(func.name)
|
self.llfunction = self.llmodule.get_global(func.name)
|
||||||
|
@ -695,34 +672,6 @@ class LLVMIRGenerator:
|
||||||
|
|
||||||
def process_SetAttr(self, insn):
|
def process_SetAttr(self, insn):
|
||||||
assert builtins.is_allocated(insn.object().type)
|
assert builtins.is_allocated(insn.object().type)
|
||||||
|
|
||||||
object_type = insn.object().type.find()
|
|
||||||
value_type = insn.value().type.find()
|
|
||||||
if "__objectid__" in object_type.attributes and \
|
|
||||||
not (types.is_function(value_type) or types.is_method(value_type)):
|
|
||||||
llidptr = self.llbuilder.gep(self.map(insn.object()),
|
|
||||||
[self.llindex(0), self.llindex(0)])
|
|
||||||
llid = self.llbuilder.load(llidptr, name="shadow.id")
|
|
||||||
llattrcount = ll.Constant(lli32, len(object_type.attributes))
|
|
||||||
llshadowpos = self.llbuilder.add(
|
|
||||||
self.llbuilder.mul(llid, llattrcount),
|
|
||||||
ll.Constant(lli32, self.attr_index(insn)))
|
|
||||||
|
|
||||||
if types.is_constructor(object_type):
|
|
||||||
shadowname = "shadow.class.{}".format(object_type.name)
|
|
||||||
else:
|
|
||||||
shadowname = "shadow.instance.{}".format(object_type.name)
|
|
||||||
|
|
||||||
llshadow = self.llmodule.get_global(shadowname)
|
|
||||||
if llshadow is None:
|
|
||||||
llshadowty = ll.ArrayType(lli8, 0)
|
|
||||||
llshadow = ll.GlobalVariable(self.llmodule, llshadowty, shadowname)
|
|
||||||
llshadow.linkage = 'internal'
|
|
||||||
|
|
||||||
llshadowptr = self.llbuilder.gep(llshadow, [self.llindex(0), llshadowpos],
|
|
||||||
name="shadow.ptr")
|
|
||||||
self.llbuilder.store(ll.Constant(lli8, 1), llshadowptr)
|
|
||||||
|
|
||||||
llptr = self.llbuilder.gep(self.map(insn.object()),
|
llptr = self.llbuilder.gep(self.map(insn.object()),
|
||||||
[self.llindex(0), self.llindex(self.attr_index(insn))],
|
[self.llindex(0), self.llindex(self.attr_index(insn))],
|
||||||
name=insn.name)
|
name=insn.name)
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
double round(double x);
|
double round(double x);
|
||||||
|
|
||||||
void ksupport_abort(void);
|
void ksupport_abort(void);
|
||||||
static void attribute_writeback(void *, void *);
|
static void attribute_writeback(void *);
|
||||||
|
|
||||||
int64_t now;
|
int64_t now;
|
||||||
|
|
||||||
|
@ -247,16 +247,15 @@ int main(void)
|
||||||
mailbox_send(&load_reply);
|
mailbox_send(&load_reply);
|
||||||
while(1);
|
while(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *__bss_start = dyld_lookup("__bss_start", request->library_info);
|
||||||
|
void *_end = dyld_lookup("_end", request->library_info);
|
||||||
|
memset(__bss_start, 0, _end - __bss_start);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(request->run_kernel) {
|
if(request->run_kernel) {
|
||||||
void (*kernel_run)() = request->library_info->init;
|
void (*kernel_run)() = request->library_info->init;
|
||||||
void *__bss_start = dyld_lookup("__bss_start", request->library_info);
|
void *typeinfo = dyld_lookup("typeinfo", request->library_info);
|
||||||
void *_end = dyld_lookup("_end", request->library_info);
|
|
||||||
void *shadow = dyld_lookup("shadow", request->library_info);
|
|
||||||
void *objects = dyld_lookup("objects", request->library_info);
|
|
||||||
|
|
||||||
memset(__bss_start, 0, _end - __bss_start);
|
|
||||||
|
|
||||||
mailbox_send_and_wait(&load_reply);
|
mailbox_send_and_wait(&load_reply);
|
||||||
|
|
||||||
|
@ -264,7 +263,7 @@ int main(void)
|
||||||
kernel_run();
|
kernel_run();
|
||||||
now_save(now);
|
now_save(now);
|
||||||
|
|
||||||
attribute_writeback(shadow, objects);
|
attribute_writeback(typeinfo);
|
||||||
|
|
||||||
struct msg_base finished_reply;
|
struct msg_base finished_reply;
|
||||||
finished_reply.type = MESSAGE_TYPE_FINISHED;
|
finished_reply.type = MESSAGE_TYPE_FINISHED;
|
||||||
|
@ -405,40 +404,36 @@ int recv_rpc(void *slot) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct shadow_attr {
|
struct attr_desc {
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
const char *tag;
|
const char *tag;
|
||||||
const char *name;
|
const char *name;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct shadow_desc {
|
struct type_desc {
|
||||||
struct shadow_attr **attributes;
|
struct attr_desc **attributes;
|
||||||
uint32_t object_count;
|
void **objects;
|
||||||
uint8_t *shadow;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void attribute_writeback(void *udescs, void *uobjects) {
|
void attribute_writeback(void *utypes) {
|
||||||
struct shadow_desc **descs = (struct shadow_desc **)udescs;
|
struct type_desc **types = (struct type_desc **)utypes;
|
||||||
void **objects = (void **)uobjects;
|
while(*types) {
|
||||||
|
struct type_desc *type = *types++;
|
||||||
while(*descs) {
|
|
||||||
struct shadow_desc *desc = *descs++;
|
|
||||||
|
|
||||||
size_t attr_count = 0;
|
size_t attr_count = 0;
|
||||||
for(struct shadow_attr **attr = desc->attributes; *attr; attr++)
|
for(struct attr_desc **attr = type->attributes; *attr; attr++)
|
||||||
attr_count++;
|
attr_count++;
|
||||||
|
|
||||||
for(int object_id = 0; object_id < desc->object_count; object_id++) {
|
void **objects = type->objects;
|
||||||
uint8_t *shadow = &desc->shadow[object_id * attr_count];
|
while(*objects) {
|
||||||
void *object = objects[object_id];
|
void *object = *objects++;
|
||||||
|
|
||||||
if(object == NULL) continue;
|
|
||||||
|
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
for(int attr_index = 0; attr_index < attr_count; attr_index++) {
|
struct attr_desc **attrs = type->attributes;
|
||||||
struct shadow_attr *attr = desc->attributes[attr_index];
|
while(*attrs) {
|
||||||
|
struct attr_desc *attr = *attrs++;
|
||||||
|
|
||||||
if(shadow[attr_index]) {
|
if(attr->tag) {
|
||||||
uintptr_t value = (uintptr_t)object + offset;
|
uintptr_t value = (uintptr_t)object + offset;
|
||||||
send_rpc(0, attr->tag, &object, &attr->name, value);
|
send_rpc(0, attr->tag, &object, &attr->name, value);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue