def make_loop_bytecode(bytecode, loop, args, returns): # Add return None co_consts = tuple(bytecode.co_consts) if None not in co_consts: co_consts += (None,) if returns: for out in returns: # Load output loadfast = ByteCodeInst.get(loop[-1].next, "LOAD_FAST", bytecode.co_varnames.index(out)) loadfast.lineno = loop[-1].lineno loop.append(loadfast) # Build tuple buildtuple = ByteCodeInst.get(loop[-1].next, "BUILD_TUPLE", len(returns)) buildtuple.lineno = loop[-1].lineno loop.append(buildtuple) else: # Load None load_none = ByteCodeInst.get(loop[-1].next, "LOAD_CONST", co_consts.index(None)) load_none.lineno = loop[-1].lineno loop.append(load_none) # Return TOS return_value = ByteCodeInst.get(loop[-1].next, "RETURN_VALUE", 0) return_value.lineno = loop[-1].lineno loop.append(return_value) # Function name loop_qualname = bytecode.func_qualname + ".__numba__loop%d__" % loop[0].offset # Argspec argspectype = type(bytecode.argspec) argspec = argspectype(args=args, varargs=(), keywords=(), defaults=()) # Code table codetable = utils.SortedMap((i.offset, i) for i in loop) # Custom bytecode object lbc = CustomByteCode(func=bytecode.func, func_qualname=loop_qualname, # Enforced in separate_loops() is_generator=False, argspec=argspec, filename=bytecode.filename, co_names=bytecode.co_names, co_varnames=bytecode.co_varnames, co_consts=co_consts, co_freevars=bytecode.co_freevars, table=codetable, labels=bytecode.labels) return lbc
def make_loop_bytecode(bytecode, loop, args): # Add return None co_consts = tuple(bytecode.co_consts) if None not in co_consts: co_consts += (None,) # Load None load_none = ByteCodeInst.get(loop[-1].next, "LOAD_CONST", co_consts.index(None)) load_none.lineno = loop[-1].lineno loop.append(load_none) # Return None return_value = ByteCodeInst.get(loop[-1].next, "RETURN_VALUE", 0) return_value.lineno = loop[-1].lineno loop.append(return_value) # Function name loopfuncname = bytecode.func_name+"__numba__loop%d__" % loop[0].offset # Argspec argspectype = type(bytecode.argspec) argspec = argspectype(args=args, varargs=(), keywords=(), defaults=()) # Code table codetable = utils.SortedMap((i.offset, i) for i in loop) # Custom bytecode object lbc = CustomByteCode(func=bytecode.func, func_name=loopfuncname, argspec=argspec, filename=bytecode.filename, co_names=bytecode.co_names, co_varnames=bytecode.co_varnames, co_consts=co_consts, co_freevars=bytecode.co_freevars, table=codetable, labels=bytecode.labels) return lbc
def insert_loop_call(bytecode, loop, args, outer, outerlabels, outernames, dispatcher_factory): endloopoffset = loop[-1].next # Accepted. Create a bytecode object for the loop args = tuple(args) lbc = make_loop_bytecode(bytecode, loop, args) # Generate dispatcher for this inner loop, and append it to the # consts tuple. disp = dispatcher_factory(lbc) disp_idx = len(bytecode.co_consts) bytecode.co_consts += (disp,) # Insert jump to the end jmp = ByteCodeInst.get(loop[0].offset, 'JUMP_ABSOLUTE', outer[-1].next) jmp.lineno = loop[0].lineno insert_instruction(outer, jmp) outerlabels.add(outer[-1].next) # Prepare arguments loadfn = ByteCodeInst.get(outer[-1].next, "LOAD_CONST", disp_idx) loadfn.lineno = loop[0].lineno insert_instruction(outer, loadfn) for arg in args: loadarg = ByteCodeInst.get(outer[-1].next, 'LOAD_FAST', bytecode.co_varnames.index(arg)) loadarg.lineno = loop[0].lineno insert_instruction(outer, loadarg) # Call function assert len(args) < 256 call = ByteCodeInst.get(outer[-1].next, "CALL_FUNCTION", len(args)) call.lineno = loop[0].lineno insert_instruction(outer, call) poptop = ByteCodeInst.get(outer[-1].next, "POP_TOP", None) poptop.lineno = loop[0].lineno insert_instruction(outer, poptop) jmpback = ByteCodeInst.get(outer[-1].next, 'JUMP_ABSOLUTE', endloopoffset) jmpback.lineno = loop[0].lineno insert_instruction(outer, jmpback) return disp
def insert_loop_call(bytecode, loop, args, lbclist, outer, outerlabels, outernames): endloopoffset = loop[-1].next # Accepted. Create a bytecode object for the loop args = tuple(args) lbc = make_loop_bytecode(bytecode, loop, args) lbclist.append(lbc) # Insert jump to the end jmp = ByteCodeInst.get(loop[0].offset, 'JUMP_ABSOLUTE', outer[-1].next) jmp.lineno = loop[0].lineno insert_instruction(outer, jmp) outerlabels.add(outer[-1].next) # Prepare arguments outernames.append(lbc.func_name) loadfn = ByteCodeInst.get(outer[-1].next, "LOAD_GLOBAL", outernames.index(lbc.func_name)) loadfn.lineno = loop[0].lineno insert_instruction(outer, loadfn) for arg in args: loadarg = ByteCodeInst.get(outer[-1].next, 'LOAD_FAST', bytecode.co_varnames.index(arg)) loadarg.lineno = loop[0].lineno insert_instruction(outer, loadarg) # Call function assert len(args) < 256 call = ByteCodeInst.get(outer[-1].next, "CALL_FUNCTION", len(args)) call.lineno = loop[0].lineno insert_instruction(outer, call) poptop = ByteCodeInst.get(outer[-1].next, "POP_TOP", None) poptop.lineno = loop[0].lineno insert_instruction(outer, poptop) jmpback = ByteCodeInst.get(outer[-1].next, 'JUMP_ABSOLUTE', endloopoffset) jmpback.lineno = loop[0].lineno insert_instruction(outer, jmpback)
def insert_loop_call(bytecode, loop, args, outer, outerlabels, returns, dispatcher_factory): endloopoffset = loop[-1].next # Accepted. Create a bytecode object for the loop args = tuple(args) lbc = make_loop_bytecode(bytecode, loop, args, returns) # Generate dispatcher for this inner loop, and append it to the # consts tuple. disp = dispatcher_factory(lbc) disp_idx = len(bytecode.co_consts) bytecode.co_consts += (disp,) # Insert jump to the end insertpt = SubOffset(loop[0].next) jmp = ByteCodeInst.get(loop[0].offset, 'JUMP_ABSOLUTE', insertpt) jmp.lineno = loop[0].lineno insert_instruction(outer, jmp) outerlabels.add(outer[-1].next) # Prepare arguments loadfn = ByteCodeInst.get(insertpt, "LOAD_CONST", disp_idx) loadfn.lineno = loop[0].lineno insert_instruction(outer, loadfn) insertpt = insertpt.next() for arg in args: loadarg = ByteCodeInst.get(insertpt, 'LOAD_FAST', bytecode.co_varnames.index(arg)) loadarg.lineno = loop[0].lineno insert_instruction(outer, loadarg) insertpt = insertpt.next() # Call function assert len(args) < 256 call = ByteCodeInst.get(insertpt, "CALL_FUNCTION", len(args)) call.lineno = loop[0].lineno insert_instruction(outer, call) insertpt = insertpt.next() if returns: # Unpack arguments unpackseq = ByteCodeInst.get(insertpt, "UNPACK_SEQUENCE", len(returns)) unpackseq.lineno = loop[0].lineno insert_instruction(outer, unpackseq) insertpt = insertpt.next() for out in returns: # Store each variable storefast = ByteCodeInst.get(insertpt, "STORE_FAST", bytecode.co_varnames.index(out)) storefast.lineno = loop[0].lineno insert_instruction(outer, storefast) insertpt = insertpt.next() else: # No return value poptop = ByteCodeInst.get(outer[-1].next, "POP_TOP", None) poptop.lineno = loop[0].lineno insert_instruction(outer, poptop) insertpt = insertpt.next() jmpback = ByteCodeInst.get(insertpt, 'JUMP_ABSOLUTE', endloopoffset) jmpback.lineno = loop[0].lineno insert_instruction(outer, jmpback) return disp
def insert_loop_call(bytecode, loop, args, outer, outerlabels, returns, dispatcher_factory): endloopoffset = loop[-1].next # Accepted. Create a bytecode object for the loop args = tuple(args) lbc = make_loop_bytecode(bytecode, loop, args, returns) # Generate dispatcher for this inner loop, and append it to the # consts tuple. disp = dispatcher_factory(lbc) disp_idx = len(bytecode.co_consts) bytecode.co_consts += (disp, ) # Insert jump to the end insertpt = SubOffset(loop[0].next) jmp = ByteCodeInst.get(loop[0].offset, 'JUMP_ABSOLUTE', insertpt) jmp.lineno = loop[0].lineno insert_instruction(outer, jmp) outerlabels.add(outer[-1].next) # Prepare arguments loadfn = ByteCodeInst.get(insertpt, "LOAD_CONST", disp_idx) loadfn.lineno = loop[0].lineno insert_instruction(outer, loadfn) insertpt = insertpt.next() for arg in args: loadarg = ByteCodeInst.get(insertpt, 'LOAD_FAST', bytecode.co_varnames.index(arg)) loadarg.lineno = loop[0].lineno insert_instruction(outer, loadarg) insertpt = insertpt.next() # Call function assert len(args) < 256 call = ByteCodeInst.get(insertpt, "CALL_FUNCTION", len(args)) call.lineno = loop[0].lineno insert_instruction(outer, call) insertpt = insertpt.next() if returns: # Unpack arguments unpackseq = ByteCodeInst.get(insertpt, "UNPACK_SEQUENCE", len(returns)) unpackseq.lineno = loop[0].lineno insert_instruction(outer, unpackseq) insertpt = insertpt.next() for out in returns: # Store each variable storefast = ByteCodeInst.get(insertpt, "STORE_FAST", bytecode.co_varnames.index(out)) storefast.lineno = loop[0].lineno insert_instruction(outer, storefast) insertpt = insertpt.next() else: # No return value poptop = ByteCodeInst.get(outer[-1].next, "POP_TOP", None) poptop.lineno = loop[0].lineno insert_instruction(outer, poptop) insertpt = insertpt.next() jmpback = ByteCodeInst.get(insertpt, 'JUMP_ABSOLUTE', endloopoffset) jmpback.lineno = loop[0].lineno insert_instruction(outer, jmpback) return disp