9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include "precompiled.hpp"
26 #include "gc/shared/gcLocker.inline.hpp"
27 #include "interpreter/interpreter.hpp"
28 #include "logging/log.hpp"
29 #include "oops/oop.inline.hpp"
30 #include "oops/fieldStreams.hpp"
31 #include "oops/method.hpp"
32 #include "oops/objArrayKlass.hpp"
33 #include "oops/valueKlass.hpp"
34 #include "oops/valueArrayKlass.hpp"
35 #include "runtime/signature.hpp"
36 #include "utilities/copy.hpp"
37
38 int ValueKlass::first_field_offset() const {
39 #ifdef ASSERT
40 int first_offset = INT_MAX;
41 for (JavaFieldStream fs(this); !fs.done(); fs.next()) {
42 if (fs.offset() < first_offset) first_offset= fs.offset();
43 }
44 #endif
45 int base_offset = instanceOopDesc::base_offset_in_bytes();
46 // The first field of value types is aligned on a long boundary
47 base_offset = align_size_up(base_offset, BytesPerLong);
48 assert(base_offset == first_offset, "inconsistent offsets");
325 THREAD);
326 assert(klass != NULL && !HAS_PENDING_EXCEPTION, "lookup shouldn't fail");
327 const GrowableArray<SigEntry>& embedded = ValueKlass::cast(klass)->collect_fields(offset);
328 sig_extended.appendAll(&embedded);
329 } else {
330 sig_extended.push(SigEntry(bt, offset));
331 if (bt == T_LONG || bt == T_DOUBLE) {
332 sig_extended.push(SigEntry(T_VOID, offset));
333 }
334 }
335 }
336 int offset = base_off + size_helper()*HeapWordSize - (base_off > 0 ? first_field_offset() : 0);
337 sig_extended.push(SigEntry(T_VOID, offset)); // hack: use T_VOID to mark end of value type fields
338 if (base_off == 0) {
339 sig_extended.sort(SigEntry::compare);
340 }
341 assert(sig_extended.at(0)._bt == T_VALUETYPE && sig_extended.at(sig_extended.length()-1)._bt == T_VOID, "broken structure");
342 return sig_extended;
343 }
344
345 // Returns the basic types and registers for fields to return an
346 // instance of this value type in registers if possible.
347 GrowableArray<SigEntry> ValueKlass::return_convention(VMRegPair*& regs, int& nb_fields) const {
348 assert(ValueTypeReturnedAsFields, "inconsistent");
349 const GrowableArray<SigEntry>& sig_vk = collect_fields();
350 nb_fields = SigEntry::count_fields(sig_vk)+1;
351 BasicType* sig_bt = NEW_RESOURCE_ARRAY(BasicType, nb_fields);
352 sig_bt[0] = T_METADATA;
353 SigEntry::fill_sig_bt(sig_vk, sig_bt+1, nb_fields-1, true);
354 regs = NEW_RESOURCE_ARRAY(VMRegPair, nb_fields);
355 int total = SharedRuntime::java_return_convention(sig_bt, regs, nb_fields);
356
357 if (total <= 0) {
358 regs = NULL;
359 }
360
361 return sig_vk;
362 }
363
364 // Create handles for all oop fields returned in registers that are
365 // going to be live across a safepoint.
366 bool ValueKlass::save_oop_results(RegisterMap& reg_map, GrowableArray<Handle>& handles) const {
367 if (ValueTypeReturnedAsFields) {
368 int nb_fields;
369 VMRegPair* regs;
370 const GrowableArray<SigEntry>& sig_vk = return_convention(regs, nb_fields);
371
372 if (regs != NULL) {
373 regs++;
374 nb_fields--;
375 save_oop_fields(sig_vk, reg_map, regs, handles, nb_fields);
376 return true;
377 }
378 }
379 return false;
380 }
381
382 // Same as above but with pre-computed return convention
383 void ValueKlass::save_oop_fields(const GrowableArray<SigEntry>& sig_vk, RegisterMap& reg_map, const VMRegPair* regs, GrowableArray<Handle>& handles, int nb_fields) const {
384 int j = 0;
385 Thread* thread = Thread::current();
386 for (int i = 0; i < sig_vk.length(); i++) {
387 BasicType bt = sig_vk.at(i)._bt;
388 if (bt == T_OBJECT || bt == T_ARRAY) {
389 int off = sig_vk.at(i)._offset;
390 VMRegPair pair = regs[j];
391 address loc = reg_map.location(pair.first());
392 oop v = *(oop*)loc;
393 assert(v == NULL || v->is_oop(), "not an oop?");
394 assert(Universe::heap()->is_in_or_null(v), "must be heap pointer");
395 handles.push(Handle(thread, v));
396 }
397 if (bt == T_VALUETYPE) {
398 continue;
399 }
400 if (bt == T_VOID &&
401 sig_vk.at(i-1)._bt != T_LONG &&
402 sig_vk.at(i-1)._bt != T_DOUBLE) {
403 continue;
404 }
405 j++;
406 }
407 assert(j == nb_fields, "missed a field?");
408 }
409
410 // Update oop fields in registers from handles after a safepoint
411 void ValueKlass::restore_oop_results(RegisterMap& reg_map, GrowableArray<Handle>& handles) const {
412 assert(ValueTypeReturnedAsFields, "inconsistent");
413 int nb_fields;
414 VMRegPair* regs;
415 const GrowableArray<SigEntry>& sig_vk = return_convention(regs, nb_fields);
416 assert(regs != NULL, "inconsistent");
417
418 regs++;
419 nb_fields--;
420
421 int j = 0;
422 for (int i = 0, k = 0; i < sig_vk.length(); i++) {
423 BasicType bt = sig_vk.at(i)._bt;
424 if (bt == T_OBJECT || bt == T_ARRAY) {
425 int off = sig_vk.at(i)._offset;
426 VMRegPair pair = regs[j];
427 address loc = reg_map.location(pair.first());
428 *(oop*)loc = handles.at(k++)();
429 }
430 if (bt == T_VALUETYPE) {
431 continue;
432 }
433 if (bt == T_VOID &&
434 sig_vk.at(i-1)._bt != T_LONG &&
435 sig_vk.at(i-1)._bt != T_DOUBLE) {
436 continue;
437 }
438 j++;
439 }
440 assert(j == nb_fields, "missed a field?");
441 }
442
443 // Fields are in registers. Create an instance of the value type and
444 // initialize it with the values of the fields.
445 oop ValueKlass::realloc_result(const GrowableArray<SigEntry>& sig_vk, const RegisterMap& reg_map, const VMRegPair* regs,
446 const GrowableArray<Handle>& handles, int nb_fields, TRAPS) {
447 oop new_vt = allocate_instance(CHECK_NULL);
448
449 int j = 0;
450 int k = 0;
451 for (int i = 0; i < sig_vk.length(); i++) {
452 BasicType bt = sig_vk.at(i)._bt;
453 if (bt == T_VALUETYPE) {
454 continue;
455 }
456 if (bt == T_VOID) {
457 if (sig_vk.at(i-1)._bt == T_LONG ||
458 sig_vk.at(i-1)._bt == T_DOUBLE) {
459 j++;
460 }
461 continue;
462 }
463 int off = sig_vk.at(i)._offset;
464 VMRegPair pair = regs[j];
465 address loc = reg_map.location(pair.first());
466 switch(bt) {
467 case T_BOOLEAN: {
468 jboolean v = *(intptr_t*)loc;
469 *(jboolean*)((address)new_vt + off) = v;
470 break;
471 }
472 case T_CHAR: {
473 jchar v = *(intptr_t*)loc;
474 *(jchar*)((address)new_vt + off) = v;
475 break;
476 }
477 case T_BYTE: {
478 jbyte v = *(intptr_t*)loc;
479 *(jbyte*)((address)new_vt + off) = v;
480 break;
481 }
482 case T_SHORT: {
483 jshort v = *(intptr_t*)loc;
484 *(jshort*)((address)new_vt + off) = v;
509 narrowOop* p = (narrowOop*)((address)new_vt + off);
510 oopDesc::encode_store_heap_oop(p, v);
511 }
512 break;
513 }
514 case T_FLOAT: {
515 jfloat v = *(jfloat*)loc;
516 *(jfloat*)((address)new_vt + off) = v;
517 break;
518 }
519 case T_DOUBLE: {
520 jdouble v = *(jdouble*)loc;
521 *(jdouble*)((address)new_vt + off) = v;
522 break;
523 }
524 default:
525 ShouldNotReachHere();
526 }
527 j++;
528 }
529 assert(j == nb_fields, "missed a field?");
530 assert(k == handles.length(), "missed an oop?");
531 return new_vt;
532 }
533
534 ValueKlass* ValueKlass::returned_value_type(const RegisterMap& map) {
535 BasicType bt = T_METADATA;
536 VMRegPair pair;
537 int nb = SharedRuntime::java_return_convention(&bt, &pair, 1);
538 assert(nb == 1, "broken");
539
540 address loc = map.location(pair.first());
541 intptr_t ptr = *(intptr_t*)loc;
542 if (Metaspace::contains((void*)ptr)) {
543 return (ValueKlass*)ptr;
544 }
545 return NULL;
546 // if (Universe::heap()->is_in_reserved((void*)ptr)) {
547 // return NULL;
548 // }
549 // return (ValueKlass*)ptr;
550 }
551
|
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include "precompiled.hpp"
26 #include "gc/shared/gcLocker.inline.hpp"
27 #include "interpreter/interpreter.hpp"
28 #include "logging/log.hpp"
29 #include "memory/metadataFactory.hpp"
30 #include "oops/oop.inline.hpp"
31 #include "oops/fieldStreams.hpp"
32 #include "oops/method.hpp"
33 #include "oops/objArrayKlass.hpp"
34 #include "oops/valueKlass.hpp"
35 #include "oops/valueArrayKlass.hpp"
36 #include "runtime/signature.hpp"
37 #include "utilities/copy.hpp"
38
39 int ValueKlass::first_field_offset() const {
40 #ifdef ASSERT
41 int first_offset = INT_MAX;
42 for (JavaFieldStream fs(this); !fs.done(); fs.next()) {
43 if (fs.offset() < first_offset) first_offset= fs.offset();
44 }
45 #endif
46 int base_offset = instanceOopDesc::base_offset_in_bytes();
47 // The first field of value types is aligned on a long boundary
48 base_offset = align_size_up(base_offset, BytesPerLong);
49 assert(base_offset == first_offset, "inconsistent offsets");
326 THREAD);
327 assert(klass != NULL && !HAS_PENDING_EXCEPTION, "lookup shouldn't fail");
328 const GrowableArray<SigEntry>& embedded = ValueKlass::cast(klass)->collect_fields(offset);
329 sig_extended.appendAll(&embedded);
330 } else {
331 sig_extended.push(SigEntry(bt, offset));
332 if (bt == T_LONG || bt == T_DOUBLE) {
333 sig_extended.push(SigEntry(T_VOID, offset));
334 }
335 }
336 }
337 int offset = base_off + size_helper()*HeapWordSize - (base_off > 0 ? first_field_offset() : 0);
338 sig_extended.push(SigEntry(T_VOID, offset)); // hack: use T_VOID to mark end of value type fields
339 if (base_off == 0) {
340 sig_extended.sort(SigEntry::compare);
341 }
342 assert(sig_extended.at(0)._bt == T_VALUETYPE && sig_extended.at(sig_extended.length()-1)._bt == T_VOID, "broken structure");
343 return sig_extended;
344 }
345
346 void ValueKlass::initialize_calling_convention() {
347 Thread* THREAD = Thread::current();
348 assert(!HAS_PENDING_EXCEPTION, "should have no exception");
349 ResourceMark rm;
350 const GrowableArray<SigEntry>& sig_vk = collect_fields();
351 int nb_fields = SigEntry::count_fields(sig_vk)+1;
352 Array<SigEntry>* extended_sig = MetadataFactory::new_array<SigEntry>(class_loader_data(), sig_vk.length(), CHECK_AND_CLEAR);
353 *((Array<SigEntry>**)adr_extended_sig()) = extended_sig;
354 for (int i = 0; i < sig_vk.length(); i++ ) {
355 extended_sig->at_put(i, sig_vk.at(i));
356 }
357
358 BasicType* sig_bt = NEW_RESOURCE_ARRAY(BasicType, nb_fields);
359 sig_bt[0] = T_METADATA;
360 SigEntry::fill_sig_bt(sig_vk, sig_bt+1, nb_fields-1, true);
361 VMRegPair* regs = NEW_RESOURCE_ARRAY(VMRegPair, nb_fields);
362 int total = SharedRuntime::java_return_convention(sig_bt, regs, nb_fields);
363
364 if (total > 0) {
365 Array<VMRegPair>* return_regs = MetadataFactory::new_array<VMRegPair>(class_loader_data(), nb_fields, CHECK_AND_CLEAR);
366 *((Array<VMRegPair>**)adr_return_regs()) = return_regs;
367 for (int i = 0; i < nb_fields; i++ ) {
368 return_regs->at_put(i, regs[i]);
369 }
370 }
371 }
372
373 // Create handles for all oop fields returned in registers that are
374 // going to be live across a safepoint.
375 bool ValueKlass::save_oop_results(RegisterMap& reg_map, GrowableArray<Handle>& handles) const {
376 if (ValueTypeReturnedAsFields) {
377 if (return_regs() != NULL) {
378 save_oop_fields(reg_map, handles);
379 return true;
380 }
381 }
382 return false;
383 }
384
385 // Same as above but with pre-computed return convention
386 void ValueKlass::save_oop_fields(const RegisterMap& reg_map, GrowableArray<Handle>& handles) const {
387 Thread* thread = Thread::current();
388 const Array<SigEntry>* sig_vk = extended_sig();
389 const Array<VMRegPair>* regs = return_regs();
390 int j = 1;
391
392 for (int i = 0; i < sig_vk->length(); i++) {
393 BasicType bt = sig_vk->at(i)._bt;
394 if (bt == T_OBJECT || bt == T_ARRAY) {
395 int off = sig_vk->at(i)._offset;
396 VMRegPair pair = regs->at(j);
397 address loc = reg_map.location(pair.first());
398 oop v = *(oop*)loc;
399 assert(v == NULL || v->is_oop(), "not an oop?");
400 assert(Universe::heap()->is_in_or_null(v), "must be heap pointer");
401 handles.push(Handle(thread, v));
402 }
403 if (bt == T_VALUETYPE) {
404 continue;
405 }
406 if (bt == T_VOID &&
407 sig_vk->at(i-1)._bt != T_LONG &&
408 sig_vk->at(i-1)._bt != T_DOUBLE) {
409 continue;
410 }
411 j++;
412 }
413 assert(j == regs->length(), "missed a field?");
414 }
415
416 // Update oop fields in registers from handles after a safepoint
417 void ValueKlass::restore_oop_results(RegisterMap& reg_map, GrowableArray<Handle>& handles) const {
418 assert(ValueTypeReturnedAsFields, "inconsistent");
419 const Array<SigEntry>* sig_vk = extended_sig();
420 const Array<VMRegPair>* regs = return_regs();
421 assert(regs != NULL, "inconsistent");
422
423 int j = 1;
424 for (int i = 0, k = 0; i < sig_vk->length(); i++) {
425 BasicType bt = sig_vk->at(i)._bt;
426 if (bt == T_OBJECT || bt == T_ARRAY) {
427 int off = sig_vk->at(i)._offset;
428 VMRegPair pair = regs->at(j);
429 address loc = reg_map.location(pair.first());
430 *(oop*)loc = handles.at(k++)();
431 }
432 if (bt == T_VALUETYPE) {
433 continue;
434 }
435 if (bt == T_VOID &&
436 sig_vk->at(i-1)._bt != T_LONG &&
437 sig_vk->at(i-1)._bt != T_DOUBLE) {
438 continue;
439 }
440 j++;
441 }
442 assert(j == regs->length(), "");
443 }
444
445 // Fields are in registers. Create an instance of the value type and
446 // initialize it with the values of the fields.
447 oop ValueKlass::realloc_result(const RegisterMap& reg_map, const GrowableArray<Handle>& handles, TRAPS) {
448 oop new_vt = allocate_instance(CHECK_NULL);
449
450 const Array<SigEntry>* sig_vk = extended_sig();
451 const Array<VMRegPair>* regs = return_regs();
452
453 int j = 1;
454 int k = 0;
455 for (int i = 0; i < sig_vk->length(); i++) {
456 BasicType bt = sig_vk->at(i)._bt;
457 if (bt == T_VALUETYPE) {
458 continue;
459 }
460 if (bt == T_VOID) {
461 if (sig_vk->at(i-1)._bt == T_LONG ||
462 sig_vk->at(i-1)._bt == T_DOUBLE) {
463 j++;
464 }
465 continue;
466 }
467 int off = sig_vk->at(i)._offset;
468 VMRegPair pair = regs->at(j);
469 address loc = reg_map.location(pair.first());
470 switch(bt) {
471 case T_BOOLEAN: {
472 jboolean v = *(intptr_t*)loc;
473 *(jboolean*)((address)new_vt + off) = v;
474 break;
475 }
476 case T_CHAR: {
477 jchar v = *(intptr_t*)loc;
478 *(jchar*)((address)new_vt + off) = v;
479 break;
480 }
481 case T_BYTE: {
482 jbyte v = *(intptr_t*)loc;
483 *(jbyte*)((address)new_vt + off) = v;
484 break;
485 }
486 case T_SHORT: {
487 jshort v = *(intptr_t*)loc;
488 *(jshort*)((address)new_vt + off) = v;
513 narrowOop* p = (narrowOop*)((address)new_vt + off);
514 oopDesc::encode_store_heap_oop(p, v);
515 }
516 break;
517 }
518 case T_FLOAT: {
519 jfloat v = *(jfloat*)loc;
520 *(jfloat*)((address)new_vt + off) = v;
521 break;
522 }
523 case T_DOUBLE: {
524 jdouble v = *(jdouble*)loc;
525 *(jdouble*)((address)new_vt + off) = v;
526 break;
527 }
528 default:
529 ShouldNotReachHere();
530 }
531 j++;
532 }
533 assert(j == regs->length(), "missed a field?");
534 assert(k == handles.length(), "missed an oop?");
535 return new_vt;
536 }
537
538 ValueKlass* ValueKlass::returned_value_type(const RegisterMap& map) {
539 BasicType bt = T_METADATA;
540 VMRegPair pair;
541 int nb = SharedRuntime::java_return_convention(&bt, &pair, 1);
542 assert(nb == 1, "broken");
543
544 address loc = map.location(pair.first());
545 intptr_t ptr = *(intptr_t*)loc;
546 if ((ptr & 1) != 0) {
547 ptr = ptr & ~1L;
548 assert(Metaspace::contains((void*)ptr), "should be klass");
549 return (ValueKlass*)ptr;
550 }
551 return NULL;
552 }
553
|