changeset 2661:83b5af0faf15

PR2910: Add rudimentary support for OpenJDK 8 class files to CACAO 2016-04-05 Andrew John Hughes <gnu_andrew@member.fsf.org> PR2910: Add rudimentary support for OpenJDK 8 class files to CACAO * Makefile.am: (ICEDTEA_PATCHES): Add new patch. * NEWS: Updated. * patches/cacao/pr2910-8_support.patch: Bump versions in CACAO and allow it to handle interface methods and constant pools in OpenJDK 8 bytecode files.
author Andrew John Hughes <gnu_andrew@member.fsf.org>
date Wed, 06 Apr 2016 17:49:46 +0100
parents d4666165e486
children 7fd913249ef5
files ChangeLog Makefile.am NEWS patches/cacao/pr2910-8_support.patch
diffstat 4 files changed, 200 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Fri Apr 01 08:28:03 2016 +0100
+++ b/ChangeLog	Wed Apr 06 17:49:46 2016 +0100
@@ -1,3 +1,15 @@
+2016-04-05  Andrew John Hughes  <gnu_andrew@member.fsf.org>
+
+	PR2910: Add rudimentary support for OpenJDK 8
+	class files to CACAO
+	* Makefile.am:
+	(ICEDTEA_PATCHES): Add new patch.
+	* NEWS: Updated.
+	* patches/cacao/pr2910-8_support.patch:
+	Bump versions in CACAO and allow it to handle
+	interface methods and constant pools in OpenJDK 8
+	bytecode files.
+
 2016-03-31  Andrew John Hughes  <gnu_andrew@member.fsf.org>
 
 	PR2908: Add missing functions for CACAO
--- a/Makefile.am	Fri Apr 01 08:28:03 2016 +0100
+++ b/Makefile.am	Wed Apr 06 17:49:46 2016 +0100
@@ -351,7 +351,8 @@
 	patches/cacao/pr2349.patch \
 	patches/cacao/pr2776-cache_api.patch \
 	patches/cacao/pr2832-refactoring_error.patch \
-	patches/cacao/pr2908-missing_functions.patch
+	patches/cacao/pr2908-missing_functions.patch \
+	patches/cacao/pr2910-8_support.patch
 else
 if USING_CACAO
 ICEDTEA_PATCHES +=
--- a/NEWS	Fri Apr 01 08:28:03 2016 +0100
+++ b/NEWS	Wed Apr 06 17:49:46 2016 +0100
@@ -212,6 +212,7 @@
   - PR2832, CA195: typeinfo.cpp: typeinfo_merge_nonarrays: Assertion `dest && result && x.any && y.any' failed
   - PR2908: Add missing functions for CACAO OpenJDK JVM implementation
   - PR2909: Install CACAO in same way as JamVM
+  - PR2910: Add rudimentary support for OpenJDK 8 class files to CACAO
 
 New in release 2.6.3 (2015-11-13):
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/cacao/pr2910-8_support.patch	Wed Apr 06 17:49:46 2016 +0100
@@ -0,0 +1,185 @@
+diff -r d38fca124cd9 src/vm/class.cpp
+--- cacao.old/cacao/src/vm/class.cpp	Mon Jul 13 13:34:45 2015 +0100
++++ cacao/cacao/src/vm/class.cpp	Wed Apr 06 01:47:19 2016 +0100
+@@ -673,17 +673,26 @@
+ 
+ void* class_getconstant(classinfo *c, u4 pos, ConstantPoolTag ctype)
+ {
++	return class_getconstant(c, pos, ctype, CONSTANT_UNUSED);
++}
++
++void* class_getconstant(classinfo *c, u4 pos, ConstantPoolTag ctype, ConstantPoolTag ctype2)
++{
+ 	// check index and type of constantpool entry
+ 	// (pos == 0 is caught by type comparison)
+-
+-	if ((((int32_t)pos) >= c->cpcount) || (c->cptags[pos] != ctype)) {
++	bool typematch = (c->cptags[pos] == ctype || (ctype2 != CONSTANT_UNUSED && c->cptags[pos] == ctype2));
++	if ((((int32_t)pos) >= c->cpcount) || !typematch) {
+ 		// this is the slow path,
+ 		// we can afford to repeat the separate checks for a better error message
+ 
+ 		if ((pos == 0) || (((int32_t)pos) >= c->cpcount)) {
+ 			exceptions_throw_classformaterror(c, "Illegal constant pool index: %u", pos);
+-		} else if (c->cptags[pos] != ctype) {
+-			exceptions_throw_classformaterror(c, "Illegal constant pool type %u (expected %u)", ctype, c->cptags[pos]);
++		} else if (!typematch) {
++			if (ctype2 == CONSTANT_UNUSED)
++				exceptions_throw_classformaterror(c, "Illegal constant pool type %u (expected %u)", c->cptags[pos], ctype);
++			else
++				exceptions_throw_classformaterror(c, "Illegal constant pool type %u (expected %u or %u)",
++												  c->cptags[pos], ctype, ctype2);
+ 		}
+ 
+ 		assert(exceptions_get_exception());
+diff -r d38fca124cd9 src/vm/class.hpp
+--- cacao.old/cacao/src/vm/class.hpp	Mon Jul 13 13:34:45 2015 +0100
++++ cacao/cacao/src/vm/class.hpp	Wed Apr 06 01:47:19 2016 +0100
+@@ -196,6 +196,7 @@
+ 
+ /* retrieve constantpool element */
+ void* class_getconstant(classinfo *c, u4 pos, ConstantPoolTag ctype);
++void* class_getconstant(classinfo *c, u4 pos, ConstantPoolTag ctype, ConstantPoolTag ctype2);
+ void* innerclass_getconstant(classinfo *c, u4 pos, ConstantPoolTag ctype);
+ 
+ /* frees all resources used by the class */
+diff -r d38fca124cd9 src/vm/global.hpp
+--- cacao.old/cacao/src/vm/global.hpp	Mon Jul 13 13:34:45 2015 +0100
++++ cacao/cacao/src/vm/global.hpp	Wed Apr 06 01:47:19 2016 +0100
+@@ -142,13 +142,13 @@
+ 
+ /* some Java related defines **************************************************/
+ 
+-#define JAVA_VERSION    "1.6.0"         /* this version is supported by CACAO */
+-#define CLASS_VERSION   "51.0"
++#define JAVA_VERSION    "1.8.0"         /* this version is supported by CACAO */
++#define CLASS_VERSION   "52.0"
+ 
+ /* Java class file constants **************************************************/
+ 
+ #define MAGIC             0xCAFEBABE
+-#define MAJOR_VERSION     51
++#define MAJOR_VERSION     52
+ #define MINOR_VERSION     0
+ 
+ 
+diff -r d38fca124cd9 src/vm/loader.cpp
+--- cacao.old/cacao/src/vm/loader.cpp	Mon Jul 13 13:34:45 2015 +0100
++++ cacao/cacao/src/vm/loader.cpp	Wed Apr 06 01:47:19 2016 +0100
+@@ -126,6 +126,7 @@
+ 
+ const ClassFileVersion ClassFileVersion::CACAO_VERSION(MAJOR_VERSION, MINOR_VERSION);
+ const ClassFileVersion ClassFileVersion::JDK_7(51, 0);
++const ClassFileVersion ClassFileVersion::JDK_8(52, 0);
+ 
+ 
+ /* loader_preinit **************************************************************
+@@ -1848,12 +1849,29 @@
+ 			break;
+ 
+ 		case REF_invokeVirtual:
++			fmi  = (constant_FMIref*) class_getconstant(c, it->reference_index, CONSTANT_Methodref);
++
++			if (!fmi)
++				return false;
++
++			if (fmi->name == utf8::init || fmi->name == utf8::clinit) {
++				exceptions_throw_classformaterror(c, "Illegal method handle");
++				return false;
++			}
++			break;
++			
+ 		case REF_invokeStatic:
+ 		case REF_invokeSpecial:
+-			fmi  = (constant_FMIref*) class_getconstant(c, it->reference_index, CONSTANT_Methodref);
+-
+-			if (!fmi)
++			if (c->version >= ClassFileVersion::JDK_8) {
++				fmi  = (constant_FMIref*) class_getconstant(c, it->reference_index,
++															CONSTANT_Methodref, CONSTANT_InterfaceMethodref);
++			} else {
++				fmi  = (constant_FMIref*) class_getconstant(c, it->reference_index, CONSTANT_Methodref);
++			}
++			
++			if (!fmi) {
+ 				return false;
++			}
+ 
+ 			if (fmi->name == utf8::init || fmi->name == utf8::clinit) {
+ 				exceptions_throw_classformaterror(c, "Illegal method handle");
+diff -r d38fca124cd9 src/vm/loader.hpp
+--- cacao.old/cacao/src/vm/loader.hpp	Mon Jul 13 13:34:45 2015 +0100
++++ cacao/cacao/src/vm/loader.hpp	Wed Apr 06 01:47:19 2016 +0100
+@@ -116,6 +116,10 @@
+ 		 */
+ 		static const ClassFileVersion JDK_7;
+ 
++		/**
++		 * The class file format version used by JDK 8
++		 */
++		static const ClassFileVersion JDK_8;
+ 
+ 		ClassFileVersion(uint16_t major, uint16_t minor = 0) : _majr(major), _minr(minor) {}
+ 
+@@ -141,6 +145,14 @@
+ 			return (*this == v) || (*this < v);
+ 		}
+ 
++		bool operator >(ClassFileVersion v) const {
++			return !(*this <= v);
++		}
++
++		bool operator >=(ClassFileVersion v) const {
++			return (*this == v) || (*this > v);
++		}
++	   
+ 		// we can't call these major/minor because GCC defines macros of that name
+ 		uint16_t majr() const { return _majr; }
+ 		uint16_t minr() const { return _minr; }
+diff -r d38fca124cd9 src/vm/method.cpp
+--- cacao.old/cacao/src/vm/method.cpp	Mon Jul 13 13:34:45 2015 +0100
++++ cacao/cacao/src/vm/method.cpp	Wed Apr 06 01:47:19 2016 +0100
+@@ -252,7 +252,7 @@
+ 
+ 			if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) {
+ 				exceptions_throw_classformaterror(c,
+-												  "Illegal method modifiers: 0x%X",
++												  "Illegal method access modifiers: 0x%X",
+ 												  m->flags);
+ 				return false;
+ 			}
+@@ -261,18 +261,28 @@
+ 				if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE |
+ 								 ACC_STATIC | ACC_STRICT | ACC_SYNCHRONIZED))) {
+ 					exceptions_throw_classformaterror(c,
+-													  "Illegal method modifiers: 0x%X",
++													  "Illegal abstract method modifiers: 0x%X",
+ 													  m->flags);
+ 					return false;
+ 				}
+ 			}
+ 
+ 			if (c->flags & ACC_INTERFACE) {
+-				if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC)) != (ACC_ABSTRACT | ACC_PUBLIC)) {
+-					exceptions_throw_classformaterror(c,
+-													  "Illegal method modifiers: 0x%X",
+-													  m->flags);
+-					return false;
++				if (c->version < ClassFileVersion::JDK_8) {
++					if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC)) != (ACC_ABSTRACT | ACC_PUBLIC)) {
++						exceptions_throw_classformaterror(c,
++														  "Illegal interface method modifiers: 0x%X",
++														  m->flags);
++						return false;
++					}
++				} else {
++					i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE));
++					if (i != ACC_PUBLIC && i != ACC_PRIVATE) {
++						exceptions_throw_classformaterror(c,
++														  "Illegal JDK 8 interface method modifiers: 0x%X",
++														  m->flags);
++						return false;
++					}
+ 				}
+ 			}
+