Skip to content

Commit 38a99fd

Browse files
author
whitequark
committedJan 2, 2016
Implement selective attribute writeback using shadow memory.
1 parent 2e33084 commit 38a99fd

File tree

7 files changed

+174
-49
lines changed

7 files changed

+174
-49
lines changed
 

Diff for: ‎artiq/compiler/builtins.py

+11-5
Original file line numberDiff line numberDiff line change
@@ -89,13 +89,13 @@ class TException(types.TMono):
8989
attributes = OrderedDict([
9090
("__name__", TStr()),
9191
("__file__", TStr()),
92-
("__line__", TInt(types.TValue(32))),
93-
("__col__", TInt(types.TValue(32))),
92+
("__line__", TInt32()),
93+
("__col__", TInt32()),
9494
("__func__", TStr()),
9595
("__message__", TStr()),
96-
("__param0__", TInt(types.TValue(64))),
97-
("__param1__", TInt(types.TValue(64))),
98-
("__param2__", TInt(types.TValue(64))),
96+
("__param0__", TInt64()),
97+
("__param1__", TInt64()),
98+
("__param2__", TInt64()),
9999
])
100100

101101
def __init__(self, name="Exception", id=0):
@@ -191,6 +191,12 @@ def is_int(typ, width=None):
191191
else:
192192
return types.is_mono(typ, "int")
193193

194+
def is_int32(typ):
195+
return is_int(typ, types.TValue(32))
196+
197+
def is_int64(typ):
198+
return is_int(typ, types.TValue(64))
199+
194200
def get_int_width(typ):
195201
if is_int(typ):
196202
return types.get_value(typ.find()["width"])

Diff for: ‎artiq/compiler/targets.py

+8-2
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,14 @@ def compile(self, module):
8181
print(function.as_entity(type_printer), file=sys.stderr)
8282

8383
llmod = module.build_llvm_ir(self)
84-
llparsedmod = llvm.parse_assembly(str(llmod))
85-
llparsedmod.verify()
84+
85+
try:
86+
llparsedmod = llvm.parse_assembly(str(llmod))
87+
llparsedmod.verify()
88+
except RuntimeError:
89+
print("====== LLVM IR DUMP (PARSE FAILED) ======", file=sys.stderr)
90+
print(str(llmod), file=sys.stderr)
91+
raise
8692

8793
if os.getenv("ARTIQ_DUMP_LLVM"):
8894
print("====== LLVM IR DUMP ======", file=sys.stderr)

Diff for: ‎artiq/compiler/transforms/llvm_ir_generator.py

+74-32
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
into LLVM intermediate representation.
44
"""
55

6-
import os, re
6+
import os, re, types as pytypes
77
from collections import defaultdict
88
from pythonparser import ast, diagnostic
9-
from llvmlite_artiq import ir as ll
9+
from llvmlite_artiq import ir as ll, binding as llvm
1010
from ...language import core as language_core
1111
from .. import types, builtins, ir
1212

@@ -418,26 +418,40 @@ def process(self, functions, attribute_writeback):
418418
return self.llmodule
419419

420420
def emit_attribute_writeback(self):
421+
llobjects = []
421422
shadow_memory_dim = defaultdict(lambda: 0)
422423

423424
for obj_id in self.object_map:
425+
while len(llobjects) <= obj_id:
426+
llobjects.append(ll.Constant(llptr, None))
427+
428+
llobject = self.llmodule.get_global("object.{}".format(obj_id))
429+
if llobject is not None:
430+
llobjects[obj_id] = llobject.bitcast(llptr)
431+
424432
obj_ref = self.object_map.retrieve(obj_id)
425-
if isinstance(obj_ref, type):
433+
if isinstance(obj_ref, (pytypes.FunctionType, pytypes.MethodType)):
434+
continue
435+
elif isinstance(obj_ref, type):
426436
_, typ = self.type_map[obj_ref]
427437
else:
428438
typ, _ = self.type_map[type(obj_ref)]
429439

430440
if shadow_memory_dim[typ] <= obj_id:
431441
shadow_memory_dim[typ] = obj_id + 1
432442

443+
lldatalayout = llvm.create_target_data(self.llmodule.data_layout)
444+
445+
llrpcattrty = self.llcontext.get_identified_type("shadow.attr")
446+
llrpcattrty.elements = [lli32, llptr, llptr]
447+
433448
lldescty = self.llcontext.get_identified_type("shadow.desc")
434-
lldescty.elements = [llptr.as_pointer(), llptr, lli32, llptr]
449+
lldescty.elements = [llrpcattrty.as_pointer().as_pointer(), lli32, llptr]
435450

436451
lldescs = []
437452
for typ in shadow_memory_dim:
438453
if "__objectid__" not in typ.attributes:
439454
continue
440-
assert list(typ.attributes.keys())[0] == "__objectid__"
441455

442456
if types.is_constructor(typ):
443457
type_name = "class.{}".format(typ.name)
@@ -455,44 +469,72 @@ def emit_attribute_writeback(self):
455469
llshadow.type = llshadowty.as_pointer()
456470
llshadow.initializer = ll.Constant(llshadowty, None)
457471

458-
def rpc_tag_error(typ):
459-
print(typ)
460-
assert False
461-
462-
rpcattrary = list(typ.attributes.keys())[1:]
463-
llrpcattraryty = ll.ArrayType(llptr, len(rpcattrary) + 1)
464-
llrpcattrary = list(map(lambda attr: self.llstr_of_str(attr), rpcattrary))
472+
def llrpcattr_of_attr(name, typ):
473+
llty = self.llty_of_type(typ)
474+
if isinstance(llty, ll.PointerType):
475+
# Work around llvmlite bug where it is unable to get a C++
476+
# object for a type if it includes an identified type in a context
477+
# other than the default.
478+
size = llptr.get_abi_size(lldatalayout)
479+
else:
480+
size = llty.get_abi_size(lldatalayout)
465481

466-
llrpcattrs = ll.GlobalVariable(self.llmodule, llrpcattraryty,
467-
name="shadow.attrs.{}".format(type_name))
468-
llrpcattrs.initializer = ll.Constant(llrpcattraryty,
469-
llrpcattrary + [ll.Constant(llptr, None)])
470-
llrpcattrs.linkage = 'internal'
482+
def rpc_tag_error(typ):
483+
print(typ)
484+
assert False
471485

472-
rpctag = b""
473-
for attr_type in list(typ.attributes.values())[1:]:
474-
if types.is_function(attr_type) or types.is_method(attr_type):
475-
continue
476-
rpctag += self._rpc_tag(attr_type, error_handler=rpc_tag_error)
477-
rpctag += b"\x00"
478-
llrpctag = self.llstr_of_str(rpctag)
486+
rpctag = b"Os"
487+
if not (types.is_function(typ) or types.is_method(typ)):
488+
rpctag += self._rpc_tag(typ, error_handler=rpc_tag_error)
489+
else:
490+
rpctag += b""
491+
rpctag += b":n\x00"
492+
llrpctag = self.llstr_of_str(rpctag)
493+
494+
llrpcattr = ll.GlobalVariable(self.llmodule, llrpcattrty,
495+
name="shadow.attr.{}.{}".format(type_name, name))
496+
llrpcattr.initializer = ll.Constant(llrpcattrty, [
497+
ll.Constant(lli32, size),
498+
self.llstr_of_str(rpctag),
499+
self.llstr_of_str(name)
500+
])
501+
llrpcattr.global_constant = True
502+
llrpcattr.unnamed_addr = True
503+
llrpcattr.linkage = 'internal'
504+
505+
return llrpcattr
506+
507+
llrpcattrs = [llrpcattr_of_attr(attr, typ.attributes[attr])
508+
for attr in typ.attributes]
509+
510+
llrpcattraryty = ll.ArrayType(llrpcattrty.as_pointer(), len(llrpcattrs) + 1)
511+
llrpcattrary = ll.GlobalVariable(self.llmodule, llrpcattraryty,
512+
name="shadow.attrs.{}".format(type_name))
513+
llrpcattrary.initializer = ll.Constant(llrpcattraryty,
514+
llrpcattrs + [ll.Constant(llrpcattrty.as_pointer(), None)])
515+
llrpcattrary.global_constant = True
516+
llrpcattrary.unnamed_addr = True
517+
llrpcattrary.linkage = 'internal'
479518

480519
lldesc = ll.GlobalVariable(self.llmodule, lldescty,
481520
name="shadow.desc.{}".format(type_name))
482521
lldesc.initializer = ll.Constant(lldescty, [
483-
llrpcattrs.bitcast(llptr.as_pointer()),
484-
llrpctag,
522+
llrpcattrary.bitcast(llrpcattrty.as_pointer().as_pointer()),
485523
ll.Constant(lli32, shadow_memory_dim[typ]),
486-
llshadow.bitcast(llptr)])
524+
llshadow.bitcast(llptr)
525+
])
526+
lldesc.global_constant = True
487527
lldesc.linkage = 'internal'
488528
lldescs.append(lldesc)
489529

490530
llglobaldescty = ll.ArrayType(lldescty.as_pointer(), len(lldescs) + 1)
491-
llglobaldesc = ll.GlobalVariable(self.llmodule, llglobaldescty,
492-
name="shadow.descs")
531+
llglobaldesc = ll.GlobalVariable(self.llmodule, llglobaldescty, name="shadow")
493532
llglobaldesc.initializer = ll.Constant(llglobaldescty,
494533
lldescs + [ll.Constant(lldescty.as_pointer(), None)])
495-
# llglobaldesc.linkage = 'internal'
534+
535+
llobjectaryty = ll.ArrayType(llptr, len(llobjects))
536+
llobjectary = ll.GlobalVariable(self.llmodule, llobjectaryty, name="objects")
537+
llobjectary.initializer = ll.Constant(llobjectaryty, llobjects)
496538

497539
def process_function(self, func):
498540
try:
@@ -661,10 +703,10 @@ def process_SetAttr(self, insn):
661703
llidptr = self.llbuilder.gep(self.map(insn.object()),
662704
[self.llindex(0), self.llindex(0)])
663705
llid = self.llbuilder.load(llidptr, name="shadow.id")
664-
llattrcount = ll.Constant(lli32, len(object_type.attributes) - 1)
706+
llattrcount = ll.Constant(lli32, len(object_type.attributes))
665707
llshadowpos = self.llbuilder.add(
666708
self.llbuilder.mul(llid, llattrcount),
667-
ll.Constant(lli32, self.attr_index(insn) - 1))
709+
ll.Constant(lli32, self.attr_index(insn)))
668710

669711
if types.is_constructor(object_type):
670712
shadowname = "shadow.class.{}".format(object_type.name)

Diff for: ‎artiq/coredevice/comm_generic.py

+10-5
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,11 @@ def check(cond, expected):
435435

436436
def _serve_rpc(self, object_map):
437437
service_id = self._read_int32()
438-
service = object_map.retrieve(service_id)
438+
if service_id == 0:
439+
service = lambda obj, attr, value: setattr(obj, attr, value)
440+
else:
441+
service = object_map.retrieve(service_id)
442+
439443
arguments = self._receive_rpc_args(object_map, service.__defaults__)
440444
return_tags = self._read_bytes()
441445
logger.debug("rpc service: [%d]%r %r -> %s", service_id, service, arguments, return_tags)
@@ -444,10 +448,11 @@ def _serve_rpc(self, object_map):
444448
result = service(*arguments)
445449
logger.debug("rpc service: %d %r == %r", service_id, arguments, result)
446450

447-
self._write_header(_H2DMsgType.RPC_REPLY)
448-
self._write_bytes(return_tags)
449-
self._send_rpc_value(bytearray(return_tags), result, result, service)
450-
self._write_flush()
451+
if service_id != 0:
452+
self._write_header(_H2DMsgType.RPC_REPLY)
453+
self._write_bytes(return_tags)
454+
self._send_rpc_value(bytearray(return_tags), result, result, service)
455+
self._write_flush()
451456
except Exception as exn:
452457
logger.debug("rpc service: %d %r ! %r", service_id, arguments, exn)
453458

Diff for: ‎artiq/runtime/ksupport.c

+59-3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
double round(double x);
2121

2222
void ksupport_abort(void);
23+
static void attribute_writeback(void *, void *);
2324

2425
int64_t now;
2526

@@ -249,14 +250,22 @@ int main(void)
249250
}
250251

251252
if(request->run_kernel) {
252-
void (*kernel_init)() = request->library_info->init;
253+
void (*kernel_run)() = request->library_info->init;
254+
void *__bss_start = dyld_lookup("__bss_start", request->library_info);
255+
void *_end = dyld_lookup("_end", request->library_info);
256+
void *shadow = dyld_lookup("shadow", request->library_info);
257+
void *objects = dyld_lookup("objects", request->library_info);
258+
259+
memset(__bss_start, 0, _end - __bss_start);
253260

254261
mailbox_send_and_wait(&load_reply);
255262

256263
now = now_init();
257-
kernel_init();
264+
kernel_run();
258265
now_save(now);
259266

267+
attribute_writeback(shadow, objects);
268+
260269
struct msg_base finished_reply;
261270
finished_reply.type = MESSAGE_TYPE_FINISHED;
262271
mailbox_send_and_wait(&finished_reply);
@@ -357,7 +366,10 @@ void send_rpc(int service, const char *tag, ...)
357366
{
358367
struct msg_rpc_send request;
359368

360-
request.type = MESSAGE_TYPE_RPC_SEND;
369+
if(service != 0)
370+
request.type = MESSAGE_TYPE_RPC_SEND;
371+
else
372+
request.type = MESSAGE_TYPE_RPC_BATCH;
361373
request.service = service;
362374
request.tag = tag;
363375
va_start(request.args, tag);
@@ -393,6 +405,50 @@ int recv_rpc(void *slot) {
393405
}
394406
}
395407

408+
struct shadow_attr {
409+
uint32_t size;
410+
const char *tag;
411+
const char *name;
412+
};
413+
414+
struct shadow_desc {
415+
struct shadow_attr **attributes;
416+
uint32_t object_count;
417+
uint8_t *shadow;
418+
};
419+
420+
void attribute_writeback(void *udescs, void *uobjects) {
421+
struct shadow_desc **descs = (struct shadow_desc **)udescs;
422+
void **objects = (void **)uobjects;
423+
424+
while(*descs) {
425+
struct shadow_desc *desc = *descs++;
426+
427+
size_t attr_count = 0;
428+
for(struct shadow_attr **attr = desc->attributes; *attr; attr++)
429+
attr_count++;
430+
431+
for(int object_id = 0; object_id < desc->object_count; object_id++) {
432+
uint8_t *shadow = &desc->shadow[object_id * attr_count];
433+
void *object = objects[object_id];
434+
435+
if(object == NULL) continue;
436+
437+
size_t offset = 0;
438+
for(int attr_index = 0; attr_index < attr_count; attr_index++) {
439+
struct shadow_attr *attr = desc->attributes[attr_index];
440+
441+
if(shadow[attr_index]) {
442+
uintptr_t value = (uintptr_t)object + offset;
443+
send_rpc(0, attr->tag, &object, &attr->name, value);
444+
}
445+
446+
offset += attr->size;
447+
}
448+
}
449+
}
450+
}
451+
396452
void lognonl(const char *fmt, ...)
397453
{
398454
struct msg_log request;

Diff for: ‎artiq/runtime/messages.h

+8
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ enum {
1717
MESSAGE_TYPE_RPC_SEND,
1818
MESSAGE_TYPE_RPC_RECV_REQUEST,
1919
MESSAGE_TYPE_RPC_RECV_REPLY,
20+
MESSAGE_TYPE_RPC_BATCH,
2021
MESSAGE_TYPE_LOG,
2122

2223
MESSAGE_TYPE_BRG_READY,
@@ -97,6 +98,13 @@ struct msg_rpc_recv_reply {
9798
struct artiq_exception *exception;
9899
};
99100

101+
struct msg_rpc_batch {
102+
int type;
103+
int service;
104+
const char *tag;
105+
void *ptr;
106+
};
107+
100108
struct msg_log {
101109
int type;
102110
const char *fmt;

Diff for: ‎artiq/runtime/session.c

+4-2
Original file line numberDiff line numberDiff line change
@@ -962,7 +962,8 @@ static int process_kmsg(struct msg_base *umsg)
962962
break;
963963
}
964964

965-
case MESSAGE_TYPE_RPC_SEND: {
965+
case MESSAGE_TYPE_RPC_SEND:
966+
case MESSAGE_TYPE_RPC_BATCH: {
966967
struct msg_rpc_send *msg = (struct msg_rpc_send *)umsg;
967968

968969
if(!send_rpc_request(msg->service, msg->tag, msg->args)) {
@@ -971,7 +972,8 @@ static int process_kmsg(struct msg_base *umsg)
971972
return 0; // restart session
972973
}
973974

974-
user_kernel_state = USER_KERNEL_WAIT_RPC;
975+
if(msg->type == MESSAGE_TYPE_RPC_SEND)
976+
user_kernel_state = USER_KERNEL_WAIT_RPC;
975977
mailbox_acknowledge();
976978
break;
977979
}

0 commit comments

Comments
 (0)
Please sign in to comment.