< prev index next >
src/share/vm/oops/valueKlass.cpp
Print this page
*** 24,33 ****
--- 24,34 ----
#include "precompiled.hpp"
#include "gc/shared/gcLocker.inline.hpp"
#include "interpreter/interpreter.hpp"
#include "logging/log.hpp"
+ #include "memory/metadataFactory.hpp"
#include "oops/oop.inline.hpp"
#include "oops/fieldStreams.hpp"
#include "oops/method.hpp"
#include "oops/objArrayKlass.hpp"
#include "oops/valueKlass.hpp"
*** 340,469 ****
}
assert(sig_extended.at(0)._bt == T_VALUETYPE && sig_extended.at(sig_extended.length()-1)._bt == T_VOID, "broken structure");
return sig_extended;
}
! // Returns the basic types and registers for fields to return an
! // instance of this value type in registers if possible.
! GrowableArray<SigEntry> ValueKlass::return_convention(VMRegPair*& regs, int& nb_fields) const {
! assert(ValueTypeReturnedAsFields, "inconsistent");
const GrowableArray<SigEntry>& sig_vk = collect_fields();
! nb_fields = SigEntry::count_fields(sig_vk)+1;
BasicType* sig_bt = NEW_RESOURCE_ARRAY(BasicType, nb_fields);
sig_bt[0] = T_METADATA;
SigEntry::fill_sig_bt(sig_vk, sig_bt+1, nb_fields-1, true);
! regs = NEW_RESOURCE_ARRAY(VMRegPair, nb_fields);
int total = SharedRuntime::java_return_convention(sig_bt, regs, nb_fields);
! if (total <= 0) {
! regs = NULL;
}
-
- return sig_vk;
}
// Create handles for all oop fields returned in registers that are
// going to be live across a safepoint.
bool ValueKlass::save_oop_results(RegisterMap& reg_map, GrowableArray<Handle>& handles) const {
if (ValueTypeReturnedAsFields) {
! int nb_fields;
! VMRegPair* regs;
! const GrowableArray<SigEntry>& sig_vk = return_convention(regs, nb_fields);
!
! if (regs != NULL) {
! regs++;
! nb_fields--;
! save_oop_fields(sig_vk, reg_map, regs, handles, nb_fields);
return true;
}
}
return false;
}
// Same as above but with pre-computed return convention
! void ValueKlass::save_oop_fields(const GrowableArray<SigEntry>& sig_vk, RegisterMap& reg_map, const VMRegPair* regs, GrowableArray<Handle>& handles, int nb_fields) const {
! int j = 0;
Thread* thread = Thread::current();
! for (int i = 0; i < sig_vk.length(); i++) {
! BasicType bt = sig_vk.at(i)._bt;
if (bt == T_OBJECT || bt == T_ARRAY) {
! int off = sig_vk.at(i)._offset;
! VMRegPair pair = regs[j];
address loc = reg_map.location(pair.first());
oop v = *(oop*)loc;
assert(v == NULL || v->is_oop(), "not an oop?");
assert(Universe::heap()->is_in_or_null(v), "must be heap pointer");
handles.push(Handle(thread, v));
}
if (bt == T_VALUETYPE) {
continue;
}
if (bt == T_VOID &&
! sig_vk.at(i-1)._bt != T_LONG &&
! sig_vk.at(i-1)._bt != T_DOUBLE) {
continue;
}
j++;
}
! assert(j == nb_fields, "missed a field?");
}
// Update oop fields in registers from handles after a safepoint
void ValueKlass::restore_oop_results(RegisterMap& reg_map, GrowableArray<Handle>& handles) const {
assert(ValueTypeReturnedAsFields, "inconsistent");
! int nb_fields;
! VMRegPair* regs;
! const GrowableArray<SigEntry>& sig_vk = return_convention(regs, nb_fields);
assert(regs != NULL, "inconsistent");
! regs++;
! nb_fields--;
!
! int j = 0;
! for (int i = 0, k = 0; i < sig_vk.length(); i++) {
! BasicType bt = sig_vk.at(i)._bt;
if (bt == T_OBJECT || bt == T_ARRAY) {
! int off = sig_vk.at(i)._offset;
! VMRegPair pair = regs[j];
address loc = reg_map.location(pair.first());
*(oop*)loc = handles.at(k++)();
}
if (bt == T_VALUETYPE) {
continue;
}
if (bt == T_VOID &&
! sig_vk.at(i-1)._bt != T_LONG &&
! sig_vk.at(i-1)._bt != T_DOUBLE) {
continue;
}
j++;
}
! assert(j == nb_fields, "missed a field?");
}
// Fields are in registers. Create an instance of the value type and
// initialize it with the values of the fields.
! oop ValueKlass::realloc_result(const GrowableArray<SigEntry>& sig_vk, const RegisterMap& reg_map, const VMRegPair* regs,
! const GrowableArray<Handle>& handles, int nb_fields, TRAPS) {
oop new_vt = allocate_instance(CHECK_NULL);
! int j = 0;
int k = 0;
! for (int i = 0; i < sig_vk.length(); i++) {
! BasicType bt = sig_vk.at(i)._bt;
if (bt == T_VALUETYPE) {
continue;
}
if (bt == T_VOID) {
! if (sig_vk.at(i-1)._bt == T_LONG ||
! sig_vk.at(i-1)._bt == T_DOUBLE) {
j++;
}
continue;
}
! int off = sig_vk.at(i)._offset;
! VMRegPair pair = regs[j];
address loc = reg_map.location(pair.first());
switch(bt) {
case T_BOOLEAN: {
jboolean v = *(intptr_t*)loc;
*(jboolean*)((address)new_vt + off) = v;
--- 341,473 ----
}
assert(sig_extended.at(0)._bt == T_VALUETYPE && sig_extended.at(sig_extended.length()-1)._bt == T_VOID, "broken structure");
return sig_extended;
}
! void ValueKlass::initialize_calling_convention() {
! Thread* THREAD = Thread::current();
! assert(!HAS_PENDING_EXCEPTION, "should have no exception");
! ResourceMark rm;
const GrowableArray<SigEntry>& sig_vk = collect_fields();
! int nb_fields = SigEntry::count_fields(sig_vk)+1;
! Array<SigEntry>* extended_sig = MetadataFactory::new_array<SigEntry>(class_loader_data(), sig_vk.length(), CHECK_AND_CLEAR);
! *((Array<SigEntry>**)adr_extended_sig()) = extended_sig;
! for (int i = 0; i < sig_vk.length(); i++ ) {
! extended_sig->at_put(i, sig_vk.at(i));
! }
!
BasicType* sig_bt = NEW_RESOURCE_ARRAY(BasicType, nb_fields);
sig_bt[0] = T_METADATA;
SigEntry::fill_sig_bt(sig_vk, sig_bt+1, nb_fields-1, true);
! VMRegPair* regs = NEW_RESOURCE_ARRAY(VMRegPair, nb_fields);
int total = SharedRuntime::java_return_convention(sig_bt, regs, nb_fields);
! if (total > 0) {
! Array<VMRegPair>* return_regs = MetadataFactory::new_array<VMRegPair>(class_loader_data(), nb_fields, CHECK_AND_CLEAR);
! *((Array<VMRegPair>**)adr_return_regs()) = return_regs;
! for (int i = 0; i < nb_fields; i++ ) {
! return_regs->at_put(i, regs[i]);
! }
}
}
// Create handles for all oop fields returned in registers that are
// going to be live across a safepoint.
bool ValueKlass::save_oop_results(RegisterMap& reg_map, GrowableArray<Handle>& handles) const {
if (ValueTypeReturnedAsFields) {
! if (return_regs() != NULL) {
! save_oop_fields(reg_map, handles);
return true;
}
}
return false;
}
// Same as above but with pre-computed return convention
! void ValueKlass::save_oop_fields(const RegisterMap& reg_map, GrowableArray<Handle>& handles) const {
Thread* thread = Thread::current();
! const Array<SigEntry>* sig_vk = extended_sig();
! const Array<VMRegPair>* regs = return_regs();
! int j = 1;
!
! for (int i = 0; i < sig_vk->length(); i++) {
! BasicType bt = sig_vk->at(i)._bt;
if (bt == T_OBJECT || bt == T_ARRAY) {
! int off = sig_vk->at(i)._offset;
! VMRegPair pair = regs->at(j);
address loc = reg_map.location(pair.first());
oop v = *(oop*)loc;
assert(v == NULL || v->is_oop(), "not an oop?");
assert(Universe::heap()->is_in_or_null(v), "must be heap pointer");
handles.push(Handle(thread, v));
}
if (bt == T_VALUETYPE) {
continue;
}
if (bt == T_VOID &&
! sig_vk->at(i-1)._bt != T_LONG &&
! sig_vk->at(i-1)._bt != T_DOUBLE) {
continue;
}
j++;
}
! assert(j == regs->length(), "missed a field?");
}
// Update oop fields in registers from handles after a safepoint
void ValueKlass::restore_oop_results(RegisterMap& reg_map, GrowableArray<Handle>& handles) const {
assert(ValueTypeReturnedAsFields, "inconsistent");
! const Array<SigEntry>* sig_vk = extended_sig();
! const Array<VMRegPair>* regs = return_regs();
assert(regs != NULL, "inconsistent");
! int j = 1;
! for (int i = 0, k = 0; i < sig_vk->length(); i++) {
! BasicType bt = sig_vk->at(i)._bt;
if (bt == T_OBJECT || bt == T_ARRAY) {
! int off = sig_vk->at(i)._offset;
! VMRegPair pair = regs->at(j);
address loc = reg_map.location(pair.first());
*(oop*)loc = handles.at(k++)();
}
if (bt == T_VALUETYPE) {
continue;
}
if (bt == T_VOID &&
! sig_vk->at(i-1)._bt != T_LONG &&
! sig_vk->at(i-1)._bt != T_DOUBLE) {
continue;
}
j++;
}
! assert(j == regs->length(), "");
}
// Fields are in registers. Create an instance of the value type and
// initialize it with the values of the fields.
! oop ValueKlass::realloc_result(const RegisterMap& reg_map, const GrowableArray<Handle>& handles, TRAPS) {
oop new_vt = allocate_instance(CHECK_NULL);
! const Array<SigEntry>* sig_vk = extended_sig();
! const Array<VMRegPair>* regs = return_regs();
!
! int j = 1;
int k = 0;
! for (int i = 0; i < sig_vk->length(); i++) {
! BasicType bt = sig_vk->at(i)._bt;
if (bt == T_VALUETYPE) {
continue;
}
if (bt == T_VOID) {
! if (sig_vk->at(i-1)._bt == T_LONG ||
! sig_vk->at(i-1)._bt == T_DOUBLE) {
j++;
}
continue;
}
! int off = sig_vk->at(i)._offset;
! VMRegPair pair = regs->at(j);
address loc = reg_map.location(pair.first());
switch(bt) {
case T_BOOLEAN: {
jboolean v = *(intptr_t*)loc;
*(jboolean*)((address)new_vt + off) = v;
*** 524,534 ****
default:
ShouldNotReachHere();
}
j++;
}
! assert(j == nb_fields, "missed a field?");
assert(k == handles.length(), "missed an oop?");
return new_vt;
}
ValueKlass* ValueKlass::returned_value_type(const RegisterMap& map) {
--- 528,538 ----
default:
ShouldNotReachHere();
}
j++;
}
! assert(j == regs->length(), "missed a field?");
assert(k == handles.length(), "missed an oop?");
return new_vt;
}
ValueKlass* ValueKlass::returned_value_type(const RegisterMap& map) {
*** 537,551 ****
int nb = SharedRuntime::java_return_convention(&bt, &pair, 1);
assert(nb == 1, "broken");
address loc = map.location(pair.first());
intptr_t ptr = *(intptr_t*)loc;
! if (Metaspace::contains((void*)ptr)) {
return (ValueKlass*)ptr;
}
return NULL;
- // if (Universe::heap()->is_in_reserved((void*)ptr)) {
- // return NULL;
- // }
- // return (ValueKlass*)ptr;
}
--- 541,553 ----
int nb = SharedRuntime::java_return_convention(&bt, &pair, 1);
assert(nb == 1, "broken");
address loc = map.location(pair.first());
intptr_t ptr = *(intptr_t*)loc;
! if ((ptr & 1) != 0) {
! ptr = ptr & ~1L;
! assert(Metaspace::contains((void*)ptr), "should be klass");
return (ValueKlass*)ptr;
}
return NULL;
}
< prev index next >