prim.hpp

Go to the documentation of this file.
00001 /* Copyright 1994, 1995 LongView Technologies L.L.C. $Revision: 1.52 $ */
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 // The file defines the interface to the internal primitives.
00025 
00026 // Primitives are divided into four categories:
00027 //                                   (canScavenge, NLR,   canBeConstantFolded)
00028 // 1) Allocation primitives.         (true,        false, false)
00029 // 2) Pure primitives.               (false,       false, true)
00030 // 3) Function primitives            (false,       false, false)
00031 // 4) Primitives who might scavenge, (true,        false, false)
00032 //    gc, or call delta.
00033 
00034 
00035 // Warning: Don't change the element order of this enum without
00036 //          adjusting the DeltaPrimitiveGenerator accordingly!
00037 
00038 enum PrimitiveGroup {
00039   NormalPrimitive,
00040 
00041   IntComparisonPrimitive,       // Integer comparison prim.
00042   IntArithmeticPrimitive,       // Integer arithmetic.
00043 
00044   FloatComparisonPrimitive,     // FP comparison prim.
00045   FloatArithmeticPrimitive,     // FP arithmetic.
00046 
00047   ObjArrayPrimitive,            // access/size
00048   ByteArrayPrimitive,           // access/size
00049   DoubleByteArrayPrimitive,     // access/size
00050   
00051   BlockPrimitive                // block-related prims (creation, invocation, contexts)
00052 };
00053 
00054 class InterpretedPrim_Cache: public ValueObj {
00055  private:
00056   u_char* hp() const { return (u_char*)this; }
00057  public:
00058   symbolOop       name() const;
00059   int             number_of_parameters() const;
00060   primitive_desc* pdesc() const;
00061   bool            has_receiver() const;
00062   bool            has_failure_code() const;
00063 };
00064 
00065 // The primitive_desc structure exposes all properties of a primitive.
00066 // Primitives are like procedures (no dispatching is necessary) and
00067 // invoked by providing a number of parameters. 
00068 
00069 class primitive_desc {
00070  public:
00071   char*  _name;         // name of the primitive
00072   fntype _fn;           // primitive entry point
00073   int    _flags;        // see unpacking below
00074   char** _types;        // provides the parameter and return types
00075                         // [0]                       -> contains the return type
00076                         // [1..number_of_parameters] -> contains types for the parameters
00077   char** _errors;       // provides a null terminated list of errors for the primitive
00078                         // excluding {FirstArgumenthasWrongType, SecondArgumenthasWrongType ...}
00079  public:
00080   // returns the name of the primitive.
00081   char* name() const { return _name; }
00082 
00083   // returns the primitive entry point.
00084   fntype fn() const { return _fn; }
00085   
00086   // flags
00087   int number_of_parameters()    const { return get_unsigned_bitfield(_flags, 0, 8); }
00088           // # of parameters (self or arguments), excluding failure block (if any); i.e., # of args
00089           // that are actually passed to C
00090   PrimitiveGroup group()        const { return (PrimitiveGroup) get_unsigned_bitfield(_flags, 8, 8); }
00091   bool is_special_prim()        const { return group() != NormalPrimitive; }
00092   bool can_scavenge()           const { return isSet(_flags, 16);  }   // can it trigger a scavenge/GC?
00093   bool can_perform_NLR()        const { return isSet(_flags, 17);  }   // can it do an NLR or process abort?
00094   bool can_fail()               const { return isSet(_flags, 18);  }
00095         // can_fail: can primitive fail with arguments of correct type?  (NB: even if !can_fail(), 
00096         // primitive will fail if argument types are wrong)
00097   bool can_invoke_delta()       const { return can_perform_NLR();  }   // can it call other Delta code?
00098   bool can_be_constant_folded() const { return isSet(_flags, 19);  }   // is it side-effect free? (so it can be const-folded if args are const)
00099   bool has_receiver()           const { return isSet(_flags, 20);  }   // does it require a receiver? ({{self prim...}})
00100   bool is_internal()            const { return isSet(_flags, 21);  }   // true for VM-internal primitives
00101   bool needs_delta_fp_code()    const { return !isSet(_flags, 22); }   // must caller set up lastDeltaFP?
00102   bool can_walk_stack()         const;                                 // can it trigger a stack print? (debug/interrupt point)
00103 
00104   // Returns the name of the primitive as a symbol
00105   symbolOop selector() const;
00106 
00107   // Evaluates the primitive with the given parameters
00108   oop eval(oop* parameters);
00109  
00110   //protected:          // NB: can't use protected:, or else Microsoft Compiler (2.1) refuses to initialize prim array
00111   // Type information of the primitive
00112   char* parameter_type(int index)       const; // 0 <= index < number_of_parameters()
00113   char* return_type()                   const;
00114 
00115 #ifdef DELTA_COMPILER
00116   // Type information for compiler
00117   // - returns NULL if type is unknown or too complicated
00118  public:
00119   Expr* parameter_klass(int index, PReg* p, Node* n) const; // 0 <= index < number_of_parameters()
00120   Expr* return_klass(PReg* p, Node* n) const; 
00121  //protected:
00122   Expr* convertToKlass(char* type, PReg* p, Node* n) const; 
00123 #endif
00124 
00125  public:
00126   // Error information
00127   char* error(int index) const { return _errors[index]; }
00128 
00129   // Comparison operation
00130   int compare(char* str, int len);
00131 
00132   // Miscellaneous operations
00133   void print();
00134   void verify();
00135   void error(char* msg);
00136 };
00137 
00138 
00139 class primitives : AllStatic {
00140  public:
00141   static void print_table();
00142 
00143   static primitive_desc* lookup(symbolOop selector)     { return lookup((char*) selector->bytes(), selector->length()); }
00144   static primitive_desc* lookup(fntype fn);
00145 
00146   static void lookup_and_patch(); // routine called by interpreter
00147 
00148   // For degbugging/profiling
00149   static void clear_counters();
00150   static void print_counters();
00151 
00152   static void initialize();
00153 
00154  private:
00155   static primitive_desc* lookup(char* selector, int len);
00156   static primitive_desc* lookup(char* selector) { return lookup(selector, strlen(selector)); }
00157   static primitive_desc* verified_lookup(char* selector); // Fails if the primitive could not be found
00158 
00159   // Primitives used by the compiler are looked up at startup
00160   static primitive_desc* _new0;
00161   static primitive_desc* _new1;
00162   static primitive_desc* _new2;
00163   static primitive_desc* _new3;
00164   static primitive_desc* _new4;
00165   static primitive_desc* _new5;
00166   static primitive_desc* _new6;
00167   static primitive_desc* _new7;
00168   static primitive_desc* _new8;
00169   static primitive_desc* _new9;
00170 
00171   static primitive_desc* _equal;
00172   static primitive_desc* _not_equal;
00173 
00174   static primitive_desc* _block_allocate;
00175   static primitive_desc* _block_allocate0;
00176   static primitive_desc* _block_allocate1;
00177   static primitive_desc* _block_allocate2;
00178 
00179   static primitive_desc* _context_allocate;
00180   static primitive_desc* _context_allocate0;
00181   static primitive_desc* _context_allocate1;
00182   static primitive_desc* _context_allocate2;
00183 
00184  public:
00185   static primitive_desc* new0() { return _new0; }
00186   static primitive_desc* new1() { return _new1; }
00187   static primitive_desc* new2() { return _new2; }
00188   static primitive_desc* new3() { return _new3; }
00189   static primitive_desc* new4() { return _new4; }
00190   static primitive_desc* new5() { return _new5; }
00191   static primitive_desc* new6() { return _new6; }
00192   static primitive_desc* new7() { return _new7; }
00193   static primitive_desc* new8() { return _new8; }
00194   static primitive_desc* new9() { return _new9; }
00195 
00196   static primitive_desc* equal()     { return _equal;     }
00197   static primitive_desc* not_equal() { return _not_equal; }
00198 
00199   static primitive_desc* block_allocate()    { return _block_allocate;  }
00200   static primitive_desc* block_allocate0()   { return _block_allocate0; }
00201   static primitive_desc* block_allocate1()   { return _block_allocate1; }
00202   static primitive_desc* block_allocate2()   { return _block_allocate2; }
00203 
00204   static primitive_desc* context_allocate()  { return _context_allocate;  }
00205   static primitive_desc* context_allocate0() { return _context_allocate0; }
00206   static primitive_desc* context_allocate1() { return _context_allocate1; }
00207   static primitive_desc* context_allocate2() { return _context_allocate2; }
00208 };

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