hotspot/src/share/vm/interpreter/bytecodes.hpp
changeset 5688 9052dc91ea67
parent 3261 c7d5aae8d3f7
child 5693 3015c564fcbc
--- a/hotspot/src/share/vm/interpreter/bytecodes.hpp	Fri May 21 02:59:24 2010 -0700
+++ b/hotspot/src/share/vm/interpreter/bytecodes.hpp	Sun May 23 01:38:26 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2010 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -280,17 +280,43 @@
     number_of_codes
   };
 
+  // Flag bits derived from format strings, can_trap, can_rewrite, etc.:
+  enum Flags {
+    // semantic flags:
+    _bc_can_trap      = 1<<0,     // bytecode execution can trap or block
+    _bc_can_rewrite   = 1<<1,     // bytecode execution has an alternate form
+
+    // format bits (determined only by the format string):
+    _fmt_has_c        = 1<<2,     // constant, such as sipush "bcc"
+    _fmt_has_j        = 1<<3,     // constant pool cache index, such as getfield "bjj"
+    _fmt_has_k        = 1<<4,     // constant pool index, such as ldc "bk"
+    _fmt_has_i        = 1<<5,     // local index, such as iload
+    _fmt_has_o        = 1<<6,     // offset, such as ifeq
+    _fmt_has_nbo      = 1<<7,     // contains native-order field(s)
+    _fmt_has_u2       = 1<<8,     // contains double-byte field(s)
+    _fmt_has_u4       = 1<<9,     // contains quad-byte field
+    _fmt_not_variable = 1<<10,    // not of variable length (simple or wide)
+    _fmt_not_simple   = 1<<11,    // either wide or variable length
+    _all_fmt_bits     = (_fmt_not_simple*2 - _fmt_has_c),
+
+    // Example derived format syndromes:
+    _fmt_b      = _fmt_not_variable,
+    _fmt_bc     = _fmt_b | _fmt_has_c,
+    _fmt_bi     = _fmt_b | _fmt_has_i,
+    _fmt_bkk    = _fmt_b | _fmt_has_k | _fmt_has_u2,
+    _fmt_bJJ    = _fmt_b | _fmt_has_j | _fmt_has_u2 | _fmt_has_nbo,
+    _fmt_bo2    = _fmt_b | _fmt_has_o | _fmt_has_u2,
+    _fmt_bo4    = _fmt_b | _fmt_has_o | _fmt_has_u4
+  };
+
  private:
   static bool        _is_initialized;
   static const char* _name          [number_of_codes];
-  static const char* _format        [number_of_codes];
-  static const char* _wide_format   [number_of_codes];
   static BasicType   _result_type   [number_of_codes];
   static s_char      _depth         [number_of_codes];
-  static u_char      _length        [number_of_codes];
-  static bool        _can_trap      [number_of_codes];
+  static u_char      _lengths       [number_of_codes];
   static Code        _java_code     [number_of_codes];
-  static bool        _can_rewrite   [number_of_codes];
+  static jchar       _flags         [(1<<BitsPerByte)*2]; // all second page for wide formats
 
   static void        def(Code code, const char* name, const char* format, const char* wide_format, BasicType result_type, int depth, bool can_trap);
   static void        def(Code code, const char* name, const char* format, const char* wide_format, BasicType result_type, int depth, bool can_trap, Code java_code);
@@ -322,24 +348,18 @@
    static Code       non_breakpoint_code_at(address bcp, methodOop method = NULL);
 
   // Bytecode attributes
-  static bool        is_defined     (int  code)    { return 0 <= code && code < number_of_codes && _format[code] != NULL; }
-  static bool        wide_is_defined(int  code)    { return is_defined(code) && _wide_format[code] != NULL; }
+  static bool        is_defined     (int  code)    { return 0 <= code && code < number_of_codes && flags(code, false) != 0; }
+  static bool        wide_is_defined(int  code)    { return is_defined(code) && flags(code, true) != 0; }
   static const char* name           (Code code)    { check(code);      return _name          [code]; }
-  static const char* format         (Code code)    { check(code);      return _format        [code]; }
-  static const char* wide_format    (Code code)    { return _wide_format[code]; }
   static BasicType   result_type    (Code code)    { check(code);      return _result_type   [code]; }
   static int         depth          (Code code)    { check(code);      return _depth         [code]; }
-  static int         length_for     (Code code)    { return _length[code]; }
-  static bool        can_trap       (Code code)    { check(code);      return _can_trap      [code]; }
+  static int         length_for     (Code code)    { check(code);      return _lengths       [code] & 0xF; }
+  static int         wide_length_for(Code code)    { check(code);      return _lengths       [code] >> 4; }
+  static bool        can_trap       (Code code)    { check(code);      return has_all_flags(code, _bc_can_trap, false); }
   static Code        java_code      (Code code)    { check(code);      return _java_code     [code]; }
-  static bool        can_rewrite    (Code code)    { check(code);      return _can_rewrite   [code]; }
-  static int         wide_length_for(Code code)    {
-    if (!is_defined(code)) {
-      return 0;
-    }
-    const char* wf = wide_format(code);
-    return (wf == NULL) ? 0 : (int)strlen(wf);
-  }
+  static bool        can_rewrite    (Code code)    { check(code);      return has_all_flags(code, _bc_can_rewrite, false); }
+  static bool        native_byte_order(Code code)  { check(code);      return has_all_flags(code, _fmt_has_nbo, false); }
+  static bool        uses_cp_cache  (Code code)    { check(code);      return has_all_flags(code, _fmt_has_j, false); }
   // if 'end' is provided, it indicates the end of the code buffer which
   // should not be read past when parsing.
   static int         special_length_at(address bcp, address end = NULL);
@@ -355,6 +375,16 @@
 
   static bool        is_zero_const  (Code code)    { return (code == _aconst_null || code == _iconst_0
                                                            || code == _fconst_0 || code == _dconst_0); }
+  static int         compute_flags  (const char* format, int more_flags = 0);  // compute the flags
+  static int         flags          (int code, bool is_wide) {
+    assert(code == (u_char)code, "must be a byte");
+    return _flags[code + (is_wide ? (1<<BitsPerByte) : 0)];
+  }
+  static int         format_bits    (Code code, bool is_wide) { return flags(code, is_wide) & _all_fmt_bits; }
+  static bool        has_all_flags  (Code code, int test_flags, bool is_wide) {
+    return (flags(code, is_wide) & test_flags) == test_flags;
+  }
+
   // Initialization
   static void        initialize     ();
 };