649 final Type asmType = Type.getMethodType(methodDesc);
650 final Type[] asmArgTypes = asmType.getArgumentTypes();
651
652 final InstructionAdapter mv = new InstructionAdapter(cw.visitMethod(getAccessModifiers(method), name,
653 methodDesc, null, exceptionNames));
654 mv.visitCode();
655
656 final Class<?> returnType = type.returnType();
657 final Type asmReturnType = Type.getType(returnType);
658
659 // Determine the first index for a local variable
660 int nextLocalVar = 1; // "this" is at 0
661 for(final Type t: asmArgTypes) {
662 nextLocalVar += t.getSize();
663 }
664 // Set our local variable index
665 final int globalRestoringRunnableVar = nextLocalVar++;
666
667 // Load the creatingGlobal object
668 loadField(mv, GLOBAL_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR);
669
670 // stack: [creatingGlobal]
671 SET_GLOBAL.invoke(mv);
672 // stack: [runnable]
673 mv.visitVarInsn(ASTORE, globalRestoringRunnableVar);
674 // stack: []
675
676 final Label tryBlockStart = new Label();
677 mv.visitLabel(tryBlockStart);
678
679 final Label callCallee = new Label();
680 final Label defaultBehavior = new Label();
681 // If this is a SAM type...
682 if (samName != null) {
683 // ...every method will be checking whether we're initialized with a
684 // function.
685 loadField(mv, IS_FUNCTION_FIELD_NAME, BOOLEAN_TYPE_DESCRIPTOR);
686 // stack: [isFunction]
687 if (name.equals(samName)) {
688 final Label notFunction = new Label();
689 mv.ifeq(notFunction);
709 // it'll fall back to default behavior
710 mv.ifne(defaultBehavior);
711 // stack: []
712 }
713 }
714
715 // At this point, this is either not a SAM method or the delegate is
716 // not a ScriptFunction. We need to emit a GET_METHOD_PROPERTY Nashorn
717 // invokedynamic.
718
719 if(name.equals("toString")) {
720 // Since every JS Object has a toString, we only override
721 // "String toString()" it if it's explicitly specified on the object.
722 loadField(mv, DELEGATE_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR);
723 // stack: [delegate]
724 HAS_OWN_TO_STRING.invoke(mv);
725 // stack: [hasOwnToString]
726 mv.ifeq(defaultBehavior);
727 }
728
729 loadField(mv, DELEGATE_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR);
730 mv.dup();
731 // stack: [delegate, delegate]
732 final String encodedName = NameCodec.encode(name);
733 mv.visitInvokeDynamicInsn(encodedName,
734 GET_METHOD_PROPERTY_METHOD_DESCRIPTOR, BOOTSTRAP_HANDLE,
735 NashornCallSiteDescriptor.GET_METHOD_PROPERTY);
736 // stack: [callee, delegate]
737 mv.visitLdcInsn(name);
738 // stack: [name, callee, delegate]
739 CHECK_FUNCTION.invoke(mv);
740 // stack: [fnCalleeOrNull, delegate]
741 final Label hasFunction = new Label();
742 mv.dup();
743 // stack: [fnCalleeOrNull, fnCalleeOrNull, delegate]
744 mv.ifnonnull(hasFunction);
745 // stack: [null, delegate]
746 // If it's null or undefined, clear stack and fall back to default
747 // behavior.
748 mv.pop2();
|
649 final Type asmType = Type.getMethodType(methodDesc);
650 final Type[] asmArgTypes = asmType.getArgumentTypes();
651
652 final InstructionAdapter mv = new InstructionAdapter(cw.visitMethod(getAccessModifiers(method), name,
653 methodDesc, null, exceptionNames));
654 mv.visitCode();
655
656 final Class<?> returnType = type.returnType();
657 final Type asmReturnType = Type.getType(returnType);
658
659 // Determine the first index for a local variable
660 int nextLocalVar = 1; // "this" is at 0
661 for(final Type t: asmArgTypes) {
662 nextLocalVar += t.getSize();
663 }
664 // Set our local variable index
665 final int globalRestoringRunnableVar = nextLocalVar++;
666
667 // Load the creatingGlobal object
668 loadField(mv, GLOBAL_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR);
669 // stack: [creatingGlobal]
670 SET_GLOBAL.invoke(mv);
671 // stack: [runnable]
672 mv.visitVarInsn(ASTORE, globalRestoringRunnableVar);
673 // stack: []
674
675 final Label tryBlockStart = new Label();
676 mv.visitLabel(tryBlockStart);
677
678 final Label callCallee = new Label();
679 final Label defaultBehavior = new Label();
680 // If this is a SAM type...
681 if (samName != null) {
682 // ...every method will be checking whether we're initialized with a
683 // function.
684 loadField(mv, IS_FUNCTION_FIELD_NAME, BOOLEAN_TYPE_DESCRIPTOR);
685 // stack: [isFunction]
686 if (name.equals(samName)) {
687 final Label notFunction = new Label();
688 mv.ifeq(notFunction);
708 // it'll fall back to default behavior
709 mv.ifne(defaultBehavior);
710 // stack: []
711 }
712 }
713
714 // At this point, this is either not a SAM method or the delegate is
715 // not a ScriptFunction. We need to emit a GET_METHOD_PROPERTY Nashorn
716 // invokedynamic.
717
718 if(name.equals("toString")) {
719 // Since every JS Object has a toString, we only override
720 // "String toString()" it if it's explicitly specified on the object.
721 loadField(mv, DELEGATE_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR);
722 // stack: [delegate]
723 HAS_OWN_TO_STRING.invoke(mv);
724 // stack: [hasOwnToString]
725 mv.ifeq(defaultBehavior);
726 }
727
728 loadField(mv, DELEGATE_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR);
729 //For the cases like scripted overridden methods invoked from super constructors get adapter global/delegate fields as null, since we
730 //cannot set these fields before invoking super constructor better solution is opt out of scripted overridden method if global/delegate fields
731 //are null and invoke super method instead
732 mv.ifnull(defaultBehavior);
733 loadField(mv, DELEGATE_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR);
734 mv.dup();
735 // stack: [delegate, delegate]
736 final String encodedName = NameCodec.encode(name);
737 mv.visitInvokeDynamicInsn(encodedName,
738 GET_METHOD_PROPERTY_METHOD_DESCRIPTOR, BOOTSTRAP_HANDLE,
739 NashornCallSiteDescriptor.GET_METHOD_PROPERTY);
740 // stack: [callee, delegate]
741 mv.visitLdcInsn(name);
742 // stack: [name, callee, delegate]
743 CHECK_FUNCTION.invoke(mv);
744 // stack: [fnCalleeOrNull, delegate]
745 final Label hasFunction = new Label();
746 mv.dup();
747 // stack: [fnCalleeOrNull, fnCalleeOrNull, delegate]
748 mv.ifnonnull(hasFunction);
749 // stack: [null, delegate]
750 // If it's null or undefined, clear stack and fall back to default
751 // behavior.
752 mv.pop2();
|