changeset 12743:7650e0dcbf51

Merge
author lana
date Fri, 21 Apr 2017 03:34:29 +0000
parents 443a768ec827 (current diff) b7690ac63aa5 (diff)
children 1ca7ed1b17b5
files
diffstat 29 files changed, 503 insertions(+), 131 deletions(-) [+]
line wrap: on
line diff
--- a/src/cpu/aarch64/vm/c1_LIRGenerator_aarch64.cpp	Thu Apr 20 18:14:04 2017 +0000
+++ b/src/cpu/aarch64/vm/c1_LIRGenerator_aarch64.cpp	Fri Apr 21 03:34:29 2017 +0000
@@ -1221,12 +1221,19 @@
   obj.load_item();
 
   // info for exceptions
-  CodeEmitInfo* info_for_exception = state_for(x);
+  CodeEmitInfo* info_for_exception =
+      (x->needs_exception_state() ? state_for(x) :
+                                    state_for(x, x->state_before(), true /*ignore_xhandler*/));
 
   CodeStub* stub;
   if (x->is_incompatible_class_change_check()) {
     assert(patching_info == NULL, "can't patch this");
     stub = new SimpleExceptionStub(Runtime1::throw_incompatible_class_change_error_id, LIR_OprFact::illegalOpr, info_for_exception);
+  } else if (x->is_invokespecial_receiver_check()) {
+    assert(patching_info == NULL, "can't patch this");
+    stub = new DeoptimizeStub(info_for_exception,
+                              Deoptimization::Reason_class_check,
+                              Deoptimization::Action_none);
   } else {
     stub = new SimpleExceptionStub(Runtime1::throw_class_cast_exception_id, obj.result(), info_for_exception);
   }
--- a/src/cpu/arm/vm/c1_LIRAssembler_arm.cpp	Thu Apr 20 18:14:04 2017 +0000
+++ b/src/cpu/arm/vm/c1_LIRAssembler_arm.cpp	Fri Apr 21 03:34:29 2017 +0000
@@ -1453,10 +1453,11 @@
       ciKlass* k = op->klass();
       assert_different_registers(res, k_RInfo, klass_RInfo, Rtemp);
 
+      if (stub->is_simple_exception_stub()) {
       // TODO: ARM - Late binding is used to prevent confusion of register allocator
       assert(stub->is_exception_throw_stub(), "must be");
       ((SimpleExceptionStub*)stub)->set_obj(op->result_opr());
-
+      }
       ciMethodData* md;
       ciProfileData* data;
       int mdo_offset_bias = 0;
--- a/src/cpu/arm/vm/c1_LIRGenerator_arm.cpp	Thu Apr 20 18:14:04 2017 +0000
+++ b/src/cpu/arm/vm/c1_LIRGenerator_arm.cpp	Fri Apr 21 03:34:29 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1412,12 +1412,20 @@
 
   obj.load_item();
 
-  CodeEmitInfo* info_for_exception = state_for(x);
+  CodeEmitInfo* info_for_exception =
+    (x->needs_exception_state() ? state_for(x) :
+                                  state_for(x, x->state_before(), true /*ignore_xhandler*/));
+
   CodeStub* stub;
   if (x->is_incompatible_class_change_check()) {
     assert(patching_info == NULL, "can't patch this");
     stub = new SimpleExceptionStub(Runtime1::throw_incompatible_class_change_error_id,
                                    LIR_OprFact::illegalOpr, info_for_exception);
+  } else if (x->is_invokespecial_receiver_check()) {
+    assert(patching_info == NULL, "can't patch this");
+    stub = new DeoptimizeStub(info_for_exception,
+                              Deoptimization::Reason_class_check,
+                              Deoptimization::Action_none);
   } else {
     stub = new SimpleExceptionStub(Runtime1::throw_class_cast_exception_id,
                                    LIR_OprFact::illegalOpr, info_for_exception);
--- a/src/cpu/ppc/vm/c1_LIRGenerator_ppc.cpp	Thu Apr 20 18:14:04 2017 +0000
+++ b/src/cpu/ppc/vm/c1_LIRGenerator_ppc.cpp	Fri Apr 21 03:34:29 2017 +0000
@@ -1131,12 +1131,19 @@
   obj.load_item();
   LIR_Opr out_reg = rlock_result(x);
   CodeStub* stub;
-  CodeEmitInfo* info_for_exception = state_for(x);
+  CodeEmitInfo* info_for_exception =
+      (x->needs_exception_state() ? state_for(x) :
+                                    state_for(x, x->state_before(), true /*ignore_xhandler*/));
 
   if (x->is_incompatible_class_change_check()) {
     assert(patching_info == NULL, "can't patch this");
     stub = new SimpleExceptionStub(Runtime1::throw_incompatible_class_change_error_id,
                                    LIR_OprFact::illegalOpr, info_for_exception);
+  } else if (x->is_invokespecial_receiver_check()) {
+    assert(patching_info == NULL, "can't patch this");
+    stub = new DeoptimizeStub(info_for_exception,
+                              Deoptimization::Reason_class_check,
+                              Deoptimization::Action_none);
   } else {
     stub = new SimpleExceptionStub(Runtime1::throw_class_cast_exception_id, obj.result(), info_for_exception);
   }
--- a/src/cpu/s390/vm/c1_LIRGenerator_s390.cpp	Thu Apr 20 18:14:04 2017 +0000
+++ b/src/cpu/s390/vm/c1_LIRGenerator_s390.cpp	Fri Apr 21 03:34:29 2017 +0000
@@ -993,12 +993,19 @@
   obj.load_item();
 
   // info for exceptions
-  CodeEmitInfo* info_for_exception = state_for (x);
+  CodeEmitInfo* info_for_exception =
+      (x->needs_exception_state() ? state_for(x) :
+                                    state_for(x, x->state_before(), true /*ignore_xhandler*/));
 
   CodeStub* stub;
   if (x->is_incompatible_class_change_check()) {
     assert(patching_info == NULL, "can't patch this");
     stub = new SimpleExceptionStub(Runtime1::throw_incompatible_class_change_error_id, LIR_OprFact::illegalOpr, info_for_exception);
+  } else if (x->is_invokespecial_receiver_check()) {
+    assert(patching_info == NULL, "can't patch this");
+    stub = new DeoptimizeStub(info_for_exception,
+                              Deoptimization::Reason_class_check,
+                              Deoptimization::Action_none);
   } else {
     stub = new SimpleExceptionStub(Runtime1::throw_class_cast_exception_id, obj.result(), info_for_exception);
   }
--- a/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp	Thu Apr 20 18:14:04 2017 +0000
+++ b/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp	Fri Apr 21 03:34:29 2017 +0000
@@ -1196,11 +1196,18 @@
   obj.load_item();
   LIR_Opr out_reg = rlock_result(x);
   CodeStub* stub;
-  CodeEmitInfo* info_for_exception = state_for(x);
+  CodeEmitInfo* info_for_exception =
+      (x->needs_exception_state() ? state_for(x) :
+                                    state_for(x, x->state_before(), true /*ignore_xhandler*/));
 
   if (x->is_incompatible_class_change_check()) {
     assert(patching_info == NULL, "can't patch this");
     stub = new SimpleExceptionStub(Runtime1::throw_incompatible_class_change_error_id, LIR_OprFact::illegalOpr, info_for_exception);
+  } else if (x->is_invokespecial_receiver_check()) {
+    assert(patching_info == NULL, "can't patch this");
+    stub = new DeoptimizeStub(info_for_exception,
+                              Deoptimization::Reason_class_check,
+                              Deoptimization::Action_none);
   } else {
     stub = new SimpleExceptionStub(Runtime1::throw_class_cast_exception_id, obj.result(), info_for_exception);
   }
--- a/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp	Thu Apr 20 18:14:04 2017 +0000
+++ b/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp	Fri Apr 21 03:34:29 2017 +0000
@@ -1429,12 +1429,17 @@
   obj.load_item();
 
   // info for exceptions
-  CodeEmitInfo* info_for_exception = state_for(x);
+  CodeEmitInfo* info_for_exception =
+      (x->needs_exception_state() ? state_for(x) :
+                                    state_for(x, x->state_before(), true /*ignore_xhandler*/));
 
   CodeStub* stub;
   if (x->is_incompatible_class_change_check()) {
     assert(patching_info == NULL, "can't patch this");
     stub = new SimpleExceptionStub(Runtime1::throw_incompatible_class_change_error_id, LIR_OprFact::illegalOpr, info_for_exception);
+  } else if (x->is_invokespecial_receiver_check()) {
+    assert(patching_info == NULL, "can't patch this");
+    stub = new DeoptimizeStub(info_for_exception, Deoptimization::Reason_class_check, Deoptimization::Action_none);
   } else {
     stub = new SimpleExceptionStub(Runtime1::throw_class_cast_exception_id, obj.result(), info_for_exception);
   }
--- a/src/cpu/x86/vm/vm_version_x86.cpp	Thu Apr 20 18:14:04 2017 +0000
+++ b/src/cpu/x86/vm/vm_version_x86.cpp	Fri Apr 21 03:34:29 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -763,12 +763,11 @@
     FLAG_SET_DEFAULT(UseCRC32Intrinsics, false);
   }
 
-  if (supports_sse4_2()) {
+  if (supports_sse4_2() && supports_clmul()) {
     if (FLAG_IS_DEFAULT(UseCRC32CIntrinsics)) {
       UseCRC32CIntrinsics = true;
     }
-  }
-  else if (UseCRC32CIntrinsics) {
+  } else if (UseCRC32CIntrinsics) {
     if (!FLAG_IS_DEFAULT(UseCRC32CIntrinsics)) {
       warning("CRC32C intrinsics are not available on this CPU");
     }
--- a/src/share/vm/c1/c1_CodeStubs.hpp	Thu Apr 20 18:14:04 2017 +0000
+++ b/src/share/vm/c1/c1_CodeStubs.hpp	Fri Apr 21 03:34:29 2017 +0000
@@ -58,6 +58,7 @@
   virtual bool is_exception_throw_stub() const   { return false; }
   virtual bool is_range_check_stub() const       { return false; }
   virtual bool is_divbyzero_stub() const         { return false; }
+  virtual bool is_simple_exception_stub() const  { return false; }
 #ifndef PRODUCT
   virtual void print_name(outputStream* out) const = 0;
 #endif
@@ -483,6 +484,7 @@
   virtual void emit_code(LIR_Assembler* e);
   virtual CodeEmitInfo* info() const             { return _info; }
   virtual bool is_exception_throw_stub() const   { return true; }
+  virtual bool is_simple_exception_stub() const  { return true; }
   virtual void visit(LIR_OpVisitState* visitor) {
     if (_obj->is_valid()) visitor->do_input(_obj);
     visitor->do_slow_case(_info);
--- a/src/share/vm/c1/c1_GraphBuilder.cpp	Thu Apr 20 18:14:04 2017 +0000
+++ b/src/share/vm/c1/c1_GraphBuilder.cpp	Fri Apr 21 03:34:29 2017 +0000
@@ -1829,6 +1829,20 @@
                 log->identify(target),
                 Bytecodes::name(code));
 
+  // invoke-special-super
+  if (bc_raw == Bytecodes::_invokespecial && !target->is_object_initializer()) {
+    ciInstanceKlass* sender_klass =
+          calling_klass->is_anonymous() ? calling_klass->host_klass() :
+                                          calling_klass;
+    if (sender_klass->is_interface()) {
+      int index = state()->stack_size() - (target->arg_size_no_receiver() + 1);
+      Value receiver = state()->stack_at(index);
+      CheckCast* c = new CheckCast(sender_klass, receiver, copy_state_before());
+      c->set_invokespecial_receiver_check();
+      state()->stack_at_put(index, append_split(c));
+    }
+  }
+
   // Some methods are obviously bindable without any type checks so
   // convert them directly to an invokespecial or invokestatic.
   if (target->is_loaded() && !target->is_abstract() && target->can_be_statically_bound()) {
--- a/src/share/vm/c1/c1_Instruction.hpp	Thu Apr 20 18:14:04 2017 +0000
+++ b/src/share/vm/c1/c1_Instruction.hpp	Fri Apr 21 03:34:29 2017 +0000
@@ -372,6 +372,7 @@
     UnorderedIsTrueFlag,
     NeedsPatchingFlag,
     ThrowIncompatibleClassChangeErrorFlag,
+    InvokeSpecialReceiverCheckFlag,
     ProfileMDOFlag,
     IsLinkedInBlockFlag,
     NeedsRangeCheckFlag,
@@ -1454,6 +1455,16 @@
   bool is_incompatible_class_change_check() const {
     return check_flag(ThrowIncompatibleClassChangeErrorFlag);
   }
+  void set_invokespecial_receiver_check() {
+    set_flag(InvokeSpecialReceiverCheckFlag, true);
+  }
+  bool is_invokespecial_receiver_check() const {
+    return check_flag(InvokeSpecialReceiverCheckFlag);
+  }
+
+  virtual bool needs_exception_state() const {
+    return !is_invokespecial_receiver_check();
+  }
 
   ciType* declared_type() const;
 };
--- a/src/share/vm/ci/ciInstanceKlass.cpp	Thu Apr 20 18:14:04 2017 +0000
+++ b/src/share/vm/ci/ciInstanceKlass.cpp	Fri Apr 21 03:34:29 2017 +0000
@@ -595,6 +595,16 @@
   return impl;
 }
 
+ciInstanceKlass* ciInstanceKlass::host_klass() {
+  assert(is_loaded(), "must be loaded");
+  if (is_anonymous()) {
+    VM_ENTRY_MARK
+    Klass* host_klass = get_instanceKlass()->host_klass();
+    return CURRENT_ENV->get_instance_klass(host_klass);
+  }
+  return NULL;
+}
+
 // Utility class for printing of the contents of the static fields for
 // use by compilation replay.  It only prints out the information that
 // could be consumed by the compiler, so for primitive types it prints
--- a/src/share/vm/ci/ciInstanceKlass.hpp	Thu Apr 20 18:14:04 2017 +0000
+++ b/src/share/vm/ci/ciInstanceKlass.hpp	Fri Apr 21 03:34:29 2017 +0000
@@ -260,6 +260,8 @@
     return NULL;
   }
 
+  ciInstanceKlass* host_klass();
+
   bool can_be_instantiated() {
     assert(is_loaded(), "must be loaded");
     return !is_interface() && !is_abstract();
--- a/src/share/vm/ci/ciMethod.cpp	Thu Apr 20 18:14:04 2017 +0000
+++ b/src/share/vm/ci/ciMethod.cpp	Fri Apr 21 03:34:29 2017 +0000
@@ -952,6 +952,13 @@
 }
 
 // ------------------------------------------------------------------
+// ciMethod::is_object_initializer
+//
+bool ciMethod::is_object_initializer() const {
+   return name() == ciSymbol::object_initializer_name();
+}
+
+// ------------------------------------------------------------------
 // ciMethod::has_member_arg
 //
 // Return true if the method is a linker intrinsic like _linkToVirtual.
--- a/src/share/vm/ci/ciMethod.hpp	Thu Apr 20 18:14:04 2017 +0000
+++ b/src/share/vm/ci/ciMethod.hpp	Fri Apr 21 03:34:29 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -337,6 +337,7 @@
   bool has_reserved_stack_access() const         { return _has_reserved_stack_access; }
   bool is_boxing_method() const;
   bool is_unboxing_method() const;
+  bool is_object_initializer() const;
 
   // Replay data methods
   void dump_name_as_ascii(outputStream* st);
--- a/src/share/vm/interpreter/interpreterRuntime.cpp	Thu Apr 20 18:14:04 2017 +0000
+++ b/src/share/vm/interpreter/interpreterRuntime.cpp	Fri Apr 21 03:34:29 2017 +0000
@@ -720,7 +720,8 @@
   Thread* THREAD = thread;
   // extract receiver from the outgoing argument list if necessary
   Handle receiver(thread, NULL);
-  if (bytecode == Bytecodes::_invokevirtual || bytecode == Bytecodes::_invokeinterface) {
+  if (bytecode == Bytecodes::_invokevirtual || bytecode == Bytecodes::_invokeinterface ||
+      bytecode == Bytecodes::_invokespecial) {
     ResourceMark rm(thread);
     methodHandle m (thread, method(thread));
     Bytecode_invoke call(m, bci(thread));
@@ -783,16 +784,25 @@
       int index = info.resolved_method()->itable_index();
       assert(info.itable_index() == index, "");
     }
+  } else if (bytecode == Bytecodes::_invokespecial) {
+    assert(info.call_kind() == CallInfo::direct_call, "must be direct call");
   } else {
     assert(info.call_kind() == CallInfo::direct_call ||
            info.call_kind() == CallInfo::vtable_call, "");
   }
 #endif
+  // Get sender or sender's host_klass, and only set cpCache entry to resolved if
+  // it is not an interface.  The receiver for invokespecial calls within interface
+  // methods must be checked for every call.
+  InstanceKlass* sender = pool->pool_holder();
+  sender = sender->is_anonymous() ? sender->host_klass() : sender;
+
   switch (info.call_kind()) {
   case CallInfo::direct_call:
     cp_cache_entry->set_direct_call(
       bytecode,
-      info.resolved_method());
+      info.resolved_method(),
+      sender->is_interface());
     break;
   case CallInfo::vtable_call:
     cp_cache_entry->set_vtable_call(
--- a/src/share/vm/interpreter/linkResolver.cpp	Thu Apr 20 18:14:04 2017 +0000
+++ b/src/share/vm/interpreter/linkResolver.cpp	Fri Apr 21 03:34:29 2017 +0000
@@ -1057,12 +1057,14 @@
 
 
 void LinkResolver::resolve_special_call(CallInfo& result,
+                                        Handle recv,
                                         const LinkInfo& link_info,
                                         TRAPS) {
   methodHandle resolved_method = linktime_resolve_special_method(link_info, CHECK);
   runtime_resolve_special_method(result, resolved_method,
                                  link_info.resolved_klass(),
                                  link_info.current_klass(),
+                                 recv,
                                  link_info.check_access(), CHECK);
 }
 
@@ -1149,6 +1151,7 @@
                                                   const methodHandle& resolved_method,
                                                   KlassHandle resolved_klass,
                                                   KlassHandle current_klass,
+                                                  Handle recv,
                                                   bool check_access, TRAPS) {
 
   // resolved method is selected method unless we have an old-style lookup
@@ -1157,21 +1160,19 @@
   // no checks for shadowing
   methodHandle sel_method(THREAD, resolved_method());
 
-  // check if this is an old-style super call and do a new lookup if so
-  { KlassHandle method_klass  = KlassHandle(THREAD,
-                                            resolved_method->method_holder());
+  if (check_access &&
+      // check if the method is not <init>
+      resolved_method->name() != vmSymbols::object_initializer_name()) {
 
-    if (check_access &&
+  // check if this is an old-style super call and do a new lookup if so
         // a) check if ACC_SUPER flag is set for the current class
-        (current_klass->is_super() || !AllowNonVirtualCalls) &&
+    if ((current_klass->is_super() || !AllowNonVirtualCalls) &&
         // b) check if the class of the resolved_klass is a superclass
         // (not supertype in order to exclude interface classes) of the current class.
         // This check is not performed for super.invoke for interface methods
         // in super interfaces.
         current_klass->is_subclass_of(resolved_klass()) &&
-        current_klass() != resolved_klass() &&
-        // c) check if the method is not <init>
-        resolved_method->name() != vmSymbols::object_initializer_name()) {
+        current_klass() != resolved_klass()) {
       // Lookup super method
       KlassHandle super_klass(THREAD, current_klass->super());
       sel_method = lookup_instance_method_in_klasses(super_klass,
@@ -1186,6 +1187,27 @@
                                             resolved_method->signature()));
       }
     }
+
+    // Check that the class of objectref (the receiver) is the current class or interface,
+    // or a subtype of the current class or interface (the sender), otherwise invokespecial
+    // throws IllegalAccessError.
+    // The verifier checks that the sender is a subtype of the class in the I/MR operand.
+    // The verifier also checks that the receiver is a subtype of the sender, if the sender is
+    // a class.  If the sender is an interface, the check has to be performed at runtime.
+    InstanceKlass* sender = InstanceKlass::cast(current_klass());
+    sender = sender->is_anonymous() ? sender->host_klass() : sender;
+    if (sender->is_interface() && recv.not_null()) {
+      Klass* receiver_klass = recv->klass();
+      if (!receiver_klass->is_subtype_of(sender)) {
+        ResourceMark rm(THREAD);
+        char buf[500];
+        jio_snprintf(buf, sizeof(buf),
+                     "Receiver class %s must be the current class or a subtype of interface %s",
+                     receiver_klass->name()->as_C_string(),
+                     sender->name()->as_C_string());
+        THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), buf);
+      }
+    }
   }
 
   // check if not static
@@ -1518,7 +1540,7 @@
 methodHandle LinkResolver::resolve_special_call_or_null(const LinkInfo& link_info) {
   EXCEPTION_MARK;
   CallInfo info;
-  resolve_special_call(info, link_info, THREAD);
+  resolve_special_call(info, Handle(), link_info, THREAD);
   if (HAS_PENDING_EXCEPTION) {
     CLEAR_PENDING_EXCEPTION;
     return methodHandle();
@@ -1534,7 +1556,7 @@
 void LinkResolver::resolve_invoke(CallInfo& result, Handle recv, const constantPoolHandle& pool, int index, Bytecodes::Code byte, TRAPS) {
   switch (byte) {
     case Bytecodes::_invokestatic   : resolve_invokestatic   (result,       pool, index, CHECK); break;
-    case Bytecodes::_invokespecial  : resolve_invokespecial  (result,       pool, index, CHECK); break;
+    case Bytecodes::_invokespecial  : resolve_invokespecial  (result, recv, pool, index, CHECK); break;
     case Bytecodes::_invokevirtual  : resolve_invokevirtual  (result, recv, pool, index, CHECK); break;
     case Bytecodes::_invokehandle   : resolve_invokehandle   (result,       pool, index, CHECK); break;
     case Bytecodes::_invokedynamic  : resolve_invokedynamic  (result,       pool, index, CHECK); break;
@@ -1563,7 +1585,7 @@
       resolve_static_call(result, link_info, /*initialize_class=*/false, CHECK);
       break;
     case Bytecodes::_invokespecial:
-      resolve_special_call(result, link_info, CHECK);
+      resolve_special_call(result, recv, link_info, CHECK);
       break;
     default:
       fatal("bad call: %s", Bytecodes::name(byte));
@@ -1576,9 +1598,10 @@
 }
 
 
-void LinkResolver::resolve_invokespecial(CallInfo& result, const constantPoolHandle& pool, int index, TRAPS) {
+void LinkResolver::resolve_invokespecial(CallInfo& result, Handle recv,
+                                         const constantPoolHandle& pool, int index, TRAPS) {
   LinkInfo link_info(pool, index, CHECK);
-  resolve_special_call(result, link_info, CHECK);
+  resolve_special_call(result, recv, link_info, CHECK);
 }
 
 
--- a/src/share/vm/interpreter/linkResolver.hpp	Thu Apr 20 18:14:04 2017 +0000
+++ b/src/share/vm/interpreter/linkResolver.hpp	Fri Apr 21 03:34:29 2017 +0000
@@ -230,6 +230,7 @@
                                                  const methodHandle& resolved_method,
                                                  KlassHandle resolved_klass,
                                                  KlassHandle current_klass,
+                                                 Handle recv,
                                                  bool check_access, TRAPS);
   static void runtime_resolve_virtual_method    (CallInfo& result,
                                                  const methodHandle& resolved_method,
@@ -256,7 +257,7 @@
   // runtime resolving from constant pool
   static void resolve_invokestatic   (CallInfo& result,
                                       const constantPoolHandle& pool, int index, TRAPS);
-  static void resolve_invokespecial  (CallInfo& result,
+  static void resolve_invokespecial  (CallInfo& result, Handle recv,
                                       const constantPoolHandle& pool, int index, TRAPS);
   static void resolve_invokevirtual  (CallInfo& result, Handle recv,
                                       const constantPoolHandle& pool, int index, TRAPS);
@@ -289,6 +290,7 @@
                                      const LinkInfo& link_info,
                                      bool initialize_klass, TRAPS);
   static void resolve_special_call  (CallInfo& result,
+                                     Handle recv,
                                      const LinkInfo& link_info,
                                      TRAPS);
   static void resolve_virtual_call  (CallInfo& result, Handle recv, KlassHandle recv_klass,
--- a/src/share/vm/oops/cpCache.cpp	Thu Apr 20 18:14:04 2017 +0000
+++ b/src/share/vm/oops/cpCache.cpp	Fri Apr 21 03:34:29 2017 +0000
@@ -140,7 +140,8 @@
 
 void ConstantPoolCacheEntry::set_direct_or_vtable_call(Bytecodes::Code invoke_code,
                                                        methodHandle method,
-                                                       int vtable_index) {
+                                                       int vtable_index,
+                                                       bool sender_is_interface) {
   bool is_vtable_call = (vtable_index >= 0);  // FIXME: split this method on this boolean
   assert(method->interpreter_entry() != NULL, "should have been set at this point");
   assert(!method->is_obsolete(),  "attempt to write obsolete method to cpCache");
@@ -204,7 +205,13 @@
   if (byte_no == 1) {
     assert(invoke_code != Bytecodes::_invokevirtual &&
            invoke_code != Bytecodes::_invokeinterface, "");
+    // Don't mark invokespecial to method as resolved if sender is an interface.  The receiver
+    // has to be checked that it is a subclass of the current class every time this bytecode
+    // is executed.
+    if (invoke_code != Bytecodes::_invokespecial || !sender_is_interface ||
+        method->name() == vmSymbols::object_initializer_name()) {
     set_bytecode_1(invoke_code);
+    }
   } else if (byte_no == 2)  {
     if (change_to_virtual) {
       assert(invoke_code == Bytecodes::_invokeinterface, "");
@@ -234,17 +241,18 @@
   NOT_PRODUCT(verify(tty));
 }
 
-void ConstantPoolCacheEntry::set_direct_call(Bytecodes::Code invoke_code, methodHandle method) {
+void ConstantPoolCacheEntry::set_direct_call(Bytecodes::Code invoke_code, methodHandle method,
+                                             bool sender_is_interface) {
   int index = Method::nonvirtual_vtable_index;
   // index < 0; FIXME: inline and customize set_direct_or_vtable_call
-  set_direct_or_vtable_call(invoke_code, method, index);
+  set_direct_or_vtable_call(invoke_code, method, index, sender_is_interface);
 }
 
 void ConstantPoolCacheEntry::set_vtable_call(Bytecodes::Code invoke_code, methodHandle method, int index) {
   // either the method is a miranda or its holder should accept the given index
   assert(method->method_holder()->is_interface() || method->method_holder()->verify_vtable_index(index), "");
   // index >= 0; FIXME: inline and customize set_direct_or_vtable_call
-  set_direct_or_vtable_call(invoke_code, method, index);
+  set_direct_or_vtable_call(invoke_code, method, index, false);
 }
 
 void ConstantPoolCacheEntry::set_itable_call(Bytecodes::Code invoke_code, const methodHandle& method, int index) {
--- a/src/share/vm/oops/cpCache.hpp	Thu Apr 20 18:14:04 2017 +0000
+++ b/src/share/vm/oops/cpCache.hpp	Fri Apr 21 03:34:29 2017 +0000
@@ -230,13 +230,15 @@
   void set_direct_or_vtable_call(
     Bytecodes::Code invoke_code,                 // the bytecode used for invoking the method
     methodHandle    method,                      // the method/prototype if any (NULL, otherwise)
-    int             vtable_index                 // the vtable index if any, else negative
+    int             vtable_index,                // the vtable index if any, else negative
+    bool            sender_is_interface
   );
 
  public:
   void set_direct_call(                          // sets entry to exact concrete method entry
     Bytecodes::Code invoke_code,                 // the bytecode used for invoking the method
-    methodHandle    method                       // the method to call
+    methodHandle    method,                      // the method to call
+    bool            sender_is_interface
   );
 
   void set_vtable_call(                          // sets entry to vtable index
--- a/src/share/vm/opto/doCall.cpp	Thu Apr 20 18:14:04 2017 +0000
+++ b/src/share/vm/opto/doCall.cpp	Fri Apr 21 03:34:29 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -505,6 +505,30 @@
     speculative_receiver_type = receiver_type != NULL ? receiver_type->speculative_type() : NULL;
   }
 
+  // invoke-super-special
+  if (iter().cur_bc_raw() == Bytecodes::_invokespecial && !orig_callee->is_object_initializer()) {
+    ciInstanceKlass* calling_klass = method()->holder();
+    ciInstanceKlass* sender_klass =
+        calling_klass->is_anonymous() ? calling_klass->host_klass() :
+                                        calling_klass;
+    if (sender_klass->is_interface()) {
+      Node* receiver_node = stack(sp() - nargs);
+      Node* cls_node = makecon(TypeKlassPtr::make(sender_klass));
+      Node* bad_type_ctrl = NULL;
+      Node* casted_receiver = gen_checkcast(receiver_node, cls_node, &bad_type_ctrl);
+      if (bad_type_ctrl != NULL) {
+        PreserveJVMState pjvms(this);
+        set_control(bad_type_ctrl);
+        uncommon_trap(Deoptimization::Reason_class_check,
+                      Deoptimization::Action_none);
+      }
+      if (stopped()) {
+        return; // MUST uncommon-trap?
+      }
+      set_stack(sp() - nargs, casted_receiver);
+    }
+  }
+
   // Note:  It's OK to try to inline a virtual call.
   // The call generator will not attempt to inline a polymorphic call
   // unless it knows how to optimize the receiver dispatch.
--- a/src/share/vm/opto/memnode.cpp	Thu Apr 20 18:14:04 2017 +0000
+++ b/src/share/vm/opto/memnode.cpp	Fri Apr 21 03:34:29 2017 +0000
@@ -61,6 +61,15 @@
   return calculate_adr_type(adr->bottom_type(), cross_check);
 }
 
+bool MemNode::check_if_adr_maybe_raw(Node* adr) {
+  if (adr != NULL) {
+    if (adr->bottom_type()->base() == Type::RawPtr || adr->bottom_type()->base() == Type::AnyPtr) {
+      return true;
+    }
+  }
+  return false;
+}
+
 #ifndef PRODUCT
 void MemNode::dump_spec(outputStream *st) const {
   if (in(Address) == NULL)  return; // node is dead
@@ -560,6 +569,7 @@
   if (offset == Type::OffsetBot)
     return NULL;            // cannot unalias unless there are precise offsets
 
+  const bool adr_maybe_raw = check_if_adr_maybe_raw(adr);
   const TypeOopPtr *addr_t = adr->bottom_type()->isa_oopptr();
 
   intptr_t size_in_bytes = memory_size();
@@ -577,6 +587,13 @@
       Node* st_base = AddPNode::Ideal_base_and_offset(st_adr, phase, st_offset);
       if (st_base == NULL)
         break;              // inscrutable pointer
+
+      // For raw accesses it's not enough to prove that constant offsets don't intersect.
+      // We need the bases to be the equal in order for the offset check to make sense.
+      if ((adr_maybe_raw || check_if_adr_maybe_raw(st_adr)) && st_base != base) {
+        break;
+      }
+
       if (st_offset != offset && st_offset != Type::OffsetBot) {
         const int MAX_STORE = BytesPerLong;
         if (st_offset >= offset + size_in_bytes ||
--- a/src/share/vm/opto/memnode.hpp	Thu Apr 20 18:14:04 2017 +0000
+++ b/src/share/vm/opto/memnode.hpp	Fri Apr 21 03:34:29 2017 +0000
@@ -78,6 +78,7 @@
   }
 
   virtual Node* find_previous_arraycopy(PhaseTransform* phase, Node* ld_alloc, Node*& mem, bool can_see_stored_value) const { return NULL; }
+  static bool check_if_adr_maybe_raw(Node* adr);
 
 public:
   // Helpers for the optimizer.  Documented in memnode.cpp.
--- a/src/share/vm/prims/methodHandles.cpp	Thu Apr 20 18:14:04 2017 +0000
+++ b/src/share/vm/prims/methodHandles.cpp	Fri Apr 21 03:34:29 2017 +0000
@@ -727,7 +727,7 @@
           assert(!is_signature_polymorphic_static(mh_invoke_id), "");
           LinkResolver::resolve_handle_call(result, link_info, THREAD);
         } else if (ref_kind == JVM_REF_invokeSpecial) {
-          LinkResolver::resolve_special_call(result,
+          LinkResolver::resolve_special_call(result, Handle(),
                         link_info, THREAD);
         } else if (ref_kind == JVM_REF_invokeVirtual) {
           LinkResolver::resolve_virtual_call(result, Handle(), defc,
@@ -755,7 +755,7 @@
       {
         assert(!HAS_PENDING_EXCEPTION, "");
         if (name == vmSymbols::object_initializer_name()) {
-          LinkResolver::resolve_special_call(result, link_info, THREAD);
+          LinkResolver::resolve_special_call(result, Handle(), link_info, THREAD);
         } else {
           break;                // will throw after end of switch
         }
--- a/src/share/vm/runtime/javaCalls.cpp	Thu Apr 20 18:14:04 2017 +0000
+++ b/src/share/vm/runtime/javaCalls.cpp	Fri Apr 21 03:34:29 2017 +0000
@@ -221,7 +221,7 @@
 void JavaCalls::call_special(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS) {
   CallInfo callinfo;
   LinkInfo link_info(klass, name, signature);
-  LinkResolver::resolve_special_call(callinfo, link_info, CHECK);
+  LinkResolver::resolve_special_call(callinfo, args->receiver(), link_info, CHECK);
   methodHandle method = callinfo.selected_method();
   assert(method.not_null(), "should have thrown exception");
 
--- a/test/TEST.ROOT	Thu Apr 20 18:14:04 2017 +0000
+++ b/test/TEST.ROOT	Fri Apr 21 03:34:29 2017 +0000
@@ -59,3 +59,6 @@
 
 # Use new module options
 useNewOptions=true
+
+# Use --patch-module instead of -Xmodule:
+useNewPatchModule=true
--- a/test/compiler/intrinsics/zip/TestCRC32.java	Thu Apr 20 18:14:04 2017 +0000
+++ b/test/compiler/intrinsics/zip/TestCRC32.java	Fri Apr 21 03:34:29 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -36,7 +36,22 @@
 import java.util.zip.Checksum;
 
 public class TestCRC32 {
-    public static void main(String[] args) {
+    // standard CRC32 polynomial
+    // coefficients in different forms
+    // normal:              polyBits = 0x04c11db7   = 0b0000 0100 1100 0001 0001 1101 1011 0111
+    // reversed:            polybits = 0xedb88320   = 0b1110 1101 1011 1000 1000 0011 0010 0000
+    // reversed reciprocal  polybits = 0x82608edb   = 0b1000 0010 0110 0000 1000 1110 1101 1011
+    //
+    //                                                  0      5    9    13   17   21   25   29
+    //                                                  |      |    |    |    |    |    |    |
+    // reversed shiftL 1    polyBits = 0x1db710641L = 0b1 1101 1011 0111 0001 0000 0110 0100 0001
+    final static long polyBits = (1L<<(32-32)) + (1L<<(32-26)) + (1L<<(32-23)) + (1L<<(32-22))
+                               + (1L<<(32-16)) + (1L<<(32-12)) + (1L<<(32-11)) + (1L<<(32-10))
+                               + (1L<<(32-8))  + (1L<<(32-7))  + (1L<<(32-5))  + (1L<<(32-4))
+                               + (1L<<(32-2))  + (1L<<(32-1))  + (1L<<(32-0));
+    final static long polyBitsShifted = polyBits>>1;
+
+    public static void main(String[] args) throws Exception {
         int offset = Integer.getInteger("offset", 0);
         int msgSize = Integer.getInteger("msgSize", 512);
         boolean multi = false;
@@ -65,11 +80,14 @@
 
         byte[] b = initializedBytes(msgSize, offset);
 
+        final long crcReference = update_byteLoop(0, b, offset);
+
         CRC32 crc0 = new CRC32();
         CRC32 crc1 = new CRC32();
         CRC32 crc2 = new CRC32();
 
         crc0.update(b, offset, msgSize);
+        check(crc0, crcReference);
 
         System.out.println("-------------------------------------------------------");
 
@@ -77,27 +95,35 @@
         for (int i = 0; i < warmupIters; i++) {
             crc1.reset();
             crc1.update(b, offset, msgSize);
+            check(crc1, crcReference);
         }
 
-        /* measure performance */
+        /* check correctness
+         * Do that before measuring performance
+         * to even better heat up involved methods.
+         */
+        for (int i = 0; i < iters; i++) {
+            crc1.reset();
+            crc1.update(b, offset, msgSize);
+            check(crc1, crcReference);
+        }
+        report("CRCs", crc1, crcReference);
+
+        /* measure performance
+         * Don't spoil times with error checking.
+         */
         long start = System.nanoTime();
         for (int i = 0; i < iters; i++) {
             crc1.reset();
             crc1.update(b, offset, msgSize);
         }
         long end = System.nanoTime();
+
         double total = (double)(end - start)/1e9;         // in seconds
         double thruput = (double)msgSize*iters/1e6/total; // in MB/s
         System.out.println("CRC32.update(byte[]) runtime = " + total + " seconds");
         System.out.println("CRC32.update(byte[]) throughput = " + thruput + " MB/s");
-
-        /* check correctness */
-        for (int i = 0; i < iters; i++) {
-            crc1.reset();
-            crc1.update(b, offset, msgSize);
-            if (!check(crc0, crc1)) break;
-        }
-        report("CRCs", crc0, crc1);
+        report("CRCs", crc1, crcReference);
 
         System.out.println("-------------------------------------------------------");
 
@@ -110,9 +136,24 @@
             crc2.reset();
             crc2.update(buf);
             buf.rewind();
+            check(crc2, crcReference);
         }
 
-        /* measure performance */
+        /* check correctness
+         * Do that before measuring performance
+         * to even better heat up involved methods.
+         */
+        for (int i = 0; i < iters; i++) {
+            crc2.reset();
+            crc2.update(buf);
+            buf.rewind();
+            check(crc2, crcReference);
+        }
+        report("CRCs", crc2, crcReference);
+
+        /* measure performance
+         * Don't spoil times with error checking.
+         */
         start = System.nanoTime();
         for (int i = 0; i < iters; i++) {
             crc2.reset();
@@ -124,31 +165,57 @@
         thruput = (double)msgSize*iters/1e6/total; // in MB/s
         System.out.println("CRC32.update(ByteBuffer) runtime = " + total + " seconds");
         System.out.println("CRC32.update(ByteBuffer) throughput = " + thruput + " MB/s");
-
-        /* check correctness */
-        for (int i = 0; i < iters; i++) {
-            crc2.reset();
-            crc2.update(buf);
-            buf.rewind();
-            if (!check(crc0, crc2)) break;
-        }
-        report("CRCs", crc0, crc2);
+        report("CRCs", crc2, crcReference);
 
         System.out.println("-------------------------------------------------------");
     }
 
-    private static void report(String s, Checksum crc0, Checksum crc1) {
-        System.out.printf("%s: crc0 = %08x, crc1 = %08x\n",
-                          s, crc0.getValue(), crc1.getValue());
+    // Just a loop over a byte array, updating the CRC byte by byte.
+    public static long update_byteLoop(long crc, byte[] buf, int offset) {
+        return update_byteLoop(crc, buf, offset, buf.length-offset);
+    }
+
+    // Just a loop over a byte array, with given length, updating the CRC byte by byte.
+    public static long update_byteLoop(long crc, byte[] buf, int offset, int length) {
+        int end = length+offset;
+        for (int i = offset; i < end; i++) {
+            crc = update_singlebyte(crc, polyBitsShifted, buf[i]);
+        }
+        return crc;
     }
 
-    private static boolean check(Checksum crc0, Checksum crc1) {
-        if (crc0.getValue() != crc1.getValue()) {
-            System.err.printf("ERROR: crc0 = %08x, crc1 = %08x\n",
-                              crc0.getValue(), crc1.getValue());
-            return false;
+    // Straight-forward implementation of CRC update by one byte.
+    // We use this very basic implementation to calculate reference
+    // results. It is necessary to have full control over how the
+    // reference results are calculated. It is not sufficient to rely
+    // on the interpreter (or c1, or c2) to do the right thing.
+    public static long update_singlebyte(long crc, long polynomial, int val) {
+        crc = (crc ^ -1L) & 0x00000000ffffffffL;  // use 1's complement of crc
+        crc =  crc ^ (val&0xff);                  // XOR in next byte from stream
+        for (int i = 0; i <  8; i++) {
+            boolean bitset = (crc & 0x01L) != 0;
+
+            crc = crc>>1;
+            if (bitset) {
+                crc = crc ^ polynomial;
+                crc = crc & 0x00000000ffffffffL;
+            }
         }
-        return true;
+        crc = (crc ^ -1L) & 0x00000000ffffffffL;  // revert taking 1's complement
+        return crc;
+    }
+
+    private static void report(String s, Checksum crc, long crcReference) {
+        System.out.printf("%s: crc = %08x, crcReference = %08x\n",
+                          s, crc.getValue(), crcReference);
+    }
+
+    private static void check(Checksum crc, long crcReference) throws Exception {
+        if (crc.getValue() != crcReference) {
+            System.err.printf("ERROR: crc = %08x, crcReference = %08x\n",
+                              crc.getValue(), crcReference);
+            throw new Exception("TestCRC32 Error");
+        }
     }
 
     private static byte[] initializedBytes(int M, int offset) {
@@ -162,7 +229,7 @@
         return bytes;
     }
 
-    private static void test_multi(int iters) {
+    private static void test_multi(int iters) throws Exception {
         int len1 = 8;    // the  8B/iteration loop
         int len2 = 32;   // the 32B/iteration loop
         int len3 = 4096; // the 4KB/iteration loop
@@ -185,37 +252,31 @@
                         (len1+len2+len3)*2+5, (len1+len2+len3)*2+7,
                         (len1+len2+len3)*3, (len1+len2+len3)*3-1, (len1+len2+len3)*3-3,
                         (len1+len2+len3)*3-5, (len1+len2+len3)*3-7 };
-        CRC32[] crc0 = new CRC32[offsets.length*sizes.length];
         CRC32[] crc1 = new CRC32[offsets.length*sizes.length];
+        long[] crcReference = new long[offsets.length*sizes.length];
         int i, j, k;
 
         System.out.printf("testing %d cases ...\n", offsets.length*sizes.length);
 
-        /* set the result from interpreter as reference */
+        // Initialize CRC32 result arrays, CRC32 reference array.
+        // Reference is calculated using a very basic Java implementation.
         for (i = 0; i < offsets.length; i++) {
             for (j = 0; j < sizes.length; j++) {
-                crc0[i*sizes.length + j] = new CRC32();
                 crc1[i*sizes.length + j] = new CRC32();
-                crc0[i*sizes.length + j].update(b, offsets[i], sizes[j]);
+                crcReference[i*sizes.length + j] = update_byteLoop(0, b, offsets[i], sizes[j]);
             }
         }
 
-        /* warm up the JIT compiler and get result */
+        // Warm up the JIT compiler. Over time, all methods involved will
+        // be executed by the interpreter, then get compiled by c1 and
+        // finally by c2. Each calculated CRC value must, in each iteration,
+        // be equal to the precalculated reference value for the test to pass.
         for (k = 0; k < iters; k++) {
             for (i = 0; i < offsets.length; i++) {
                 for (j = 0; j < sizes.length; j++) {
                     crc1[i*sizes.length + j].reset();
                     crc1[i*sizes.length + j].update(b, offsets[i], sizes[j]);
-                }
-            }
-        }
-
-        /* check correctness */
-        for (i = 0; i < offsets.length; i++) {
-            for (j = 0; j < sizes.length; j++) {
-                if (!check(crc0[i*sizes.length + j], crc1[i*sizes.length + j])) {
-                    System.out.printf("offsets[%d] = %d", i, offsets[i]);
-                    System.out.printf("\tsizes[%d] = %d\n", j, sizes[j]);
+                    check(crc1[i*sizes.length + j], crcReference[i*sizes.length + j]);
                 }
             }
         }
--- a/test/compiler/intrinsics/zip/TestCRC32C.java	Thu Apr 20 18:14:04 2017 +0000
+++ b/test/compiler/intrinsics/zip/TestCRC32C.java	Fri Apr 21 03:34:29 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -36,7 +36,23 @@
 import java.util.zip.Checksum;
 
 public class TestCRC32C {
-    public static void main(String[] args) {
+    // CRC32C (Castagnoli) polynomial
+    // coefficients in different forms
+    // normal:              polyBits = 0x1edc6f41   = 0b0001 1110 1101 1100 0110 1111 0100 0001
+    // reversed:            polybits = 0x82f63b78   = 0b1000 0010 1111 0110 0011 1011 0111 1000
+    // reversed reciprocal  polybits = 0x8f6e37a0   = 0b1000 1111 0110 1110 0011 0111 1010 0000
+    //
+    //                                                  0      5    9    13   17   21   25   29
+    //                                                  |      |    |    |    |    |    |    |
+    // reversed shiftL 1    polyBits = 0x105ec76f1L = 0b1 0000 0101 1110 1100 0111 0110 1111 0001
+    final static long polyBits = (1L<<(32-32)) + (1L<<(32-28)) + (1L<<(32-27))
+                               + (1L<<(32-26)) + (1L<<(32-25)) + (1L<<(32-23)) + (1L<<(32-22))
+                               + (1L<<(32-20)) + (1L<<(32-19)) + (1L<<(32-18)) + (1L<<(32-14))
+                               + (1L<<(32-13)) + (1L<<(32-11)) + (1L<<(32-10)) + (1L<<(32-9))
+                               + (1L<<(32-8))  + (1L<<(32-6))  + (1L<<(32-0));
+    final static long polyBitsShifted = polyBits>>1;
+
+    public static void main(String[] args) throws Exception {
         int offset = Integer.getInteger("offset", 0);
         int msgSize = Integer.getInteger("msgSize", 512);
         boolean multi = false;
@@ -65,11 +81,14 @@
 
         byte[] b = initializedBytes(msgSize, offset);
 
+        final long crcReference = update_byteLoop(0, b, offset);
+
         CRC32C crc0 = new CRC32C();
         CRC32C crc1 = new CRC32C();
         CRC32C crc2 = new CRC32C();
 
         crc0.update(b, offset, msgSize);
+        check(crc0, crcReference);
 
         System.out.println("-------------------------------------------------------");
 
@@ -77,27 +96,35 @@
         for (int i = 0; i < warmupIters; i++) {
             crc1.reset();
             crc1.update(b, offset, msgSize);
+            check(crc1, crcReference);
         }
 
-        /* measure performance */
+        /* check correctness
+         * Do that before measuring performance
+         * to even better heat up involved methods.
+         */
+        for (int i = 0; i < iters; i++) {
+            crc1.reset();
+            crc1.update(b, offset, msgSize);
+            check(crc1, crcReference);
+        }
+        report("CRCs", crc1, crcReference);
+
+        /* measure performance
+         * Don't spoil times with error checking.
+         */
         long start = System.nanoTime();
         for (int i = 0; i < iters; i++) {
             crc1.reset();
             crc1.update(b, offset, msgSize);
         }
         long end = System.nanoTime();
+
         double total = (double)(end - start)/1e9;         // in seconds
         double thruput = (double)msgSize*iters/1e6/total; // in MB/s
         System.out.println("CRC32C.update(byte[]) runtime = " + total + " seconds");
         System.out.println("CRC32C.update(byte[]) throughput = " + thruput + " MB/s");
-
-        /* check correctness */
-        for (int i = 0; i < iters; i++) {
-            crc1.reset();
-            crc1.update(b, offset, msgSize);
-            if (!check(crc0, crc1)) break;
-        }
-        report("CRCs", crc0, crc1);
+        report("CRCs", crc1, crcReference);
 
         System.out.println("-------------------------------------------------------");
 
@@ -110,9 +137,24 @@
             crc2.reset();
             crc2.update(buf);
             buf.rewind();
+            check(crc2, crcReference);
         }
 
-        /* measure performance */
+        /* check correctness
+         * Do that before measuring performance
+         * to even better heat up involved methods.
+         */
+        for (int i = 0; i < iters; i++) {
+            crc2.reset();
+            crc2.update(buf);
+            buf.rewind();
+            check(crc2, crcReference);
+        }
+        report("CRCs", crc2, crcReference);
+
+        /* measure performance
+         * Don't spoil times with error checking.
+         */
         start = System.nanoTime();
         for (int i = 0; i < iters; i++) {
             crc2.reset();
@@ -124,31 +166,57 @@
         thruput = (double)msgSize*iters/1e6/total; // in MB/s
         System.out.println("CRC32C.update(ByteBuffer) runtime = " + total + " seconds");
         System.out.println("CRC32C.update(ByteBuffer) throughput = " + thruput + " MB/s");
-
-        /* check correctness */
-        for (int i = 0; i < iters; i++) {
-            crc2.reset();
-            crc2.update(buf);
-            buf.rewind();
-            if (!check(crc0, crc2)) break;
-        }
-        report("CRCs", crc0, crc2);
+        report("CRCs", crc2, crcReference);
 
         System.out.println("-------------------------------------------------------");
     }
 
-    private static void report(String s, Checksum crc0, Checksum crc1) {
-        System.out.printf("%s: crc0 = %08x, crc1 = %08x\n",
-                          s, crc0.getValue(), crc1.getValue());
+    // Just a loop over a byte array, updating the CRC byte by byte.
+    public static long update_byteLoop(long crc, byte[] buf, int offset) {
+        return update_byteLoop(crc, buf, offset, buf.length-offset);
+    }
+
+    // Just a loop over a byte array, with given length, updating the CRC byte by byte.
+    public static long update_byteLoop(long crc, byte[] buf, int offset, int length) {
+        int end = length+offset;
+        for (int i = offset; i < end; i++) {
+            crc = update_singlebyte(crc, polyBitsShifted, buf[i]);
+        }
+        return crc;
     }
 
-    private static boolean check(Checksum crc0, Checksum crc1) {
-        if (crc0.getValue() != crc1.getValue()) {
-            System.err.printf("ERROR: crc0 = %08x, crc1 = %08x\n",
-                              crc0.getValue(), crc1.getValue());
-            return false;
+    // Straight-forward implementation of CRC update by one byte.
+    // We use this very basic implementation to calculate reference
+    // results. It is necessary to have full control over how the
+    // reference results are calculated. It is not sufficient to rely
+    // on the interpreter (or c1, or c2) to do the right thing.
+    public static long update_singlebyte(long crc, long polynomial, int val) {
+        crc = (crc ^ -1L) & 0x00000000ffffffffL;  // use 1's complement of crc
+        crc =  crc ^ (val&0xff);                  // XOR in next byte from stream
+        for (int i = 0; i <  8; i++) {
+            boolean bitset = (crc & 0x01L) != 0;
+
+            crc = crc>>1;
+            if (bitset) {
+                crc = crc ^ polynomial;
+                crc = crc & 0x00000000ffffffffL;
+            }
         }
-        return true;
+        crc = (crc ^ -1L) & 0x00000000ffffffffL;  // revert taking 1's complement
+        return crc;
+    }
+
+    private static void report(String s, Checksum crc, long crcReference) {
+        System.out.printf("%s: crc = %08x, crcReference = %08x\n",
+                          s, crc.getValue(), crcReference);
+    }
+
+    private static void check(Checksum crc, long crcReference) throws Exception {
+        if (crc.getValue() != crcReference) {
+            System.err.printf("ERROR: crc = %08x, crcReference = %08x\n",
+                              crc.getValue(), crcReference);
+            throw new Exception("TestCRC32C Error");
+        }
     }
 
     private static byte[] initializedBytes(int M, int offset) {
@@ -162,7 +230,7 @@
         return bytes;
     }
 
-    private static void test_multi(int iters) {
+    private static void test_multi(int iters) throws Exception {
         int len1 = 8;    // the  8B/iteration loop
         int len2 = 32;   // the 32B/iteration loop
         int len3 = 4096; // the 4KB/iteration loop
@@ -185,37 +253,31 @@
                         (len1+len2+len3)*2+5, (len1+len2+len3)*2+7,
                         (len1+len2+len3)*3, (len1+len2+len3)*3-1, (len1+len2+len3)*3-3,
                         (len1+len2+len3)*3-5, (len1+len2+len3)*3-7 };
-        CRC32C[] crc0 = new CRC32C[offsets.length*sizes.length];
         CRC32C[] crc1 = new CRC32C[offsets.length*sizes.length];
+        long[] crcReference = new long[offsets.length*sizes.length];
         int i, j, k;
 
         System.out.printf("testing %d cases ...\n", offsets.length*sizes.length);
 
-        /* set the result from interpreter as reference */
+        // Initialize CRC32C result arrays, CRC32C reference array.
+        // Reference is calculated using a very basic Java implementation.
         for (i = 0; i < offsets.length; i++) {
             for (j = 0; j < sizes.length; j++) {
-                crc0[i*sizes.length + j] = new CRC32C();
                 crc1[i*sizes.length + j] = new CRC32C();
-                crc0[i*sizes.length + j].update(b, offsets[i], sizes[j]);
+                crcReference[i*sizes.length + j] = update_byteLoop(0, b, offsets[i], sizes[j]);
             }
         }
 
-        /* warm up the JIT compiler and get result */
+        // Warm up the JIT compiler. Over time, all methods involved will
+        // be executed by the interpreter, then get compiled by c1 and
+        // finally by c2. Each calculated CRC value must, in each iteration,
+        // be equal to the precalculated reference value for the test to pass.
         for (k = 0; k < iters; k++) {
             for (i = 0; i < offsets.length; i++) {
                 for (j = 0; j < sizes.length; j++) {
                     crc1[i*sizes.length + j].reset();
                     crc1[i*sizes.length + j].update(b, offsets[i], sizes[j]);
-                }
-            }
-        }
-
-        /* check correctness */
-        for (i = 0; i < offsets.length; i++) {
-            for (j = 0; j < sizes.length; j++) {
-                if (!check(crc0[i*sizes.length + j], crc1[i*sizes.length + j])) {
-                    System.out.printf("offsets[%d] = %d", i, offsets[i]);
-                    System.out.printf("\tsizes[%d] = %d\n", j, sizes[j]);
+                    check(crc1[i*sizes.length + j], crcReference[i*sizes.length + j]);
                 }
             }
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/unsafe/TestRawAliasing.java	Fri Apr 21 03:34:29 2017 +0000
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8178047
+ * @run main/othervm -XX:CompileCommand=exclude,*.main -XX:-TieredCompilation -XX:-BackgroundCompilation compiler.unsafe.TestRawAliasing
+ * @modules java.base/jdk.internal.misc:+open
+ */
+
+package compiler.unsafe;
+
+import java.lang.reflect.Field;
+
+public class TestRawAliasing {
+    static private final jdk.internal.misc.Unsafe UNSAFE;
+    static {
+        try {
+            Field f = jdk.internal.misc.Unsafe.class.getDeclaredField("theUnsafe");
+            f.setAccessible(true);
+            UNSAFE = (jdk.internal.misc.Unsafe) f.get(null);
+        } catch (Exception e) {
+            throw new RuntimeException("Unable to get Unsafe instance.", e);
+        }
+    }
+
+    static private final int OFFSET_X = 50;
+    static private final int OFFSET_Y = 100;
+
+    private static int test(long base_plus_offset_x, long base_plus_offset_y, int magic_value) {
+        // write 0 to a location
+        UNSAFE.putByte(base_plus_offset_x - OFFSET_X, (byte)0);
+        // write unfoldable value to really the same location with another base
+        UNSAFE.putByte(base_plus_offset_y - OFFSET_Y, (byte)magic_value);
+        // read the value back, should be equal to "unfoldable_value"
+        return UNSAFE.getByte(base_plus_offset_x - OFFSET_X);
+    }
+
+    private static final int OFF_HEAP_AREA_SIZE = 128;
+    private static final byte MAGIC = 123;
+
+    // main is excluded from compilation since we don't want the test method to inline and make base values fold
+    public static void main(String... args) {
+        long base = UNSAFE.allocateMemory(OFF_HEAP_AREA_SIZE);
+        for (int i = 0; i < 100_000; i++) {
+            if (test(base + OFFSET_X, base + OFFSET_Y, MAGIC) != MAGIC) {
+                throw new RuntimeException("Unexpected magic value");
+            }
+        }
+    }
+}