X-Git-Url: http://git.buserror.net/cgi-bin/gitweb.cgi?p=polintos%2Fscott%2Fpriv.git;a=blobdiff_plain;f=lib%2Fc%2B%2B%2Forb.cc;h=8533f52347146f677a142a539cca850b675819e3;hp=f922a7fbbe440c4a5a36a25fcfdbd7494f8d8226;hb=263f276afb0b78c5c8914a54975d383425869d66;hpb=7da27a216a7f4bb3331fe315cdbec69bfcf2c762 diff --git a/lib/c++/orb.cc b/lib/c++/orb.cc index f922a7f..8533f52 100644 --- a/lib/c++/orb.cc +++ b/lib/c++/orb.cc @@ -1,53 +1,109 @@ #include +#include namespace System { - namespace RunTime { - // This function could be made to do a binary search if we can - // manage to somehow sort the IFaceTables... +namespace RunTime { + using namespace ::System::Exceptions::Std; - uintptr_t downcast(::System::_i_Object *obj, - const unsigned long *new_guid) - { - if (!obj) + // This function could be made to do a binary search if we can + // manage to somehow sort the IFaceTables... + uintptr_t downcast(::System::_i_Object *obj, const GUID *new_guid) + { + if (!obj) + return 0; + + void unsupported_long_size(); + + if (sizeof(long) != 4 && sizeof(long) != 8) + unsupported_long_size(); + + IFaceTable *tbl = obj->info->concrete_IFaceTable; + unsigned long new_guid_first = new_guid->l[0]; + + // This doesn't use guids_equal(), as that would eliminate the + // ability to cache the first word of new_guid. The compiler + // *might* do it anyway, but this code was written before + // guids_equal existed, and I don't want to risk removing an + // optimization by changing it now without testing how GCC + // behaves. + + while (true) { + if (tbl->info->guid->l[0] == new_guid_first && + tbl->info->guid->l[1] == new_guid->l[1] && + (sizeof(long) == 8 || + (tbl->info->guid->l[2] == new_guid->l[2] && + tbl->info->guid->l[3] == new_guid->l[3]))) + break; + + tbl++; + if (__builtin_expect(!tbl->info->guid->l[0], 0)) return 0; + } + + uintptr_t ptr = reinterpret_cast(obj); + + ptr += obj->info->concrete; + ptr += tbl->offset; + + return ptr; + }; - void unsupported_long_size(); - - if (sizeof(long) != 4 && sizeof(long) != 8) - unsupported_long_size(); - - IFaceTable *tbl = obj->info->concrete_IFaceTable; - unsigned long new_guid_first = *new_guid; - - // This doesn't use guids_equal(), as that would eliminate the - // ability to cache the first word of new_guid. The compiler - // *might* do it anyway, but this code was written before - // guids_equal existed, and I don't want to risk removing an - // optimization by changing it now without testing how GCC - // behaves. - - do { - if (*tbl->guid == new_guid_first && - tbl->guid[1] == new_guid[1] && - (sizeof(long) == 8 || - (tbl->guid[2] == new_guid[2] && - tbl->guid[3] == new_guid[3]))) - break; - - tbl++; - } while (tbl->guid); - - uintptr_t ptr = reinterpret_cast(obj); - - ptr += obj->info->concrete; - ptr += tbl->offset; - - return ptr; + namespace Priv { + typedef void (*MethodEntry)(ParamInfoBlock *pib); + + struct Object { + MethodEntry entry; + void *ptr; // pointer to the class interface }; - + + typedef ::Util::RadixTree ObjTable; +// ObjTable objtable; + unsigned long get_pc() { return reinterpret_cast(__builtin_return_address(0)); } + + void exception_to_array(::System::VStruct *ex, Array *ar) + { + // FIXME: marshall struct + } + + void handle_message(ParamInfoBlock *pib) + { + Message *msg = reinterpret_cast(pib->segments[0].ptr); + + switch (msg->seg0.opcode) { + case Segment0::InvokeMethod: { + if (pib->segments[0].len < sizeof(InvokeMethod)) + throw_idl(ShortMessage, 0, pib->segments[0].len, + sizeof(InvokeMethod)); + +// ID obj = pib->objlist[0]; + break; + } + + default: + throw_idl(InvalidOpcode, msg->seg0.opcode); + } + } + } +}} + +extern "C" void abort(); + +extern "C" void handle_message(::System::RunTime::ParamInfoBlock *pib, + ::System::RunTime::Array *ex_arr) +{ + try { + ::System::RunTime::Priv::handle_message(pib); + } + + catch (::System::Exceptions::Exception &ex) { + ::System::RunTime::Priv::exception_to_array(&ex, ex_arr); + } + + catch (...) { + abort(); } }