00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 # include "incls/_precompiled.incl"
00025 # include "incls/_callBack.cpp.incl"
00026 
00027 void callBack::initialize(oop receiver, symbolOop selector) {
00028   assert(selector->is_symbol(), "must be symbol");
00029   Universe::set_callBack(receiver, selector);
00030 }
00031 
00032 static char* store_byte(char* chunk, char b) {
00033   *chunk = b;
00034   return chunk + sizeof(char);
00035 }
00036 
00037 static char* store_long(char* chunk, long l) {
00038   *((long*) chunk) = l;
00039   return chunk + sizeof(long);
00040 }
00041 
00042 extern "C" int handlePascalCallBackStub();
00043 extern "C" int handleCCallBackStub();
00044 
00045 void* callBack::registerPascalCall(int index, int nofArgs) {
00046   void* result = malloc(15);
00047   char* chunk = (char*) result;
00048 
00049   
00050   chunk = store_byte(chunk, '\xB9');
00051   chunk = store_long(chunk, index);
00052 
00053   
00054   chunk = store_byte(chunk, '\xBA');
00055   chunk = store_long(chunk, nofArgs * sizeof(int));
00056 
00057   
00058   chunk = store_byte(chunk, '\xE9');
00059   chunk = store_long(chunk, ((long) &handlePascalCallBackStub) - (4 + (long) chunk));
00060 
00061   return result;
00062 }
00063 
00064 void* callBack::registerCCall(int index) {
00065   void* result = malloc(10);
00066   char* chunk = (char*) result;
00067 
00068   
00069   chunk = store_byte(chunk, '\xB9');
00070   chunk = store_long(chunk, index);
00071 
00072   
00073   chunk = store_byte(chunk, '\xE9');
00074   chunk = store_long(chunk, ((long) &handleCCallBackStub) - (4 + (long) chunk));
00075 
00076   return result;
00077 }
00078 
00079 void callBack::unregister(void* block) {
00080   assert(block, "block is not valid");
00081   free((char*) block);
00082 }
00083 
00084 
00085 
00086 
00087 
00088 typedef void* (__stdcall *call_out_func_4)(int a, int b, int c, int d);
00089 
00090 extern "C" bool have_nlr_through_C;
00091 
00092 extern "C" volatile void* handleCallBack(int index, int params) {
00093   DeltaProcess* proc = NULL;
00094 
00095   if (Universe::callBack_receiver()->is_nil()) {
00096     warning("callBack receiver is not set");
00097   }
00098 
00099   int low  = get_unsigned_bitfield(params,  0, 16);
00100   int high = get_unsigned_bitfield(params, 16, 16);
00101 
00102   if (DeltaProcess::active()->thread_id() != os::current_thread_id()) {
00103     
00104     
00105     
00106     proc = Processes::find_from_thread_id(os::current_thread_id());
00107     assert(proc, "process must be present");
00108     DLLs::exit_async_call(&proc);
00109   }
00110  
00111 
00112   oop res = Delta::call(Universe::callBack_receiver(),
00113                         Universe::callBack_selector(),
00114                         as_smiOop(index),
00115                         as_smiOop(high),
00116                         as_smiOop(low));
00117 
00118   assert(DeltaProcess::active()->thread_id() == os::current_thread_id(), "check for process torch");
00119 
00120   void* result;
00121 
00122   
00123 
00124   if (have_nlr_through_C) {
00125     
00126     ErrorHandler::continue_nlr_in_delta();
00127   }
00128 
00129   if (res->is_smi()) {
00130     result = (void*) smiOop(res)->value();
00131   } else if (res->is_proxy()) {
00132     result = (void*) proxyOop(res)->get_pointer();
00133   } else {
00134     warning("Wrong return type for call back, returning NULL");
00135     result = NULL;
00136   }
00137 
00138   
00139   
00140 
00141   if (proc) {
00142     
00143     proc->transfer_and_continue();
00144   }
00145 
00146   
00147   return result;
00148 }