diff options
Diffstat (limited to 'project/JavaLangObject.scala')
-rw-r--r-- | project/JavaLangObject.scala | 243 |
1 files changed, 243 insertions, 0 deletions
diff --git a/project/JavaLangObject.scala b/project/JavaLangObject.scala new file mode 100644 index 0000000..ff82b94 --- /dev/null +++ b/project/JavaLangObject.scala @@ -0,0 +1,243 @@ +/* + * Hard-coded IR for java.lang.Object. + */ + +import scala.scalajs.ir +import ir._ +import ir.Definitions._ +import ir.Infos._ +import ir.Trees._ +import ir.Types._ +import ir.Position.NoPosition + +/** Hard-coded IR for java.lang.Object. + * We cannot so much as begin to fake a compilation of java.lang.Object, + * because Object is hijacked so much by scalac itself that it does not like + * at all to try to compile that class. So we have to bypass entirely the + * compiler to define java.lang.Object. + */ +object JavaLangObject { + + /** Optimizer hints with `@inline` + * Unfortunately we do not have access to private details of + * [[OptimizerHints]], so we cannot do this cleanly. But it is fine + * somehow because we're part of the same project implementation. + */ + private def inlineOptimizerHints = new OptimizerHints(2) + + val InfoAndTree = (Info, Definition) + + private def Info = ClassInfo( + name = "java.lang.Object", + encodedName = "O", + ancestorCount = 0, + kind = ClassKind.Class, + superClass = "", + ancestors = List("O"), + methods = List( + MethodInfo("__init__"), + MethodInfo("init___"), + MethodInfo("hashCode__I", + calledMethods = Map( + "jl_System$" -> List("identityHashCode__O__I") + ), + accessedModules = List("jl_System") + ), + MethodInfo("equals__O__Z", + optimizerHints = inlineOptimizerHints + ), + MethodInfo("clone__O", + calledMethods = Map( + "sjsr_package$" -> List("cloneObject__sjs_js_Object__sjs_js_Object"), + "jl_CloneNotSupportedException" -> List("init___") + ), + instantiatedClasses = List("jl_CloneNotSupportedException"), + accessedModules = List("sjsr_package"), + accessedClassData = List("jl_Cloneable"), + optimizerHints = inlineOptimizerHints + ), + MethodInfo("notify__V"), + MethodInfo("notifyAll__V"), + MethodInfo("toString__T", + calledMethods = Map( + "O" -> List("hashCode__I"), + "jl_Class" -> List("getName__T"), + "jl_Integer$" -> List("toHexString__I__T") + ), + accessedModules = List("jl_Integer") + ), + MethodInfo("finalize__V"), + MethodInfo("clone__", + calledMethods = Map( + "O" -> List("clone__O") + ) + ), + MethodInfo("notify__", + calledMethods = Map( + "O" -> List("notify__V") + ) + ), + MethodInfo("notifyAll__", + calledMethods = Map( + "O" -> List("notifyAll__V") + ) + ), + MethodInfo("finalize__", + calledMethods = Map( + "O" -> List("finalize__V") + ) + ) + ) + ) + + private def Definition = { + implicit val DummyPos = NoPosition + + // ClassType(Object) is normally invalid, but not in this class def + val ThisType = ClassType(ObjectClass) + + val classDef = ClassDef( + Ident("O", Some("java.lang.Object")), + ClassKind.Class, + None, + Nil, + List( + /* def this() = () */ + MethodDef( + Ident("init___", Some("<init>")), + Nil, + AnyType, + This()(ThisType))(None), + + /* def hashCode(): Int = System.identityHashCode(this) */ + MethodDef( + Ident("hashCode__I", Some("hashCode__I")), + Nil, + IntType, + { + Apply( + LoadModule(ClassType("jl_System$")), + Ident("identityHashCode__O__I", Some("identityHashCode")), + List(This()(ThisType)))(IntType) + })(None), + + /* def equals(that: Object): Boolean = this eq that */ + MethodDef( + Ident("equals__O__Z", Some("equals__O__Z")), + List(ParamDef(Ident("that", Some("that")), AnyType, mutable = false)), + BooleanType, + { + BinaryOp(BinaryOp.===, + This()(ThisType), + VarRef(Ident("that", Some("that")), mutable = false)(AnyType)) + })(None), + + /* protected def clone(): Object = + * if (this.isInstanceOf[Cloneable]) <clone>(this) + * else throw new CloneNotSupportedException() + */ + MethodDef( + Ident("clone__O", Some("clone__O")), + Nil, + AnyType, + { + If(IsInstanceOf(This()(ThisType), ClassType("jl_Cloneable")), { + Apply(LoadModule(ClassType("sjsr_package$")), + Ident("cloneObject__sjs_js_Object__sjs_js_Object", Some("cloneObject")), + List(This()(ThisType)))(AnyType) + }, { + Throw(New(ClassType("jl_CloneNotSupportedException"), + Ident("init___", Some("<init>")), Nil)) + })(AnyType) + })(None), + + /* def toString(): String = + * getClass().getName() + "@" + Integer.toHexString(hashCode()) + */ + MethodDef( + Ident("toString__T", Some("toString__T")), + Nil, + ClassType(StringClass), + { + BinaryOp(BinaryOp.String_+, BinaryOp(BinaryOp.String_+, + Apply( + GetClass(This()(ThisType)), + Ident("getName__T"), Nil)(ClassType(StringClass)), + // + + StringLiteral("@")), + // + + Apply( + LoadModule(ClassType("jl_Integer$")), + Ident("toHexString__I__T"), + List(Apply(This()(ThisType), Ident("hashCode__I"), Nil)(IntType)))( + ClassType(StringClass))) + })(None), + + /* Since wait() is not supported in any way, a correct implementation + * of notify() and notifyAll() is to do nothing. + */ + + /* def notify(): Unit = () */ + MethodDef( + Ident("notify__V", Some("notify__V")), + Nil, + NoType, + Skip())(None), + + /* def notifyAll(): Unit = () */ + MethodDef( + Ident("notifyAll__V", Some("notifyAll__V")), + Nil, + NoType, + Skip())(None), + + /* def finalize(): Unit = () */ + MethodDef( + Ident("finalize__V", Some("finalize__V")), + Nil, + NoType, + Skip())(None), + + /* Reflective proxies + * Note that we do not need to proxy the following methods, since + * they are defined on Any in the Scala hierarchy and therefore a + * reflective call is never emitted: + * - equals + * - getClass + * - hashCode + * - toString + */ + + MethodDef(Ident("clone__"), Nil, AnyType, + Apply(This()(ThisType), Ident("clone__O"), Nil)(AnyType))(None), + + MethodDef(Ident("notify__"), Nil, AnyType, Block( + Apply(This()(ThisType), Ident("notify__V"), Nil)(NoType), + Undefined()))(None), + + MethodDef(Ident("notifyAll__"), Nil, AnyType, Block( + Apply(This()(ThisType), Ident("notifyAll__V"), Nil)(NoType), + Undefined()))(None), + + MethodDef(Ident("finalize__"), Nil, AnyType, Block( + Apply(This()(ThisType), Ident("finalize__V"), Nil)(NoType), + Undefined()))(None), + + // Exports + + /* JSExport for toString(). */ + MethodDef( + StringLiteral("toString"), + Nil, + AnyType, + { + Apply(This()(ThisType), + Ident("toString__T", Some("toString__T")), + Nil)(ClassType(StringClass)) + })(None) + )) + + Hashers.hashClassDef(classDef) + } + +} |