callBack.cpp

Go to the documentation of this file.
00001 /* Copyright 1994, 1995 LongView Technologies L.L.C. $Revision: 1.19 $ */
00002 /* Copyright (c) 2006, Sun Microsystems, Inc.
00003 All rights reserved.
00004 
00005 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 
00006 following conditions are met:
00007 
00008     * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
00009     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following 
00010           disclaimer in the documentation and/or other materials provided with the distribution.
00011     * Neither the name of Sun Microsystems nor the names of its contributors may be used to endorse or promote products derived 
00012           from this software without specific prior written permission.
00013 
00014 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 
00015 NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
00016 THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
00017 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
00018 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
00019 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
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   // MOV ECX, index
00050   chunk = store_byte(chunk, '\xB9');
00051   chunk = store_long(chunk, index);
00052 
00053   // MOV EDX, number of bytes for parameters
00054   chunk = store_byte(chunk, '\xBA');
00055   chunk = store_long(chunk, nofArgs * sizeof(int));
00056 
00057   // JMP _handleCCallStub
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   // MOV ECX, index
00069   chunk = store_byte(chunk, '\xB9');
00070   chunk = store_long(chunk, index);
00071 
00072   // JMP _handleCCallStub
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 // handleCallBack is called from the two assembly stubs:
00085 // - handlePascalCallBackStub
00086 // - handleCCallBackStub
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     // We'are now back in a asynchronous DLL call so give up the control
00104     // Fix this:
00105     //   remove warning when it has been tested
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   // convert return result
00123 
00124   if (have_nlr_through_C) {
00125     // Continues the NLR after at the next Delta frame
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   // Return value has to be converted before we transfer control to another 
00139   // thread.
00140 
00141   if (proc) {
00142     // We'are now back in a asynchronous DLL call so give up the control
00143     proc->transfer_and_continue();
00144   }
00145 
00146   // Call Delta level error routine
00147   return result;
00148 }

Generated on Mon Oct 9 13:37:05 2006 for Strongtalk VM by  doxygen 1.4.7