-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support signature polymorphic methods (MethodHandle
and VarHandle
)
#16225
Changes from all commits
f6a7900
14a80fd
2b7ceed
6c015ca
f282614
fb8bed8
8415b6b
0f24589
2a24379
1b0b830
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
// scalajs: --skip | ||
import scala.language.unsafeNulls | ||
|
||
import java.lang.invoke._, MethodType.methodType | ||
|
||
// A copy of tests/run/i11332.scala | ||
// to test the bootstrap minimisation which failed | ||
// (because bootstrap runs under explicit nulls) | ||
class Foo: | ||
def neg(x: Int): Int = -x | ||
|
||
object Test: | ||
def main(args: Array[String]): Unit = | ||
val l = MethodHandles.lookup() | ||
val self = new Foo() | ||
|
||
val res4 = { | ||
l // explicit chain method call - previously derivedSelect broke the type | ||
.findVirtual(classOf[Foo], "neg", methodType(classOf[Int], classOf[Int])) | ||
.invokeExact(self, 4): Int | ||
} | ||
assert(-4 == res4) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
// scalajs: --skip | ||
import scala.language.unsafeNulls | ||
|
||
import java.lang.invoke._, MethodType.methodType | ||
|
||
class Foo: | ||
def neg(x: Int): Int = -x | ||
def rev(s: String): String = s.reverse | ||
def over(l: Long): String = "long" | ||
def over(i: Int): String = "int" | ||
def unit(s: String): Unit = () | ||
def obj(s: String): Object = s | ||
|
||
object Test: | ||
def main(args: Array[String]): Unit = | ||
val l = MethodHandles.lookup() | ||
val self = new Foo() | ||
val mhNeg = l.findVirtual(classOf[Foo], "neg", methodType(classOf[Int], classOf[Int])) | ||
val mhRev = l.findVirtual(classOf[Foo], "rev", methodType(classOf[String], classOf[String])) | ||
val mhOverL = l.findVirtual(classOf[Foo], "over", methodType(classOf[String], classOf[Long])) | ||
val mhOverI = l.findVirtual(classOf[Foo], "over", methodType(classOf[String], classOf[Int])) | ||
val mhUnit = l.findVirtual(classOf[Foo], "unit", methodType(classOf[Unit], classOf[String])) | ||
val mhObj = l.findVirtual(classOf[Foo], "obj", methodType(classOf[Any], classOf[String])) | ||
val mhCL = l.findStatic(classOf[ClassLoader], "getPlatformClassLoader", methodType(classOf[ClassLoader])) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This broke the CI because some of our jobs are running on Java 8 which does not define this method: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
||
assert(-42 == (mhNeg.invokeExact(self, 42): Int)) | ||
assert(-33 == (mhNeg.invokeExact(self, 33): Int)) | ||
|
||
assert("oof" == (mhRev.invokeExact(self, "foo"): String)) | ||
assert("rab" == (mhRev.invokeExact(self, "bar"): String)) | ||
|
||
assert("long" == (mhOverL.invokeExact(self, 1L): String)) | ||
assert("int" == (mhOverI.invokeExact(self, 1): String)) | ||
|
||
assert(-3 == (id(mhNeg.invokeExact(self, 3)): Int)) | ||
expectWrongMethod(mhNeg.invokeExact(self, 4)) | ||
|
||
{ mhUnit.invokeExact(self, "hi"): Unit; () } // explicit block | ||
val hi2: Unit = mhUnit.invokeExact(self, "hi2") | ||
assert((()) == hi2) | ||
def hi3: Unit = mhUnit.invokeExact(self, "hi3") | ||
assert((()) == hi3) | ||
|
||
{ mhObj.invokeExact(self, "any"); () } // explicit block | ||
val any2 = mhObj.invokeExact(self, "any2") | ||
assert("any2" == any2) | ||
def any3 = mhObj.invokeExact(self, "any3") | ||
assert("any3" == any3) | ||
|
||
assert(null != (mhCL.invoke(): ClassLoader)) | ||
assert(null != (mhCL.invoke().asInstanceOf[ClassLoader]: ClassLoader)) | ||
assert(null != (mhCL.invokeExact(): ClassLoader)) | ||
assert(null != (mhCL.invokeExact().asInstanceOf[ClassLoader]: ClassLoader)) | ||
|
||
expectWrongMethod { | ||
l // explicit chain method call | ||
.findVirtual(classOf[Foo], "neg", methodType(classOf[Int], classOf[Int])) | ||
.invokeExact(self, 3) | ||
} | ||
val res4 = { | ||
l // explicit chain method call | ||
.findVirtual(classOf[Foo], "neg", methodType(classOf[Int], classOf[Int])) | ||
.invokeExact(self, 4): Int | ||
} | ||
assert(-4 == res4) | ||
|
||
def id[T](x: T): T = x | ||
|
||
def expectWrongMethod(op: => Any) = try { | ||
op | ||
throw new AssertionError("expected operation to fail but it didn't") | ||
} catch case expected: WrongMethodTypeException => () |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
// test: -jvm 11+ | ||
// scalajs: --skip | ||
import java.lang.invoke._ | ||
import scala.runtime.IntRef | ||
|
||
object Test { | ||
def main(args: Array[String]): Unit = { | ||
val ref = new scala.runtime.IntRef(0) | ||
val varHandle = MethodHandles.lookup() | ||
.in(classOf[IntRef]) | ||
.findVarHandle(classOf[IntRef], "elem", classOf[Int]) | ||
assert(0 == (varHandle.getAndSet(ref, 1): Int)) | ||
assert(1 == (varHandle.getAndSet(ref, 2): Int)) | ||
assert(2 == ref.elem) | ||
|
||
assert((()) == (varHandle.set(ref, 3): Any)) | ||
assert(3 == (varHandle.get(ref): Int)) | ||
|
||
assert(true == (varHandle.compareAndSet(ref, 3, 4): Any)) | ||
assert(4 == (varHandle.get(ref): Int)) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't
originalSignaturePolymorphic
be involved here, somehow?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Like how? The function Select will be pickled as a SELECTin with the name "invokeExact" and the "in" as MethodHandle, which during unpickling will pick the original method and that's why we have to fix it up.