提交 7774bc6a 编写于 作者: A asaha

Merge

...@@ -945,6 +945,18 @@ f26f6895c9dfb32dfb4c228d69b371d8ab118536 jdk8u121-b10 ...@@ -945,6 +945,18 @@ f26f6895c9dfb32dfb4c228d69b371d8ab118536 jdk8u121-b10
11f91811e4d7e5ddfaf938dcf386ec8fe5bf7b7c jdk8u121-b11 11f91811e4d7e5ddfaf938dcf386ec8fe5bf7b7c jdk8u121-b11
b132b08b28bf23a26329928cf6b4ffda5857f4d3 jdk8u121-b12 b132b08b28bf23a26329928cf6b4ffda5857f4d3 jdk8u121-b12
90f94521c3515e5f27af0ab9b31d036e88bb322a jdk8u121-b13 90f94521c3515e5f27af0ab9b31d036e88bb322a jdk8u121-b13
c0a1ba0df20fda10ddb8599e888eb56ad98b3874 jdk8u131-b00
0b85ccd6240991e1a501602ff5addec6b88ae0af jdk8u131-b01
ef90c721a4e59b01ca36f25619010a1afe9ed4d5 jdk8u131-b02
0ca47d0811b01ecf8651b6045a1e33a4a9bed0ee jdk8u131-b03
dab1d597165207e14b6886b1823c1e990bc776a3 jdk8u131-b04
c965fc1aa840a0903709ad69aa0e2100330ccd84 jdk8u131-b05
6e4cfbc7534f83902692132efb61683528c04a59 jdk8u131-b06
5b3cb4fbdbc7bdeb7c78a8703c3084ce068f6691 jdk8u131-b07
db221c0a423e776bec5c3198d11d3f26827bd786 jdk8u131-b08
56e71d16083904ceddfdd1d66312582a42781646 jdk8u131-b09
1da23ae49386608550596502d90a381ee6c1dfaa jdk8u131-b10
829ea9b92cda9545652f1b309f56c57383024ebb jdk8u131-b11
5aa8c4ca51f0e666d368a4f119ed734d3ac59d7c jdk8u122-b00 5aa8c4ca51f0e666d368a4f119ed734d3ac59d7c jdk8u122-b00
2198ef7e1c1702b3506b95b5d8c886ad5a12bbe5 jdk8u122-b01 2198ef7e1c1702b3506b95b5d8c886ad5a12bbe5 jdk8u122-b01
58d961f47dd4ee1d516512b7744e0f1fc83d8f52 jdk8u122-b02 58d961f47dd4ee1d516512b7744e0f1fc83d8f52 jdk8u122-b02
......
...@@ -1023,11 +1023,16 @@ void LIRGenerator::do_CheckCast(CheckCast* x) { ...@@ -1023,11 +1023,16 @@ void LIRGenerator::do_CheckCast(CheckCast* x) {
obj.load_item(); obj.load_item();
LIR_Opr out_reg = rlock_result(x); LIR_Opr out_reg = rlock_result(x);
CodeStub* stub; 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()) { if (x->is_incompatible_class_change_check()) {
assert(patching_info == NULL, "can't patch this"); assert(patching_info == NULL, "can't patch this");
stub = new SimpleExceptionStub(Runtime1::throw_incompatible_class_change_error_id, LIR_OprFact::illegalOpr, info_for_exception); 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);
} else { } else {
stub = new SimpleExceptionStub(Runtime1::throw_class_cast_exception_id, obj.result(), info_for_exception); stub = new SimpleExceptionStub(Runtime1::throw_class_cast_exception_id, obj.result(), info_for_exception);
} }
......
...@@ -1228,12 +1228,17 @@ void LIRGenerator::do_CheckCast(CheckCast* x) { ...@@ -1228,12 +1228,17 @@ void LIRGenerator::do_CheckCast(CheckCast* x) {
obj.load_item(); obj.load_item();
// info for exceptions // 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; CodeStub* stub;
if (x->is_incompatible_class_change_check()) { if (x->is_incompatible_class_change_check()) {
assert(patching_info == NULL, "can't patch this"); assert(patching_info == NULL, "can't patch this");
stub = new SimpleExceptionStub(Runtime1::throw_incompatible_class_change_error_id, LIR_OprFact::illegalOpr, info_for_exception); 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);
} else { } else {
stub = new SimpleExceptionStub(Runtime1::throw_class_cast_exception_id, obj.result(), info_for_exception); stub = new SimpleExceptionStub(Runtime1::throw_class_cast_exception_id, obj.result(), info_for_exception);
} }
......
/* /*
* Copyright (c) 1999, 2013, 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -57,6 +57,7 @@ class CodeStub: public CompilationResourceObj { ...@@ -57,6 +57,7 @@ class CodeStub: public CompilationResourceObj {
virtual bool is_exception_throw_stub() const { return false; } virtual bool is_exception_throw_stub() const { return false; }
virtual bool is_range_check_stub() const { return false; } virtual bool is_range_check_stub() const { return false; }
virtual bool is_divbyzero_stub() const { return false; } virtual bool is_divbyzero_stub() const { return false; }
virtual bool is_simple_exception_stub() const { return false; }
#ifndef PRODUCT #ifndef PRODUCT
virtual void print_name(outputStream* out) const = 0; virtual void print_name(outputStream* out) const = 0;
#endif #endif
...@@ -484,6 +485,7 @@ class SimpleExceptionStub: public CodeStub { ...@@ -484,6 +485,7 @@ class SimpleExceptionStub: public CodeStub {
virtual void emit_code(LIR_Assembler* e); virtual void emit_code(LIR_Assembler* e);
virtual CodeEmitInfo* info() const { return _info; } virtual CodeEmitInfo* info() const { return _info; }
virtual bool is_exception_throw_stub() const { return true; } virtual bool is_exception_throw_stub() const { return true; }
virtual bool is_simple_exception_stub() const { return true; }
virtual void visit(LIR_OpVisitState* visitor) { virtual void visit(LIR_OpVisitState* visitor) {
if (_obj->is_valid()) visitor->do_input(_obj); if (_obj->is_valid()) visitor->do_input(_obj);
visitor->do_slow_case(_info); visitor->do_slow_case(_info);
......
...@@ -1837,6 +1837,20 @@ void GraphBuilder::invoke(Bytecodes::Code code) { ...@@ -1837,6 +1837,20 @@ void GraphBuilder::invoke(Bytecodes::Code code) {
log->identify(target), log->identify(target),
Bytecodes::name(code)); 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 // Some methods are obviously bindable without any type checks so
// convert them directly to an invokespecial or invokestatic. // convert them directly to an invokespecial or invokestatic.
if (target->is_loaded() && !target->is_abstract() && target->can_be_statically_bound()) { if (target->is_loaded() && !target->is_abstract() && target->can_be_statically_bound()) {
......
...@@ -381,6 +381,7 @@ class Instruction: public CompilationResourceObj { ...@@ -381,6 +381,7 @@ class Instruction: public CompilationResourceObj {
UnorderedIsTrueFlag, UnorderedIsTrueFlag,
NeedsPatchingFlag, NeedsPatchingFlag,
ThrowIncompatibleClassChangeErrorFlag, ThrowIncompatibleClassChangeErrorFlag,
InvokeSpecialReceiverCheckFlag,
ProfileMDOFlag, ProfileMDOFlag,
IsLinkedInBlockFlag, IsLinkedInBlockFlag,
NeedsRangeCheckFlag, NeedsRangeCheckFlag,
...@@ -1456,6 +1457,16 @@ LEAF(CheckCast, TypeCheck) ...@@ -1456,6 +1457,16 @@ LEAF(CheckCast, TypeCheck)
bool is_incompatible_class_change_check() const { bool is_incompatible_class_change_check() const {
return check_flag(ThrowIncompatibleClassChangeErrorFlag); 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; ciType* declared_type() const;
}; };
......
/* /*
* Copyright (c) 1999, 2014, 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -58,6 +58,7 @@ ciInstanceKlass::ciInstanceKlass(KlassHandle h_k) : ...@@ -58,6 +58,7 @@ ciInstanceKlass::ciInstanceKlass(KlassHandle h_k) :
_nonstatic_field_size = ik->nonstatic_field_size(); _nonstatic_field_size = ik->nonstatic_field_size();
_has_nonstatic_fields = ik->has_nonstatic_fields(); _has_nonstatic_fields = ik->has_nonstatic_fields();
_has_default_methods = ik->has_default_methods(); _has_default_methods = ik->has_default_methods();
_is_anonymous = ik->is_anonymous();
_nonstatic_fields = NULL; // initialized lazily by compute_nonstatic_fields: _nonstatic_fields = NULL; // initialized lazily by compute_nonstatic_fields:
_implementor = NULL; // we will fill these lazily _implementor = NULL; // we will fill these lazily
...@@ -100,6 +101,7 @@ ciInstanceKlass::ciInstanceKlass(ciSymbol* name, ...@@ -100,6 +101,7 @@ ciInstanceKlass::ciInstanceKlass(ciSymbol* name,
_nonstatic_field_size = -1; _nonstatic_field_size = -1;
_has_nonstatic_fields = false; _has_nonstatic_fields = false;
_nonstatic_fields = NULL; _nonstatic_fields = NULL;
_is_anonymous = false;
_loader = loader; _loader = loader;
_protection_domain = protection_domain; _protection_domain = protection_domain;
_is_shared = false; _is_shared = false;
...@@ -591,6 +593,16 @@ ciInstanceKlass* ciInstanceKlass::implementor() { ...@@ -591,6 +593,16 @@ ciInstanceKlass* ciInstanceKlass::implementor() {
return impl; 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 // Utility class for printing of the contents of the static fields for
// use by compilation replay. It only prints out the information that // use by compilation replay. It only prints out the information that
// could be consumed by the compiler, so for primitive types it prints // could be consumed by the compiler, so for primitive types it prints
......
/* /*
* Copyright (c) 1999, 2013, 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -53,6 +53,7 @@ private: ...@@ -53,6 +53,7 @@ private:
bool _has_subklass; bool _has_subklass;
bool _has_nonstatic_fields; bool _has_nonstatic_fields;
bool _has_default_methods; bool _has_default_methods;
bool _is_anonymous;
ciFlags _flags; ciFlags _flags;
jint _nonstatic_field_size; jint _nonstatic_field_size;
...@@ -177,6 +178,10 @@ public: ...@@ -177,6 +178,10 @@ public:
return _has_default_methods; return _has_default_methods;
} }
bool is_anonymous() {
return _is_anonymous;
}
ciInstanceKlass* get_canonical_holder(int offset); ciInstanceKlass* get_canonical_holder(int offset);
ciField* get_field_by_offset(int field_offset, bool is_static); ciField* get_field_by_offset(int field_offset, bool is_static);
ciField* get_field_by_name(ciSymbol* name, ciSymbol* signature, bool is_static); ciField* get_field_by_name(ciSymbol* name, ciSymbol* signature, bool is_static);
...@@ -248,6 +253,8 @@ public: ...@@ -248,6 +253,8 @@ public:
return NULL; return NULL;
} }
ciInstanceKlass* host_klass();
// Dump the current state of this klass for compilation replay. // Dump the current state of this klass for compilation replay.
virtual void dump_replay_data(outputStream* out); virtual void dump_replay_data(outputStream* out);
}; };
......
/* /*
* Copyright (c) 1999, 2013, 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -947,6 +947,13 @@ bool ciMethod::is_compiled_lambda_form() const { ...@@ -947,6 +947,13 @@ bool ciMethod::is_compiled_lambda_form() const {
return iid == vmIntrinsics::_compiledLambdaForm; return iid == vmIntrinsics::_compiledLambdaForm;
} }
// ------------------------------------------------------------------
// ciMethod::is_object_initializer
//
bool ciMethod::is_object_initializer() const {
return name() == ciSymbol::object_initializer_name();
}
// ------------------------------------------------------------------ // ------------------------------------------------------------------
// ciMethod::has_member_arg // ciMethod::has_member_arg
// //
......
/* /*
* Copyright (c) 1999, 2013, 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -331,6 +331,7 @@ class ciMethod : public ciMetadata { ...@@ -331,6 +331,7 @@ class ciMethod : public ciMetadata {
bool can_be_statically_bound() const { return _can_be_statically_bound; } bool can_be_statically_bound() const { return _can_be_statically_bound; }
bool is_boxing_method() const; bool is_boxing_method() const;
bool is_unboxing_method() const; bool is_unboxing_method() const;
bool is_object_initializer() const;
// Replay data methods // Replay data methods
void dump_name_as_ascii(outputStream* st); void dump_name_as_ascii(outputStream* st);
......
...@@ -690,7 +690,8 @@ IRT_END ...@@ -690,7 +690,8 @@ IRT_END
IRT_ENTRY(void, InterpreterRuntime::resolve_invoke(JavaThread* thread, Bytecodes::Code bytecode)) { IRT_ENTRY(void, InterpreterRuntime::resolve_invoke(JavaThread* thread, Bytecodes::Code bytecode)) {
// extract receiver from the outgoing argument list if necessary // extract receiver from the outgoing argument list if necessary
Handle receiver(thread, NULL); Handle receiver(thread, NULL);
if (bytecode == Bytecodes::_invokevirtual || bytecode == Bytecodes::_invokeinterface) { if (bytecode == Bytecodes::_invokevirtual || bytecode == Bytecodes::_invokeinterface ||
bytecode == Bytecodes::_invokespecial) {
ResourceMark rm(thread); ResourceMark rm(thread);
methodHandle m (thread, method(thread)); methodHandle m (thread, method(thread));
Bytecode_invoke call(m, bci(thread)); Bytecode_invoke call(m, bci(thread));
...@@ -756,16 +757,25 @@ IRT_ENTRY(void, InterpreterRuntime::resolve_invoke(JavaThread* thread, Bytecodes ...@@ -756,16 +757,25 @@ IRT_ENTRY(void, InterpreterRuntime::resolve_invoke(JavaThread* thread, Bytecodes
int index = info.resolved_method()->itable_index(); int index = info.resolved_method()->itable_index();
assert(info.itable_index() == index, ""); assert(info.itable_index() == index, "");
} }
} else if (bytecode == Bytecodes::_invokespecial) {
assert(info.call_kind() == CallInfo::direct_call, "must be direct call");
} else { } else {
assert(info.call_kind() == CallInfo::direct_call || assert(info.call_kind() == CallInfo::direct_call ||
info.call_kind() == CallInfo::vtable_call, ""); info.call_kind() == CallInfo::vtable_call, "");
} }
#endif #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() ? InstanceKlass::cast(sender->host_klass()) : sender;
switch (info.call_kind()) { switch (info.call_kind()) {
case CallInfo::direct_call: case CallInfo::direct_call:
cache_entry(thread)->set_direct_call( cache_entry(thread)->set_direct_call(
bytecode, bytecode,
info.resolved_method()); info.resolved_method(),
sender->is_interface());
break; break;
case CallInfo::vtable_call: case CallInfo::vtable_call:
cache_entry(thread)->set_vtable_call( cache_entry(thread)->set_vtable_call(
......
...@@ -915,11 +915,11 @@ void LinkResolver::linktime_resolve_static_method(methodHandle& resolved_method, ...@@ -915,11 +915,11 @@ void LinkResolver::linktime_resolve_static_method(methodHandle& resolved_method,
} }
void LinkResolver::resolve_special_call(CallInfo& result, KlassHandle resolved_klass, Symbol* method_name, void LinkResolver::resolve_special_call(CallInfo& result, Handle recv, KlassHandle resolved_klass, Symbol* method_name,
Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS) { Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS) {
methodHandle resolved_method; methodHandle resolved_method;
linktime_resolve_special_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK); linktime_resolve_special_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK);
runtime_resolve_special_method(result, resolved_method, resolved_klass, current_klass, check_access, CHECK); runtime_resolve_special_method(result, resolved_method, resolved_klass, current_klass, recv, check_access, CHECK);
} }
// throws linktime exceptions // throws linktime exceptions
...@@ -1018,7 +1018,7 @@ void LinkResolver::linktime_resolve_special_method(methodHandle& resolved_method ...@@ -1018,7 +1018,7 @@ void LinkResolver::linktime_resolve_special_method(methodHandle& resolved_method
// throws runtime exceptions // throws runtime exceptions
void LinkResolver::runtime_resolve_special_method(CallInfo& result, methodHandle resolved_method, KlassHandle resolved_klass, void LinkResolver::runtime_resolve_special_method(CallInfo& result, methodHandle resolved_method, KlassHandle resolved_klass,
KlassHandle current_klass, bool check_access, TRAPS) { KlassHandle current_klass, Handle recv, bool check_access, TRAPS) {
// resolved method is selected method unless we have an old-style lookup // resolved method is selected method unless we have an old-style lookup
// for a superclass method // for a superclass method
...@@ -1026,21 +1026,19 @@ void LinkResolver::runtime_resolve_special_method(CallInfo& result, methodHandle ...@@ -1026,21 +1026,19 @@ void LinkResolver::runtime_resolve_special_method(CallInfo& result, methodHandle
// no checks for shadowing // no checks for shadowing
methodHandle sel_method(THREAD, resolved_method()); 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 && if (check_access &&
// check if the method is not <init>
resolved_method->name() != vmSymbols::object_initializer_name()) {
// 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 // 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 // b) check if the class of the resolved_klass is a superclass
// (not supertype in order to exclude interface classes) of the current class. // (not supertype in order to exclude interface classes) of the current class.
// This check is not performed for super.invoke for interface methods // This check is not performed for super.invoke for interface methods
// in super interfaces. // in super interfaces.
current_klass->is_subclass_of(resolved_klass()) && current_klass->is_subclass_of(resolved_klass()) &&
current_klass() != resolved_klass() && current_klass() != resolved_klass()) {
// c) check if the method is not <init>
resolved_method->name() != vmSymbols::object_initializer_name()) {
// Lookup super method // Lookup super method
KlassHandle super_klass(THREAD, current_klass->super()); KlassHandle super_klass(THREAD, current_klass->super());
lookup_instance_method_in_klasses(sel_method, super_klass, lookup_instance_method_in_klasses(sel_method, super_klass,
...@@ -1055,6 +1053,27 @@ void LinkResolver::runtime_resolve_special_method(CallInfo& result, methodHandle ...@@ -1055,6 +1053,27 @@ void LinkResolver::runtime_resolve_special_method(CallInfo& result, methodHandle
resolved_method->signature())); 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() ? InstanceKlass::cast(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 // check if not static
...@@ -1481,7 +1500,7 @@ methodHandle LinkResolver::resolve_special_call_or_null( ...@@ -1481,7 +1500,7 @@ methodHandle LinkResolver::resolve_special_call_or_null(
bool check_access) { bool check_access) {
EXCEPTION_MARK; EXCEPTION_MARK;
CallInfo info; CallInfo info;
resolve_special_call(info, resolved_klass, name, signature, current_klass, check_access, THREAD); resolve_special_call(info, Handle(), resolved_klass, name, signature, current_klass, check_access, THREAD);
if (HAS_PENDING_EXCEPTION) { if (HAS_PENDING_EXCEPTION) {
CLEAR_PENDING_EXCEPTION; CLEAR_PENDING_EXCEPTION;
return methodHandle(); return methodHandle();
...@@ -1497,7 +1516,7 @@ methodHandle LinkResolver::resolve_special_call_or_null( ...@@ -1497,7 +1516,7 @@ methodHandle LinkResolver::resolve_special_call_or_null(
void LinkResolver::resolve_invoke(CallInfo& result, Handle recv, constantPoolHandle pool, int index, Bytecodes::Code byte, TRAPS) { void LinkResolver::resolve_invoke(CallInfo& result, Handle recv, constantPoolHandle pool, int index, Bytecodes::Code byte, TRAPS) {
switch (byte) { switch (byte) {
case Bytecodes::_invokestatic : resolve_invokestatic (result, pool, index, CHECK); break; 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::_invokevirtual : resolve_invokevirtual (result, recv, pool, index, CHECK); break;
case Bytecodes::_invokehandle : resolve_invokehandle (result, pool, index, CHECK); break; case Bytecodes::_invokehandle : resolve_invokehandle (result, pool, index, CHECK); break;
case Bytecodes::_invokedynamic : resolve_invokedynamic (result, pool, index, CHECK); break; case Bytecodes::_invokedynamic : resolve_invokedynamic (result, pool, index, CHECK); break;
...@@ -1528,13 +1547,13 @@ void LinkResolver::resolve_invokestatic(CallInfo& result, constantPoolHandle poo ...@@ -1528,13 +1547,13 @@ void LinkResolver::resolve_invokestatic(CallInfo& result, constantPoolHandle poo
} }
void LinkResolver::resolve_invokespecial(CallInfo& result, constantPoolHandle pool, int index, TRAPS) { void LinkResolver::resolve_invokespecial(CallInfo& result, Handle recv, constantPoolHandle pool, int index, TRAPS) {
KlassHandle resolved_klass; KlassHandle resolved_klass;
Symbol* method_name = NULL; Symbol* method_name = NULL;
Symbol* method_signature = NULL; Symbol* method_signature = NULL;
KlassHandle current_klass; KlassHandle current_klass;
resolve_pool(resolved_klass, method_name, method_signature, current_klass, pool, index, CHECK); resolve_pool(resolved_klass, method_name, method_signature, current_klass, pool, index, CHECK);
resolve_special_call(result, resolved_klass, method_name, method_signature, current_klass, true, CHECK); resolve_special_call(result, recv, resolved_klass, method_name, method_signature, current_klass, true, CHECK);
} }
......
/* /*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -142,7 +142,7 @@ class LinkResolver: AllStatic { ...@@ -142,7 +142,7 @@ class LinkResolver: AllStatic {
static void linktime_resolve_virtual_method (methodHandle &resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature,KlassHandle current_klass, bool check_access, TRAPS); static void linktime_resolve_virtual_method (methodHandle &resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature,KlassHandle current_klass, bool check_access, TRAPS);
static void linktime_resolve_interface_method (methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS); static void linktime_resolve_interface_method (methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS);
static void runtime_resolve_special_method (CallInfo& result, methodHandle resolved_method, KlassHandle resolved_klass, KlassHandle current_klass, bool check_access, TRAPS); static void runtime_resolve_special_method (CallInfo& result, methodHandle resolved_method, KlassHandle resolved_klass, KlassHandle current_klass, Handle recv, bool check_access, TRAPS);
static void runtime_resolve_virtual_method (CallInfo& result, methodHandle resolved_method, KlassHandle resolved_klass, Handle recv, KlassHandle recv_klass, bool check_null_and_abstract, TRAPS); static void runtime_resolve_virtual_method (CallInfo& result, methodHandle resolved_method, KlassHandle resolved_klass, Handle recv, KlassHandle recv_klass, bool check_null_and_abstract, TRAPS);
static void runtime_resolve_interface_method (CallInfo& result, methodHandle resolved_method, KlassHandle resolved_klass, Handle recv, KlassHandle recv_klass, bool check_null_and_abstract, TRAPS); static void runtime_resolve_interface_method (CallInfo& result, methodHandle resolved_method, KlassHandle resolved_klass, Handle recv, KlassHandle recv_klass, bool check_null_and_abstract, TRAPS);
...@@ -173,7 +173,7 @@ class LinkResolver: AllStatic { ...@@ -173,7 +173,7 @@ class LinkResolver: AllStatic {
// resolved_klass = specified class (i.e., static receiver class) // resolved_klass = specified class (i.e., static receiver class)
// current_klass = sending method holder (i.e., class containing the method containing the call being resolved) // current_klass = sending method holder (i.e., class containing the method containing the call being resolved)
static void resolve_static_call (CallInfo& result, KlassHandle& resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, bool initialize_klass, TRAPS); static void resolve_static_call (CallInfo& result, KlassHandle& resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, bool initialize_klass, TRAPS);
static void resolve_special_call (CallInfo& result, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS); static void resolve_special_call (CallInfo& result, Handle recv, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS);
static void resolve_virtual_call (CallInfo& result, Handle recv, KlassHandle recv_klass, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, bool check_null_and_abstract, TRAPS); static void resolve_virtual_call (CallInfo& result, Handle recv, KlassHandle recv_klass, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, bool check_null_and_abstract, TRAPS);
static void resolve_interface_call(CallInfo& result, Handle recv, KlassHandle recv_klass, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, bool check_null_and_abstract, TRAPS); static void resolve_interface_call(CallInfo& result, Handle recv, KlassHandle recv_klass, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, bool check_null_and_abstract, TRAPS);
static void resolve_handle_call (CallInfo& result, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, TRAPS); static void resolve_handle_call (CallInfo& result, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, TRAPS);
...@@ -196,7 +196,7 @@ class LinkResolver: AllStatic { ...@@ -196,7 +196,7 @@ class LinkResolver: AllStatic {
// runtime resolving from constant pool // runtime resolving from constant pool
static void resolve_invokestatic (CallInfo& result, constantPoolHandle pool, int index, TRAPS); static void resolve_invokestatic (CallInfo& result, constantPoolHandle pool, int index, TRAPS);
static void resolve_invokespecial (CallInfo& result, constantPoolHandle pool, int index, TRAPS); static void resolve_invokespecial (CallInfo& result, Handle recv, constantPoolHandle pool, int index, TRAPS);
static void resolve_invokevirtual (CallInfo& result, Handle recv, constantPoolHandle pool, int index, TRAPS); static void resolve_invokevirtual (CallInfo& result, Handle recv, constantPoolHandle pool, int index, TRAPS);
static void resolve_invokeinterface(CallInfo& result, Handle recv, constantPoolHandle pool, int index, TRAPS); static void resolve_invokeinterface(CallInfo& result, Handle recv, constantPoolHandle pool, int index, TRAPS);
static void resolve_invokedynamic (CallInfo& result, constantPoolHandle pool, int index, TRAPS); static void resolve_invokedynamic (CallInfo& result, constantPoolHandle pool, int index, TRAPS);
......
/* /*
* Copyright (c) 1998, 2015, 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -144,7 +144,8 @@ void ConstantPoolCacheEntry::set_parameter_size(int value) { ...@@ -144,7 +144,8 @@ void ConstantPoolCacheEntry::set_parameter_size(int value) {
void ConstantPoolCacheEntry::set_direct_or_vtable_call(Bytecodes::Code invoke_code, void ConstantPoolCacheEntry::set_direct_or_vtable_call(Bytecodes::Code invoke_code,
methodHandle method, 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 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->interpreter_entry() != NULL, "should have been set at this point");
assert(!method->is_obsolete(), "attempt to write obsolete method to cpCache"); assert(!method->is_obsolete(), "attempt to write obsolete method to cpCache");
...@@ -208,7 +209,13 @@ void ConstantPoolCacheEntry::set_direct_or_vtable_call(Bytecodes::Code invoke_co ...@@ -208,7 +209,13 @@ void ConstantPoolCacheEntry::set_direct_or_vtable_call(Bytecodes::Code invoke_co
if (byte_no == 1) { if (byte_no == 1) {
assert(invoke_code != Bytecodes::_invokevirtual && assert(invoke_code != Bytecodes::_invokevirtual &&
invoke_code != Bytecodes::_invokeinterface, ""); 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); set_bytecode_1(invoke_code);
}
} else if (byte_no == 2) { } else if (byte_no == 2) {
if (change_to_virtual) { if (change_to_virtual) {
assert(invoke_code == Bytecodes::_invokeinterface, ""); assert(invoke_code == Bytecodes::_invokeinterface, "");
...@@ -238,17 +245,18 @@ void ConstantPoolCacheEntry::set_direct_or_vtable_call(Bytecodes::Code invoke_co ...@@ -238,17 +245,18 @@ void ConstantPoolCacheEntry::set_direct_or_vtable_call(Bytecodes::Code invoke_co
NOT_PRODUCT(verify(tty)); 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; int index = Method::nonvirtual_vtable_index;
// index < 0; FIXME: inline and customize set_direct_or_vtable_call // 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) { 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 // 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), ""); assert(method->method_holder()->is_interface() || method->method_holder()->verify_vtable_index(index), "");
// index >= 0; FIXME: inline and customize set_direct_or_vtable_call // 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, methodHandle method, int index) { void ConstantPoolCacheEntry::set_itable_call(Bytecodes::Code invoke_code, methodHandle method, int index) {
......
...@@ -229,13 +229,15 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC { ...@@ -229,13 +229,15 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC {
void set_direct_or_vtable_call( void set_direct_or_vtable_call(
Bytecodes::Code invoke_code, // the bytecode used for invoking the method Bytecodes::Code invoke_code, // the bytecode used for invoking the method
methodHandle method, // the method/prototype if any (NULL, otherwise) 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: public:
void set_direct_call( // sets entry to exact concrete method entry void set_direct_call( // sets entry to exact concrete method entry
Bytecodes::Code invoke_code, // the bytecode used for invoking the method 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 void set_vtable_call( // sets entry to vtable index
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -483,6 +483,30 @@ void Parse::do_call() { ...@@ -483,6 +483,30 @@ void Parse::do_call() {
speculative_receiver_type = receiver_type != NULL ? receiver_type->speculative_type() : NULL; 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. // Note: It's OK to try to inline a virtual call.
// The call generator will not attempt to inline a polymorphic call // The call generator will not attempt to inline a polymorphic call
// unless it knows how to optimize the receiver dispatch. // unless it knows how to optimize the receiver dispatch.
......
/* /*
* Copyright (c) 2008, 2014, 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -673,7 +673,7 @@ Handle MethodHandles::resolve_MemberName(Handle mname, KlassHandle caller, TRAPS ...@@ -673,7 +673,7 @@ Handle MethodHandles::resolve_MemberName(Handle mname, KlassHandle caller, TRAPS
defc, name, type, caller, THREAD); defc, name, type, caller, THREAD);
} else if (ref_kind == JVM_REF_invokeSpecial) { } else if (ref_kind == JVM_REF_invokeSpecial) {
LinkResolver::resolve_special_call(result, LinkResolver::resolve_special_call(result,
defc, name, type, caller, caller.not_null(), THREAD); Handle(), defc, name, type, caller, caller.not_null(), THREAD);
} else if (ref_kind == JVM_REF_invokeVirtual) { } else if (ref_kind == JVM_REF_invokeVirtual) {
LinkResolver::resolve_virtual_call(result, Handle(), defc, LinkResolver::resolve_virtual_call(result, Handle(), defc,
defc, name, type, caller, caller.not_null(), false, THREAD); defc, name, type, caller, caller.not_null(), false, THREAD);
...@@ -700,7 +700,7 @@ Handle MethodHandles::resolve_MemberName(Handle mname, KlassHandle caller, TRAPS ...@@ -700,7 +700,7 @@ Handle MethodHandles::resolve_MemberName(Handle mname, KlassHandle caller, TRAPS
assert(!HAS_PENDING_EXCEPTION, ""); assert(!HAS_PENDING_EXCEPTION, "");
if (name == vmSymbols::object_initializer_name()) { if (name == vmSymbols::object_initializer_name()) {
LinkResolver::resolve_special_call(result, LinkResolver::resolve_special_call(result,
defc, name, type, caller, caller.not_null(), THREAD); Handle(), defc, name, type, caller, caller.not_null(), THREAD);
} else { } else {
break; // will throw after end of switch break; // will throw after end of switch
} }
......
/* /*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -231,7 +231,7 @@ void JavaCalls::call_virtual(JavaValue* result, Handle receiver, KlassHandle spe ...@@ -231,7 +231,7 @@ void JavaCalls::call_virtual(JavaValue* result, Handle receiver, KlassHandle spe
void JavaCalls::call_special(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS) { void JavaCalls::call_special(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS) {
CallInfo callinfo; CallInfo callinfo;
LinkResolver::resolve_special_call(callinfo, klass, name, signature, KlassHandle(), false, CHECK); LinkResolver::resolve_special_call(callinfo, args->receiver(), klass, name, signature, KlassHandle(), false, CHECK);
methodHandle method = callinfo.selected_method(); methodHandle method = callinfo.selected_method();
assert(method.not_null(), "should have thrown exception"); assert(method.not_null(), "should have thrown exception");
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册