public StackSaver getStackSaver()

in bytekit-core/src/main/java/com/alibaba/bytekit/asm/location/Location.java [244:399]


        public StackSaver getStackSaver() {
            StackSaver stackSaver = null;
            if(whenComplete) {
                stackSaver = new StackSaver() {

                    @Override
                    public void store(InsnList instructions, BindingContext bindingContext) {
                        AbstractInsnNode insnNode = bindingContext.getLocation().getInsnNode();
                        MethodProcessor methodProcessor = bindingContext.getMethodProcessor();
                        if (insnNode instanceof MethodInsnNode) {
                            MethodInsnNode methodInsnNode = (MethodInsnNode) insnNode;
                            String uniqueNameForMethod = AsmUtils.uniqueNameForMethod(methodInsnNode.owner, methodInsnNode.name,
                                    methodInsnNode.desc);
                            Type invokeReturnType = Type.getMethodType(methodInsnNode.desc).getReturnType();
                            
                            if(!invokeReturnType.equals(Type.VOID_TYPE)) {
                                LocalVariableNode invokeReturnVariableNode = methodProcessor.initInvokeReturnVariableNode(
                                        uniqueNameForMethod, invokeReturnType);
                                AsmOpUtils.storeVar(instructions, invokeReturnType, invokeReturnVariableNode.index);
                            }
                        } else {
                            throw new IllegalArgumentException(
                                    "InvokeReturnBinding location is not MethodInsnNode, insnNode: " + insnNode);
                        }
                        
                    }

                    @Override
                    public void load(InsnList instructions, BindingContext bindingContext) {
                        AbstractInsnNode insnNode = bindingContext.getLocation().getInsnNode();
                        MethodProcessor methodProcessor = bindingContext.getMethodProcessor();
                        if (insnNode instanceof MethodInsnNode) {
                            MethodInsnNode methodInsnNode = (MethodInsnNode) insnNode;
                            String uniqueNameForMethod = AsmUtils.uniqueNameForMethod(methodInsnNode.owner, methodInsnNode.name,
                                    methodInsnNode.desc);
                            Type invokeReturnType = Type.getMethodType(methodInsnNode.desc).getReturnType();
                            
                            if(!invokeReturnType.equals(Type.VOID_TYPE)) {
                                LocalVariableNode invokeReturnVariableNode = methodProcessor.initInvokeReturnVariableNode(
                                        uniqueNameForMethod, invokeReturnType);
                                AsmOpUtils.loadVar(instructions, invokeReturnType, invokeReturnVariableNode.index);
                            }
                        } else {
                            throw new IllegalArgumentException(
                                    "InvokeReturnBinding location is not MethodInsnNode, insnNode: " + insnNode);
                        }
                    }

                    @Override
                    public Type getType(BindingContext bindingContext) {
                        MethodInsnNode methodInsnNode = (MethodInsnNode) insnNode;
                        return Type.getMethodType(methodInsnNode.desc).getReturnType();
                    }
                    
                };
            }else {
                stackSaver = new StackSaver() {

                    @Override
                    public void store(InsnList instructions, BindingContext bindingContext) {
                        // 需要从要调用的 函数的 des ,找到参数的类型,再从栈上一个个吐出来,再保存到数组里
                        Location location = bindingContext.getLocation();
                        MethodProcessor methodProcessor = bindingContext.getMethodProcessor();
                        if(location instanceof InvokeLocation) {
                            InvokeLocation invokeLocation = (InvokeLocation) location;
                            // 如果是非 static的,会有this指针 
                            MethodInsnNode methodInsnNode = (MethodInsnNode)invokeLocation.getInsnNode();
                            Type methodType = Type.getMethodType(methodInsnNode.desc);
                            boolean isStatic = AsmUtils.isStatic(methodInsnNode);
                            Type[] argumentTypes = methodType.getArgumentTypes();
                            
//                            // 如果是非static,则存放到数组的index要多 1
//                            AsmOpUtils.push(instructions, argumentTypes.length + (isStatic ? 0 : 1));
//                            AsmOpUtils.newArray(instructions, AsmOpUtils.OBJECT_TYPE);
//                            LocalVariableNode invokeArgsVariableNode = methodProcessor.initInvokeArgsVariableNode();
//                            AsmOpUtils.storeVar(instructions, AsmOpUtils.OBJECT_ARRAY_TYPE, invokeArgsVariableNode.index);

                            // 从invoke的参数的后面,一个个存到数组里
//                            for(int i = argumentTypes.length - 1; i >= 0 ; --i) {
//                                AsmOpUtils.loadVar(instructions, AsmOpUtils.OBJECT_ARRAY_TYPE, invokeArgsVariableNode.index);
//
//                                AsmOpUtils.swap(instructions, argumentTypes[i], AsmOpUtils.OBJECT_ARRAY_TYPE);
//                                // 如果是非static,则存放到数组的index要多 1
//                                AsmOpUtils.push(instructions, i + (isStatic ? 0 : 1));
//                                AsmOpUtils.swap(instructions, argumentTypes[i], Type.INT_TYPE);
//                                
//                                AsmOpUtils.box(instructions, argumentTypes[i]);
//                                AsmOpUtils.arrayStore(instructions, AsmOpUtils.OBJECT_TYPE);
//                                
//                            }
                            // 处理this
//                            if(!isStatic) {
//                                AsmOpUtils.loadVar(instructions, AsmOpUtils.OBJECT_ARRAY_TYPE, invokeArgsVariableNode.index);
//
//                                AsmOpUtils.swap(instructions, AsmOpUtils.OBJECT_TYPE, AsmOpUtils.OBJECT_ARRAY_TYPE);
//                                AsmOpUtils.push(instructions, 0);
//                                AsmOpUtils.swap(instructions, AsmOpUtils.OBJECT_TYPE, Type.INT_TYPE);
//                                AsmOpUtils.arrayStore(instructions, AsmOpUtils.OBJECT_TYPE);
//                            }
                            
                        }else {
                            throw new IllegalArgumentException("location is not a InvokeLocation, location: " + location);
                        }
                        
                    }

                    @Override
                    public void load(InsnList instructions, BindingContext bindingContext) {
                        // 从数组里取出来,一个个再放到栈上,要检查是否要unbox
                        Location location = bindingContext.getLocation();
                        MethodProcessor methodProcessor = bindingContext.getMethodProcessor();
                        LocalVariableNode invokeArgsVariableNode = methodProcessor.initInvokeArgsVariableNode();
                        
                        if(location instanceof InvokeLocation) {
                            InvokeLocation invokeLocation = (InvokeLocation) location;
                            // 如果是非 static的,会有this指针 
                            MethodInsnNode methodInsnNode = (MethodInsnNode)invokeLocation.getInsnNode();
                            Type methodType = Type.getMethodType(methodInsnNode.desc);
                            boolean isStatic = AsmUtils.isStatic(methodInsnNode);
                            Type[] argumentTypes = methodType.getArgumentTypes();
                            
//                            if(!isStatic) {
//                                // 取出this
//                                AsmOpUtils.loadVar(instructions, AsmOpUtils.OBJECT_ARRAY_TYPE, invokeArgsVariableNode.index);
//                                AsmOpUtils.push(instructions, 0);
//                                AsmOpUtils.arrayLoad(instructions, AsmOpUtils.OBJECT_TYPE);
//                                AsmOpUtils.checkCast(instructions, Type.getObjectType(methodInsnNode.owner));
//                            }
//                            
//                            for(int i = 0; i < argumentTypes.length; ++i) {
//                                AsmOpUtils.loadVar(instructions, AsmOpUtils.OBJECT_ARRAY_TYPE, invokeArgsVariableNode.index);
//                                AsmOpUtils.push(instructions, i + (isStatic ? 0 : 1));
//                                AsmOpUtils.arrayLoad(instructions, AsmOpUtils.OBJECT_TYPE);
//                                // TODO 这里直接 unbox 就可以了??unbox里带有 check cast
//                                if(AsmOpUtils.needBox(argumentTypes[i])) {
//                                    AsmOpUtils.unbox(instructions, argumentTypes[i]);
//                                }else {
//                                    AsmOpUtils.checkCast(instructions, argumentTypes[i]);
//                                }
//                            }
                            
                        }else {
                            throw new IllegalArgumentException("location is not a InvokeLocation, location: " + location);
                        }
                    }

                    @Override
                    public Type getType(BindingContext bindingContext) {
                        throw new UnsupportedOperationException("InvokeLocation saver do not support getType()");
                    }
                    
                };
            }

            return stackSaver;
        }