# HG changeset patch # User Andrew John Hughes # Date 1459961386 -3600 # Node ID 83b5af0faf15c06c3a753012735a6b2074345d49 # Parent d4666165e4862d11a96baa5bcff4d96478a5aafc PR2910: Add rudimentary support for OpenJDK 8 class files to CACAO 2016-04-05 Andrew John Hughes 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. diff -r d4666165e486 -r 83b5af0faf15 ChangeLog --- 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 + + 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 PR2908: Add missing functions for CACAO diff -r d4666165e486 -r 83b5af0faf15 Makefile.am --- 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 += diff -r d4666165e486 -r 83b5af0faf15 NEWS --- 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): diff -r d4666165e486 -r 83b5af0faf15 patches/cacao/pr2910-8_support.patch --- /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; ++ } + } + } +