69 |
69 |
70 private static final MethodHandle IS_FUNCTION_MH = findOwnMH("isFunctionMH", boolean.class, Object.class, ScriptFunctionData.class); |
70 private static final MethodHandle IS_FUNCTION_MH = findOwnMH("isFunctionMH", boolean.class, Object.class, ScriptFunctionData.class); |
71 |
71 |
72 private static final MethodHandle IS_NONSTRICT_FUNCTION = findOwnMH("isNonStrictFunction", boolean.class, Object.class, Object.class, ScriptFunctionData.class); |
72 private static final MethodHandle IS_NONSTRICT_FUNCTION = findOwnMH("isNonStrictFunction", boolean.class, Object.class, Object.class, ScriptFunctionData.class); |
73 |
73 |
|
74 private static final MethodHandle ADD_ZEROTH_ELEMENT = findOwnMH("addZerothElement", Object[].class, Object[].class, Object.class); |
|
75 |
74 /** The parent scope. */ |
76 /** The parent scope. */ |
75 private final ScriptObject scope; |
77 private final ScriptObject scope; |
76 |
78 |
77 private final ScriptFunctionData data; |
79 private final ScriptFunctionData data; |
78 |
80 |
544 MethodHandle getCallMethodHandle(final MethodType type, final String bindName) { |
546 MethodHandle getCallMethodHandle(final MethodType type, final String bindName) { |
545 return pairArguments(bindToNameIfNeeded(bindToCalleeIfNeeded(getBestInvoker(type, null)), bindName), type); |
547 return pairArguments(bindToNameIfNeeded(bindToCalleeIfNeeded(getBestInvoker(type, null)), bindName), type); |
546 } |
548 } |
547 |
549 |
548 private static MethodHandle bindToNameIfNeeded(final MethodHandle methodHandle, final String bindName) { |
550 private static MethodHandle bindToNameIfNeeded(final MethodHandle methodHandle, final String bindName) { |
549 return bindName == null ? methodHandle : MH.insertArguments(methodHandle, 1, bindName); |
551 if (bindName == null) { |
|
552 return methodHandle; |
|
553 } else { |
|
554 // if it is vararg method, we need to extend argument array with |
|
555 // a new zeroth element that is set to bindName value. |
|
556 final MethodType methodType = methodHandle.type(); |
|
557 final int parameterCount = methodType.parameterCount(); |
|
558 final boolean isVarArg = parameterCount > 0 && methodType.parameterType(parameterCount - 1).isArray(); |
|
559 |
|
560 if (isVarArg) { |
|
561 return MH.filterArguments(methodHandle, 1, MH.insertArguments(ADD_ZEROTH_ELEMENT, 1, bindName)); |
|
562 } else { |
|
563 return MH.insertArguments(methodHandle, 1, bindName); |
|
564 } |
|
565 } |
550 } |
566 } |
551 |
567 |
552 /** |
568 /** |
553 * Get the guard that checks if a {@link ScriptFunction} is equal to |
569 * Get the guard that checks if a {@link ScriptFunction} is equal to |
554 * a known ScriptFunction, using reference comparison |
570 * a known ScriptFunction, using reference comparison |
582 } |
598 } |
583 |
599 |
584 @SuppressWarnings("unused") |
600 @SuppressWarnings("unused") |
585 private static boolean isNonStrictFunction(final Object self, final Object arg, final ScriptFunctionData data) { |
601 private static boolean isNonStrictFunction(final Object self, final Object arg, final ScriptFunctionData data) { |
586 return self instanceof ScriptFunction && ((ScriptFunction)self).data == data && arg instanceof ScriptObject; |
602 return self instanceof ScriptFunction && ((ScriptFunction)self).data == data && arg instanceof ScriptObject; |
|
603 } |
|
604 |
|
605 @SuppressWarnings("unused") |
|
606 private static Object[] addZerothElement(final Object[] args, final Object value) { |
|
607 // extends input array with by adding new zeroth element |
|
608 final Object[] src = (args == null)? ScriptRuntime.EMPTY_ARRAY : args; |
|
609 final Object[] result = new Object[src.length + 1]; |
|
610 System.arraycopy(src, 0, result, 1, src.length); |
|
611 result[0] = value; |
|
612 return result; |
587 } |
613 } |
588 |
614 |
589 private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) { |
615 private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) { |
590 final Class<?> own = ScriptFunction.class; |
616 final Class<?> own = ScriptFunction.class; |
591 final MethodType mt = MH.type(rtype, types); |
617 final MethodType mt = MH.type(rtype, types); |