def iadd(self, old, args, value): assert len(args) == 2 assert value == 1 ref, perm, perm_inv = old refval = ref(args[0]) owned = perm(args[0], refval) idx = perm_inv(args[0], args[1]) ref = util.partial_update(ref, (args[0],), refval + 1) # We are modeling the ownership with three functions, # 1) a refcount number: the number of objects owned by `owner` # 2) a function with the property that the first `refval` objects owned by `owner` # 3) a function that is the inverse of 2) # For example, consider 5 'ownable' objects in the system, # Where `owner` has 2 objects: 3 and 2. The state might look like: #-------------------------- # 3 | 2 | 1 | 4 | 5 #-------------------------- # ^ # refval # Now, iadd is incrementing the refcnt by allocating args[2] # To do this we have to swap the current position of args[2] with the # Slot at refval. # For example, if args[1] is 5, we update the state by swapping the `1` # at index refval with the index of args[1]. #-------------------------- # 3 | 2 | 5 | 4 | 1 #-------------------------- # ^ # refval # Write the new value (args[1]) into position refval and maintain the # inverse function perm = util.partial_update(perm, (args[0], refval), args[1]) perm_inv = util.partial_update(perm_inv, (args[0], args[1]), refval) # Write the previous value of refval to the previous location of args[1] perm = util.partial_update(perm, (args[0], idx), owned) perm_inv = util.partial_update(perm_inv, (args[0], owned), idx) return (ref, perm, perm_inv)
def isub(self, old, args, value): assert len(args) == 2 assert value == 1 ref, perm, perm_inv = old ref = util.partial_update(ref, (args[0],), ref(args[0]) - 1) refval = ref(args[0]) owned = perm(args[0], refval) idx = perm_inv(args[0], args[1]) perm = util.partial_update(perm, (args[0], refval), args[1]) perm_inv = util.partial_update(perm_inv, (args[0], args[1]), refval) perm = util.partial_update(perm, (args[0], idx), owned) perm_inv = util.partial_update(perm_inv, (args[0], owned), idx) return (ref, perm, perm_inv)
def set(self, old, args, value): # "raw" assignment of a lambda without any accessor arguments if isinstance(value, types.FunctionType): assert not args return lambda *args: value(*args, oldfn=old) elif self.get_arity() == 0: # assignment to a value return value else: # assignment with value with partial arguments return util.partial_update(old, args, value)
def isub(self, old, args, value): assert len(args) == 2 assert value == 1 ref, perm1, perm2, perm_inv = old ref = util.partial_update(ref, (args[0],), ref(args[0]) - 1) refval = ref(args[0]) owned_x = perm1(args[0], refval) owned_y = perm2(args[0], refval) idx = perm_inv(args[0], *args[1]) perm1 = util.partial_update(perm1, (args[0], refval), args[1][0]) perm2 = util.partial_update(perm2, (args[0], refval), args[1][1]) perm_inv = util.partial_update(perm_inv, (args[0], args[1][0], args[1][1]), refval) perm1 = util.partial_update(perm1, (args[0], idx), owned_x) perm2 = util.partial_update(perm2, (args[0], idx), owned_y) perm_inv = util.partial_update(perm_inv, (args[0], owned_x, owned_y), idx) return (ref, perm1, perm2, perm_inv)
def hvm_invalidate_tlb(ctx, pid): uf = ctx.globals['#tlbinv'] ctx.globals['#tlbinv'] = util.partial_update(uf, (pid, ), z3.BoolVal(True))