1 /*
   2  * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #include "interpreter/extendedBytecodes.hpp"
  26 #include "interpreter/interpreter.hpp"
  27 #include "interpreter/interp_masm.hpp"
  28 #include "interpreter/templateInterpreterGenerator.hpp"
  29 #include "interpreter/templateTable.hpp"
  30 
  31 BCSetTemplate* BCSetTemplate::_BCSetTemplates[Bytecodes::number_of_bcset];
  32 
  33 //------------------------------------------------------------------------------------------------------------------------
  34 
  35 void BCSetTemplate::initialize() {
  36   for (int i = 0; i < Bytecodes::number_of_bcset; i++) {
  37     _BCSetTemplates[i] = NULL;
  38   }
  39   assign(Bytecodes::_bcset_int, initialize_type_I_BCSet());
  40   assign(Bytecodes::_bcset_float, initialize_type_F_BCSet());
  41 
  42 }
  43 
  44 // This method should be in TemplateInterpreter rather than in
  45 // the TypedBytecodesGenerator class
  46 Bytecodes::BCSet BCSetTemplate::resolve(Symbol* type) {
  47   switch(type->byte_at(0)) {
  48     case 'B':
  49       return Bytecodes::_bcset_byte;
  50     case 'S':
  51       return Bytecodes::_bcset_short;
  52     case 'I':
  53       return Bytecodes::_bcset_int;
  54     case 'J':
  55       return Bytecodes::_bcset_long;
  56     case 'C':
  57       return Bytecodes::_bcset_char;
  58     case 'F':
  59       return Bytecodes::_bcset_float;
  60     case 'D':
  61       return Bytecodes::_bcset_double;
  62     case 'L':
  63       return Bytecodes::_bcset_reference;
  64     case '[':
  65       return Bytecodes::_bcset_array;
  66     default:
  67       ShouldNotReachHere();
  68   }
  69   return Bytecodes::_bcset_illegal;
  70 }
  71 
  72 void BCSetTemplate::assign(Bytecodes::BCSet bcset, BCSetTemplate* gen) {
  73   assert(_BCSetTemplates[bcset] == NULL, "Double assignment");
  74   _BCSetTemplates[bcset] = gen;
  75 }
  76 
  77 //------------------------------------------------------------------------------------------------------------------------
  78 
  79 void BCSetTemplate::define_alias(Bytecodes::Code new_bytecode, Bytecodes::Code existing_bytecode) {
  80   assert(Bytecodes::bcset(new_bytecode) == _bcset, "BType mismatch");
  81   assert(Bytecodes::bcset(existing_bytecode) == Bytecodes::_bcset_default, "Aliasing only works to legacy bytecodes");
  82   assert(Bytecodes::is_defined(new_bytecode), "Sanity check");
  83   if (_aliases == NULL) {
  84     _aliases = new (ResourceObj::C_HEAP, mtInternal)
  85                               GrowableArray<Alias>(8, true);      // Hard coded random constant => BAD!
  86   }
  87   Alias alias;
  88   alias._extended_bytecode = new_bytecode;
  89   alias._alias = existing_bytecode;
  90   _aliases->push(alias);
  91 }
  92 
  93 void BCSetTemplate::define_template(Bytecodes::Code code, int flags, TosState in, TosState out, void (*gen)(), char filler) {
  94   assert(filler == ' ', "just checkin'");
  95   define_template(code, flags, in, out, (Template::generator)gen, 0);
  96 }
  97 
  98 void BCSetTemplate::define_template(Bytecodes::Code code, int flags, TosState in, TosState out, void (*gen)(TosState tos), TosState tos) {
  99   define_template(code, flags, in, out, (Template::generator)gen, (int)tos);
 100 }
 101 
 102 void BCSetTemplate::define_template(Bytecodes::Code code, int flags, TosState in, TosState out,
 103     void (*gen)(int arg), int arg) {
 104   const int iswd = 1 << Template::wide_bit;
 105   // determine which table to use
 106   bool is_wide = (flags & iswd) != 0;
 107   // make sure that typed bytecode have a vtos entry point
 108   // TosCa is currently not supported by typed bytecodes
 109   // temporarely disabling this assert to test typed I bytecodes with legacy templates
 110   // assert(in == vtos, "typed bytecodes have vtos entry point only");
 111   Template t;
 112   t.initialize(code, flags, in, out, gen, arg);
 113   if (_templates == NULL) {
 114     _templates = new (ResourceObj::C_HEAP, mtInternal)
 115                    GrowableArray<Template>(8, true);      // Hard coded random constant => BAD!
 116   }
 117   _templates->push(t);
 118 }
 119 
 120 //------------------------------------------------------------------------------------------------------------------------
 121 
 122 #define USE_ALIASES 1
 123 
 124 BCSetTemplate* BCSetTemplate::initialize_type_I_BCSet() {
 125   // For better readability
 126   const char _    = ' ';
 127   const int  ____ = 0;
 128   const int  ubcp = 1 << Template::uses_bcp_bit;
 129   const int  disp = 1 << Template::does_dispatch_bit;
 130   const int  clvm = 1 << Template::calls_vm_bit;
 131   const int  iswd = 1 << Template::wide_bit;
 132   BCSetTemplate* t = new BCSetTemplate(Bytecodes::_bcset_int);
 133 #if USE_ALIASES
 134   // Aliases based implementation
 135   t->define_alias(Bytecodes::cast(Bytecodes::_typed_I_aload)      , Bytecodes::_nofast_iload);
 136   t->define_alias(Bytecodes::cast(Bytecodes::_typed_I_aload_0)    , Bytecodes::_iload_0);
 137   t->define_alias(Bytecodes::cast(Bytecodes::_typed_I_aload_1)    , Bytecodes::_iload_1);
 138   t->define_alias(Bytecodes::cast(Bytecodes::_typed_I_aload_2)    , Bytecodes::_iload_2);
 139   t->define_alias(Bytecodes::cast(Bytecodes::_typed_I_aload_3)    , Bytecodes::_iload_3);
 140   t->define_alias(Bytecodes::cast(Bytecodes::_typed_I_astore)     , Bytecodes::_istore);
 141   t->define_alias(Bytecodes::cast(Bytecodes::_typed_I_astore_0)   , Bytecodes::_istore_0);
 142   t->define_alias(Bytecodes::cast(Bytecodes::_typed_I_astore_1)   , Bytecodes::_istore_1);
 143   t->define_alias(Bytecodes::cast(Bytecodes::_typed_I_astore_2)   , Bytecodes::_istore_2);
 144   t->define_alias(Bytecodes::cast(Bytecodes::_typed_I_astore_3)   , Bytecodes::_istore_3);
 145   t->define_alias(Bytecodes::cast(Bytecodes::_typed_I_aaload)     , Bytecodes::_iaload);
 146   t->define_alias(Bytecodes::cast(Bytecodes::_typed_I_aastore)    , Bytecodes::_iastore);
 147   t->define_alias(Bytecodes::cast(Bytecodes::_typed_I_areturn)    , Bytecodes::_ireturn);
 148   t->define_alias(Bytecodes::cast(Bytecodes::_typed_I_aconst_null), Bytecodes::_iconst_0);
 149 #else
 150   // Templates based implementation
 151 
 152   t->define_template(Bytecodes::cast(Bytecodes::_typed_I_aload)   , ubcp|____|clvm|____, vtos, itos, TemplateTable::iload   ,  _  );
 153   t->define_template(Bytecodes::cast(Bytecodes::_typed_I_aload_0) , ubcp|____|____|____, vtos, itos, TemplateTable::iload   ,  0  );
 154   t->define_template(Bytecodes::cast(Bytecodes::_typed_I_aload_1) , ubcp|____|____|____, vtos, itos, TemplateTable::iload   ,  1  );
 155   t->define_template(Bytecodes::cast(Bytecodes::_typed_I_aload_2) , ubcp|____|____|____, vtos, itos, TemplateTable::iload   ,  2  );
 156   t->define_template(Bytecodes::cast(Bytecodes::_typed_I_aload_3) , ubcp|____|____|____, vtos, itos, TemplateTable::iload   ,  3  );
 157   t->define_template(Bytecodes::cast(Bytecodes::_typed_I_astore)  , ubcp|____|clvm|____, itos, vtos, TemplateTable::istore  ,  _  );
 158   t->define_template(Bytecodes::cast(Bytecodes::_typed_I_astore_0), ubcp|____|____|____, itos, vtos, TemplateTable::istore  ,  0  );
 159   t->define_template(Bytecodes::cast(Bytecodes::_typed_I_astore_1), ubcp|____|____|____, itos, vtos, TemplateTable::istore  ,  1  );
 160   t->define_template(Bytecodes::cast(Bytecodes::_typed_I_astore_2), ubcp|____|____|____, itos, vtos, TemplateTable::istore  ,  2  );
 161   t->define_template(Bytecodes::cast(Bytecodes::_typed_I_astore_3), ubcp|____|____|____, itos, vtos, TemplateTable::istore  ,  3  );
 162   t->define_template(Bytecodes::cast(Bytecodes::_typed_I_aaload)  , ____|____|____|____, itos, itos, TemplateTable::iaload  ,  _  );
 163   t->define_template(Bytecodes::cast(Bytecodes::_typed_I_aastore) , ____|____|clvm|____, itos, vtos, TemplateTable::iastore ,  _  );
 164   t->define_template(Bytecodes::cast(Bytecodes::_typed_I_areturn) , ____|disp|clvm|____, itos, itos, TemplateTable::_return , itos );
 165   // wide variants
 166   t->define_template(Bytecodes::cast(Bytecodes::_typed_I_aload)   , ubcp|____|____|iswd, vtos, itos, TemplateTable::wide_iload  ,  _  );
 167   t->define_template(Bytecodes::cast(Bytecodes::_typed_I_astore)  , ubcp|____|____|iswd, vtos, vtos, TemplateTable::wide_istore ,  _  );
 168 #endif
 169   // A new template is required for typed anewarray
 170   t->define_template(Bytecodes::cast(Bytecodes::_typed_I_anewarray)  , ubcp|____|clvm|____, itos, atos, TemplateTable::new_primitive_array ,  T_INT );
 171   return t;
 172 }
 173 
 174 BCSetTemplate* BCSetTemplate::initialize_type_F_BCSet() {
 175   // For better readability
 176   const char _    = ' ';
 177   const int  ____ = 0;
 178   const int  ubcp = 1 << Template::uses_bcp_bit;
 179   const int  disp = 1 << Template::does_dispatch_bit;
 180   const int  clvm = 1 << Template::calls_vm_bit;
 181   const int  iswd = 1 << Template::wide_bit;
 182   BCSetTemplate* t = new BCSetTemplate(Bytecodes::_bcset_float);
 183 #if USE_ALIASES
 184   // Aliases based implementation
 185   t->define_alias(Bytecodes::cast(Bytecodes::_typed_F_aload)      , Bytecodes::_fload);
 186   t->define_alias(Bytecodes::cast(Bytecodes::_typed_F_aload_0)    , Bytecodes::_fload_0);
 187   t->define_alias(Bytecodes::cast(Bytecodes::_typed_F_aload_1)    , Bytecodes::_fload_1);
 188   t->define_alias(Bytecodes::cast(Bytecodes::_typed_F_aload_2)    , Bytecodes::_fload_2);
 189   t->define_alias(Bytecodes::cast(Bytecodes::_typed_F_aload_3)    , Bytecodes::_fload_3);
 190   t->define_alias(Bytecodes::cast(Bytecodes::_typed_F_astore)     , Bytecodes::_fstore);
 191   t->define_alias(Bytecodes::cast(Bytecodes::_typed_F_astore_0)   , Bytecodes::_fstore_0);
 192   t->define_alias(Bytecodes::cast(Bytecodes::_typed_F_astore_1)   , Bytecodes::_fstore_1);
 193   t->define_alias(Bytecodes::cast(Bytecodes::_typed_F_astore_2)   , Bytecodes::_fstore_2);
 194   t->define_alias(Bytecodes::cast(Bytecodes::_typed_F_astore_3)   , Bytecodes::_fstore_3);
 195   t->define_alias(Bytecodes::cast(Bytecodes::_typed_F_aaload)     , Bytecodes::_faload);
 196   t->define_alias(Bytecodes::cast(Bytecodes::_typed_F_aastore)    , Bytecodes::_fastore);
 197   t->define_alias(Bytecodes::cast(Bytecodes::_typed_F_areturn)    , Bytecodes::_freturn);
 198   t->define_alias(Bytecodes::cast(Bytecodes::_typed_F_aconst_null), Bytecodes::_fconst_0);
 199 #else
 200   // Templates based implementation
 201   t->define_template(Bytecodes::cast(Bytecodes::_typed_F_aload)   ,  ubcp|____|clvm|____, vtos, ftos, TemplateTable::fload   ,  _  );
 202   t->define_template(Bytecodes::cast(Bytecodes::_typed_F_aload_0) ,  ubcp|____|____|____, vtos, ftos, TemplateTable::fload   ,  0  );
 203   t->define_template(Bytecodes::cast(Bytecodes::_typed_F_aload_1) ,  ubcp|____|____|____, vtos, ftos, TemplateTable::fload   ,  1  );
 204   t->define_template(Bytecodes::cast(Bytecodes::_typed_F_aload_2) ,  ubcp|____|____|____, vtos, ftos, TemplateTable::fload   ,  2  );
 205   t->define_template(Bytecodes::cast(Bytecodes::_typed_F_aload_3) ,  ubcp|____|____|____, vtos, ftos, TemplateTable::fload   ,  3  );
 206   t->define_template(Bytecodes::cast(Bytecodes::_typed_F_astore)  ,  ubcp|____|clvm|____, ftos, vtos, TemplateTable::fstore  ,  _  );
 207   t->define_template(Bytecodes::cast(Bytecodes::_typed_F_astore_0),  ubcp|____|____|____, ftos, vtos, TemplateTable::fstore  ,  0  );
 208   t->define_template(Bytecodes::cast(Bytecodes::_typed_F_astore_1),  ubcp|____|____|____, ftos, vtos, TemplateTable::fstore  ,  1  );
 209   t->define_template(Bytecodes::cast(Bytecodes::_typed_F_astore_2),  ubcp|____|____|____, ftos, vtos, TemplateTable::fstore  ,  2  );
 210   t->define_template(Bytecodes::cast(Bytecodes::_typed_F_astore_3),  ubcp|____|____|____, ftos, vtos, TemplateTable::fstore  ,  3  );
 211   t->define_template(Bytecodes::cast(Bytecodes::_typed_F_aaload)  ,  ____|____|____|____, itos, ftos, TemplateTable::faload  ,  _  );
 212   t->define_template(Bytecodes::cast(Bytecodes::_typed_F_aastore) ,  ____|____|clvm|____, ftos, vtos, TemplateTable::fastore ,  _  );
 213   t->define_template(Bytecodes::cast(Bytecodes::_typed_F_areturn) ,  ____|disp|clvm|____, ftos, ftos, TemplateTable::_return , ftos );
 214   // wide variants
 215   t->define_template(Bytecodes::cast(Bytecodes::_typed_F_aload)   ,  ubcp|____|____|iswd, vtos, ftos, TemplateTable::wide_fload  ,  _  );
 216   t->define_template(Bytecodes::cast(Bytecodes::_typed_F_astore)  ,  ubcp|____|____|iswd, vtos, vtos, TemplateTable::wide_fstore ,  _  );
 217 #endif
 218   // A new template is required for typed anewarray
 219     t->define_template(Bytecodes::cast(Bytecodes::_typed_F_anewarray)  , ubcp|____|clvm|____, itos, atos, TemplateTable::new_primitive_array ,  T_FLOAT );
 220 
 221   return t;
 222 }
 223 
 224 #undef USE_ALIASES