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/_prim.cpp.incl"
00026 
00027 
00028 
00029 
00030 
00031 #include "prims.inc"
00032 
00033 
00034 
00035 
00036 typedef  oop (*prim_fntype0)();
00037 typedef  oop (*prim_fntype1)(oop);
00038 typedef  oop (*prim_fntype2)(oop, oop);
00039 typedef  oop (*prim_fntype3)(oop, oop, oop);
00040 typedef  oop (*prim_fntype4)(oop, oop, oop, oop);
00041 typedef  oop (*prim_fntype5)(oop, oop, oop, oop, oop);
00042 typedef  oop (*prim_fntype6)(oop, oop, oop, oop, oop, oop);
00043 typedef  oop (*prim_fntype7)(oop, oop, oop, oop, oop, oop, oop);
00044 typedef  oop (*prim_fntype8)(oop, oop, oop, oop, oop, oop, oop, oop);
00045 typedef  oop (*prim_fntype9)(oop, oop, oop, oop, oop, oop, oop, oop, oop);
00046 
00047 
00048 oop primitive_desc::eval(oop* a) {
00049   const bool reverseArgs = true;        
00050   oop res;
00051   if (reverseArgs) {
00052     switch (number_of_parameters()) {
00053       case  0: res = ((prim_fntype0)_fn)(); break;
00054       case  1: res = ((prim_fntype1)_fn)(a[0]); break;
00055       case  2: res = ((prim_fntype2)_fn)(a[1], a[0]); break;
00056       case  3: res = ((prim_fntype3)_fn)(a[2], a[1], a[0]); break;
00057       case  4: res = ((prim_fntype4)_fn)(a[3], a[2], a[1], a[0]); break;
00058       case  5: res = ((prim_fntype5)_fn)(a[4], a[3], a[2], a[1], a[0]); break;
00059       case  6: res = ((prim_fntype6)_fn)(a[5], a[4], a[3], a[2], a[1], a[0]); break;
00060       case  7: res = ((prim_fntype7)_fn)(a[6], a[5], a[4], a[3], a[2], a[1], a[0]); break;
00061       case  8: res = ((prim_fntype8)_fn)(a[7], a[6], a[5], a[4], a[3], a[2], a[1], a[0]); break;
00062       case  9: res = ((prim_fntype9)_fn)(a[8], a[7], a[6], a[5], a[4], a[3], a[2], a[1], a[0]); break;
00063       default: ShouldNotReachHere();
00064     }
00065   } else {
00066     switch (number_of_parameters()) {
00067       case  0: res = ((prim_fntype0)_fn)(); break;
00068       case  1: res = ((prim_fntype1)_fn)(a[0]); break;
00069       case  2: res = ((prim_fntype2)_fn)(a[0], a[1]); break;
00070       case  3: res = ((prim_fntype3)_fn)(a[0], a[1], a[2]); break;
00071       case  4: res = ((prim_fntype4)_fn)(a[0], a[1], a[2], a[3]); break;
00072       case  5: res = ((prim_fntype5)_fn)(a[0], a[1], a[2], a[3], a[4]); break;
00073       case  6: res = ((prim_fntype6)_fn)(a[0], a[1], a[2], a[3], a[4], a[5]); break;
00074       case  7: res = ((prim_fntype7)_fn)(a[0], a[1], a[2], a[3], a[4], a[5], a[6]); break;
00075       case  8: res = ((prim_fntype8)_fn)(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]); break;
00076       case  9: res = ((prim_fntype9)_fn)(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8]); break;
00077       default: ShouldNotReachHere();
00078     }
00079   }
00080   return res;
00081 }
00082 
00083 
00084 void primitives::print_table() {
00085   std->print_cr("Primitive table:");
00086   for (int index = 0; index < size_of_primitive_table; index++) {
00087     primitive_desc* e = primitive_table[index];
00088     std->print("%3d ",index);
00089     e->print();
00090   }
00091   std->print_cr(" - format: <index> <name> <number_of_parameters> <flags> [category]");
00092   std->print_cr("    flags:  R = has receiver,           F = has failure block,");
00093   std->print_cr("            S = can scavenge,           N = can perform NLR,");
00094   std->print_cr("            C = can be constant folded, D = can invoke Delta code");
00095   std->print_cr("            I = internal,               P = needs Delta fp code");
00096   std->print_cr("            W = can walk stack (computed)");
00097 }
00098 
00099 
00100 bool primitive_desc::can_walk_stack() const {
00101   return can_scavenge() || can_invoke_delta() || can_perform_NLR();
00102 }
00103 
00104 
00105 symbolOop primitive_desc::selector() const {
00106   return oopFactory::new_symbol(name());
00107 }
00108 
00109 
00110 void primitive_desc::print() {
00111   std->print("%48s %d %s%s%s%s%s%s%s%s%s",
00112              name(), 
00113              number_of_parameters(),
00114              has_receiver()           ? "R" : "_",
00115              can_fail()               ? "F" : "_",
00116              can_scavenge()           ? "S" : "_",
00117              can_walk_stack()         ? "W" : "_",
00118              can_perform_NLR()        ? "N" : "_",
00119              can_be_constant_folded() ? "C" : "_",
00120              can_invoke_delta()       ? "D" : "_",
00121              is_internal()            ? "I" : "_",
00122              needs_delta_fp_code()    ? "P" : "_");
00123   switch(group()) {
00124     case IntComparisonPrimitive:   std->print(", smi compare");           break;
00125     case IntArithmeticPrimitive:   std->print(", smi arith");             break;
00126     case FloatComparisonPrimitive: std->print(", double compare");        break;
00127     case FloatArithmeticPrimitive: std->print(", double arith");          break;
00128     case ByteArrayPrimitive:       std->print(", byte array op.");        break;
00129     case DoubleByteArrayPrimitive: std->print(", double-byte array op."); break;
00130     case ObjArrayPrimitive:        std->print(", array op.");             break;
00131     case BlockPrimitive:           std->print(", block/context");         break;
00132     case NormalPrimitive:                                                 break;
00133     default: fatal("Unknown primitive group");
00134   }
00135   std->cr();
00136 }
00137 
00138 
00139 char* primitive_desc::parameter_type(int index) const {
00140   assert((0 <= index) && (index < number_of_parameters()), "illegal parameter index");
00141   return _types[1 + index];
00142 }
00143 
00144 
00145 char* primitive_desc::return_type() const { 
00146   return _types[0];
00147 }
00148 
00149 
00150 Expr* primitive_desc::convertToKlass(char* type, PReg* p, Node* n) const {
00151   if (0 == strcmp(type, "SmallInteger")) return new KlassExpr(Universe::smiKlassObj(), p, n);
00152   if (0 == strcmp(type, "Double"))       return new KlassExpr(Universe::doubleKlassObj(), p, n);
00153   if (0 == strcmp(type, "Float"))        return new KlassExpr(Universe::doubleKlassObj(), p, n);
00154   if (0 == strcmp(type, "Symbol"))       return new KlassExpr(Universe::symbolKlassObj(), p, n);
00155   if (0 == strcmp(type, "Boolean")) {
00156     
00157     Expr* t = new ConstantExpr(Universe::trueObj(), p, NULL);
00158     Expr* f = new ConstantExpr(Universe::falseObj(), p, NULL);
00159     return new MergeExpr(t, f, p, NULL);
00160   }
00161 
00162   
00163   
00164   
00165   
00166   return NULL;
00167 }
00168 
00169 
00170 Expr* primitive_desc::parameter_klass(int index, PReg* p, Node* n) const {
00171   return convertToKlass(parameter_type(index), p, n);
00172 }
00173 
00174 
00175 Expr* primitive_desc::return_klass(PReg* p, Node* n) const {
00176   return convertToKlass(return_type(), p, n);
00177 }
00178 
00179 
00180 void primitive_desc::error(char* msg) {
00181   print();
00182   ::error(msg);
00183 }
00184 
00185 void primitive_desc::verify() {
00186   bool ok = true;
00187   if (can_invoke_delta()) {
00188     if (!can_scavenge()) error("canInvokeDelta implies canScavenge");
00189     if (!can_walk_stack()) error("canInvokeDelta implies can_walk_stack");
00190     if (can_be_constant_folded()) error("canInvokeDelta implies !canbeConstantFolded");
00191     if (!can_perform_NLR()) error("canInvokeDelta implies canPerformNLR");
00192   }
00193   if (can_be_constant_folded()) {
00194     if (can_perform_NLR()) error("canbeConstantFolded implies !canPerformNLR");
00195   }
00196   if (group() == BlockPrimitive) {
00197     if (!can_walk_stack()) error("blocks must have can_walk_stack");
00198   }
00199 }
00200 
00201 int primitive_desc::compare(char* str, int len) {
00202   int src_len = strlen(name());
00203   int sign = strncmp(name(), str, min(src_len, len));
00204   if (sign != 0 || src_len == len) return sign;
00205   return src_len < len ? -1 : 1;
00206 }
00207 
00208 primitive_desc* primitives::lookup(char* s, int len) {
00209   int first = 0;
00210   int last  = size_of_primitive_table;
00211 
00212   primitive_desc* element;
00213   do {
00214     int middle = first + (last - first)/2;
00215     element    = primitive_table[middle];
00216     int sign   = element->compare(s, len);
00217          if (sign == -1) first = middle + 1;
00218     else if (sign ==  1) last  = middle - 1;
00219     else return element;
00220   } while (first < last);
00221 
00222   assert(first == last, "check for one element");
00223   element = primitive_table[first];
00224 
00225   return element->compare(s, len) == 0 ? element : NULL;
00226 }
00227 
00228 
00229 primitive_desc* primitives::lookup(fntype fn) {
00230   for (int index = 0; index < size_of_primitive_table; index++) {
00231     primitive_desc* e = primitive_table[index];
00232     if (e->fn() == fn) return e;
00233   }
00234   return NULL;
00235 }
00236 
00237 
00238 void primitives::lookup_and_patch() {
00239   
00240   frame f = DeltaProcess::active()->last_frame();
00241   CodeIterator it(f.hp());
00242   oop* selector_addr = it.aligned_oop(1);
00243 
00244   symbolOop sel = symbolOop(*selector_addr);
00245   assert(sel->is_symbol(), "symbol expected");
00246   
00247   primitive_desc* pdesc = primitives::lookup(sel);
00248   if (pdesc != NULL && !pdesc->is_internal()) {
00249     
00250     *f.hp() = u_char(Bytecodes::primitive_call_code_for(Bytecodes::Code(*f.hp())));
00251     *selector_addr = oop(pdesc->fn());
00252   } else {
00253     
00254     it.advance();
00255     f.set_hp(it.hp());
00256 
00257     { ResourceMark rm;
00258       
00259       std->print("primitive lookup error\n");
00260       sel->print_value(); std->print(" not found\n");
00261     }
00262     if (DeltaProcess::active()->is_scheduler()) {
00263       ResourceMark rm;
00264       DeltaProcess::active()->trace_stack();
00265       fatal("primitive lookup error in scheduler");
00266     } else {
00267       DeltaProcess::active()->suspend(primitive_lookup_error);
00268     }
00269     ShouldNotReachHere();
00270   }
00271 }
00272 
00273 
00274 void prim_init() { 
00275   primitives::initialize();
00276   primitive_desc* prev = NULL;
00277   for (int index = 0; index < size_of_primitive_table; index++) {
00278     primitive_desc* e = primitive_table[index];
00279     e->verify();
00280     if (prev) {
00281       guarantee(strcmp(prev->name(), e->name()) == -1, "primitive table not sorted");
00282     }
00283   }
00284   primitives::clear_counters();
00285 }
00286 
00287 
00288 void primitives::clear_counters() {
00289   behaviorPrimitives::number_of_calls        = 0;
00290   byteArrayPrimitives::number_of_calls       = 0;
00291   callBackPrimitives::number_of_calls        = 0;
00292   doubleByteArrayPrimitives::number_of_calls = 0;
00293   debugPrimitives::number_of_calls           = 0;
00294   doubleOopPrimitives::number_of_calls       = 0;
00295   methodOopPrimitives::number_of_calls       = 0;
00296   mixinOopPrimitives::number_of_calls        = 0;
00297   objArrayPrimitives::number_of_calls        = 0;
00298   oopPrimitives::number_of_calls             = 0;
00299   processOopPrimitives::number_of_calls      = 0;
00300   proxyOopPrimitives::number_of_calls        = 0;
00301   smiOopPrimitives::number_of_calls          = 0;
00302   systemPrimitives::number_of_calls          = 0;
00303 }
00304 
00305 
00306 static void print_calls(char* name, int inc, int* total) {
00307   if (inc > 0) {
00308     lprintf(" %s:\t%6d\n", name, inc);
00309     *total = *total + inc;
00310   }
00311 }
00312 
00313 
00314 void primitives::print_counters() {
00315   int total = 0;
00316   lprintf("Primitive call counters:\n");
00317   print_calls("Behavoir",        behaviorPrimitives::number_of_calls,        &total);
00318   print_calls("byteArray",       byteArrayPrimitives::number_of_calls,       &total);
00319   print_calls("callBack",        callBackPrimitives::number_of_calls,        &total);
00320   print_calls("doubelByteArray", doubleByteArrayPrimitives::number_of_calls, &total);
00321   print_calls("debug",           debugPrimitives::number_of_calls,           &total);
00322   print_calls("double",          doubleOopPrimitives::number_of_calls,       &total);
00323   print_calls("method",          methodOopPrimitives::number_of_calls,       &total);
00324   print_calls("mixin",           mixinOopPrimitives::number_of_calls,        &total);
00325   print_calls("objArray",        objArrayPrimitives::number_of_calls,        &total);
00326   print_calls("oop",             oopPrimitives::number_of_calls,             &total);
00327   print_calls("process",         processOopPrimitives::number_of_calls,      &total);
00328   print_calls("proxy",           proxyOopPrimitives::number_of_calls,        &total);
00329   print_calls("smi",             smiOopPrimitives::number_of_calls,          &total);
00330   print_calls("system",          systemPrimitives::number_of_calls,          &total);
00331   lprintf("Total:\t%6d\n", total);
00332 
00333 }
00334 
00335 primitive_desc* InterpretedPrim_Cache::pdesc() const {
00336   CodeIterator c(hp());
00337   switch (c.code()) {
00338     case Bytecodes::prim_call:
00339     case Bytecodes::prim_call_failure:
00340     case Bytecodes::prim_call_self:
00341     case Bytecodes::prim_call_self_failure:
00342       return primitives::lookup((fntype) c.word_at(1));
00343 
00344     case Bytecodes::prim_call_lookup:
00345     case Bytecodes::prim_call_failure_lookup:
00346     case Bytecodes::prim_call_self_lookup:
00347     case Bytecodes::prim_call_self_failure_lookup:
00348       return primitives::lookup(symbolOop(c.oop_at(1)));
00349 
00350     default: fatal("Wrong bytecode");
00351   }
00352   return NULL;
00353 }
00354 
00355 bool InterpretedPrim_Cache::has_receiver() const {
00356   CodeIterator c(hp());
00357   switch (c.code()) {
00358     case Bytecodes::prim_call_self:
00359     case Bytecodes::prim_call_self_failure:
00360     case Bytecodes::prim_call_self_lookup:
00361     case Bytecodes::prim_call_self_failure_lookup:
00362       return true;
00363 
00364     case Bytecodes::prim_call:
00365     case Bytecodes::prim_call_failure:
00366     case Bytecodes::prim_call_lookup:
00367     case Bytecodes::prim_call_failure_lookup:
00368        return false;
00369 
00370     default: fatal("Wrong bytecode");
00371   }
00372   return false;
00373 }
00374 
00375 symbolOop InterpretedPrim_Cache::name() const {
00376   CodeIterator c(hp());
00377   switch (c.code()) {
00378     case Bytecodes::prim_call:
00379     case Bytecodes::prim_call_failure:
00380     case Bytecodes::prim_call_self:
00381     case Bytecodes::prim_call_self_failure:
00382       return primitives::lookup((fntype) c.word_at(1))->selector();
00383 
00384     case Bytecodes::prim_call_lookup:
00385     case Bytecodes::prim_call_failure_lookup:
00386     case Bytecodes::prim_call_self_lookup:
00387     case Bytecodes::prim_call_self_failure_lookup:
00388       return symbolOop(c.oop_at(1));
00389 
00390     default: fatal("Wrong bytecode");
00391   }
00392   return NULL;
00393 }
00394 
00395 int InterpretedPrim_Cache::number_of_parameters() const {
00396   int result = name()->number_of_arguments()
00397              + (has_receiver()     ? 1 : 0)
00398              - (has_failure_code() ? 1 : 0);
00399   assert(pdesc() == NULL || pdesc()->number_of_parameters() == result, "checking result");
00400   return result;
00401 }
00402 
00403 bool InterpretedPrim_Cache::has_failure_code() const {
00404   CodeIterator c(hp());
00405   switch (c.code()) {
00406     case Bytecodes::prim_call_failure:
00407     case Bytecodes::prim_call_failure_lookup:
00408     case Bytecodes::prim_call_self_failure:
00409     case Bytecodes::prim_call_self_failure_lookup:
00410       return true;
00411 
00412     case Bytecodes::prim_call:
00413     case Bytecodes::prim_call_lookup:
00414     case Bytecodes::prim_call_self_lookup:
00415     case Bytecodes::prim_call_self:
00416       return false;
00417 
00418     default: fatal("Wrong bytecode");
00419   }
00420   return false;
00421 }
00422 
00423 primitive_desc* primitives::_new0;
00424 primitive_desc* primitives::_new1;
00425 primitive_desc* primitives::_new2;
00426 primitive_desc* primitives::_new3;
00427 primitive_desc* primitives::_new4;
00428 primitive_desc* primitives::_new5;
00429 primitive_desc* primitives::_new6;
00430 primitive_desc* primitives::_new7;
00431 primitive_desc* primitives::_new8;
00432 primitive_desc* primitives::_new9;
00433 primitive_desc* primitives::_equal;
00434 primitive_desc* primitives::_not_equal;
00435 primitive_desc* primitives::_block_allocate;
00436 primitive_desc* primitives::_block_allocate0;
00437 primitive_desc* primitives::_block_allocate1;
00438 primitive_desc* primitives::_block_allocate2;
00439 primitive_desc* primitives::_context_allocate;
00440 primitive_desc* primitives::_context_allocate0;
00441 primitive_desc* primitives::_context_allocate1;
00442 primitive_desc* primitives::_context_allocate2;
00443 
00444 primitive_desc* primitives::verified_lookup(char* selector) {
00445   primitive_desc* result = lookup(selector);
00446   if (result == NULL) {
00447     err->print_cr("Verified primitive lookup failed");
00448     err->print_cr(" selector = %s", selector);
00449     fatal("aborted"); 
00450   }
00451   return result;
00452 }
00453 
00454 void primitives::initialize() {
00455   _new0              = verified_lookup("primitiveNew0");
00456   _new1              = verified_lookup("primitiveNew1");
00457   _new2              = verified_lookup("primitiveNew2");
00458   _new3              = verified_lookup("primitiveNew3");
00459   _new4              = verified_lookup("primitiveNew4");
00460   _new5              = verified_lookup("primitiveNew5");
00461   _new6              = verified_lookup("primitiveNew6");
00462   _new7              = verified_lookup("primitiveNew7");
00463   _new8              = verified_lookup("primitiveNew8");
00464   _new9              = verified_lookup("primitiveNew9");
00465 
00466   _equal             = verified_lookup("primitiveEqual:");
00467   _not_equal         = verified_lookup("primitiveNotEqual:");
00468 
00469   _block_allocate    = verified_lookup("primitiveCompiledBlockAllocate:");
00470   _block_allocate0   = verified_lookup("primitiveCompiledBlockAllocate0");
00471   _block_allocate1   = verified_lookup("primitiveCompiledBlockAllocate1");
00472   _block_allocate2   = verified_lookup("primitiveCompiledBlockAllocate2");
00473   _context_allocate  = verified_lookup("primitiveCompiledContextAllocate:");
00474   _context_allocate0 = verified_lookup("primitiveCompiledContextAllocate0");
00475   _context_allocate1 = verified_lookup("primitiveCompiledContextAllocate1");
00476   _context_allocate2 = verified_lookup("primitiveCompiledContextAllocate2");
00477 }