209 } |
209 } |
210 |
210 |
211 return error; |
211 return error; |
212 } |
212 } |
213 |
213 |
|
214 /* |
|
215 * Delete saved global references - if any - for: |
|
216 * - a potentially thrown Exception |
|
217 * - a returned refernce/array value |
|
218 * See invoker_doInvoke() and invoke* methods where global references |
|
219 * are being saved. |
|
220 */ |
|
221 static void |
|
222 deletePotentiallySavedGlobalRefs(JNIEnv *env, InvokeRequest *request) |
|
223 { |
|
224 /* Delete potentially saved return value */ |
|
225 if ((request->invokeType == INVOKE_CONSTRUCTOR) || |
|
226 (returnTypeTag(request->methodSignature) == JDWP_TAG(OBJECT)) || |
|
227 (returnTypeTag(request->methodSignature) == JDWP_TAG(ARRAY))) { |
|
228 if (request->returnValue.l != NULL) { |
|
229 tossGlobalRef(env, &(request->returnValue.l)); |
|
230 } |
|
231 } |
|
232 /* Delete potentially saved exception */ |
|
233 if (request->exception != NULL) { |
|
234 tossGlobalRef(env, &(request->exception)); |
|
235 } |
|
236 } |
|
237 |
|
238 /* |
|
239 * Delete global argument references from the request which got put there before a |
|
240 * invoke request was carried out. See fillInvokeRequest(). |
|
241 */ |
|
242 static void |
|
243 deleteGlobalArgumentRefs(JNIEnv *env, InvokeRequest *request) |
|
244 { |
|
245 void *cursor; |
|
246 jint argIndex = 0; |
|
247 jvalue *argument = request->arguments; |
|
248 jbyte argumentTag = firstArgumentTypeTag(request->methodSignature, &cursor); |
|
249 |
|
250 if (request->clazz != NULL) { |
|
251 tossGlobalRef(env, &(request->clazz)); |
|
252 } |
|
253 if (request->instance != NULL) { |
|
254 tossGlobalRef(env, &(request->instance)); |
|
255 } |
|
256 /* Delete global argument references */ |
|
257 while (argIndex < request->argumentCount) { |
|
258 if ((argumentTag == JDWP_TAG(OBJECT)) || |
|
259 (argumentTag == JDWP_TAG(ARRAY))) { |
|
260 if (argument->l != NULL) { |
|
261 tossGlobalRef(env, &(argument->l)); |
|
262 } |
|
263 } |
|
264 argument++; |
|
265 argIndex++; |
|
266 argumentTag = nextArgumentTypeTag(&cursor); |
|
267 } |
|
268 } |
|
269 |
214 static jvmtiError |
270 static jvmtiError |
215 fillInvokeRequest(JNIEnv *env, InvokeRequest *request, |
271 fillInvokeRequest(JNIEnv *env, InvokeRequest *request, |
216 jbyte invokeType, jbyte options, jint id, |
272 jbyte invokeType, jbyte options, jint id, |
217 jthread thread, jclass clazz, jmethodID method, |
273 jthread thread, jclass clazz, jmethodID method, |
218 jobject instance, |
274 jobject instance, |
320 |
376 |
321 static void |
377 static void |
322 invokeConstructor(JNIEnv *env, InvokeRequest *request) |
378 invokeConstructor(JNIEnv *env, InvokeRequest *request) |
323 { |
379 { |
324 jobject object; |
380 jobject object; |
|
381 |
|
382 JDI_ASSERT_MSG(request->clazz, "Request clazz null"); |
325 object = JNI_FUNC_PTR(env,NewObjectA)(env, request->clazz, |
383 object = JNI_FUNC_PTR(env,NewObjectA)(env, request->clazz, |
326 request->method, |
384 request->method, |
327 request->arguments); |
385 request->arguments); |
328 request->returnValue.l = NULL; |
386 request->returnValue.l = NULL; |
329 if (object != NULL) { |
387 if (object != NULL) { |
336 { |
394 { |
337 switch(returnTypeTag(request->methodSignature)) { |
395 switch(returnTypeTag(request->methodSignature)) { |
338 case JDWP_TAG(OBJECT): |
396 case JDWP_TAG(OBJECT): |
339 case JDWP_TAG(ARRAY): { |
397 case JDWP_TAG(ARRAY): { |
340 jobject object; |
398 jobject object; |
|
399 JDI_ASSERT_MSG(request->clazz, "Request clazz null"); |
341 object = JNI_FUNC_PTR(env,CallStaticObjectMethodA)(env, |
400 object = JNI_FUNC_PTR(env,CallStaticObjectMethodA)(env, |
342 request->clazz, |
401 request->clazz, |
343 request->method, |
402 request->method, |
344 request->arguments); |
403 request->arguments); |
345 request->returnValue.l = NULL; |
404 request->returnValue.l = NULL; |
424 { |
483 { |
425 switch(returnTypeTag(request->methodSignature)) { |
484 switch(returnTypeTag(request->methodSignature)) { |
426 case JDWP_TAG(OBJECT): |
485 case JDWP_TAG(OBJECT): |
427 case JDWP_TAG(ARRAY): { |
486 case JDWP_TAG(ARRAY): { |
428 jobject object; |
487 jobject object; |
|
488 JDI_ASSERT_MSG(request->instance, "Request instance null"); |
429 object = JNI_FUNC_PTR(env,CallObjectMethodA)(env, |
489 object = JNI_FUNC_PTR(env,CallObjectMethodA)(env, |
430 request->instance, |
490 request->instance, |
431 request->method, |
491 request->method, |
432 request->arguments); |
492 request->arguments); |
433 request->returnValue.l = NULL; |
493 request->returnValue.l = NULL; |
511 { |
571 { |
512 switch(returnTypeTag(request->methodSignature)) { |
572 switch(returnTypeTag(request->methodSignature)) { |
513 case JDWP_TAG(OBJECT): |
573 case JDWP_TAG(OBJECT): |
514 case JDWP_TAG(ARRAY): { |
574 case JDWP_TAG(ARRAY): { |
515 jobject object; |
575 jobject object; |
|
576 JDI_ASSERT_MSG(request->clazz, "Request clazz null"); |
|
577 JDI_ASSERT_MSG(request->instance, "Request instance null"); |
516 object = JNI_FUNC_PTR(env,CallNonvirtualObjectMethodA)(env, |
578 object = JNI_FUNC_PTR(env,CallNonvirtualObjectMethodA)(env, |
517 request->instance, |
579 request->instance, |
518 request->clazz, |
580 request->clazz, |
519 request->method, |
581 request->method, |
520 request->arguments); |
582 request->arguments); |
637 |
704 |
638 jobject exception; |
705 jobject exception; |
639 |
706 |
640 JNI_FUNC_PTR(env,ExceptionClear)(env); |
707 JNI_FUNC_PTR(env,ExceptionClear)(env); |
641 |
708 |
642 switch (request->invokeType) { |
709 switch (invokeType) { |
643 case INVOKE_CONSTRUCTOR: |
710 case INVOKE_CONSTRUCTOR: |
644 invokeConstructor(env, request); |
711 invokeConstructor(env, request); |
645 break; |
712 break; |
646 case INVOKE_STATIC: |
713 case INVOKE_STATIC: |
647 invokeStatic(env, request); |
714 invokeStatic(env, request); |
648 break; |
715 break; |
649 case INVOKE_INSTANCE: |
716 case INVOKE_INSTANCE: |
650 if (request->options & JDWP_INVOKE_OPTIONS(NONVIRTUAL) ) { |
717 if (options & JDWP_INVOKE_OPTIONS(NONVIRTUAL) ) { |
651 invokeNonvirtual(env, request); |
718 invokeNonvirtual(env, request); |
652 } else { |
719 } else { |
653 invokeVirtual(env, request); |
720 invokeVirtual(env, request); |
654 } |
721 } |
655 break; |
722 break; |
723 exc = request->exception; |
790 exc = request->exception; |
724 returnValue = request->returnValue; |
791 returnValue = request->returnValue; |
725 } |
792 } |
726 |
793 |
727 /* |
794 /* |
|
795 * At this time, there's no need to retain global references on |
|
796 * arguments since the reply is processed. No one will deal with |
|
797 * this request ID anymore, so we must call deleteGlobalArgumentRefs(). |
|
798 * |
|
799 * We cannot delete saved exception or return value references |
|
800 * since otherwise a deleted handle would escape when writing |
|
801 * the response to the stream. Instead, we clean those refs up |
|
802 * after writing the respone. |
|
803 */ |
|
804 deleteGlobalArgumentRefs(env, request); |
|
805 |
|
806 /* |
728 * Give up the lock before I/O operation |
807 * Give up the lock before I/O operation |
729 */ |
808 */ |
730 debugMonitorExit(invokerLock); |
809 debugMonitorExit(invokerLock); |
731 eventHandler_unlock(); |
810 eventHandler_unlock(); |
732 |
|
733 |
811 |
734 if (!detached) { |
812 if (!detached) { |
735 outStream_initReply(&out, id); |
813 outStream_initReply(&out, id); |
736 (void)outStream_writeValue(env, &out, tag, returnValue); |
814 (void)outStream_writeValue(env, &out, tag, returnValue); |
737 (void)outStream_writeObjectTag(env, &out, exc); |
815 (void)outStream_writeObjectTag(env, &out, exc); |
738 (void)outStream_writeObjectRef(env, &out, exc); |
816 (void)outStream_writeObjectRef(env, &out, exc); |
739 outStream_sendReply(&out); |
817 outStream_sendReply(&out); |
740 } |
818 } |
|
819 |
|
820 /* |
|
821 * Delete potentially saved global references of return value |
|
822 * and exception |
|
823 */ |
|
824 eventHandler_lock(); // for proper lock order |
|
825 debugMonitorEnter(invokerLock); |
|
826 deletePotentiallySavedGlobalRefs(env, request); |
|
827 debugMonitorExit(invokerLock); |
|
828 eventHandler_unlock(); |
741 } |
829 } |
742 |
830 |
743 jboolean |
831 jboolean |
744 invoker_isEnabled(jthread thread) |
832 invoker_isEnabled(jthread thread) |
745 { |
833 { |