Merged new changes from default (manually: src/vm/jit/emit-common.cpp, src/vm/ji
authorStefan Ring <stefan@complang.tuwien.ac.at>
Mon, 13 Oct 2008 14:34:46 +0000 (16:34 +0200)
committerStefan Ring <stefan@complang.tuwien.ac.at>
Mon, 13 Oct 2008 14:34:46 +0000 (16:34 +0200)
t/emit-common.hpp)

--HG--
branch : subtype-trunk

1  2 
src/vm/jit/alpha/codegen.c
src/vm/jit/emit-common.hpp
src/vm/jit/i386/codegen.c
src/vm/jit/x86_64/codegen.c

index d44e2f8d16e005a618f278b9c6e39fcbef83d8cf,bb5f050f82ced2be5400d5c93ba7bafe8b08e500..b136fd4dcaaefac36a11c63d4a751ac2f4c60b23
@@@ -57,7 -57,7 +57,7 @@@
  #include "vm/jit/emit-common.hpp"
  #include "vm/jit/jit.hpp"
  #include "vm/jit/linenumbertable.hpp"
- #include "vm/jit/parse.h"
+ #include "vm/jit/parse.hpp"
  #include "vm/jit/patcher-common.hpp"
  #include "vm/jit/reg.h"
  #include "vm/jit/replace.hpp"
@@@ -2722,49 -2722,24 +2722,49 @@@ gen_method
                                        M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
                                        M_ALD(REG_ITMP3, REG_PV, disp);
  
 -                                      M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
 -                                      /*                              if (s1 != REG_ITMP1) { */
 -                                      /*                                      M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, baseval)); */
 -                                      /*                                      M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval)); */
 -                                      /*  #if defined(ENABLE_THREADS) */
 -                                      /*                                      codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase); */
 -                                      /*  #endif */
 -                                      /*                                      M_ISUB(REG_ITMP2, REG_ITMP1, REG_ITMP2); */
 -
 -                                      /*                              } else { */
 -                                      M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
 -                                      M_ISUB(REG_ITMP2, REG_ITMP3, REG_ITMP2);
 -                                      M_ALD(REG_ITMP3, REG_PV, disp);
 -                                      M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
 -
 -                                      /*                              } */
 -                                      M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3);
 -                                      emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP3, s1);
 +                                      if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) {
 +                                              M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
 +                                              M_LADD(REG_ITMP1, REG_ITMP2, REG_ITMP1);
 +                                              M_ALD(REG_ITMP1, REG_ITMP1, 0);
 +                                              M_CMPEQ(REG_ITMP1, REG_ITMP3, REG_ITMP1);
 +                                              emit_label_bnez(cd, BRANCH_LABEL_6, REG_ITMP1);  /* good */
 +
 +                                              if (super == NULL) {
 +                                                      M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
 +                                                      M_CMPEQ_IMM(REG_ITMP1, OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]), REG_ITMP1);
 +                                                      emit_label_beqz(cd, BRANCH_LABEL_10, REG_ITMP1);  /* throw */
 +                                              }
 +
 +                                              M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_depth));
 +                                              M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, subtype_depth));
 +                                              M_CMPLE(REG_ITMP1, REG_ITMP3, REG_ITMP3);
 +                                              emit_label_beqz(cd, BRANCH_LABEL_9, REG_ITMP3);  /* throw */
 +                                              /* reload */
 +                                              M_ALD(REG_ITMP3, REG_PV, disp);
 +                                              M_ALD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow));
 +                                              M_S8ADDQ(REG_ITMP1, REG_ITMP2, REG_ITMP2);
 +                                              M_ALD(REG_ITMP1, REG_ITMP2, -DISPLAY_SIZE*8);
 +                                              M_CMPEQ(REG_ITMP1, REG_ITMP3, REG_ITMP1);
 +                                              emit_label_bnez(cd, BRANCH_LABEL_7, REG_ITMP1);  /* good */
 +
 +                                              emit_label(cd, BRANCH_LABEL_9);
 +                                              if (super == NULL)
 +                                                      emit_label(cd, BRANCH_LABEL_10);
 +
 +                                              /* reload s1, might have been destroyed */
 +                                              emit_load_s1(jd, iptr, REG_ITMP1);
 +                                              M_ALD_INTERN(s1, REG_ZERO, TRAP_ClassCastException);
 +
 +                                              emit_label(cd, BRANCH_LABEL_7);
 +                                              emit_label(cd, BRANCH_LABEL_6);
 +                                              /* reload s1, might have been destroyed */
 +                                              emit_load_s1(jd, iptr, REG_ITMP1);
 +                                      }
 +                                      else {
 +                                              M_ALD(REG_ITMP2, REG_ITMP2, super->vftbl->subtype_offset);
 +                                              M_CMPEQ(REG_ITMP2, REG_ITMP3, REG_ITMP2);
 +                                              emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP2, s1);
 +                                      }
  
                                        if (super != NULL)
                                                emit_label(cd, BRANCH_LABEL_5);
                                        emit_label_beqz(cd, BRANCH_LABEL_5, s1);
                                }
  
 -                              M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
 -                              M_ALD(REG_ITMP2, REG_PV, disp);
 +                              M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
 +                              M_ALD(REG_ITMP3, REG_PV, disp);
 +
 +                              if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) {
 +                                      M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
 +                                      M_LADD(REG_ITMP1, REG_ITMP2, REG_ITMP1);
 +                                      M_ALD(REG_ITMP1, REG_ITMP1, 0);
 +                                      M_CMPEQ(REG_ITMP1, REG_ITMP3, REG_ITMP1);
 +                                      emit_label_beqz(cd, BRANCH_LABEL_8, REG_ITMP1);
 +                                      ICONST(d, 1);
 +                                      emit_label_br(cd, BRANCH_LABEL_6);  /* true */
 +                                      emit_label(cd, BRANCH_LABEL_8);
 +
 +                                      if (super == NULL) {
 +                                              M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
 +                                              M_CMPEQ_IMM(REG_ITMP1, OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]), REG_ITMP1);
 +                                              emit_label_beqz(cd, BRANCH_LABEL_10, REG_ITMP1);  /* false */
 +                                      }
  
 -                              M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
 -                              M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
 -                              M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
 +                                      M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_depth));
  
 -                              M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
 -                              M_CMPULE(REG_ITMP1, REG_ITMP2, d);
 +                                      M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, subtype_depth));
 +                                      M_CMPLE(REG_ITMP1, REG_ITMP3, REG_ITMP3);
 +                                      emit_label_beqz(cd, BRANCH_LABEL_9, REG_ITMP3);  /* false */
 +                                      /* reload */
 +                                      M_ALD(REG_ITMP3, REG_PV, disp);
 +                                      M_ALD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow));
 +                                      M_S8ADDQ(REG_ITMP1, REG_ITMP2, REG_ITMP2);
 +                                      M_ALD(REG_ITMP1, REG_ITMP2, -DISPLAY_SIZE*8);
 +                                      M_CMPEQ(REG_ITMP1, REG_ITMP3, d);
 +
 +                                      if (d == REG_ITMP2)
 +                                              emit_label_br(cd, BRANCH_LABEL_7);
 +                                      emit_label(cd, BRANCH_LABEL_9);
 +                                      if (super == NULL)
 +                                              emit_label(cd, BRANCH_LABEL_10);
 +                                      if (d == REG_ITMP2) {
 +                                              M_CLR(d);
 +
 +                                              emit_label(cd, BRANCH_LABEL_7);
 +                                      }
 +                                      emit_label(cd, BRANCH_LABEL_6);
 +                              }
 +                              else {
 +                                      M_ALD(REG_ITMP2, REG_ITMP2, super->vftbl->subtype_offset);
 +                                      M_CMPEQ(REG_ITMP2, REG_ITMP3, d);
 +                              }
  
                                if (super != NULL)
                                        emit_label(cd, BRANCH_LABEL_5);
index b96bc08ea213fe19a7c355b3dfde5cdf9d8f6ae5,e499f557e3e581e282d241e6e201163964dcb04a..611eca43d943175d53a70e6dba14fe1a9b107aef
@@@ -1,9 -1,7 +1,7 @@@
  /* src/vm/jit/emit-common.hpp - common code emitter functions
  
-    Copyright (C) 2006, 2007 R. Grafl, A. Krall, C. Kruegel, C. Oates,
-    R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
-    C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
-    Institut f. Computersprachen - TU Wien
+    Copyright (C) 2006, 2007, 2008
+    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
  
     This file is part of CACAO.
  
  #define BRANCH_LABEL_4    4
  #define BRANCH_LABEL_5    5
  #define BRANCH_LABEL_6    6
 +#define BRANCH_LABEL_7    7
 +#define BRANCH_LABEL_8    8
 +#define BRANCH_LABEL_9    9
 +#define BRANCH_LABEL_10  10
  
  
  /* constant range macros ******************************************************/
@@@ -163,8 -157,14 +161,14 @@@ void emit_label_bcc(codegendata *cd, s
  void emit_label_br(codegendata *cd, s4 label);
  
  #if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
- void emit_label_beqz(codegendata *cd, s4 label, s4 reg);
- void emit_label_bnez(codegendata *cd, s4 label, s4 reg);
+ void emit_label_beqz(codegendata* cd, int label, int reg);
+ void emit_label_bnez(codegendata* cd, int label, int reg);
+ void emit_label_bltz(codegendata* cd, int label, int reg);
+ void emit_label_bgtz(codegendata* cd, int label, int reg);
+ #endif
+ #if SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS
+ void emit_label_bne(codegendata* cd, int label, int s1, int s2);
  #endif
  
  #if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
index bdedf5b6459f6c813c9f85ff1099689106b164ad,3d667c726a4fbc344de6f99829d97b0230128bb6..c7adf83a5bddb1b7d8c110e6ea20420fdb3bc110
@@@ -60,7 -60,7 +60,7 @@@
  #include "vm/jit/jit.hpp"
  #include "vm/jit/jitcache.hpp"
  #include "vm/jit/linenumbertable.hpp"
- #include "vm/jit/parse.h"
+ #include "vm/jit/parse.hpp"
  #include "vm/jit/patcher-common.hpp"
  #include "vm/jit/reg.h"
  #include "vm/jit/replace.hpp"
@@@ -3231,50 -3231,37 +3231,50 @@@ gen_method
                                        }
  
                                        M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
 -
                                        if (super == NULL) {
                                                patcher_add_patch_ref(jd, PATCHER_checkcast_class,
                                                                                        iptr->sx.s23.s3.c.ref,
                                                                                        0);
                                        }
 -
                                        M_MOV_IMM(supervftbl, REG_ITMP3);
                                        JITCACHE_ADD_CACHED_REF_JD(jd, CRT_CLASSINFO_VFTBL, super);
  
 -                                      M_ILD32(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
 +                                      if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) {
 +                                              M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
 +                                              M_CMP_MEMINDEX(REG_ITMP2, 0, REG_ITMP1, 0, REG_ITMP3);
 +                                              emit_label_beq(cd, BRANCH_LABEL_6);  /* good */
  
 -                                      /*                              if (s1 != REG_ITMP1) { */
 -                                      /*                                      emit_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, baseval), REG_ITMP1); */
 -                                      /*                                      emit_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, diffval), REG_ITMP3); */
 -                                      /* #if defined(ENABLE_THREADS) */
 -                                      /*                                      codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase); */
 -                                      /* #endif */
 -                                      /*                                      emit_alu_reg_reg(cd, ALU_SUB, REG_ITMP1, REG_ITMP2); */
 +                                              if (super == NULL) {
 +                                                      M_ICMP_IMM(OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]), REG_ITMP1);
 +                                                      emit_label_bne(cd, BRANCH_LABEL_10);  /* throw */
 +                                              }
  
 -                                      /*                              } else { */
 -                                      M_ILD32(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
 -                                      M_ISUB(REG_ITMP3, REG_ITMP2);
 -                                      M_MOV_IMM(supervftbl, REG_ITMP3);
 -                                      JITCACHE_ADD_CACHED_REF_JD(jd, CRT_CLASSINFO_VFTBL, super);
 -                                      M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
 +                                              M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_depth));
 +                                              M_CMP_MEMBASE(REG_ITMP2, OFFSET(vftbl_t, subtype_depth), REG_ITMP1);
 +                                              emit_label_bgt(cd, BRANCH_LABEL_9);  /* throw */
 +
 +                                              M_ALD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow));
 +                                              M_CMP_MEMINDEX(REG_ITMP2, -4*DISPLAY_SIZE, REG_ITMP1, 2, REG_ITMP3);
 +                                              emit_label_beq(cd, BRANCH_LABEL_7);  /* good */
 +
 +                                              emit_label(cd, BRANCH_LABEL_9);
 +                                              if (super == NULL)
 +                                                      emit_label(cd, BRANCH_LABEL_10);
 +
 +                                              /* reload s1, might have been destroyed */
 +                                              emit_load_s1(jd, iptr, REG_ITMP1);
 +                                              M_ALD_MEM(s1, TRAP_ClassCastException);
  
 -                                      /*                              } */
 +                                              emit_label(cd, BRANCH_LABEL_7);
 +                                              emit_label(cd, BRANCH_LABEL_6);
 +                                              /* reload s1, might have been destroyed */
 +                                              emit_load_s1(jd, iptr, REG_ITMP1);
 +                                      }
 +                                      else {
 +                                              M_CMP_MEMBASE(REG_ITMP2, super->vftbl->subtype_offset, REG_ITMP3);
  
 -                                      M_CMP(REG_ITMP3, REG_ITMP2);
 -                                      emit_classcast_check(cd, iptr, BRANCH_ULE, REG_ITMP3, s1);
 +                                              emit_classcast_check(cd, iptr, BRANCH_NE, REG_ITMP3, s1);
 +                                      }
  
                                        if (super != NULL)
                                                emit_label(cd, BRANCH_LABEL_5);
                                        emit_label_beq(cd, BRANCH_LABEL_5);
                                }
  
 -                              M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
 -
 +                              M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
                                if (super == NULL) {
                                        patcher_add_patch_ref(jd, PATCHER_instanceof_class,
                                                                                iptr->sx.s23.s3.c.ref, 0);
                                }
 -
 -                              M_MOV_IMM(supervftbl, REG_ITMP2);
 +                              M_MOV_IMM(supervftbl, REG_ITMP3);
                                JITCACHE_ADD_CACHED_REF_JD(jd, CRT_CLASSINFO_VFTBL, super);
 -                              M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
 -                              M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, diffval));
 -                              M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
 -
 -                              M_ISUB(REG_ITMP2, REG_ITMP1);
 -                              M_CLR(d);                                 /* may be REG_ITMP2 */
 -                              M_CMP(REG_ITMP3, REG_ITMP1);
 -                              M_BA(5);
 -                              M_MOV_IMM(1, d);
 +
 +                              if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) {
 +                                      M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
 +                                      M_CMP_MEMINDEX(REG_ITMP2, 0, REG_ITMP1, 0, REG_ITMP3);
 +                                      emit_label_bne(cd, BRANCH_LABEL_8); /* jump over INC/SETE */
 +                                      if (d == REG_ITMP2) {
 +                                              M_SETE(d);
 +                                              M_BSEXT(d, d);
 +                                      } else
 +                                              M_IINC(d);
 +                                      emit_label_br(cd, BRANCH_LABEL_6);  /* true */
 +                                      emit_label(cd, BRANCH_LABEL_8);
 +
 +                                      if (super == NULL) {
 +                                              M_ICMP_IMM(OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]), REG_ITMP1);
 +                                              emit_label_bne(cd, BRANCH_LABEL_10);  /* false */
 +                                      }
 +
 +                                      M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_depth));
 +                                      M_CMP_MEMBASE(REG_ITMP2, OFFSET(vftbl_t, subtype_depth), REG_ITMP1);
 +                                      emit_label_bgt(cd, BRANCH_LABEL_9);  /* false */
 +
 +                                      M_ALD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow));
 +                                      M_CMP_MEMINDEX(REG_ITMP2, -4*DISPLAY_SIZE, REG_ITMP1, 2, REG_ITMP3);
 +                                      M_SETE(d);
 +                                      if (d == REG_ITMP2) {
 +                                              M_BSEXT(d, d);
 +
 +                                              emit_label_br(cd, BRANCH_LABEL_7); /* jump over M_CLR */
 +                                      }
 +
 +                                      emit_label(cd, BRANCH_LABEL_9);
 +                                      if (super == NULL)
 +                                              emit_label(cd, BRANCH_LABEL_10);
 +                                      if (d == REG_ITMP2) {
 +                                              M_CLR(d);
 +
 +                                              emit_label(cd, BRANCH_LABEL_7);
 +                                      }
 +                                      emit_label(cd, BRANCH_LABEL_6);
 +                              }
 +                              else {
 +                                      M_CMP_MEMBASE(REG_ITMP2, super->vftbl->subtype_offset, REG_ITMP3);
 +
 +                                      M_SETE(d);
 +                                      if (d == REG_ITMP2)
 +                                              M_BSEXT(d, d);
 +                              }
  
                                if (super != NULL)
                                        emit_label(cd, BRANCH_LABEL_5);
index ff7bf884adf8c04bf84fa4e75f8dba34c68e03af,18e86af090d752928ae9b0e0fbf5c9f3b3a4eb3c..96f4967bc9f052f7a74ea741adf8dee33a2389bd
@@@ -63,7 -63,7 +63,7 @@@
  #include "vm/jit/jit.hpp"
  #include "vm/jit/linenumbertable.hpp"
  #include "vm/jit/methodheader.h"
- #include "vm/jit/parse.h"
+ #include "vm/jit/parse.hpp"
  #include "vm/jit/patcher-common.hpp"
  #include "vm/jit/reg.h"
  #include "vm/jit/replace.hpp"
@@@ -2567,41 -2567,30 +2567,41 @@@ gen_method
                                        M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
                                        M_ALD(REG_ITMP3, RIP, disp);
  
 -                                      M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
 -
 -                                      /*                                      if (s1 != REG_ITMP1) { */
 -                                      /*                                              emit_movl_membase_reg(cd, REG_ITMP3, */
 -                                      /*                                                                                              OFFSET(vftbl_t, baseval), */
 -                                      /*                                                                                              REG_ITMP1); */
 -                                      /*                                              emit_movl_membase_reg(cd, REG_ITMP3, */
 -                                      /*                                                                                              OFFSET(vftbl_t, diffval), */
 -                                      /*                                                                                              REG_ITMP3); */
 -                                      /*  #if defined(ENABLE_THREADS) */
 -                                      /*                                              codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase); */
 -                                      /*  #endif */
 -                                      /*                                              emit_alu_reg_reg(cd, ALU_SUB, REG_ITMP1, REG_ITMP2); */
 -
 -                                      /*                                      } else { */
 -
 -                                      M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
 -                                      M_ISUB(REG_ITMP3, REG_ITMP2);
 -                                      M_ALD(REG_ITMP3, RIP, disp);
 -                                      M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
 -                                      /*                                      } */
 -
 -                                      M_ICMP(REG_ITMP3, REG_ITMP2);
 -                                      emit_classcast_check(cd, iptr, BRANCH_UGT, REG_ITMP3, s1);
 +                                      if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) {
 +                                              M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
 +                                              M_LCMP_MEMINDEX(REG_ITMP2, 0, REG_ITMP1, 0, REG_ITMP3);
 +                                              emit_label_beq(cd, BRANCH_LABEL_6);  /* good */
 +
 +                                              if (super == NULL) {
 +                                                      M_LCMP_IMM(OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]), REG_ITMP1);
 +                                                      emit_label_bne(cd, BRANCH_LABEL_10);  /* throw */
 +                                              }
 +
 +                                              M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_depth));
 +                                              M_ICMP_MEMBASE(REG_ITMP2, OFFSET(vftbl_t, subtype_depth), REG_ITMP1);
 +                                              emit_label_bgt(cd, BRANCH_LABEL_9);  /* throw */
 +
 +                                              M_ALD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow));
 +                                              M_LCMP_MEMINDEX(REG_ITMP2, -8*DISPLAY_SIZE, REG_ITMP1, 3, REG_ITMP3);
 +                                              emit_label_beq(cd, BRANCH_LABEL_7);  /* good */
 +
 +                                              emit_label(cd, BRANCH_LABEL_9);
 +                                              if (super == NULL)
 +                                                      emit_label(cd, BRANCH_LABEL_10);
 +
 +                                              /* reload s1, might have been destroyed */
 +                                              emit_load_s1(jd, iptr, REG_ITMP1);
 +                                              M_ALD_MEM(s1, TRAP_ClassCastException);
 +
 +                                              emit_label(cd, BRANCH_LABEL_7);
 +                                              emit_label(cd, BRANCH_LABEL_6);
 +                                              /* reload s1, might have been destroyed */
 +                                              emit_load_s1(jd, iptr, REG_ITMP1);
 +                                      }
 +                                      else {
 +                                              M_LCMP_MEMBASE(REG_ITMP2, super->vftbl->subtype_offset, REG_ITMP3);
 +                                              emit_classcast_check(cd, iptr, BRANCH_NE, REG_ITMP3, s1);
 +                                      }
  
                                        if (super != NULL)
                                                emit_label(cd, BRANCH_LABEL_5);
                                        disp = dseg_add_address(cd, super->vftbl);
                                }
  
 -                              M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
 -                              M_ALD(REG_ITMP2, RIP, disp);
 +                              M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
 +                              M_ALD(REG_ITMP3, RIP, disp);
 +
 +                              if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) {
 +                                      M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
 +                                      M_LCMP_MEMINDEX(REG_ITMP2, 0, REG_ITMP1, 0, REG_ITMP3);
 +                                      emit_label_bne(cd, BRANCH_LABEL_8); /* jump over INC/SETE */
 +                                      if (d == REG_ITMP2) {
 +                                              M_SETE(d);
 +                                              M_BSEXT(d, d);
 +                                      } else
 +                                              M_LINC(d);
 +                                      emit_label_br(cd, BRANCH_LABEL_6);  /* true */
 +                                      emit_label(cd, BRANCH_LABEL_8);
 +
 +                                      if (super == NULL) {
 +                                              M_LCMP_IMM(OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]), REG_ITMP1);
 +                                              emit_label_bne(cd, BRANCH_LABEL_10);  /* false */
 +                                      }
  
 -                              M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
 -                              M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, diffval));
 -                              M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
 +                                      M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_depth));
 +                                      M_ICMP_MEMBASE(REG_ITMP2, OFFSET(vftbl_t, subtype_depth), REG_ITMP1);
 +                                      emit_label_bgt(cd, BRANCH_LABEL_9);  /* false */
  
 -                              M_ISUB(REG_ITMP2, REG_ITMP1);
 -                              M_CLR(d); /* may be REG_ITMP2 */
 -                              M_ICMP(REG_ITMP3, REG_ITMP1);
 -                              M_SETULE(d);
 +                                      M_ALD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow));
 +                                      M_LCMP_MEMINDEX(REG_ITMP2, -8*DISPLAY_SIZE, REG_ITMP1, 3, REG_ITMP3);
 +                                      M_SETE(d);
 +                                      if (d == REG_ITMP2) {
 +                                              M_BSEXT(d, d);
 +
 +                                              emit_label_br(cd, BRANCH_LABEL_7); /* jump over M_CLR */
 +                                      }
 +
 +                                      emit_label(cd, BRANCH_LABEL_9);
 +                                      if (super == NULL)
 +                                              emit_label(cd, BRANCH_LABEL_10);
 +                                      if (d == REG_ITMP2) {
 +                                              M_CLR(d);
 +
 +                                              emit_label(cd, BRANCH_LABEL_7);
 +                                      }
 +                                      emit_label(cd, BRANCH_LABEL_6);
 +                              }
 +                              else {
 +                                      M_LCMP_MEMBASE(REG_ITMP2, super->vftbl->subtype_offset, REG_ITMP3);
 +                                      M_SETE(d);
 +                                      if (d == REG_ITMP2)
 +                                              M_BSEXT(d, d);
 +                              }
  
                                if (super != NULL)
                                        emit_label(cd, BRANCH_LABEL_5);