305 // 1 - flattened or not flattened
306 // 2 - if not flattened: argument is buffered (value) or in heap (value and objects)
307 if (cp_entry->is_flattened()) {
308 Klass* field_k = vklass->get_value_field_klass(field_index);
309 ValueKlass* field_vk = ValueKlass::cast(field_k);
310 oop vt_oop = *(oop*)f.interpreter_frame_expression_stack_at(tos_idx);
311 assert(vt_oop != NULL && oopDesc::is_oop(vt_oop) && vt_oop->is_value(),"argument must be a value type");
312 assert(field_vk == vt_oop->klass(), "Must match");
313 field_vk->value_store(field_vk->data_for_oop(vt_oop),
314 ((char*)(oopDesc*)new_value_h()) + field_offset, in_heap, false);
315 } else { // not flattened
316 oop voop = *(oop*)f.interpreter_frame_expression_stack_at(tos_idx);
317 assert(voop != NULL || !cp_entry->is_flattenable(),
318 "NULL checks for non flattenable fields must have been performed in interpreter assembly template");
319 assert(voop == NULL || oopDesc::is_oop(voop),"checking argument");
320 if (VTBuffer::is_in_vt_buffer(voop)) {
321 // new value field is currently allocated in a TLVB, a heap allocated
322 // copy must be created because a field must never point to a TLVB allocated value
323 Handle voop_h = Handle(THREAD, voop);
324 ValueKlass* field_vk = ValueKlass::cast(voop->klass());
325 assert(field_vk == vklass->get_value_field_klass(field_index), "Sanity check");
326 instanceOop field_copy = field_vk->allocate_instance(CHECK_((type2size[field_type]) * AbstractInterpreter::stackElementSize));
327 Handle field_copy_h = Handle(THREAD, field_copy);
328 field_vk->value_store(field_vk->data_for_oop(voop_h()), field_vk->data_for_oop(field_copy_h()), true, false);
329 if (in_heap) {
330 new_value_h()->obj_field_put(field_offset, field_copy_h());
331 } else {
332 new_value_h()->obj_field_put_raw(field_offset, field_copy_h());
333 }
334 } else { // not buffered
335 if (in_heap) {
336 new_value_h()->obj_field_put(field_offset, voop);
337 } else {
338 new_value_h()->obj_field_put_raw(field_offset, voop);
339 }
340 }
341 }
342 } else { // not T_OBJECT nor T_ARRAY
343 intptr_t* addr = f.interpreter_frame_expression_stack_at(tos_idx);
344 copy_primitive_argument(addr, new_value_h, field_offset, field_type);
345 }
476 }
477 IRT_END
478
479 IRT_ENTRY(void, InterpreterRuntime::newarray(JavaThread* thread, BasicType type, jint size))
480 oop obj = oopFactory::new_typeArray(type, size, CHECK);
481 thread->set_vm_result(obj);
482 IRT_END
483
484
485 IRT_ENTRY(void, InterpreterRuntime::anewarray(JavaThread* thread, ConstantPool* pool, int index, jint size))
486 Klass* klass = pool->klass_at(index, CHECK);
487 if (klass->is_value()) { // Logically creates elements, ensure klass init
488 klass->initialize(CHECK);
489 }
490 arrayOop obj = oopFactory::new_array(klass, size, CHECK);
491 thread->set_vm_result(obj);
492 IRT_END
493
494 IRT_ENTRY(void, InterpreterRuntime::value_array_load(JavaThread* thread, arrayOopDesc* array, int index))
495 Klass* klass = array->klass();
496 assert(klass->is_valueArray_klass() || klass->is_objArray_klass(), "expected value or object array oop");
497
498 if (klass->is_objArray_klass()) {
499 thread->set_vm_result(((objArrayOop) array)->obj_at(index));
500 } else {
501 ValueArrayKlass* vaklass = ValueArrayKlass::cast(klass);
502 ValueKlass* vklass = vaklass->element_klass();
503 arrayHandle ah(THREAD, array);
504 bool in_heap;
505 instanceOop value_holder = vklass->allocate_buffered_or_heap_instance(&in_heap, CHECK);
506 void* src = ((valueArrayOop)ah())->value_at_addr(index, vaklass->layout_helper());
507 vklass->value_store(src, vklass->data_for_oop(value_holder),
508 vaklass->element_byte_size(), in_heap, false);
509 thread->set_vm_result(value_holder);
510 }
511 IRT_END
512
513 IRT_ENTRY(void, InterpreterRuntime::value_array_store(JavaThread* thread, arrayOopDesc* array, int index, void* val))
514 Klass* klass = array->klass();
515 assert(klass->is_valueArray_klass() || klass->is_objArray_klass(), "expected value or object array oop");
516 Handle array_h(THREAD, array);
517
518 if (ArrayKlass::cast(klass)->element_klass() != ((oop)val)->klass()) {
519 THROW(vmSymbols::java_lang_ArrayStoreException());
520 }
521 if (klass->is_objArray_klass()) {
522 if(VTBuffer::is_in_vt_buffer(val)) {
523 // A Java heap allocated copy must be made because an array cannot
524 // reference a thread-local buffered value
525 Handle val_h(THREAD, (oop)val);
526 ObjArrayKlass* aklass = ObjArrayKlass::cast(klass);
527 Klass* eklass = aklass->element_klass();
528 assert(eklass->is_value(), "Sanity check");
529 assert(eklass == ((oop)val)->klass(), "Sanity check");
530 ValueKlass* vklass = ValueKlass::cast(eklass);
531 // allocate heap instance
532 instanceOop res = vklass->allocate_instance(CHECK);
533 Handle res_h(THREAD, res);
534 // copy value
535 vklass->value_store(((char*)(oopDesc*)val_h()) + vklass->first_field_offset(),
536 ((char*)(oopDesc*)res_h()) + vklass->first_field_offset(),true, false);
537 val = res_h();
538 }
539 ((objArrayOop) array_h())->obj_at_put(index, (oop)val);
540 } else {
541 valueArrayOop varray = (valueArrayOop)array;
542 ValueArrayKlass* vaklass = ValueArrayKlass::cast(klass);
543 ValueKlass* vklass = vaklass->element_klass();
544 const int lh = vaklass->layout_helper();
545 vklass->value_store(vklass->data_for_oop((oop)val), varray->value_at_addr(index, lh),
546 vaklass->element_byte_size(), true, false);
547 }
548 IRT_END
549
550 IRT_ENTRY(void, InterpreterRuntime::multianewarray(JavaThread* thread, jint* first_size_address))
551 // We may want to pass in more arguments - could make this slightly faster
552 LastFrameAccessor last_frame(thread);
553 ConstantPool* constants = last_frame.method()->constants();
554 int i = last_frame.get_index_u2(Bytecodes::_multianewarray);
555 Klass* klass = constants->klass_at(i, CHECK);
556 int nof_dims = last_frame.number_of_dimensions();
557 assert(klass->is_klass(), "not a class");
558 assert(nof_dims >= 1, "multianewarray rank must be nonzero");
559
560 if (klass->is_value()) { // Logically creates elements, ensure klass init
561 klass->initialize(CHECK);
562 }
563
564 // We must create an array of jints to pass to multi_allocate.
565 ResourceMark rm(thread);
566 const int small_dims = 10;
567 jint dim_array[small_dims];
568 jint *dims = &dim_array[0];
569 if (nof_dims > small_dims) {
570 dims = (jint*) NEW_RESOURCE_ARRAY(jint, nof_dims);
571 }
572 for (int index = 0; index < nof_dims; index++) {
573 // offset from first_size_address is addressed as local[index]
574 int n = Interpreter::local_offset_in_bytes(index)/jintSize;
575 dims[index] = first_size_address[n];
576 }
577 oop obj = ArrayKlass::cast(klass)->multi_allocate(nof_dims, dims, CHECK);
578 thread->set_vm_result(obj);
579 IRT_END
580
581 IRT_LEAF(void, InterpreterRuntime::recycle_vtbuffer(void* alloc_ptr))
582 JavaThread* thread = (JavaThread*)Thread::current();
583 VTBuffer::recycle_vtbuffer(thread, alloc_ptr);
584 IRT_END
585
586 IRT_ENTRY(void, InterpreterRuntime::recycle_buffered_values(JavaThread* thread))
587 frame f = thread->last_frame();
588 assert(f.is_interpreted_frame(), "recycling can only be triggered from interpreted frames");
589 VTBuffer::recycle_vt_in_frame(thread, &f);
590 IRT_END
591
592 IRT_ENTRY(void, InterpreterRuntime::fix_frame_vt_alloc_ptr(JavaThread* thread))
593 frame f = thread->last_frame();
594 VTBuffer::fix_frame_vt_alloc_ptr(f, VTBufferChunk::chunk(thread->vt_alloc_ptr()));
595 IRT_END
596
597 IRT_ENTRY(void, InterpreterRuntime::return_value(JavaThread* thread, oopDesc* obj))
598 assert(VTBuffer::is_in_vt_buffer(obj), "Must only be called for buffered values");
|
305 // 1 - flattened or not flattened
306 // 2 - if not flattened: argument is buffered (value) or in heap (value and objects)
307 if (cp_entry->is_flattened()) {
308 Klass* field_k = vklass->get_value_field_klass(field_index);
309 ValueKlass* field_vk = ValueKlass::cast(field_k);
310 oop vt_oop = *(oop*)f.interpreter_frame_expression_stack_at(tos_idx);
311 assert(vt_oop != NULL && oopDesc::is_oop(vt_oop) && vt_oop->is_value(),"argument must be a value type");
312 assert(field_vk == vt_oop->klass(), "Must match");
313 field_vk->value_store(field_vk->data_for_oop(vt_oop),
314 ((char*)(oopDesc*)new_value_h()) + field_offset, in_heap, false);
315 } else { // not flattened
316 oop voop = *(oop*)f.interpreter_frame_expression_stack_at(tos_idx);
317 assert(voop != NULL || !cp_entry->is_flattenable(),
318 "NULL checks for non flattenable fields must have been performed in interpreter assembly template");
319 assert(voop == NULL || oopDesc::is_oop(voop),"checking argument");
320 if (VTBuffer::is_in_vt_buffer(voop)) {
321 // new value field is currently allocated in a TLVB, a heap allocated
322 // copy must be created because a field must never point to a TLVB allocated value
323 Handle voop_h = Handle(THREAD, voop);
324 ValueKlass* field_vk = ValueKlass::cast(voop->klass());
325 assert(!cp_entry->is_flattenable() || field_vk == vklass->get_value_field_klass(field_index), "Sanity check");
326 instanceOop field_copy = field_vk->allocate_instance(CHECK_((type2size[field_type]) * AbstractInterpreter::stackElementSize));
327 Handle field_copy_h = Handle(THREAD, field_copy);
328 field_vk->value_store(field_vk->data_for_oop(voop_h()), field_vk->data_for_oop(field_copy_h()), true, false);
329 if (in_heap) {
330 new_value_h()->obj_field_put(field_offset, field_copy_h());
331 } else {
332 new_value_h()->obj_field_put_raw(field_offset, field_copy_h());
333 }
334 } else { // not buffered
335 if (in_heap) {
336 new_value_h()->obj_field_put(field_offset, voop);
337 } else {
338 new_value_h()->obj_field_put_raw(field_offset, voop);
339 }
340 }
341 }
342 } else { // not T_OBJECT nor T_ARRAY
343 intptr_t* addr = f.interpreter_frame_expression_stack_at(tos_idx);
344 copy_primitive_argument(addr, new_value_h, field_offset, field_type);
345 }
476 }
477 IRT_END
478
479 IRT_ENTRY(void, InterpreterRuntime::newarray(JavaThread* thread, BasicType type, jint size))
480 oop obj = oopFactory::new_typeArray(type, size, CHECK);
481 thread->set_vm_result(obj);
482 IRT_END
483
484
485 IRT_ENTRY(void, InterpreterRuntime::anewarray(JavaThread* thread, ConstantPool* pool, int index, jint size))
486 Klass* klass = pool->klass_at(index, CHECK);
487 if (klass->is_value()) { // Logically creates elements, ensure klass init
488 klass->initialize(CHECK);
489 }
490 arrayOop obj = oopFactory::new_array(klass, size, CHECK);
491 thread->set_vm_result(obj);
492 IRT_END
493
494 IRT_ENTRY(void, InterpreterRuntime::value_array_load(JavaThread* thread, arrayOopDesc* array, int index))
495 Klass* klass = array->klass();
496 assert(klass->is_valueArray_klass(), "expected value or object array oop");
497
498 ValueArrayKlass* vaklass = ValueArrayKlass::cast(klass);
499 ValueKlass* vklass = vaklass->element_klass();
500 arrayHandle ah(THREAD, array);
501 bool in_heap;
502 instanceOop value_holder = vklass->allocate_buffered_or_heap_instance(&in_heap, CHECK);
503 void* src = ((valueArrayOop)ah())->value_at_addr(index, vaklass->layout_helper());
504 vklass->value_store(src, vklass->data_for_oop(value_holder),
505 vaklass->element_byte_size(), in_heap, false);
506 thread->set_vm_result(value_holder);
507 IRT_END
508
509 IRT_ENTRY(void, InterpreterRuntime::value_array_store(JavaThread* thread, void* val, arrayOopDesc* array, int index))
510 assert(val != NULL, "can't store null into flat array");
511 Klass* klass = array->klass();
512 assert(klass->is_valueArray_klass(), "expected value array");
513 assert(ArrayKlass::cast(klass)->element_klass() == ((oop)val)->klass(), "Store type incorrect");
514
515 valueArrayOop varray = (valueArrayOop)array;
516 ValueArrayKlass* vaklass = ValueArrayKlass::cast(klass);
517 ValueKlass* vklass = vaklass->element_klass();
518 const int lh = vaklass->layout_helper();
519 vklass->value_store(vklass->data_for_oop((oop)val), varray->value_at_addr(index, lh),
520 vaklass->element_byte_size(), true, false);
521 IRT_END
522
523 IRT_ENTRY(void, InterpreterRuntime::multianewarray(JavaThread* thread, jint* first_size_address))
524 // We may want to pass in more arguments - could make this slightly faster
525 LastFrameAccessor last_frame(thread);
526 ConstantPool* constants = last_frame.method()->constants();
527 int i = last_frame.get_index_u2(Bytecodes::_multianewarray);
528 Klass* klass = constants->klass_at(i, CHECK);
529 int nof_dims = last_frame.number_of_dimensions();
530 assert(klass->is_klass(), "not a class");
531 assert(nof_dims >= 1, "multianewarray rank must be nonzero");
532
533 if (klass->is_value()) { // Logically creates elements, ensure klass init
534 klass->initialize(CHECK);
535 }
536
537 // We must create an array of jints to pass to multi_allocate.
538 ResourceMark rm(thread);
539 const int small_dims = 10;
540 jint dim_array[small_dims];
541 jint *dims = &dim_array[0];
542 if (nof_dims > small_dims) {
543 dims = (jint*) NEW_RESOURCE_ARRAY(jint, nof_dims);
544 }
545 for (int index = 0; index < nof_dims; index++) {
546 // offset from first_size_address is addressed as local[index]
547 int n = Interpreter::local_offset_in_bytes(index)/jintSize;
548 dims[index] = first_size_address[n];
549 }
550 oop obj = ArrayKlass::cast(klass)->multi_allocate(nof_dims, dims, CHECK);
551 thread->set_vm_result(obj);
552 IRT_END
553
554 IRT_ENTRY(void, InterpreterRuntime::value_heap_copy(JavaThread* thread, oopDesc* value))
555 assert(VTBuffer::is_in_vt_buffer(value), "Must only be called for buffered values");
556 ValueKlass* vk = ValueKlass::cast(value->klass());
557 Handle val_h(THREAD, value);
558 instanceOop obj = vk->allocate_instance(CHECK);
559 Handle obj_h(THREAD, obj);
560 vk->value_store(vk->data_for_oop(val_h()), vk->data_for_oop(obj_h()), true, false);
561 thread->set_vm_result(obj_h());
562 IRT_END
563
564 IRT_LEAF(void, InterpreterRuntime::recycle_vtbuffer(void* alloc_ptr))
565 JavaThread* thread = (JavaThread*)Thread::current();
566 VTBuffer::recycle_vtbuffer(thread, alloc_ptr);
567 IRT_END
568
569 IRT_ENTRY(void, InterpreterRuntime::recycle_buffered_values(JavaThread* thread))
570 frame f = thread->last_frame();
571 assert(f.is_interpreted_frame(), "recycling can only be triggered from interpreted frames");
572 VTBuffer::recycle_vt_in_frame(thread, &f);
573 IRT_END
574
575 IRT_ENTRY(void, InterpreterRuntime::fix_frame_vt_alloc_ptr(JavaThread* thread))
576 frame f = thread->last_frame();
577 VTBuffer::fix_frame_vt_alloc_ptr(f, VTBufferChunk::chunk(thread->vt_alloc_ptr()));
578 IRT_END
579
580 IRT_ENTRY(void, InterpreterRuntime::return_value(JavaThread* thread, oopDesc* obj))
581 assert(VTBuffer::is_in_vt_buffer(obj), "Must only be called for buffered values");
|