X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Fjit%2Fi386%2Fcodegen.c;h=8eab0fbf0511a4cce0d56cac92d930db7c06b8ed;hb=8c6bb03b79a31fcdb02e2331a91a928d558c2845;hp=1a8e1c84c54b2e29f3265d547ccf270e6f81f951;hpb=9be3416493d9b07d279f80c76ffcce16e3016cab;p=cacao.git diff --git a/src/vm/jit/i386/codegen.c b/src/vm/jit/i386/codegen.c index 1a8e1c84c..8eab0fbf0 100644 --- a/src/vm/jit/i386/codegen.c +++ b/src/vm/jit/i386/codegen.c @@ -36,12 +36,12 @@ #include "vm/jit/i386/codegen.h" #include "vm/jit/i386/emit.h" -#include "mm/memory.h" +#include "mm/memory.hpp" -#include "native/localref.h" -#include "native/native.h" +#include "native/localref.hpp" +#include "native/native.hpp" -#include "threads/lock-common.h" +#include "threads/lock.hpp" #include "vm/jit/builtin.hpp" #include "vm/exceptions.hpp" @@ -59,7 +59,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" @@ -3178,35 +3178,49 @@ 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); - 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); - 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); @@ -3337,24 +3351,72 @@ gen_method: 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_ITMP3); + + 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); - M_MOV_IMM(supervftbl, REG_ITMP2); + 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_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_CMP_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_CMP(REG_ITMP3, REG_ITMP1); - M_BA(5); - M_MOV_IMM(1, d); + M_ALD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow)); + M_CMP_MEMINDEX(REG_ITMP2, -4*DISPLAY_SIZE, REG_ITMP1, 2, REG_ITMP3); + if (d >= 4) { + M_SETE(REG_ITMP1); + M_BSEXT(REG_ITMP1, d); + } + else { + 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); + + if (d >= 4) { + M_SETE(REG_ITMP1); + M_BSEXT(REG_ITMP1, d); + } + else { + M_SETE(d); + if (d == REG_ITMP2) + M_BSEXT(d, d); + } + } if (super != NULL) emit_label(cd, BRANCH_LABEL_5);