Skip to content
Permalink
Browse files
8242496: [lworld] new and defaultvalue don't perform checks on class …
…to instantiate

Reviewed-by: dsimms
  • Loading branch information
fparain committed Apr 14, 2020
1 parent aee9550 commit acffd197fa1749c3e867073cc8ddf6c48b9fcb7d
Show file tree
Hide file tree
Showing 5 changed files with 155 additions and 0 deletions.
@@ -4337,6 +4337,7 @@ void TemplateTable::_new() {
__ get_unsigned_2_byte_index_at_bcp(rdx, 1);
Label slow_case;
Label done;
Label is_not_value;

__ get_cpool_and_tags(rcx, rax);

@@ -4350,6 +4351,15 @@ void TemplateTable::_new() {
// get InstanceKlass
__ load_resolved_klass_at_index(rcx, rcx, rdx);

__ movl(rdx, Address(rcx, InstanceKlass::misc_flags_offset()));
__ andl(rdx, InstanceKlass::_misc_kind_field_mask);
__ cmpl(rdx, InstanceKlass::_misc_kind_value_type);
__ jcc(Assembler::notEqual, is_not_value);

__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_InstantiationError));

__ bind(is_not_value);

// make sure klass is initialized & doesn't have finalizer
__ cmpb(Address(rcx, InstanceKlass::init_state_offset()), InstanceKlass::fully_initialized);
__ jcc(Assembler::notEqual, slow_case);
@@ -4377,6 +4387,7 @@ void TemplateTable::defaultvalue() {

Label slow_case;
Label done;
Label is_value;

__ get_unsigned_2_byte_index_at_bcp(rdx, 1);
__ get_cpool_and_tags(rcx, rax);
@@ -4391,6 +4402,16 @@ void TemplateTable::defaultvalue() {
// get InstanceKlass
__ load_resolved_klass_at_index(rcx, rcx, rdx);

__ movl(rdx, Address(rcx, InstanceKlass::misc_flags_offset()));
__ andl(rdx, InstanceKlass::_misc_kind_field_mask);
__ cmpl(rdx, InstanceKlass::_misc_kind_value_type);
__ jcc(Assembler::equal, is_value);

// in the future, defaultvalue will just return null instead of throwing an exception
__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_IncompatibleClassChangeError));

__ bind(is_value);

// make sure klass is fully initialized
__ cmpb(Address(rcx, InstanceKlass::init_state_offset()), InstanceKlass::fully_initialized);
__ jcc(Assembler::notEqual, slow_case);
@@ -234,6 +234,10 @@ JRT_ENTRY(void, InterpreterRuntime::_new(JavaThread* thread, ConstantPool* pool,
Klass* k = pool->klass_at(index, CHECK);
InstanceKlass* klass = InstanceKlass::cast(k);

if (klass->is_value()) {
THROW(vmSymbols::java_lang_InstantiationError());
}

// Make sure we are not instantiating an abstract klass
klass->check_valid_for_instantiation(true, CHECK);

@@ -297,6 +301,11 @@ void copy_primitive_argument(intptr_t* addr, Handle instance, int offset, BasicT
JRT_ENTRY(void, InterpreterRuntime::defaultvalue(JavaThread* thread, ConstantPool* pool, int index))
// Getting the ValueKlass
Klass* k = pool->klass_at(index, CHECK);
if (!k->is_value()) {
// inconsistency with 'new' which throws an InstantiationError
// in the future, defaultvalue will just return null instead of throwing an exception
THROW(vmSymbols::java_lang_IncompatibleClassChangeError());
}
assert(k->is_value(), "defaultvalue argument must be the value type class");
ValueKlass* vklass = ValueKlass::cast(k);

@@ -881,6 +890,10 @@ JRT_ENTRY(void, InterpreterRuntime::throw_AbstractMethodErrorVerbose(JavaThread*
LinkResolver::throw_abstract_method_error(mh, recvKlass, THREAD);
JRT_END

JRT_ENTRY(void, InterpreterRuntime::throw_InstantiationError(JavaThread* thread))
THROW(vmSymbols::java_lang_InstantiationError());
JRT_END


JRT_ENTRY(void, InterpreterRuntime::throw_IncompatibleClassChangeError(JavaThread* thread))
THROW(vmSymbols::java_lang_IncompatibleClassChangeError());
@@ -86,6 +86,7 @@ class InterpreterRuntime: AllStatic {
Klass* recvKlass,
Method* missingMethod);

static void throw_InstantiationError(JavaThread* thread);
static void throw_IncompatibleClassChangeError(JavaThread* thread);
static void throw_IncompatibleClassChangeErrorVerbose(JavaThread* thread,
Klass* resc,
@@ -163,6 +163,7 @@ class InstanceKlass: public Klass {
friend class JVMCIVMStructs;
friend class ClassFileParser;
friend class CompileReplay;
friend class TemplateTable;

public:
static const KlassID ID = InstanceKlassID;
@@ -0,0 +1,119 @@
/*
* Copyright (c) 2017, 2019, 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.
*/

package runtime.valhalla.valuetypes;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.invoke.*;
import java.lang.ref.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.*;

import static jdk.test.lib.Asserts.*;

import jdk.experimental.bytecode.MacroCodeBuilder;
import jdk.experimental.bytecode.MacroCodeBuilder.CondKind;
import jdk.experimental.bytecode.TypeTag;
import jdk.test.lib.Platform;
import jdk.test.lib.Utils;

import jdk.experimental.value.MethodHandleBuilder;

import javax.tools.*;

/**
* @test CreationErrorTest
* @summary Test data movement with inline types
* @modules java.base/jdk.experimental.bytecode
* java.base/jdk.experimental.value
* @library /test/lib
* @run main/othervm -Xint -Xmx128m -XX:-ShowMessageBoxOnError
* -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
* -Djava.lang.invoke.MethodHandle.DUMP_CLASS_FILES=false
* runtime.valhalla.valuetypes.CreationErrorTest
*/

public class CreationErrorTest {

static inline class InlineClass {
int i = 0;
}

static class IdentityClass {
long l = 0L;
}

static MethodHandles.Lookup LOOKUP = MethodHandles.lookup();

public static void main(String[] args) {
testErroneousObjectCreation();
testErroneousValueCreation();
}

static void testErroneousObjectCreation() {
MethodHandle testNewOnInlineClass = MethodHandleBuilder.loadCode(
LOOKUP,
"testNewOnInlineClass",
MethodType.methodType(boolean.class),
CODE -> {
CODE.new_(InlineClass.class)
.iconst_1()
.return_(TypeTag.Z);
});
Throwable error = null;
try {
boolean result = (boolean) testNewOnInlineClass.invokeExact();
} catch (Throwable t) {
error = t;
}
System.out.println("error="+error);
assertTrue(error != null && error instanceof InstantiationError, "Invariant");

}

// Note: this test might become obsolete if defaultvalue is extended to accept identity classes
static void testErroneousValueCreation() {
MethodHandle testDefaultvalueOnIdentityClass = MethodHandleBuilder.loadCode(
LOOKUP,
"testDefaultValueOnIdentityClass",
MethodType.methodType(boolean.class),
CODE -> {
CODE.defaultvalue(IdentityClass.class)
.iconst_1()
.return_(TypeTag.Z);
});
Throwable error = null;
try {
boolean result = (boolean) testDefaultvalueOnIdentityClass.invokeExact();
} catch (Throwable t) {
error = t;
}
System.out.println("error="+error);
assertTrue(error != null && error instanceof IncompatibleClassChangeError, "Invariant");

}
}

0 comments on commit acffd19

Please sign in to comment.