<commit_before>package net.runelite.asm.execution;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import net.runelite.asm.Method;
import net.runelite.asm.attributes.code.instruction.types.ReturnInstruction;
import net.runelite.asm.attributes.code.instructions.InvokeStatic;
import net.runelite.asm.attributes.code.instructions.Return;
import net.runelite.deob.deobfuscators.rename.MappingExecutorUtil;
import net.runelite.deob.deobfuscators.rename.ParallelExecutorMapping;

public class ParallellMappingExecutor
{
	private Execution e, e2;
	private InstructionContext p1, p2;
	public ParallelExecutorMapping mappings;

	public ParallellMappingExecutor(Execution one, Execution two)
	{
		this.e = one;
		this.e2 = two;
	}
	
	boolean step1 = true, step2 = true;

	public boolean step()
	{		
		p1 = p2 = null;
		
		if (e.frames.isEmpty())
			return false;
		
		Frame f1 = e.frames.get(0),
			f2 = f1.other;
		
		if (f2 == null)
		{
			// why?
			e.frames.remove(0);
			return step();
		}
		
		//assert e2.frames.contains(f2);
		
//		assert f1.other.other == f1;
//		assert f2.other.other == f2;

		//assert f1.other == f2;
		assert f2.other == f1;

		//assert f1.isExecuting() == f2.isExecuting();

		// this will happen because conditional branches will create their frame
		// before realizing its already executed it before, so it will set the frame
		// as not executing
		if (!f1.isExecuting() || !f2.isExecuting())
		{	
//			assert f1.returnTo == null;
//			assert f2.returnTo == null;
			
			// XXX I dont know if this is right! only helps a few fields.
			// XXX if a frame exits from a jump loop it would step out which might be bad
			//popStack(f1);
			//popStack(f2);
			
			e.frames.remove(f1);
			e2.frames.remove(f2);
			
			step1 = step2 = true;
			
			return step();
		}
		
		Frame old1 = new Frame(f1), old2 = new Frame(f2);
		int s1 = e.frames.size(), s2 = e2.frames.size();

		// step frame
		if (step1)
			f1.execute();
		else
			step1 = true;
		
		if (step2)
			f2.execute();
		else
			step2 = true;
		
		Frame oldf1 = f1, oldf2 = f2;
		
		f1 = popStack(f1);
		f2 = popStack(f2);
		
		if (oldf1 != f1 && oldf2 != f2)
			if (oldf1.otherStatic == oldf2 && oldf2.otherStatic == oldf1)
			{
				mappings.map(oldf1.getMethod(), oldf2.getMethod());
			//	System.out.println("STEP OUT " + oldf1.getMethod() + " <-> " + oldf2.getMethod());
			}
		
//		if (e.frames.size() - s1 != e2.frames.size() - s2)
//		{
//			System.out.println("fr mismatch");
//		}
		
		if (oldf1 != f1 || oldf2 != f2)
		{
			if (f1 == oldf1)
				step1 = false;
			if (f2 == oldf2)
				step2 = false;
			return step();
		}
		
		if (oldf1 != f1 || oldf2 != f2)
		{
//			assert oldf1 != f1;
//			assert oldf2 != f2;
//			
//			Method m1 = oldf1.getMethod(), m2 = oldf2.getMethod();
//			
//			System.out.println("RETURN MAP " + m1 + " -> " + m2);
//			
//			// if one exits and the other doesnt, the functions arent equal
//			assert oldf1.otherStatic == oldf2;
//			assert oldf2.otherStatic == oldf1;
		}

		// get what each frame is paused/exited on
		p1 = f1.getInstructions().get(f1.getInstructions().size() - 1);
		p2 = f2.getInstructions().get(f2.getInstructions().size() - 1);

		// frames can stop executing at different times if one sees a jump
		// that has been done before, so stop both and remove the pending branch
		// of the jump
		if (!f1.isExecuting() || !f2.isExecuting())
		{
			return step();
		}
		
		if (MappingExecutorUtil.isInlineable(p1.getInstruction()) && !MappingExecutorUtil.isInlineable(p2.getInstruction()))
		{
			if (stepInto(f1) == null)
			{
				f1.stop();
				return step();
			}
			
			//try
			//{
				step2 = false;
				return step();
//			}
//			finally
//			{
//				step2 = true;
//			}
		}
		else if (MappingExecutorUtil.isInlineable(p2.getInstruction()) && !MappingExecutorUtil.isInlineable(p1.getInstruction()))
		{
			if (stepInto(f2) == null)
			{
				f2.stop();
				return step();
			}

			//try
			//{
				step1 = false;
				return step();
//			}
//			finally
//			{
//				step1 = true;
//			}
		}
		else if (MappingExecutorUtil.isInlineable(p1.getInstruction()) && MappingExecutorUtil.isInlineable(p2.getInstruction()))
		{
			Frame stepf1 = stepInto(f1);
			Frame stepf2 = stepInto(f2);
			
			if (stepf1 == null)
			{
				f1.stop();
			}
			if (stepf2 == null)
			{
				f2.stop();
			}
			if (stepf1 == null || stepf2 == null)
				return step();
			
			stepf1.otherStatic = stepf2;
			stepf2.otherStatic = stepf1;
			
			doubleStep.add(stepf1.getMethod());
			//System.out.println("STEP " + stepf1.getMethod() + " <-> " + stepf2.getMethod());
			
			return step();
		}

		assert e.paused;
		assert e2.paused;
		
		return true;
	}
	public static Set<Method> doubleStep = new HashSet();

	public InstructionContext getP1()
	{<commit_msg>Don't stop frames that can't step into static functions. It can happen if the same function steps into a static function multiple places which then steps into another static function at one place. Even though its been stepped into before it shouldn't stop execution of the top level function.<commit_after>package net.runelite.asm.execution;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import net.runelite.asm.Method;
import net.runelite.asm.attributes.code.instruction.types.ReturnInstruction;
import net.runelite.asm.attributes.code.instructions.InvokeStatic;
import net.runelite.asm.attributes.code.instructions.Return;
import net.runelite.deob.deobfuscators.rename.MappingExecutorUtil;
import net.runelite.deob.deobfuscators.rename.ParallelExecutorMapping;

public class ParallellMappingExecutor
{
	private Execution e, e2;
	private InstructionContext p1, p2;
	public ParallelExecutorMapping mappings;

	public ParallellMappingExecutor(Execution one, Execution two)
	{
		this.e = one;
		this.e2 = two;
	}
	
	boolean step1 = true, step2 = true;

	public boolean step()
	{		
		p1 = p2 = null;
		
		if (e.frames.isEmpty())
			return false;
		
		Frame f1 = e.frames.get(0),
			f2 = f1.other;
		
		if (f2 == null)
		{
			// why?
			e.frames.remove(0);
			return step();
		}
		
		//assert e2.frames.contains(f2);
		
//		assert f1.other.other == f1;
//		assert f2.other.other == f2;

		//assert f1.other == f2;
		assert f2.other == f1;

		//assert f1.isExecuting() == f2.isExecuting();

		// this will happen because conditional branches will create their frame
		// before realizing its already executed it before, so it will set the frame
		// as not executing
		if (!f1.isExecuting() || !f2.isExecuting())
		{	
//			assert f1.returnTo == null;
//			assert f2.returnTo == null;
			
			// XXX I dont know if this is right! only helps a few fields.
			// XXX if a frame exits from a jump loop it would step out which might be bad
			//popStack(f1);
			//popStack(f2);
			
			e.frames.remove(f1);
			e2.frames.remove(f2);
			
			step1 = step2 = true;
			
			return step();
		}
		
		Frame old1 = new Frame(f1), old2 = new Frame(f2);
		int s1 = e.frames.size(), s2 = e2.frames.size();

		// step frame
		if (step1)
			f1.execute();
		else
			step1 = true;
		
		if (step2)
			f2.execute();
		else
			step2 = true;
		
		Frame oldf1 = f1, oldf2 = f2;
		
		f1 = popStack(f1);
		f2 = popStack(f2);
		
		if (oldf1 != f1 && oldf2 != f2)
			if (oldf1.otherStatic == oldf2 && oldf2.otherStatic == oldf1)
			{
				mappings.map(oldf1.getMethod(), oldf2.getMethod());
			//	System.out.println("STEP OUT " + oldf1.getMethod() + " <-> " + oldf2.getMethod());
			}
		
//		if (e.frames.size() - s1 != e2.frames.size() - s2)
//		{
//			System.out.println("fr mismatch");
//		}
		
		if (oldf1 != f1 || oldf2 != f2)
		{
			if (f1 == oldf1)
				step1 = false;
			if (f2 == oldf2)
				step2 = false;
			return step();
		}
		
		if (oldf1 != f1 || oldf2 != f2)
		{
//			assert oldf1 != f1;
//			assert oldf2 != f2;
//			
//			Method m1 = oldf1.getMethod(), m2 = oldf2.getMethod();
//			
//			System.out.println("RETURN MAP " + m1 + " -> " + m2);
//			
//			// if one exits and the other doesnt, the functions arent equal
//			assert oldf1.otherStatic == oldf2;
//			assert oldf2.otherStatic == oldf1;
		}

		// get what each frame is paused/exited on
		p1 = f1.getInstructions().get(f1.getInstructions().size() - 1);
		p2 = f2.getInstructions().get(f2.getInstructions().size() - 1);

		// frames can stop executing at different times if one sees a jump
		// that has been done before, so stop both and remove the pending branch
		// of the jump
		if (!f1.isExecuting() || !f2.isExecuting())
		{
			return step();
		}
		
		if (MappingExecutorUtil.isInlineable(p1.getInstruction()) && !MappingExecutorUtil.isInlineable(p2.getInstruction()))
		{
			if (stepInto(f1) == null)
			{
				//f1.stop();
				return step();
			}
			
			//try
			//{
				step2 = false;
				return step();
//			}
//			finally
//			{
//				step2 = true;
//			}
		}
		else if (MappingExecutorUtil.isInlineable(p2.getInstruction()) && !MappingExecutorUtil.isInlineable(p1.getInstruction()))
		{
			if (stepInto(f2) == null)
			{
				//f2.stop();
				return step();
			}

			//try
			//{
				step1 = false;
				return step();
//			}
//			finally
//			{
//				step1 = true;
//			}
		}
		else if (MappingExecutorUtil.isInlineable(p1.getInstruction()) && MappingExecutorUtil.isInlineable(p2.getInstruction()))
		{
			Frame stepf1 = stepInto(f1);
			Frame stepf2 = stepInto(f2);
			
			if (stepf1 == null)
			{
				//f1.stop();
			}
			if (stepf2 == null)
			{
				//f2.stop();
			}
			if (stepf1 == null || stepf2 == null)
				return step();
			
			stepf1.otherStatic = stepf2;
			stepf2.otherStatic = stepf1;
			
			doubleStep.add(stepf1.getMethod());
			//System.out.println("STEP " + stepf1.getMethod() + " <-> " + stepf2.getMethod());
			
			return step();
		}

		assert e.paused;
		assert e2.paused;
		
		return true;
	}
	public static Set<Method> doubleStep = new HashSet();

	public InstructionContext getP1()
	{
{'fraction_non_alphanumeric': 0.15035489353194043, 'fraction_numerical': 0.028791362591222634, 'mean_word_length': 2.707931801334322, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7322325', 'n_tokens_mistral': 4315, 'n_tokens_neox': 3693, 'n_words': 864}