Beispiel #1
0
 def optimize(self, instructions):
     for i, inst in enumerate(instructions):
         if inst.name in ("getlocal",
                          "setlocal") and 0 <= inst.argument < 4:
             new_instruction = "%s%s" % (inst.name, inst.argument)
             instructions[i] = get_instruction(new_instruction)()
     return instructions
Beispiel #2
0
    def optimize(self, instructions):
        new_instructions = []
        for inst1, inst2 in group(instructions):
            if inst1 is None or inst2 is None:
                continue

            key = inst1.name, inst2.name
            if key in self.branches:
                combined = get_instruction(self.branches[key])
                new_instructions.append(combined(inst2.labelname))
            else:
                new_instructions.append(inst1)

        return new_instructions
Beispiel #3
0
    def optimize(self, instructions):
        new_instructions = []
        for inst1, inst2 in group(instructions):
            if inst1 is None or inst2 is None:
                continue

            key = inst1.name, inst2.name
            if key in self.branches:
                combined = get_instruction(self.branches[key])
                new_instructions.append(combined(inst2.labelname))
            else:
                new_instructions.append(inst1)

        return new_instructions
Beispiel #4
0
    def optimize(self):
        """
        Do some not so simple optimizations.
        """
        for _ in xrange(2):
            jumps = {}

            # instructions to remove
            remv_inst = set()

            # register -> set([prev, curr])
            remv_regs = {}

            institer = iter(self.instructions)
            instructions = [institer.next()]

            # First pass - mark anything needed for the second pass.
            for newinst in institer:
                instructions.append(newinst)
                prev, curr = instructions[-2:]

                # Gather all jumps by their respective labels.
                if curr.jumplike:
                    jumps.setdefault(curr.labelname, []).append(curr)

                S = set((prev, curr))

                # Detect if there are any references to this register other than
                # the setlocal/getlocal sequence here.
                if prev.name in SET_LOCALS and \
                   curr.name in GET_LOCALS and \
                   prev.argument == curr.argument:
                    remv_inst.update(S)
                    remv_regs[curr.argument] = S

                # PyPy-specific optimization: some opcodes have an unnecessary
                # StoreResult at the end, so callpropvoid and some setproperty's
                # have a pushnull and an unused register afterwards. Stop that.
                elif prev.name in ("pushnull", "pushundefined") and \
                     curr.name in SET_LOCALS:
                    remv_inst.update(S)
                    remv_regs[curr.argument] = S

                elif curr.name in GET_LOCALS:
                    if curr.argument in remv_regs:
                        remv_inst -= remv_regs[curr.argument]

                elif curr.name in SET_LOCALS:
                    # If we have any
                    remv_regs.pop(curr.argument, None)

                elif curr.name == "kill":
                    # If we're going to remove this register, mark the kill for deletion too.
                    if curr.argument in remv_regs:
                        remv_inst.add(curr)

                prev = curr

            institer = iter(self.instructions)
            instructions = [institer.next()]
            # Second pass
            for newinst in institer:
                instructions.append(newinst)
                keep_going = True
                while keep_going:
                    prev, curr = instructions[-2:]
                    test = prev.name, curr.name

                    # Prevent errors with jumps and lone labels.
                    if curr.name == "label" and curr.labelname not in jumps:
                        instructions = instructions[:-1]

                    # Branch optimizations geared for PyPy.
                    elif test in BRANCH_OPTIMIZE:
                        instructions = instructions[:-2]
                        new = get_instruction(BRANCH_OPTIMIZE[test])(
                            curr.labelname)
                        jumps[curr.labelname].remove(curr)
                        jumps[curr.labelname].append(new)
                        instructions.append(new)

                    # Two opcodes in a row that do nothing should be removed.
                    elif prev.name in GET_LOCALS and curr.name in SET_LOCALS \
                             and prev.argument == curr.argument:
                        instructions = instructions[:-2]

                    # jump then label -> remove the jump.
                    elif test == ("jump", "label"
                                  ) and prev.labelname == curr.labelname:
                        # Don't remove the label, we may need it for a backref later on.
                        instructions.pop(-2)
                        jumps[prev.labelname].remove(prev)

                    # return after return -> remove the second return.
                    elif prev.name in ("returnvalue", "returnvoid") and \
                         curr.name in ("returnvalue", "returnvoid"):
                        instructions.pop()

                    # label then jump -> remove both and rename.
                    elif test == ("label", "jump"):
                        for jump in jumps[prev.labelname]:
                            jump.labelname = curr.labelname
                        jumps[curr.labelname].remove(curr)
                        jumps[curr.labelname].extend(jumps[prev.labelname])
                        del jumps[prev.labelname]
                        instructions = instructions[:-2]

                    elif curr in remv_inst:
                        instructions.pop()

                    else:
                        keep_going = False

            self.instructions = instructions

        # Third pass - pack in those registers.
        institer = iter(self.instructions)
        inst = [institer.next()]
        # local_names is the arguments to the method
        used_registers = dict((i, i) for i in xrange(len(self.local_names)))

        for newinst in institer:
            curr = inst[-1]
            if curr.name in SET_LOCALS:
                index = used_registers.setdefault(curr.argument,
                                                  len(used_registers))
                instructions[-1] = get_instruction('setlocal')(index)

            elif curr.name in GET_LOCALS:
                inst[-1] = get_instruction('getlocal')(used_registers.get(
                    curr.argument, curr.argument))

            elif curr.name == "kill":
                inst[-1] = get_instruction('kill')(used_registers.get(
                    curr.argument, curr.argument))

        self.numlocals = len(used_registers)
        self.instructions = instructions
Beispiel #5
0
 def emit(self, name, *a, **kw):
     """
     Emit an instruction, with given arguments.
     """
     return self.add_instruction(get_instruction(name)(*a, **kw))
Beispiel #6
0
    def optimize(self):
        """
        Do some not so simple optimizations.
        """
        for _ in xrange(2):
            jumps = {}

            # instructions to remove
            remv_inst = set()

            # register -> set([prev, curr])
            remv_regs = {}

            institer = iter(self.instructions)
            instructions = [institer.next()]

            # First pass - mark anything needed for the second pass.
            for newinst in institer:
                instructions.append(newinst)
                prev, curr = instructions[-2:]

                # Gather all jumps by their respective labels.
                if curr.jumplike:
                    jumps.setdefault(curr.labelname, []).append(curr)

                S = set((prev, curr))

                # Detect if there are any references to this register other than
                # the setlocal/getlocal sequence here.
                if prev.name in SET_LOCALS and curr.name in GET_LOCALS and prev.argument == curr.argument:
                    remv_inst.update(S)
                    remv_regs[curr.argument] = S

                # PyPy-specific optimization: some opcodes have an unnecessary
                # StoreResult at the end, so callpropvoid and some setproperty's
                # have a pushnull and an unused register afterwards. Stop that.
                elif prev.name in ("pushnull", "pushundefined") and curr.name in SET_LOCALS:
                    remv_inst.update(S)
                    remv_regs[curr.argument] = S

                elif curr.name in GET_LOCALS:
                    if curr.argument in remv_regs:
                        remv_inst -= remv_regs[curr.argument]

                elif curr.name in SET_LOCALS:
                    # If we have any
                    remv_regs.pop(curr.argument, None)

                elif curr.name == "kill":
                    # If we're going to remove this register, mark the kill for deletion too.
                    if curr.argument in remv_regs:
                        remv_inst.add(curr)

                prev = curr

            institer = iter(self.instructions)
            instructions = [institer.next()]
            # Second pass
            for newinst in institer:
                instructions.append(newinst)
                keep_going = True
                while keep_going:
                    prev, curr = instructions[-2:]
                    test = prev.name, curr.name

                    # Prevent errors with jumps and lone labels.
                    if curr.name == "label" and curr.labelname not in jumps:
                        instructions = instructions[:-1]

                    # Branch optimizations geared for PyPy.
                    elif test in BRANCH_OPTIMIZE:
                        instructions = instructions[:-2]
                        new = get_instruction(BRANCH_OPTIMIZE[test])(curr.labelname)
                        jumps[curr.labelname].remove(curr)
                        jumps[curr.labelname].append(new)
                        instructions.append(new)

                    # Two opcodes in a row that do nothing should be removed.
                    elif prev.name in GET_LOCALS and curr.name in SET_LOCALS and prev.argument == curr.argument:
                        instructions = instructions[:-2]

                    # jump then label -> remove the jump.
                    elif test == ("jump", "label") and prev.labelname == curr.labelname:
                        # Don't remove the label, we may need it for a backref later on.
                        instructions.pop(-2)
                        jumps[prev.labelname].remove(prev)

                    # return after return -> remove the second return.
                    elif prev.name in ("returnvalue", "returnvoid") and curr.name in ("returnvalue", "returnvoid"):
                        instructions.pop()

                    # label then jump -> remove both and rename.
                    elif test == ("label", "jump"):
                        for jump in jumps[prev.labelname]:
                            jump.labelname = curr.labelname
                        jumps[curr.labelname].remove(curr)
                        jumps[curr.labelname].extend(jumps[prev.labelname])
                        del jumps[prev.labelname]
                        instructions = instructions[:-2]

                    elif curr in remv_inst:
                        instructions.pop()

                    else:
                        keep_going = False

            self.instructions = instructions

        # Third pass - pack in those registers.
        institer = iter(self.instructions)
        inst = [institer.next()]
        # local_names is the arguments to the method
        used_registers = dict((i, i) for i in xrange(len(self.local_names)))

        for newinst in institer:
            curr = inst[-1]
            if curr.name in SET_LOCALS:
                index = used_registers.setdefault(curr.argument, len(used_registers))
                instructions[-1] = get_instruction("setlocal")(index)

            elif curr.name in GET_LOCALS:
                inst[-1] = get_instruction("getlocal")(used_registers.get(curr.argument, curr.argument))

            elif curr.name == "kill":
                inst[-1] = get_instruction("kill")(used_registers.get(curr.argument, curr.argument))

        self.numlocals = len(used_registers)
        self.instructions = instructions
Beispiel #7
0
 def emit(self, name, *a, **kw):
     """
     Emit an instruction, with given arguments.
     """
     print "   ", name, a
     return self.add_instruction(get_instruction(name)(*a, **kw))
Beispiel #8
0
 def optimize(self, instructions):
     for i, inst in enumerate(instructions):
         if inst.name in ("getlocal", "setlocal") and 0 <= inst.argument < 4:
             new_instruction = "%s%s" % (inst.name, inst.argument)
             instructions[i] = get_instruction(new_instruction)()
     return instructions