Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8242496: [lworld] new and defaultvalue don't perform checks on class to instantiate #21

Closed
wants to merge 2 commits into from
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -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");

}
}