示例#1
0
def analyze_loop(settings, code, index):
    instr = code[index]
    if not (instr[0] == byteplay.FOR_ITER and
            (index >= 2 and code[index - 2][0] == byteplay.GET_ITER)):
        return 0
    # Now we found GET_ITER and FOR_ITER instructions

    # Try to find SETUP_LOOP
    for rel_index in orig_xrange(index - 3, -1, -1):
        if code[rel_index][0] == byteplay.SETUP_LOOP:
            setup_index = rel_index
            break
    else:
        return 0

    # Try to find JUMP_ABSOLUTE and POP_BLOCK by label from FOR_ITER
    pop_block_label = instr[1]
    for rel_index in orig_xrange(index + 1, len(code) - 1):
        if code[rel_index][0] is pop_block_label:
            pop_block_index = rel_index + 1
            break
    else:
        return 0
    if not (code[pop_block_index - 2][0] == byteplay.JUMP_ABSOLUTE
            and code[pop_block_index - 2][1] is code[index - 1][0]
            and code[pop_block_index][0] == byteplay.POP_BLOCK):
        return 0
    # It's busy to check POP_BLOCK instruction existence to
    # distinguish real for-loops from a list comprehensions

    # Try to find marker of current line's number
    for rel_index in orig_xrange(setup_index - 1, -1, -1):
        if code[rel_index][0] == byteplay.SetLineno:
            head_lineno = code[rel_index][1]
            break
    else:
        head_lineno = None

    head = code[setup_index + 1:index - 2]
    body = code[index + 1:pop_block_index - 2]
    # Don't forget that "else_body" loop part is also exists

    settings['head_lineno'] = head_lineno
    try:
        state = recompiler.recompile_body(settings, body)
    except recompiler.RecompileError as err:
        if settings['profile']:
            profiler.exc(settings, 'Recompilation failed', err)
        return 0

    # Insert head_handler right before GET_ITER instruction
    head_hook = hook.create_head_hook(state, pop_block_label)
    code[index - 2:index - 2] = head_hook

    if settings['profile']:
        profiler.note(settings, 'Recompilation succeeded')

    # Return length of analyzed code
    return len(head_hook)
示例#2
0
def exec_loop(
    iterable,
    settings,
    matcode,
    used_vars,
    real_vars_indexes,
    need_store_counter,
    globals_dict,
    locals_dict,
    folded,
):
    try:
        # Check whether iterable for-loop argument has type "xrange"
        range_desc = check_iterable(settings, iterable)
        try:
            # If so, retreive it's parameters
            start, step, iters_count, last = range_desc
        except TypeError:
            return None

        # Load necessary variables, check it's types and make vector
        # for further operations with matrixes appending unit row
        vector = load_vars(
            settings,
            used_vars,
            globals_dict,
            locals_dict,
        ) + [1]
    except TypeError as err:
        err.message = "Can't run optimized loop: " + err.message
        if settings['profile']:
            profiler.exc(settings, "Hook didn't allow optimization", err)
        return None

    # Define constant values in matrix code
    matcode = define_values(matcode, folded, {
        'start': start,
        'step': step,
        'iters_count': iters_count,
    })

    # Add last detail to matrix code before it's execution
    matcode.append([END])

    # Run matrix code
    vector = run.run_matcode(settings, matcode, vector)

    if settings['profile']:
        profiler.success(settings,
                         'Optimized execution of %s iterations' % iters_count)

    # Pack real variables' values to a list that will be unpacked in
    # the main function to the values that would be assigned to the
    # globals and the locals. We can't implement storing variables like
    # its' loading because locals() dictionary is read-only.
    packed = [vector[index] for index in real_vars_indexes]
    if need_store_counter:
        packed.append(last)
    return packed
示例#3
0
def exec_loop(
    iterable, settings, matcode, used_vars, real_vars_indexes,
    need_store_counter, globals_dict, locals_dict, folded,
):
    try:
        # Check whether iterable for-loop argument has type "xrange"
        range_desc = check_iterable(settings, iterable)
        try:
            # If so, retreive it's parameters
            start, step, iters_count, last = range_desc
        except TypeError:
            return None
        
        # Load necessary variables, check it's types and make vector
        # for further operations with matrixes appending unit row
        vector = load_vars(
            settings, used_vars, globals_dict, locals_dict,
        ) + [1]
    except TypeError as err:
        err.message = "Can't run optimized loop: " + err.message
        if settings['profile']:
            profiler.exc(settings, "Hook didn't allow optimization", err)
        return None
        
    # Define constant values in matrix code
    matcode = define_values(matcode, folded, {
        'start': start, 'step': step, 'iters_count': iters_count,
    })
    
    # Add last detail to matrix code before it's execution
    matcode.append([END])
    
    # Run matrix code
    vector = run.run_matcode(settings, matcode, vector)
    
    if settings['profile']:
        profiler.success(settings,
                'Optimized execution of %s iterations' % iters_count)
    
    # Pack real variables' values to a list that will be unpacked in
    # the main function to the values that would be assigned to the
    # globals and the locals. We can't implement storing variables like
    # its' loading because locals() dictionary is read-only.
    packed = [vector[index] for index in real_vars_indexes]
    if need_store_counter:
        packed.append(last)
    return packed
示例#4
0
def analyze_loop(settings, code, index):
    instr = code[index]
    if not (
        instr[0] == byteplay.FOR_ITER and
        (index >= 2 and code[index - 2][0] == byteplay.GET_ITER)
    ):
        return 0
    # Now we found GET_ITER and FOR_ITER instructions
    
    # Try to find SETUP_LOOP
    for rel_index in orig_xrange(index - 3, -1, -1):
        if code[rel_index][0] == byteplay.SETUP_LOOP:
            setup_index = rel_index
            break
    else:
        return 0
    
    # Try to find JUMP_ABSOLUTE and POP_BLOCK by label from FOR_ITER
    pop_block_label = instr[1]
    for rel_index in orig_xrange(index + 1, len(code) - 1):
        if code[rel_index][0] is pop_block_label:
            pop_block_index = rel_index + 1
            break
    else:
        return 0
    if not (
        code[pop_block_index - 2][0] == byteplay.JUMP_ABSOLUTE and
        code[pop_block_index - 2][1] is code[index - 1][0] and
        code[pop_block_index][0] == byteplay.POP_BLOCK
    ):
        return 0
    # It's busy to check POP_BLOCK instruction existence to
    # distinguish real for-loops from a list comprehensions
    
    # Try to find marker of current line's number
    for rel_index in orig_xrange(setup_index - 1, -1, -1):
        if code[rel_index][0] == byteplay.SetLineno:
            head_lineno = code[rel_index][1]
            break
    else:
        head_lineno = None
    
    head = code[setup_index + 1:index - 2]
    body = code[index + 1:pop_block_index - 2]
    # Don't forget that "else_body" loop part is also exists
    
    settings['head_lineno'] = head_lineno
    try:
        state = recompiler.recompile_body(settings, body)
    except recompiler.RecompileError as err:
        if settings['profile']:
            profiler.exc(settings, 'Recompilation failed', err)
        return 0
    
    # Insert head_handler right before GET_ITER instruction
    head_hook = hook.create_head_hook(state, pop_block_label)
    code[index - 2:index - 2] = head_hook
    
    if settings['profile']:
        profiler.note(settings, 'Recompilation succeeded')
    
    # Return length of analyzed code
    return len(head_hook)