Skip to content

Commit

Permalink
Adjust lambda assertions, refactor
Browse files Browse the repository at this point in the history
The assertions fail in some cases because MC uses PacketBuffer::writeVarInt as a BiConsumer<PacketBuffer, Integer>, but writeVarInt only takes one arg.  However, this still does not work, as it's not detected as a call to writeVarInt in this case.
  • Loading branch information
Pokechu22 committed Feb 17, 2022
1 parent 05c25e4 commit 3d25566
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 24 deletions.
55 changes: 32 additions & 23 deletions burger/toppings/packetinstructions.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
from jawa.transforms import simple_swap

from .topping import Topping
from burger.util import InvokeDynamicInfo
from burger.util import InvokeDynamicInfo, REF_invokeStatic

SUB_INS_EPSILON = .01
PACKETBUF_NAME = "packetbuffer" # Used to specially identify the PacketBuffer we care about
Expand Down Expand Up @@ -641,15 +641,12 @@ def _handle_2_arg_buffer_call(classloader, classes, instruction, verbose,
condition="it.hasNext()"))
info = args[1]
assert isinstance(info, InvokeDynamicInfo)
assert len(info.method_desc.args) >= 2 # May be more if locals are referenced
operations.append(Operation(instruction.pos, "store",
type=info.method_desc.args[-1].name.replace("/", "."),
var="itv", value="it.next()"))
operations += _PIT._sub_operations(
operations += _PIT._lambda_operations(
classloader, classes, instruction, verbose,
info.method_class, info.method_name,
info.method_desc,
info.stored_args + [PACKETBUF_NAME, "itv"]
info, [instance, "itv"]
)
# Jank: the part of the program that converts loop+endloop
# to a nested setup sorts the operations.
Expand Down Expand Up @@ -688,33 +685,22 @@ def _handle_3_arg_buffer_call(classloader, classes, instruction, verbose,
assert isinstance(key_info, InvokeDynamicInfo)
assert isinstance(val_info, InvokeDynamicInfo)
# TODO: these are violated
assert len(key_info.method_desc.args) >= 2 # May be more if locals are referenced
assert len(val_info.method_desc.args) >= 2 # May be more if locals are referenced
key_type = key_info.method_desc.args[-1].name.replace("/", ".")
val_type = val_info.method_desc.args[-1].name.replace("/", ".")
operations.append(Operation(instruction.pos, "store",
type="Map.Entry<" + key_type + ", " + val_type + ">",
var="itv", value="it.next()"))
operations += _PIT._sub_operations(
operations += _PIT._lambda_operations(
classloader, classes, instruction, verbose,
key_info.method_class, key_info.method_name,
key_info.method_desc,
key_info.stored_args + [PACKETBUF_NAME, "itv.getKey()"]
key_info, [instance, "itv.getKey()"]
)
# TODO: Does the SUB_INS_EPSILON work correctly here?
operations += _PIT._sub_operations(
# I think this will lead to [1.01, 1.02, 1.03, 1.01, 1.02, 1.03]
# which would get sorted wrongly, but I'm not sure
operations += _PIT._lambda_operations(
classloader, classes, instruction, verbose,
val_info.method_class, val_info.method_name,
val_info.method_desc,
val_info.stored_args + [PACKETBUF_NAME, "itv.getValue()"]
val_info, [instance, "itv.getValue()"]
)
# Jank: the part of the program that converts loop+endloop
# to a nested setup sorts the operations.
# Thus, if instruction.pos is used, _sub_operations
# adds epsilon to each sub-instruction, making them
# come after the endloop.
# Assume that 1 - SUB_INS_EPSILON (e.g. .99) will put
# the endloop past everything.
operations.append(Operation(instruction.pos + 1 - SUB_INS_EPSILON, "endloop"))
return operations
else:
Expand Down Expand Up @@ -786,6 +772,29 @@ def _sub_operations(classloader, classes, instruction, verbose, invoked_class,

return operations

@staticmethod
def _lambda_operations(classloader, classes, instruction, verbose, info, args):
assert isinstance(info, InvokeDynamicInfo)
assert len(args) == len(info.instantiated_desc.args)

effective_args = info.stored_args + args
if info.ref_kind == REF_invokeStatic:
assert len(effective_args) == len(info.method_desc.args)
else:
# The `this` parameter must be supplied. Usually this will be in
# effective_args, but it's also valid to use Class::function
# and then provide an instance of class along with the parameters
# to function.
assert len(effective_args) == len(info.method_desc.args) + 1
# I don't think Java allows pre-supplying other arguments in this
# case (as that'd require reordering them to make `this` first).
assert len(info.stored_args) == 0 or len(info.stored_args) == 1

return _PIT._sub_operations(
classloader, classes, instruction, verbose, info.method_class,
info.method_name, info.method_desc, effective_args
)

@staticmethod
def format(operations):
"""Constructs output structure"""
Expand Down
7 changes: 6 additions & 1 deletion burger/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class Example {
# arguments automatically filled in. The bootstrap arguments are:
# args[0] is samMethodType, signature of the implemented method
# args[1] is implMethod, the method handle that is used
# args[2] is instantiatedMethodType, runtime signature of the implemented method
# args[2] is instantiatedMethodType, narrower signature of the implemented method
# We only really care about the method handle, and just assume that the
# method handle satisfies instantiatedMethodType, and that that also
# satisfies samMethodType. instantiatedMethodType could maybe be used
Expand All @@ -65,6 +65,11 @@ class Example {
methodhandle = cf.constants.get(bootstrap.bootstrap_args[1])
self.ref_kind = methodhandle.reference_kind

# instantiatedMethodType does have a use when executing the created
# object, so store it for later.
instantiated = cf.constants.get(bootstrap.bootstrap_args[2])
self.instantiated_desc = method_descriptor(instantiated.descriptor.value)

assert self.ref_kind >= REF_getField and self.ref_kind <= REF_invokeInterface
# Javac does not appear to use REF_getField, REF_getStatic,
# REF_putField, or REF_putStatic, so don't bother handling fields here.
Expand Down

0 comments on commit 3d25566

Please sign in to comment.