--- /dev/null
+CACAO is currently under development and unfinished. The current version
+is not allowed to be distributed. Copies of CACAO source can be obtained
+from the authors on request for educational and research purposes free
+of charge. We will make available the sources under GNU licences in the
+future when the sources are stable. Commercial licences can be obtained
+via andi@complang.tuwien.ac.at.
+
+ NO WARRANTY
+
+ BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
--- /dev/null
+################################################################################
+# Makefile for the JavaVM - compiler CACAO #
+################################################################################
+#
+# Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+#
+# See file COPYRIGHT for information on usage and disclaimer of warranties
+#
+# Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+# Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
+#
+# Last Change: 1997/10/30
+#
+#
+# ATTENTION: This version of the makefile only works with gmake.
+# This Makefile not only generates object files, but also additional
+# files needed during compilation:
+# nativetypes.hh
+# nativetables.hh
+# All object files and the *.hh can be deleted savely. They will be
+# generated automatically.
+#
+################################################################################
+
+##################### generation of the excutable ##############################
+
+# Enabling/disabling thread support
+USE_THREADS = YES
+#USE_THREADS = NO
+
+ifeq ($(USE_THREADS),YES)
+THREAD_OBJ = threads/threads.a
+THREAD_CFLAGS = -DUSE_THREADS -DEXTERNAL_OVERFLOW -DDONT_FREE_FIRST
+else
+THREAD_OBJ =
+THREAD_CFLAGS =
+endif
+
+CC = cc
+#CFLAGS = -g -mieee -Wall $(THREAD_CFLAGS)
+CFLAGS = -mieee -O3 -Wall $(THREAD_CFLAGS)
+
+#CC = cc
+#CFLAGS = -g3 -ieee $(THREAD_CFLAGS)
+#CFLAGS = -O3 -ieee $(THREAD_CFLAGS)
+
+OBJ = main.o tables.o loader.o compiler.o newcomp.o builtin.o asmpart.o \
+ toolbox/toolbox.a native.o $(THREAD_OBJ)
+OBJH = headers.o tables.o loader.o builtin.o toolbox/toolbox.a $(THREAD_OBJ)
+
+cacao: $(OBJ)
+ $(CC) $(CFLAGS) -o cacao $(OBJ) -lm
+cacaoh: $(OBJH)
+ $(CC) $(CFLAGS) -o cacaoh $(OBJH) -lm
+
+main.o: main.c global.h tables.h compiler.h ncomp/ncomp.h loader.h \
+ asmpart.h builtin.h native.h
+
+headers.o: headers.c global.h tables.h loader.h
+
+loader.o: loader.c global.h loader.h tables.h native.h asmpart.h
+
+compiler.o: builtin.h compiler.h global.h loader.h tables.h native.h \
+ asmpart.h compiler.c comp/*.c sysdep/gen.c sysdep/disass.c
+
+newcomp.o: builtin.h ncomp/ncomp.h global.h loader.h tables.h native.h \
+ asmpart.h ncomp/ncompdef.h ncomp/*.c sysdep/ngen.h sysdep/ngen.c sysdep/disass.c
+
+builtin.o: builtin.c global.h loader.h builtin.h tables.h sysdep/native-math.h
+
+native.o: native.c global.h tables.h native.h asmpart.h builtin.h \
+ nativetypes.hh nativetable.hh nat/*.c
+
+tables.o: tables.c global.h tables.h
+
+global.h: sysdep/types.h toolbox/*.h
+ touch global.h
+
+toolbox/toolbox.a: toolbox/*.c toolbox/*.h
+ cd toolbox; make toolbox.a "CFLAGS=$(CFLAGS)" "CC=$(CC)"
+
+ifeq ($(USE_THREADS),YES)
+threads/threads.a: threads/*.c threads/*.h sysdep/threads.h
+ cd threads; make threads.a "USE_THREADS=$(USE_THREADS)" "CFLAGS=$(CFLAGS)" "CC=$(CC)"
+endif
+
+asmpart.o: sysdep/asmpart.c
+ rm -f asmpart.s
+ $(CC) -E sysdep/asmpart.c > asmpart.s
+ $(CC) -c -o asmpart.o asmpart.s
+ rm -f asmpart.s
+
+
+########################### support targets ####################################
+
+clean:
+ rm -f *.o cacao cacaoh cacao.tgz nativetable.hh nativetypes.hh \
+ core tst/core
+ cd toolbox; make clean
+ cd threads; make clean
+
+tar:
+ rm -f cacao.tgz cacao.tar
+ tar -cvf cacao.tar Makefile */Makefile README COPYRIGHT tst/*.java \
+ doc/*.doc html/*.html *.[ch] comp/*.[ch] ncomp/*.[ch] alpha/*.doc alpha/*.[ch] \
+ nat/*.[ch] toolbox/*.[ch] threads/*.[ch] # sparc/*.[ch]
+ ls -l cacao.tar
+ gzip -9 cacao.tar
+ mv cacao.tar.gz cacao.tgz
+ ls -l cacao.tgz
+
+
+########################## supported architectures #############################
+
+config-alpha:
+ rm -f sysdep
+ ln -s alpha sysdep
+ rm -f threads/sysdep
+ ln -s ../sysdep threads/sysdep
+ make clean
+
+config-sparc:
+ rm -f sysdep
+ ln -s sparc sysdep
+ rm -f threads/sysdep
+ ln -s ../sysdep threads/sysdep
+ make clean
+
+
+
+##################### generation of NATIVE - header files ######################
+
+nativetypes.hh nativetable.hh : cacaoh
+ ./cacaoh java.lang.Object \
+ java.lang.String \
+ java.lang.Class \
+ java.lang.ClassLoader \
+ java.lang.Compiler \
+ java.lang.Double \
+ java.lang.Float \
+ java.lang.Math \
+ java.lang.Runtime \
+ java.lang.SecurityManager \
+ java.lang.System \
+ java.lang.Thread \
+ java.lang.ThreadGroup \
+ java.lang.Throwable \
+\
+ java.io.File \
+ java.io.FileDescriptor \
+ java.io.FileInputStream \
+ java.io.FileOutputStream \
+ java.io.PrintStream \
+ java.io.RandomAccessFile \
+\
+ java.util.Properties \
+ java.util.Date
+
+
\ No newline at end of file
--- /dev/null
+************************* README for CACAO version 0.15 ************************
+
+The current sources of CACAO version 0.15 are a snapshot during development.
+They will change in the near future and are badly documented. This version
+is not intended for public distribution. It is made available only for
+educational and research purposes.
+
+To use the CACAO sources put the cacao015.tgz file in a newly created
+directory and uncompress it using gzip and extract the files using tar.
+Make sure you have installed gmake. Enter:
+
+make config-alpha
+make
+
+After this you should have a working version of cacao and cacaoh. How to
+invoke cacao and which class library has to be used is described at the
+CACAO home page (http://www.complang.tuwien.ac.at/java/cacao/index.html).
+
+Under Linux this version currently works only using the option -cf.
+If you want to use the Digital Unix C-compiler change the variable $CC
+in the Makefile from gcc to cc.
+
+The Sparc port is unfinished and not working. So typing "make config-sparc"
+makes no sense in the moment. Threads are currently also not supported.
+
+For questions mail me at cacao@complang.tuwien.ac.at, for very urgent
+questions mail me at andi@complang.tuwien.ac.at.
+
+Have fun with CACAO
+
+ Andreas Krall
--- /dev/null
+/****************************** asmpart.c **************************************
+* *
+* is an assembly language file, but called .c to fake the preprocessor. *
+* It contains the Java-C interface functions for Alpha processors. *
+* *
+* Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst *
+* *
+* See file COPYRIGHT for information on usage and disclaimer of warranties *
+* *
+* Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at *
+* Andreas Krall EMAIL: cacao@complang.tuwien.ac.at *
+* *
+* Last Change: 1997/04/26 *
+* *
+*******************************************************************************/
+
+
+#define v0 $0
+
+#define t0 $1
+#define t1 $2
+#define t2 $3
+#define t3 $4
+#define t4 $5
+#define t5 $6
+#define t6 $7
+#define t7 $8
+
+#define s0 $9
+#define s1 $10
+#define s2 $11
+#define s3 $12
+#define s4 $13
+#define s5 $14
+#define s6 $15
+
+#define a0 $16
+#define a1 $17
+#define a2 $18
+#define a3 $19
+#define a4 $20
+#define a5 $21
+
+#define t8 $22
+#define t9 $23
+#define t10 $24
+#define t11 $25
+#define ra $26
+#define t12 $27
+
+#define pv t12
+#define AT $at
+#define gp $29
+#define sp $30
+#define zero $31
+
+#define itmp1 $25
+#define itmp2 $28
+#define itmp3 $29
+
+#define xptr itmp1
+#define xpc itmp2
+
+#define sf0 $f2
+#define sf1 $f3
+#define sf2 $f4
+#define sf3 $f5
+#define sf4 $f6
+#define sf5 $f7
+#define sf6 $f8
+#define sf7 $f9
+
+#define fzero $f31
+
+
+#define PAL_imb 134
+
+#define offobjarr 24
+#define offarrsize 8
+
+ .text
+ .set noat
+ .set noreorder
+
+
+/********************* exported functions and variables ***********************/
+
+ .globl has_no_x_instr_set
+ .globl synchronize_caches
+ .globl asm_calljavamethod
+ .globl asm_call_jit_compiler
+ .globl asm_dumpregistersandcall
+ .globl asm_handle_exception
+ .globl asm_handle_nat_exception
+ .globl asm_signal_exception
+ .globl new_builtin_checkcast
+ .globl new_builtin_checkarraycast
+ .globl new_builtin_aastore
+ .globl new_builtin_monitorenter
+ .globl new_builtin_monitorexit
+ .globl new_builtin_idiv
+ .globl new_builtin_irem
+ .globl new_builtin_ldiv
+ .globl new_builtin_lrem
+ .globl perform_alpha_threadswitch
+ .globl initialize_thread_stack
+ .globl used_stack_top
+
+
+/*************************** imported variables *******************************/
+
+ .globl newcompiler
+
+
+/*************************** imported functions *******************************/
+
+ .globl compiler_compile
+ .globl builtin_monitorexit
+ .globl builtin_throw_exception
+ .globl builtin_trace_exception
+ .globl class_java_lang_Object
+
+/*********************** function has_no_x_instr_set ***************************
+* *
+* determines if the byte support instruction set (21164a and higher) *
+* is available. *
+* *
+*******************************************************************************/
+
+ .ent has_no_x_instr_set
+has_no_x_instr_set:
+
+ .long 0x47e03c20 # amask 1,$0
+ jmp zero,(ra) # return
+
+ .end has_no_x_instr_set
+
+
+/********************* function synchronize_caches ****************************/
+
+ .ent synchronize_caches
+synchronize_caches:
+
+ call_pal PAL_imb # synchronise instruction cache
+ jmp zero,(ra) # return
+
+ .end synchronize_caches
+
+
+/********************* function asm_calljavamethod *****************************
+* *
+* This function calls a Java-method (which possibly needs compilation) *
+* with up to 4 parameters. *
+* *
+* This functions calls the JIT-compiler which eventually translates the *
+* method into machine code. *
+* *
+* An possibly throwed exception will be returned to the caller as function *
+* return value, so the java method cannot return a fucntion value (this *
+* function usually calls 'main' and '<clinit>' which do not return a *
+* function value). *
+* *
+* C-prototype: *
+* javaobject_header *asm_calljavamethod (methodinfo *m, *
+* void *arg1, void *arg2, void *arg3, void *arg4); *
+* *
+*******************************************************************************/
+
+#define MethodPointer -8
+#define FrameSize -12
+#define IsSync -16
+#define IsLeaf -20
+#define IntSave -24
+#define FltSave -28
+#define ExTableSize -32
+#define ExTableStart -32
+
+#define ExEntrySize -32
+#define ExStartPC -8
+#define ExEndPC -16
+#define ExHandlerPC -24
+#define ExCatchType -32
+
+ .ent asm_calljavamethod
+
+call_name:
+ .ascii "calljavamethod\0\0"
+
+ .align 3
+ .quad 0 # catch type all
+ .quad calljava_xhandler # end pc
+ .quad calljava_xhandler # end pc
+ .quad asm_calljavamethod # start pc
+ .long 1 # extable size
+ .long 0 # fltsave
+ .long 0 # intsave
+ .long 0 # isleaf
+ .long 0 # IsSync
+ .long 32 # frame size
+ .quad 0 # method pointer (pointer to name) @@@@@
+
+asm_calljavamethod:
+
+ ldgp gp,0(pv)
+ lda sp,-32(sp) # allocate stack space
+ stq gp,24(sp) # save global pointer
+ stq ra,0(sp) # save return address
+
+ stq $16,16(sp) # save method pointer for compiler
+ lda $0,16(sp) # pass pointer to method pointer via $0
+
+ bis $17,$17,$16 # pass the remaining parameters
+ bis $18,$18,$17
+ bis $19,$19,$18
+ bis $20,$20,$19
+
+ lda $28,asm_call_jit_compiler # fake virtual function call
+ stq $28,8(sp) # store function address
+ bis sp,sp,$28 # set method pointer
+
+ ldq pv,8($28) # method call as in Java
+ jmp ra,(pv) # call JIT compiler
+calljava_jit:
+ lda pv,-64(ra) # asm_calljavamethod-calljava_jit(ra) !!!!!!
+
+calljava_return:
+
+ ldq ra,0(sp) # restore return address
+ ldq gp,24(sp) # restore global pointer
+ lda sp,32(sp) # free stack space
+ ldl $0,newcompiler # load newcompiler flag
+ subq $0,1,$0 # negate for clearing $0
+ beq $0,calljava_ret # if newcompiler skip ex copying
+ bis $1,$1,$0 # pass exception to caller (C)
+calljava_ret:
+ jmp zero,(ra)
+
+calljava_xhandler:
+
+ ldq gp,24(sp) # restore global pointer
+ mov itmp1,a0
+ jsr ra,builtin_throw_exception
+ ldq ra,0(sp) # restore return address
+ lda sp,32(sp) # free stack space
+ jmp zero,(ra)
+ .end asm_calljavamethod
+
+
+/****************** function asm_call_jit_compiler *****************************
+* *
+* invokes the compiler for untranslated JavaVM methods. *
+* *
+* Register R0 contains a pointer to the method info structure (prepared *
+* by createcompilerstub). Using the return address in R26 and the *
+* offset in the LDA instruction or using the value in methodptr R28 the *
+* patching address for storing the method address can be computed: *
+* *
+* method address was either loaded using *
+* M_LDQ (REG_PV, REG_PV, a) # invokestatic/special ($27) *
+* M_LDA (REG_PV, REG_RA, low) *
+* M_LDAH(REG_PV, REG_RA, high) # optional *
+* or *
+* M_LDQ (REG_PV, REG_METHODPTR, m) # invokevirtual/interface ($28) *
+* in the static case the method pointer can be computed using the *
+* return address and the lda function following the jmp instruction *
+* *
+*******************************************************************************/
+
+
+ .ent asm_call_jit_compiler
+asm_call_jit_compiler:
+
+ ldgp gp,0(pv)
+ ldl $22,-8(ra) # load instruction LDQ PV,xxx($yy)
+ srl $22,16,$22 # shift right register number $yy
+ and $22,31,$22 # isolate register number
+ subl $22,28,$22 # test for REG_METHODPTR
+ beq $22,noregchange
+ ldl $22,0(ra) # load instruction LDA PV,xxx(RA)
+ sll $22,48,$22
+ sra $22,48,$22 # isolate offset
+ addq $22,ra,$28 # compute update address
+ ldl $22,4(ra) # load instruction LDAH PV,xxx(PV)
+ srl $22,16,$22 # isolate instruction code
+ lda $22,-0x177b($22) # test for LDAH
+ bne $22,noregchange
+ ldl $22,0(ra) # load instruction LDA PV,xxx(RA)
+ sll $22,16,$22 # compute high offset
+ addl $22,0,$22 # sign extend high offset
+ addq $22,$28,$28 # compute update address
+noregchange:
+ lda sp,-14*8(sp) # reserve stack space
+ stq $16,0*8(sp) # save all argument registers
+ stq $17,1*8(sp) # they could be used by method
+ stq $18,2*8(sp)
+ stq $19,3*8(sp)
+ stq $20,4*8(sp)
+ stq $21,5*8(sp)
+ stt $f16,6*8(sp)
+ stt $f17,7*8(sp)
+ stt $f18,8*8(sp)
+ stt $f19,9*8(sp)
+ stt $f20,10*8(sp)
+ stt $f21,11*8(sp)
+ stq $28,12*8(sp) # save method pointer
+ stq ra,13*8(sp) # save return address
+
+ ldq $16,0($0) # pass 'methodinfo' pointer to
+ jsr ra,compiler_compile # compiler
+ ldgp gp,0(ra)
+
+ call_pal PAL_imb # synchronise instruction cache
+
+ ldq $16,0*8(sp) # load argument registers
+ ldq $17,1*8(sp)
+ ldq $18,2*8(sp)
+ ldq $19,3*8(sp)
+ ldq $20,4*8(sp)
+ ldq $21,5*8(sp)
+ ldt $f16,6*8(sp)
+ ldt $f17,7*8(sp)
+ ldt $f18,8*8(sp)
+ ldt $f19,9*8(sp)
+ ldt $f20,10*8(sp)
+ ldt $f21,11*8(sp)
+ ldq $28,12*8(sp) # load method pointer
+ ldq ra,13*8(sp) # load return address
+ lda sp,14*8(sp) # deallocate stack area
+
+ ldl $22,-8(ra) # load instruction LDQ PV,xxx($yy)
+ sll $22,48,$22
+ sra $22,48,$22 # isolate offset
+
+ addq $22,$28,$22 # compute update address via method pointer
+ stq $0,0($22) # save new method address there
+
+ bis $0,$0,pv # load method address into pv
+
+ jmp zero, (pv) # and call method. The method returns
+ # directly to the caller (ra).
+
+ .end asm_call_jit_compiler
+
+
+/****************** function asm_dumpregistersandcall **************************
+* *
+* This funtion saves all callee saved registers and calls the function *
+* which is passed as parameter. *
+* *
+* This function is needed by the garbage collector, which needs to access *
+* all registers which are stored on the stack. Unused registers are *
+* cleared to avoid interferances with the GC. *
+* *
+* void asm_dumpregistersandcall (functionptr f); *
+* *
+*******************************************************************************/
+
+ .ent asm_dumpregistersandcall
+asm_dumpregistersandcall:
+ lda sp,-16*8(sp) # allocate stack
+ stq ra,0(sp) # save return address
+
+ stq $9,1*8(sp) # save all callee saved registers
+ stq $10,2*8(sp) # intialize the remaining registers
+ stq $11,3*8(sp)
+ stq $12,4*8(sp)
+ stq $13,5*8(sp)
+ stq $14,6*8(sp)
+ stq $15,7*8(sp)
+ stt $f2,8*8(sp)
+ stt $f3,9*8(sp)
+ stt $f4,10*8(sp)
+ stt $f5,11*8(sp)
+ stt $f6,12*8(sp)
+ stt $f7,13*8(sp)
+ stt $f8,14*8(sp)
+ stt $f9,15*8(sp)
+
+ bis zero,zero,$0 # intialize the remaining registers
+ bis zero,zero,$1
+ bis zero,zero,$2
+ bis zero,zero,$3
+ bis zero,zero,$4
+ bis zero,zero,$5
+ bis zero,zero,$6
+ bis zero,zero,$7
+ bis zero,zero,$8
+ bis zero,zero,$17
+ bis zero,zero,$18
+ bis zero,zero,$19
+ bis zero,zero,$20
+ bis zero,zero,$21
+ bis zero,zero,$22
+ bis zero,zero,$23
+ bis zero,zero,$24
+ bis zero,zero,$25
+ bis zero,zero,$26
+ bis zero,zero,$27
+ bis zero,zero,$28
+ bis zero,zero,$29
+ cpys $f31,$f31,$f0
+ cpys $f31,$f31,$f1
+ cpys $f31,$f31,$f10
+ cpys $f31,$f31,$f11
+ cpys $f31,$f31,$f12
+ cpys $f31,$f31,$f13
+ cpys $f31,$f31,$f14
+ cpys $f31,$f31,$f15
+ cpys $f31,$f31,$f16
+ cpys $f31,$f31,$f17
+ cpys $f31,$f31,$f18
+ cpys $f31,$f31,$f19
+ cpys $f31,$f31,$f20
+ cpys $f31,$f31,$f21
+ cpys $f31,$f31,$f22
+ cpys $f31,$f31,$f23
+ cpys $f31,$f31,$f24
+ cpys $f31,$f31,$f25
+ cpys $f31,$f31,$f26
+ cpys $f31,$f31,$f27
+ cpys $f31,$f31,$f28
+ cpys $f31,$f31,$f29
+ cpys $f31,$f31,$f30
+
+ bis $16,$16,pv # load function pointer
+ jmp ra,(pv) # and call function
+
+ ldq ra,0(sp) # load return address
+ lda sp,16*8(sp) # deallocate stack
+ jmp zero,(ra) # return
+
+ .end asm_dumpregistersandcall
+
+
+/********************* function asm_handle_exception ***************************
+* *
+* This function handles an exception. It does not use the usual calling *
+* conventions. The exception pointer is passed in REG_ITMP1 and the *
+* pc from the exception raising position is passed in REG_ITMP2. It searches *
+* the local exception table for a handler. If no one is found, it unwinds *
+* stacks and continues searching the callers. *
+* *
+* void asm_handle_exception (exceptionptr, exceptionpc); *
+* *
+*******************************************************************************/
+
+ .ent asm_handle_nat_exception
+asm_handle_nat_exception:
+
+ ldl t0,0(ra) # load instruction LDA PV,xxx(RA)
+ sll t0,48,t0
+ sra t0,48,t0 # isolate offset
+ addq t0,ra,pv # compute update address
+ ldl t0,4(ra) # load instruction LDAH PV,xxx(PV)
+ srl t0,16,t0 # isolate instruction code
+ lda t0,-0x177b(t0) # test for LDAH
+ bne t0,asm_handle_exception
+ ldl t0,0(ra) # load instruction LDA PV,xxx(RA)
+ sll t0,16,t0 # compute high offset
+ addl t0,0,t0 # sign extend high offset
+ addq t0,pv,pv # compute update address
+
+ .aent asm_handle_exception
+asm_handle_exception:
+
+ lda sp,-18*8(sp) # allocate stack
+ stq t0,0*8(sp) # save possible used registers
+ stq t1,1*8(sp) # also registers used by builtin_checkcast
+ stq t2,2*8(sp)
+ stq t3,3*8(sp)
+ stq t4,4*8(sp)
+ stq t5,5*8(sp)
+ stq t6,6*8(sp)
+ stq t7,7*8(sp)
+ stq t8,8*8(sp)
+ stq t9,9*8(sp)
+ stq t10,10*8(sp)
+ stq v0,11*8(sp)
+ stq a0,12*8(sp)
+ stq a1,13*8(sp)
+ stq a2,14*8(sp)
+ stq a3,15*8(sp)
+ stq a4,16*8(sp)
+ stq a5,17*8(sp)
+
+ lda t3,1(zero) # set no unwind flag
+ex_stack_loop:
+ lda sp,-5*8(sp) # allocate stack
+ stq xptr,0*8(sp) # save used register
+ stq xpc,1*8(sp)
+ stq pv,2*8(sp)
+ stq ra,3*8(sp)
+ stq t3,4*8(sp)
+
+ mov xptr,a0
+ ldq a1,MethodPointer(pv)
+ mov xpc,a2
+ mov t3,a3
+ br ra,ex_trace # set ra for gp loading
+ex_trace:
+ ldgp gp,0(ra) # load gp
+ jsr ra,builtin_trace_exception # builtin_trace_exception(xptr,methodptr)
+
+ ldq xptr,0*8(sp) # restore used register
+ ldq xpc,1*8(sp)
+ ldq pv,2*8(sp)
+ ldq ra,3*8(sp)
+ ldq t3,4*8(sp)
+ lda sp,5*8(sp) # deallocate stack
+
+ ldl t0,ExTableSize(pv) # t0 = exception table size
+ beq t0,empty_table # if empty table skip
+ lda t1,ExTableStart(pv) # t1 = start of exception table
+
+ex_table_loop:
+ ldq t2,ExStartPC(t1) # t2 = exception start pc
+ cmple t2,xpc,t2 # t2 = (startpc <= xpc)
+ beq t2,ex_table_cont # if (false) continue
+ ldq t2,ExEndPC(t1) # t2 = exception end pc
+ cmplt xpc,t2,t2 # t2 = (xpc < endpc)
+ beq t2,ex_table_cont # if (false) continue
+ ldq a1,ExCatchType(t1) # arg1 = exception catch type
+ beq a1,ex_handle_it # NULL catches everything
+ mov xptr,a0 # arg0 = exception pointer
+
+ lda sp,-7*8(sp) # allocate stack
+ stq t0,0*8(sp) # save used register
+ stq t1,1*8(sp)
+ stq t3,2*8(sp)
+ stq xptr,3*8(sp)
+ stq xpc,4*8(sp)
+ stq pv,5*8(sp)
+ stq ra,6*8(sp)
+
+ br ra,ex_gpload # set ra for gp loading
+ex_gpload:
+ ldgp gp,0(ra) # load gp
+ jsr ra,builtin_checkcast # builtin_checkcast(xptr,catchtype)
+
+ ldq t0,0*8(sp) # restore used register
+ ldq t1,1*8(sp)
+ ldq t3,2*8(sp)
+ ldq xptr,3*8(sp)
+ ldq xpc,4*8(sp)
+ ldq pv,5*8(sp)
+ ldq ra,6*8(sp)
+ lda sp,7*8(sp) # deallocate stack
+
+ beq v0,ex_table_cont # if (false) continue
+
+ex_handle_it:
+
+ ldq xpc,ExHandlerPC(t1) # xpc = exception handler pc
+
+ beq t3,ex_jump # if (!(no stack unwinding) skip
+
+ ldq t0,0*8(sp) # restore possible used registers
+ ldq t1,1*8(sp) # also registers used by builtin_checkcast
+ ldq t2,2*8(sp)
+ ldq t3,3*8(sp)
+ ldq t4,4*8(sp)
+ ldq t5,5*8(sp)
+ ldq t6,6*8(sp)
+ ldq t7,7*8(sp)
+ ldq t8,8*8(sp)
+ ldq t9,9*8(sp)
+ ldq t10,10*8(sp)
+ ldq v0,11*8(sp)
+ ldq a0,12*8(sp)
+ ldq a1,13*8(sp)
+ ldq a2,14*8(sp)
+ ldq a3,15*8(sp)
+ ldq a4,16*8(sp)
+ ldq a5,17*8(sp)
+ lda sp,18*8(sp) # deallocate stack
+
+ex_jump:
+ jmp zero,(xpc) # jump to the handler
+
+ex_table_cont:
+ lda t1,ExEntrySize(t1) # next exception table entry
+ subl t0,1,t0 # decrement entry counter
+ bgt t0,ex_table_loop # if (t0 > 0) next entry
+
+empty_table:
+ beq t3,ex_already_cleared # if here the first time, then
+ lda sp,18*8(sp) # deallocate stack and
+ clr t3 # clear the no unwind flag
+ex_already_cleared:
+ ldl t0,IsSync(pv) # t0 = SyncOffset
+ beq t0,no_monitor_exit # if zero no monitorexit
+ addq sp,t0,t0 # add Offset to stackptr
+ ldq a0,-8(t0) # load monitorexit pointer
+
+ lda sp,-7*8(sp) # allocate stack
+ stq t0,0*8(sp) # save used register
+ stq t1,1*8(sp)
+ stq t3,2*8(sp)
+ stq xptr,3*8(sp)
+ stq xpc,4*8(sp)
+ stq pv,5*8(sp)
+ stq ra,6*8(sp)
+
+ br ra,ex_mon_load # set ra for gp loading
+ex_mon_load:
+ ldgp gp,0(ra) # load gp
+ jsr ra,builtin_monitorexit # builtin_monitorexit(objectptr)
+
+ ldq t0,0*8(sp) # restore used register
+ ldq t1,1*8(sp)
+ ldq t3,2*8(sp)
+ ldq xptr,3*8(sp)
+ ldq xpc,4*8(sp)
+ ldq pv,5*8(sp)
+ ldq ra,6*8(sp)
+ lda sp,7*8(sp) # deallocate stack
+
+no_monitor_exit:
+ ldl t0,FrameSize(pv) # t0 = frame size
+ addq sp,t0,sp # unwind stack
+ mov sp,t0 # t0 = pointer to save area
+ ldl t1,IsLeaf(pv) # t1 = is leaf procedure
+ bne t1,ex_no_restore # if (leaf) skip
+ ldq ra,-8(t0) # restore ra
+ lda t0,-8(t0) # t0--
+ex_no_restore:
+ mov ra,xpc # the new xpc is ra
+ ldl t1,IntSave(pv) # t1 = saved int register count
+ br t2,ex_int1 # t2 = current pc
+ex_int1:
+ lda t2,44(t2) # lda t2,ex_int2-ex_int1(t2) !!!!!!!!!!!!!!!
+ negl t1,t1 # negate register count
+ s4addq t1,t2,t2 # t2 = ex_int_sav - 4 * register count
+ jmp zero,(t2) # jump to save position
+ ldq s0,-56(t0)
+ ldq s1,-48(t0)
+ ldq s2,-40(t0)
+ ldq s3,-32(t0)
+ ldq s4,-24(t0)
+ ldq s5,-16(t0)
+ ldq s6,-8(t0)
+ex_int2:
+ s8addq t1,t0,t0 # t0 = t0 - 8 * register count
+
+ ldl t1,FltSave(pv) # t1 = saved flt register count
+ br t2,ex_flt1 # t2 = current pc
+ex_flt1:
+ lda t2,48(t2) # lda t2,ex_flt2-ex_flt1(t2) !!!!!!!!!!!!!!!
+ negl t1,t1 # negate register count
+ s4addq t1,t2,t2 # t2 = ex_flt_sav - 4 * register count
+ jmp zero,(t2) # jump to save position
+ ldt $f2,-64(t0)
+ ldt $f3,-56(t0)
+ ldt $f4,-48(t0)
+ ldt $f5,-40(t0)
+ ldt $f6,-32(t0)
+ ldt $f7,-24(t0)
+ ldt $f8,-16(t0)
+ ldt $f9,-8(t0)
+ex_flt2:
+ ldl t0,0(ra) # load instruction LDA PV,xxx(RA)
+ sll t0,48,t0
+ sra t0,48,t0 # isolate offset
+ addq t0,ra,pv # compute update address
+ ldl t0,4(ra) # load instruction LDAH PV,xxx(PV)
+ srl t0,16,t0 # isolate instruction code
+ lda t0,-0x177b(t0) # test for LDAH
+ bne t0,ex_stack_loop
+ ldl t0,0(ra) # load instruction LDA PV,xxx(RA)
+ sll t0,16,t0 # compute high offset
+ addl t0,0,t0 # sign extend high offset
+ addq t0,pv,pv # compute update address
+ br ex_stack_loop
+
+ .end asm_handle_exception
+
+
+/********************* function asm_signal_exception ***************************
+* *
+* This function handles an exception which was catched by a signal. *
+* *
+* void asm_signal_exception (exceptionptr, signalcontext); *
+* *
+*******************************************************************************/
+
+#define sigctxstack 0*8 /* sigstack state to restore */
+#define sigctxmask 1*8 /* signal mask to restore */
+#define sigctxpc 2*8 /* pc at time of signal */
+#define sigctxpsl 3*8 /* psl to retore */
+#define sigctxr00 4*8 /* processor regs 0 to 31 */
+#define sigctxr01 5*8
+#define sigctxr02 6*8
+#define sigctxr03 7*8
+#define sigctxr04 8*8
+#define sigctxr05 9*8
+#define sigctxr06 10*8
+#define sigctxr07 11*8
+#define sigctxr08 12*8
+#define sigctxr09 13*8
+#define sigctxr10 14*8
+#define sigctxr11 15*8
+#define sigctxr12 16*8
+#define sigctxr13 17*8
+#define sigctxr14 18*8
+#define sigctxr15 19*8
+#define sigctxr16 20*8
+#define sigctxr17 21*8
+#define sigctxr18 22*8
+#define sigctxr19 23*8
+#define sigctxr20 24*8
+#define sigctxr21 25*8
+#define sigctxr22 26*8
+#define sigctxr23 27*8
+#define sigctxr24 28*8
+#define sigctxr25 29*8
+#define sigctxr26 30*8
+#define sigctxr27 31*8
+#define sigctxr28 32*8
+#define sigctxr29 33*8
+#define sigctxr30 34*8
+#define sigctxr31 35*8
+
+#define sigctxfpuse 36*8 /* fp has been used */
+#define sigctxf00 37*8 /* fp regs 0 to 31 */
+#define sigctxf01 38*8
+#define sigctxf02 39*8
+#define sigctxf03 40*8
+#define sigctxf04 41*8
+#define sigctxf05 42*8
+#define sigctxf06 43*8
+#define sigctxf07 44*8
+#define sigctxf08 45*8
+#define sigctxf09 46*8
+#define sigctxf10 47*8
+#define sigctxf11 48*8
+#define sigctxf12 49*8
+#define sigctxf13 50*8
+#define sigctxf14 51*8
+#define sigctxf15 52*8
+#define sigctxf16 53*8
+#define sigctxf17 54*8
+#define sigctxf18 55*8
+#define sigctxf19 56*8
+#define sigctxf20 57*8
+#define sigctxf21 58*8
+#define sigctxf22 59*8
+#define sigctxf23 60*8
+#define sigctxf24 61*8
+#define sigctxf25 62*8
+#define sigctxf26 63*8
+#define sigctxf27 64*8
+#define sigctxf28 65*8
+#define sigctxf29 66*8
+#define sigctxf30 67*8
+#define sigctxf31 68*8
+
+#define sigctxhfpcr 69*8 /* floating point control register */
+#define sigctxsfpcr 70*8 /* software fpcr */
+
+ .ent asm_signal_exception
+asm_signal_exception:
+
+ mov a0,xptr
+ mov a1,sp
+ ldq xpc,sigctxpc(sp)
+ ldq v0,sigctxr00(sp) # restore possible used registers
+ ldq t0,sigctxr01(sp)
+ ldq t1,sigctxr02(sp)
+ ldq t2,sigctxr03(sp)
+ ldq t3,sigctxr04(sp)
+ ldq t4,sigctxr05(sp)
+ ldq t5,sigctxr06(sp)
+ ldq t6,sigctxr07(sp)
+ ldq t7,sigctxr08(sp)
+ ldq s0,sigctxr09(sp)
+ ldq s1,sigctxr10(sp)
+ ldq s2,sigctxr11(sp)
+ ldq s3,sigctxr12(sp)
+ ldq s4,sigctxr13(sp)
+ ldq s5,sigctxr14(sp)
+ ldq s6,sigctxr15(sp)
+ ldq a0,sigctxr16(sp)
+ ldq a1,sigctxr17(sp)
+ ldq a2,sigctxr18(sp)
+ ldq a3,sigctxr19(sp)
+ ldq a4,sigctxr20(sp)
+ ldq a5,sigctxr21(sp)
+ ldq t8,sigctxr22(sp)
+ ldq t9,sigctxr23(sp)
+ ldq t10,sigctxr24(sp)
+ ldq ra,sigctxr26(sp)
+ ldq pv,sigctxr27(sp)
+ ldq sp,sigctxr30(sp)
+ br asm_handle_nat_exception
+ .end asm_signal_exception
+
+
+/********************* function new_builtin_monitorenter ***********************
+* *
+* Does null check and calls monitorenter or throws an exception *
+* *
+*******************************************************************************/
+
+ .ent new_builtin_monitorenter
+new_builtin_monitorenter:
+
+ ldgp gp,0(pv)
+ lda pv,builtin_monitorenter
+ beq a0,nb_monitorenter # if (null) throw exception
+ jmp zero,(pv) # else call builtin_monitorenter
+
+nb_monitorenter:
+ ldq xptr,proto_java_lang_NullPointerException
+ lda xpc,-4(ra) # faulting address is return adress - 4
+ br asm_handle_nat_exception
+ .end new_builtin_monitorenter
+
+
+/********************* function new_builtin_monitorexit ************************
+* *
+* Does null check and calls monitorexit or throws an exception *
+* *
+*******************************************************************************/
+
+ .ent new_builtin_monitorexit
+new_builtin_monitorexit:
+
+ ldgp gp,0(pv)
+ lda pv,builtin_monitorexit
+ beq a0,nb_monitorexit # if (null) throw exception
+ jmp zero,(pv) # else call builtin_monitorexit
+
+nb_monitorexit:
+ ldq xptr,proto_java_lang_NullPointerException
+ lda xpc,-4(ra) # faulting address is return adress - 4
+ br asm_handle_nat_exception
+ .end new_builtin_monitorenter
+
+
+/************************ function new_builtin_idiv ****************************
+* *
+* Does null check and calls idiv or throws an exception *
+* *
+*******************************************************************************/
+
+ .ent new_builtin_idiv
+new_builtin_idiv:
+
+ ldgp gp,0(pv)
+ lda pv,builtin_idiv
+ beq a1,nb_idiv # if (null) throw exception
+ jmp zero,(pv) # else call builtin_idiv
+
+nb_idiv:
+ ldq xptr,proto_java_lang_ArithmeticException
+ lda xpc,-4(ra) # faulting address is return adress - 4
+ br asm_handle_nat_exception
+ .end new_builtin_idiv
+
+
+/************************ function new_builtin_ldiv ****************************
+* *
+* Does null check and calls ldiv or throws an exception *
+* *
+*******************************************************************************/
+
+ .ent new_builtin_ldiv
+new_builtin_ldiv:
+
+ ldgp gp,0(pv)
+ lda pv,builtin_ldiv
+ beq a1,nb_ldiv # if (null) throw exception
+ jmp zero,(pv) # else call builtin_ldiv
+
+nb_ldiv:
+ ldq xptr,proto_java_lang_ArithmeticException
+ lda xpc,-4(ra) # faulting address is return adress - 4
+ br asm_handle_nat_exception
+ .end new_builtin_ldiv
+
+
+/************************ function new_builtin_irem ****************************
+* *
+* Does null check and calls irem or throws an exception *
+* *
+*******************************************************************************/
+
+ .ent new_builtin_irem
+new_builtin_irem:
+
+ ldgp gp,0(pv)
+ lda pv,builtin_irem
+ beq a1,nb_irem # if (null) throw exception
+ jmp zero,(pv) # else call builtin_irem
+
+nb_irem:
+ ldq xptr,proto_java_lang_ArithmeticException
+ lda xpc,-4(ra) # faulting address is return adress - 4
+ br asm_handle_nat_exception
+ .end new_builtin_irem
+
+
+/************************ function new_builtin_lrem ****************************
+* *
+* Does null check and calls lrem or throws an exception *
+* *
+*******************************************************************************/
+
+ .ent new_builtin_lrem
+new_builtin_lrem:
+
+ ldgp gp,0(pv)
+ lda pv,builtin_lrem
+ beq a1,nb_lrem # if (null) throw exception
+ jmp zero,(pv) # else call builtin_lrem
+
+nb_lrem:
+ ldq xptr,proto_java_lang_ArithmeticException
+ lda xpc,-4(ra) # faulting address is return adress - 4
+ br asm_handle_nat_exception
+ .end new_builtin_lrem
+
+
+/*********************** function new_builtin_checkcast ************************
+* *
+* Does the cast check and eventually throws an exception *
+* *
+*******************************************************************************/
+
+ .ent new_builtin_checkcast
+new_builtin_checkcast:
+
+ ldgp gp,0(pv)
+ lda sp,-16(sp) # allocate stack space
+ stq ra,0(sp) # save return address
+ stq a0,8(sp) # save object pointer
+ jsr ra,builtin_checkcast # builtin_checkcast
+ ldgp gp,0(ra)
+ beq v0,nb_ccast_throw # if (false) throw exception
+ ldq ra,0(sp) # restore return address
+ ldq v0,8(sp) # return object pointer
+ lda sp,16(sp) # free stack space
+ jmp zero,(ra)
+
+nb_ccast_throw:
+ ldq xptr,proto_java_lang_ClassCastException
+ ldq ra,0(sp) # restore return address
+ lda sp,16(sp) # free stack space
+ lda xpc,-4(ra) # faulting address is return adress - 4
+ br asm_handle_nat_exception
+ .end new_builtin_checkcast
+
+
+/******************* function new_builtin_checkarraycast ***********************
+* *
+* Does the cast check and eventually throws an exception *
+* *
+*******************************************************************************/
+
+ .ent new_builtin_checkarraycast
+new_builtin_checkarraycast:
+
+ ldgp gp,0(pv)
+ lda sp,-16(sp) # allocate stack space
+ stq ra,0(sp) # save return address
+ stq a0,8(sp) # save object pointer
+ jsr ra,builtin_checkarraycast # builtin_checkarraycast
+ ldgp gp,0(ra)
+ beq v0,nb_carray_throw # if (false) throw exception
+ ldq ra,0(sp) # restore return address
+ ldq v0,8(sp) # return object pointer
+ lda sp,16(sp) # free stack space
+ jmp zero,(ra)
+
+nb_carray_throw:
+ ldq xptr,proto_java_lang_ClassCastException
+ ldq ra,0(sp) # restore return address
+ lda sp,16(sp) # free stack space
+ lda xpc,-4(ra) # faulting address is return adress - 4
+ br asm_handle_nat_exception
+ .end new_builtin_checkarraycast
+
+
+/******************* function new_builtin_aastore ******************************
+* *
+* Does the cast check and eventually throws an exception *
+* *
+*******************************************************************************/
+
+ .ent new_builtin_aastore
+new_builtin_aastore:
+
+ ldgp gp,0(pv)
+ beq a0,nb_aastore_null # if null pointer throw exception
+ ldl t0,offarrsize(a0) # load size
+ lda sp,-24(sp) # allocate stack space
+ stq ra,0(sp) # save return address
+ s8addq a1,a0,t1 # add index*8 to arrayref
+ cmpult a1,t0,t0 # do bound check
+ beq t0,nb_aastore_bound # if out of bounds throw exception
+ mov a2,a1 # object is second argument
+ stq t1,8(sp) # save store position
+ stq a1,16(sp) # save object
+ jsr ra,builtin_canstore # builtin_canstore(arrayref,object)
+ ldgp gp,0(ra)
+ ldq ra,0(sp) # restore return address
+ ldq a0,8(sp) # restore store position
+ ldq a1,16(sp) # restore object
+ lda sp,24(sp) # free stack space
+ beq v0,nb_aastore_throw # if (false) throw exception
+ stq a1,offobjarr(a0) # store objectptr in array
+ jmp zero,(ra)
+
+nb_aastore_null:
+ ldq xptr,proto_java_lang_NullPointerException
+ mov ra,xpc # faulting address is return adress
+ br asm_handle_nat_exception
+
+nb_aastore_bound:
+ ldq xptr,proto_java_lang_ArrayIndexOutOfBoundsException
+ lda sp,24(sp) # free stack space
+ mov ra,xpc # faulting address is return adress
+ br asm_handle_nat_exception
+
+nb_aastore_throw:
+ ldq xptr,proto_java_lang_ArrayStoreException
+ mov ra,xpc # faulting address is return adress
+ br asm_handle_nat_exception
+
+ .end new_builtin_aastore
+
+
+/********************** function initialize_thread_stack ***********************
+* *
+* initialized a thread stack *
+* *
+*******************************************************************************/
+
+ .ent initialize_thread_stack
+initialize_thread_stack:
+
+ lda a1,-128(a1)
+ stq zero, 0(a1)
+ stq zero, 8(a1)
+ stq zero, 16(a1)
+ stq zero, 24(a1)
+ stq zero, 32(a1)
+ stq zero, 40(a1)
+ stq zero, 48(a1)
+ stt fzero, 56(a1)
+ stt fzero, 64(a1)
+ stt fzero, 72(a1)
+ stt fzero, 80(a1)
+ stt fzero, 88(a1)
+ stt fzero, 96(a1)
+ stt fzero, 104(a1)
+ stt fzero, 112(a1)
+ stq a0, 120(a1)
+ mov a1, v0
+ jmp zero,(ra)
+ .end initialize_thread_stack
+
+
+/******************* function perform_alpha_threadswitch ***********************
+* *
+* performs a threadswitch *
+* *
+*******************************************************************************/
+
+ .ent perform_alpha_threadswitch
+perform_alpha_threadswitch:
+
+ subq sp,128,sp
+ stq s0, 0(sp)
+ stq s1, 8(sp)
+ stq s2, 16(sp)
+ stq s3, 24(sp)
+ stq s4, 32(sp)
+ stq s5, 40(sp)
+ stq s6, 48(sp)
+ stt sf0, 56(sp)
+ stt sf1, 64(sp)
+ stt sf2, 72(sp)
+ stt sf3, 80(sp)
+ stt sf4, 88(sp)
+ stt sf5, 96(sp)
+ stt sf6, 104(sp)
+ stt sf7, 112(sp)
+ stq ra, 120(sp)
+ stq sp, 0(a0)
+ ldq sp, 0(a1)
+ ldq s0, 0(sp)
+ ldq s1, 8(sp)
+ ldq s2, 16(sp)
+ ldq s3, 24(sp)
+ ldq s4, 32(sp)
+ ldq s5, 40(sp)
+ ldq s6, 48(sp)
+ ldt sf0, 56(sp)
+ ldt sf1, 64(sp)
+ ldt sf2, 72(sp)
+ ldt sf3, 80(sp)
+ ldt sf4, 88(sp)
+ ldt sf5, 96(sp)
+ ldt sf6, 104(sp)
+ ldt sf7, 112(sp)
+ ldq ra, 120(sp)
+ mov ra, t12
+ addq sp, 128, sp
+ jmp zero,(ra)
+ .end perform_alpha_threadswitch
+
+
+/*********************** function used_stack_top *******************************
+* *
+* returns $sp *
+* *
+*******************************************************************************/
+
+ .ent used_stack_top
+used_stack_top:
+
+ mov sp, v0
+ jmp zero,(ra)
+ .end used_stack_top
--- /dev/null
+/***************************** calling.doc *************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Das ist eine kurze Dokumentation "uber die internen Aufrufskonventionen
+ der Java-Methoden in der DEC-ALHPA-Version.
+
+ Author: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1997/02/05
+
+*******************************************************************************/
+FILE: calling.doc
+
+Das ist eine kurze Dokumentation "uber die internen Aufrufskonventionen
+der Java-Methoden in der DEC-ALHPA-Version.
+
+-------------------------------------------------------------------------------
+
+
+Die Aufrufskonventionen halten sich weitgehende an die Konventionen
+f"ur normale C-Funktionen, allerdings mit einigen zus"atzlichen
+Registerbelegungen:
+
+R28 ..... enth"alt bei einem Methodenaufruf auf jeden Fall den Zeiger
+ auf die zugeh"orige 'methodinfo'-Struktur, die gegebenenfalls an
+ den JIT-Compiler weitergegeben werden muss.
+
+ Wenn von Java-Methoden aus direkt C-Funktionen aufgerufen werden,
+ (f"ur die nat"urlich auch keine 'methodinfo'-Struktur existiert),
+ dann hat dieses Register keinen definierten Wert (Alle von der
+ JavaVM verwendeten Funktionen, z. B. 'builtin_new', etc. werden
+ so aufgerufen)
+
+R1 ...... enth"alt nach Methodenbeendigung entweder NULL oder einen Zeiger
+ auf ein Objekt vom Typ java.lang.Throwable (oder einem davon
+ abgeleiteten Typ).
+ Wenn das der Fall ist, dann wurde in der Methode eine Exception
+ geworfen, die nicht abgefangen werden konnte, und jetzt beim
+ Aufrufer weiter bearbeitet werden muss.
+
+
+
+Die restlichen Register folgen den normalen Konventionen, aber ich gebe
+hier noch einmal eine kurze "Ubersicht:
+
+
+INTEGER-REGISTER:
+
+R0 ........ R"uckgabewert von den Methoden f"ur die Typen:
+ INT,LONG,ADDRESS
+
+R1 ........ Adresse der geworfenen Exception (oder NULL)
+
+R2-R8 ..... tempor"are Register (werden im Unterprogram zerst"ort)
+
+R9-R15 .... gesicherte Register (werden im Unterprogramm nicht ver"andert)
+
+R16-R21 ... Argumentregister 1 - 6 (hier werden die ersten sechs Methoden-
+ Argumente eingetragen, sofern sie von den Typen INT,LONG,ADDRESS
+ sind. Diese Argumentregister werden im Unterprogramm zerst"ort
+
+R22-R24 ... tempor"are Register
+ (werden im Unterprogramm zerst"ort)
+
+R25 ....... tempor"ares Register f"ur kurzfristige Zwischenergebnisse
+ (wird im Unterprogramm zerst"ort)
+
+R26 (ra) .. R"ucksprungadresse (bleibt im Unterprogramm erhalten)
+
+R27 (pv) .. Prozedurzeiger. Dieses Register muss auf jeden Fall einen Zeiger
+ auf die aufgerufene Prozedur enthalten (damit die Zugriffe
+ auf das Datensegment funktionieren k"onnen).
+ (der Wert bleibt im Unterprogramm erhalten)
+
+R28 ....... Zeiger auf die 'methodinfo' - Struktur. Muss auf jeden Fall bei
+ allen Methodenaufrufen richtig gesetzt sein (wegen eines eventuellen
+ Compiler-Aufrufs)
+ (wird im Unterprogramm zerst"ort)
+
+R29 ....... tempor"ares Register f"ur kurzfristige Zwischenergebnisse
+ (wird im Unterprogramm zerst"ort)
+
+R30 (sp) .. Zeiger auf die Untergrenze des Stack (der Stack w"achst von
+ oben nach unten)
+
+R31 ....... enth"alt immer NULL
+
+
+
+FLIESSKOMMA-REGISTER:
+
+
+F0 ........ enth"alt die R"uckgabewert der Methoden vom Typ:
+ FLOAT, DOUBLE
+F1 ........ enth"alt den Imagin"aranteil von einem komplexen Funktionswert
+ (wird von mir nicht benutzt)
+
+F2-F9 ..... gesicherte Register (werden im Unterprogramm nicht ver"andert)
+
+F10-F15 ... tempor"are Register (werden im Unterprogramm zerst"ort)
+
+F16-F21 ... Argumentregister f"ur die ersten 6 Parameter, sofern diese
+ vom den Typen FLOAT oder DOUBLE sind
+
+F22-F24 ... tempor"are Register (werden im Unterprogramm zerst"ort)
+
+F25-F31 ... tempor"are Register f"ur kurzfristige Zwischenergebnisse
+ (werden im Unterprogramm zerst"ort)
+
+F31 ....... enth"alt immer 0.0
+
+
+
+PARAMETER"UBERGABE AM STACK:
+
+Bei mehr als sechs Parametern reicht der Platz in den Registern nicht mehr
+aus, daf"ur werden alle Parameter ab dem Siebenten am Stack "ubergeben,
+und zwar nach folgendem Muster:
+
+
+ | ..... |
+ --------------------------------------------------
+ | Parameter 9 ( 64 bit, egal bei welchem Typ) |
+ --------------------------------------------------
+ | Parameter 8 ( 64 bit, egal bei welchem Typ |
+ --------------------------------------------------
+ R30 (sp) ---> | Parameter 7 ( 64 bit, egal bei welchem Typ) |
+ --------------------------------------------------
+
+Der Stackpointer zeigt dabei auf die Untergrenze des Parameterbereichs.
+
+
+
+
+
+VOLLST"ANDIGES LAYOUT EINES STACKFRAMES:
+
+Jede Methode muss (wenn es keine Leaf-Methode ist, auf jeden Fall) gewisse
+Registerinhalte am Stack sichern.
+Eventuell werden auch noch lokale Werte, die nicht mehr in Registern
+Platz finden, ebenfalls am Stack aufbewahrt, und die Parameter"ubergabe
+bei mehr als 6 Parametern ben"otigt ebenfalls Platz am Stack.
+
+Ein vollst"andiger Stackframe hat also dieses Aussehen (jeder Eintrag
+im Stackframe ist unabh"angig vom Typ auf jedem Fall 64 bit lang, die
+Gr"ossenangaben der Bereiche sind in solchen Einheiten von 64 Bit
+angegeben):
+
+ ---------------------------------------------
+ | Parameter n (vom Aufrufer) |
+ ---------------------------------------------
+ | Parameter n-1 |
+ ---------------------------------------------
+ | ... |
+ ---------------------------------------------
+ SP vorher -> | Parameter 7 |
+ ============================================= ---
+ | gesichertes RA | savedregs_num
+ ---------------------------------------------
+ | andere gesicherte Register |
+ ============================================= ---
+ | Platz f"ur lokale Werte, die nicht mehr | localvars_num
+ | in Register passen |
+ ============================================= ---
+ | .... | arguments_num
+ ---------------------------------------------
+ | Parameter 8 |
+ ---------------------------------------------
+ SP ---> | Parameter 7 (f"ur aufgerufenen Methoden) |
+ ============================================= ---
+
+
+Damit die Anf"ange der einzelnen Bereiche (im Codegenerator) leichter
+ausgedr"uckt werden k"onnen, sind ein paar Hilfsvariablen vorgesehen, die
+die Adressierung der einzelnen Bereiche vereinfachen:
+ localvars_base = arguments_num
+ savedregs_base = localvars_base + localvars_num
+ parentargs_base = savedregs_base + savedregs_num
+
--- /dev/null
+/****************************** asmpart.c **************************************
+* *
+* is an assembly language file, but called .c to fake the preprocessor. *
+* It contains the Java-C interace functions for Alpha processors. *
+* *
+* Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst *
+* *
+* See file COPYRIGHT for information on usage and disclaimer of warranties *
+* *
+* Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at *
+* Andreas Krall EMAIL: cacao@complang.tuwien.ac.at *
+* *
+* Last Change: 1997/04/26 *
+* *
+*******************************************************************************/
+
+#define v0 r0
+
+#define t0 r1
+#define t1 r2
+#define t2 r3
+#define t3 r4
+#define t4 r5
+#define t5 r6
+#define t6 r7
+#define t7 r8
+
+#define s0 r9
+#define s1 r10
+#define s2 r11
+#define s3 r12
+#define s4 r13
+#define s5 r14
+#define s6 r15
+
+#define a0 r16
+#define a1 r17
+#define a2 r18
+#define a3 r19
+#define a4 r20
+#define a5 r21
+
+#define t8 r22
+#define t9 r23
+#define t10 r24
+#define t11 r25
+#define ra r26
+#define t12 r27
+
+#define pv t12
+#define AT .
+#define gp r29
+#define sp r30
+#define zero r31
+
+#define PAL_imb 134
+
+
+/* .set noat
+ .set noreorder
+*/
+
+
+/********************* exported functions and variables ***********************/
+
+/* .globl has_no_x_instr_set
+ .globl synchronize_caches
+ .globl asm_calljavamethod
+ .globl asm_call_jit_compiler
+ .globl asm_dumpregistersandcall
+*/
+
+/*************************** imported functions *******************************/
+
+/* .globl compiler_compile
+*/
+
+/*********************** function has_no_x_instr_set ***************************
+* *
+* determines if the byte support instruction set (21164a and higher) *
+* is available. *
+* *
+*******************************************************************************/
+ zero <- t0
+
+ .ident has_no_x_instr_set
+ .psect code_sec, code
+has_no_x_instr_set::
+
+/* .long 0x47e03c20 ; amask 1,r0
+*/
+
+ zap r0,1,r0
+
+ jmp zero,(ra) ; return
+
+ .end has_no_x_instr_set
+
+
+/********************* function synchronize_caches ****************************/
+
+ .ident synchronize_caches
+ .psect code_sec, code
+synchronize_caches::
+
+ call_pal PAL_imb ; synchronise instruction cache
+ jmp zero,(ra) ; return
+
+ .end synchronize_caches
+
+
+
+/********************* function asm_calljavamethod *****************************
+* *
+* This function calls a Java-method (which possibly needs compilation) *
+* with up to 4 parameters. *
+* *
+* This functions calls the JIT-compiler which eventually translates the *
+* method into machine code. *
+* *
+* An possibly throwed exception will be returned to the caller as function *
+* return value, so the java method cannot return a fucntion value (this *
+* function usually calls 'main' and '<clinit>' which do not return a *
+* function value). *
+* *
+* C-prototype: *
+* javaobject_header *asm_calljavamethod (methodinfo *m, *
+* void *arg1, void *arg2, void *arg3, void *arg4); *
+* *
+*******************************************************************************/
+
+ .ident asm_calljavamethod
+ .psect codesect3, code
+ .external asm_call_jit_compiler
+
+asm_calljavamethod::
+
+; ldgp gp,0(pv)
+; .prologue 1
+ lda sp,-24(sp) ; allocate stack space
+ stq ra,0(sp) ; save return address
+
+ stq r16,16(sp) ; save method pointer for compiler
+ lda r0,16(sp) ; pass pointer to method pointer via r0
+
+ bis r17,r17,r16 ; pass the remaining parameters
+ bis r18,r18,r17
+ bis r19,r19,r18
+ bis r20,r20,r19
+
+ la r28,asm_call_jit_compiler ; fake virtual function call
+ ; Changed!! from lda
+
+ stq r28,8(sp) ; store function address
+ bis sp,sp,r28 ; set method pointer
+
+ ldq pv,8(r28) ; method call as in Java
+ jmp ra,(pv) ; call JIT compiler
+
+ ldq ra,0(sp) ; restore return address
+ lda sp,24(sp) ; free stack space
+
+ bis r1,r1,r0 ; pass exception to caller (C)
+ jmp zero,(ra)
+
+ .end asm_calljavamethod
+
+
+/****************** function asm_call_jit_compiler *****************************
+* *
+* invokes the compiler for untranslated JavaVM methods. *
+* *
+* Register R0 contains a pointer to the method info structure (prepared *
+* by createcompilerstub). Using the return address in R26 and the *
+* offset in the LDA instruction or using the value in methodptr R28 the *
+* patching address for storing the method address can be computed: *
+* *
+* method address was either loaded using *
+* M_LDQ (REG_PV, REG_PV, a) ; invokestatic/special (r27) *
+* M_LDA (REG_PV, REG_RA, low) *
+* M_LDAH(REG_PV, REG_RA, high) ; optional *
+* or *
+* M_LDQ (REG_PV, REG_METHODPTR, m) ; invokevirtual/interace (r28) *
+* in the static case the method pointer can be computed using the *
+* return address and the lda function following the jmp instruction *
+* *
+*******************************************************************************/
+
+
+ .ident asm_call_jit_compiler
+ .psect code_sec1, code
+ .external compiler_compile
+
+asm_call_jit_compiler::
+
+; ldgp gp,0(pv)
+; .prologue 1
+ ldl r22,-8(ra) ; load instruction LDQ PV,xxx(ryy)
+ srl r22,16,r22 ; shift right register number ryy
+ and r22,31,r22 ; isolate register number
+ subl r22,28,r22 ; test for REG_METHODPTR
+ beq r22,noregchange
+ ldl r22,0(ra) ; load instruction LDA PV,xxx(RA)
+ sll r22,48,r22
+ sra r22,48,r22 ; isolate offset
+ addq r22,ra,r28 ; compute update address
+ ldl r22,4(ra) ; load instruction LDAH PV,xxx(PV)
+ srl r22,16,r22 ; isolate instruction code
+ lda r22,-0x177b(r22) ; test for LDAH
+ bne r22,noregchange
+ ldl r22,0(ra) ; load instruction LDA PV,xxx(RA)
+ sll r22,16,r22 ; compute high offset
+ addl r22,0,r22 ; sign extend high offset
+ addq r22,r28,r28 ; compute update address
+noregchange:
+ lda sp,-14*8(sp) ; reserve stack space
+ stq r16,0*8(sp) ; save all argument registers
+ stq r17,1*8(sp) ; they could be used by method
+ stq r18,2*8(sp)
+ stq r19,3*8(sp)
+ stq r20,4*8(sp)
+ stq r21,5*8(sp)
+ stt f16,6*8(sp)
+ stt f17,7*8(sp)
+ stt f18,8*8(sp)
+ stt f19,9*8(sp)
+ stt f20,10*8(sp)
+ stt f21,11*8(sp)
+ stq r28,12*8(sp) ; save method pointer
+ stq ra,13*8(sp) ; save return address
+
+ ldq r16,0(r0) ; pass 'methodinfo' pointer to
+ bsr ra,compiler_compile ; compiler
+; ldgp gp,0(ra)
+
+ call_pal PAL_imb ; synchronise instruction cache
+
+ ldq r16,0*8(sp) ; load argument registers
+ ldq r17,1*8(sp)
+ ldq r18,2*8(sp)
+ ldq r19,3*8(sp)
+ ldq r20,4*8(sp)
+ ldq r21,5*8(sp)
+ ldt f16,6*8(sp)
+ ldt f17,7*8(sp)
+ ldt f18,8*8(sp)
+ ldt f19,9*8(sp)
+ ldt f20,10*8(sp)
+ ldt f21,11*8(sp)
+ ldq r28,12*8(sp) ; load method pointer
+ ldq ra,13*8(sp) ; load return address
+ lda sp,14*8(sp) ; deallocate stack area
+
+ ldl r22,-8(ra) ; load instruction LDQ PV,xxx(ryy)
+ sll r22,48,r22
+ sra r22,48,r22 ; isolate offset
+
+ addq r22,r28,r22 ; compute update address via method pointer
+ stq r0,0(r22) ; save new method address there
+
+ bis r0,r0,pv ; load method address into pv
+
+ jmp zero, (pv) ; and call method. The method returns
+ ; directly to the caller (ra).
+
+ .end asm_call_jit_compiler
+
+
+/****************** function asm_dumpregistersandcall **************************
+* *
+* This funtion saves all callee saved registers and calls the function *
+* which is passed as parameter. *
+* *
+* This function is needed by the garbage collector, which needs to access *
+* all registers which are stored on the stack. Unused registers are *
+* cleared to avoid intererances with the GC. *
+* *
+* void asm_dumpregistersandcall (functionptr f); *
+* *
+*******************************************************************************/
+
+ .ident asm_dumpregistersandcall
+ .psect code_sec2, code
+asm_dumpregistersandcall::
+ lda sp,-16*8(sp) ; allocate stack
+ stq ra,0(sp) ; save return address
+
+ stq r9,1*8(sp) ; save all callee saved registers
+ stq r10,2*8(sp) ; intialize the remaining registers
+ stq r11,3*8(sp)
+ stq r12,4*8(sp)
+ stq r13,5*8(sp)
+ stq r14,6*8(sp)
+ stq r15,7*8(sp)
+ stt f2,8*8(sp)
+ stt f3,9*8(sp)
+ stt f4,10*8(sp)
+ stt f5,11*8(sp)
+ stt f6,12*8(sp)
+ stt f7,13*8(sp)
+ stt f8,14*8(sp)
+ stt f9,15*8(sp)
+
+ bis zero,zero,r0 ; intialize the remaining registers
+ bis zero,zero,r1
+ bis zero,zero,r2
+ bis zero,zero,r3
+ bis zero,zero,r4
+ bis zero,zero,r5
+ bis zero,zero,r6
+ bis zero,zero,r7
+ bis zero,zero,r8
+ bis zero,zero,r17
+ bis zero,zero,r18
+ bis zero,zero,r19
+ bis zero,zero,r20
+ bis zero,zero,r21
+ bis zero,zero,r22
+ bis zero,zero,r23
+ bis zero,zero,r24
+ bis zero,zero,r25
+ bis zero,zero,r26
+ bis zero,zero,r27
+ bis zero,zero,r28
+ bis zero,zero,r29
+ cpys f31,f31,f0
+ cpys f31,f31,f1
+ cpys f31,f31,f10
+ cpys f31,f31,f11
+ cpys f31,f31,f12
+ cpys f31,f31,f13
+ cpys f31,f31,f14
+ cpys f31,f31,f15
+ cpys f31,f31,f16
+ cpys f31,f31,f17
+ cpys f31,f31,f18
+ cpys f31,f31,f19
+ cpys f31,f31,f20
+ cpys f31,f31,f21
+ cpys f31,f31,f22
+ cpys f31,f31,f23
+ cpys f31,f31,f24
+ cpys f31,f31,f25
+ cpys f31,f31,f26
+ cpys f31,f31,f27
+ cpys f31,f31,f28
+ cpys f31,f31,f29
+ cpys f31,f31,f30
+
+ bis r16,r16,pv ; load function pointer
+ jmp ra,(pv) ; and call function
+
+ ldq ra,0(sp) ; load return address
+ lda sp,16*8(sp) ; deallocate stack
+ jmp zero,(ra) ; return
+
+ .end
+
--- /dev/null
+/*************************** alpha/defines.h ***********************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ system-dependent definitions
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+ Mark Probst EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1997/09/11
+
+*******************************************************************************/
+
+#define USE_INTERNAL_THREADS
+
+#define HAVE_FCNTL
+#define HAVE_IOCTL
--- /dev/null
+/********************************* disass.c ************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ A very primitive disassembler for Alpha machine code for easy debugging.
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+ Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1997/10/22
+
+*******************************************************************************/
+
+
+#define ITYPE_UNDEF 0
+#define ITYPE_JMP 1
+#define ITYPE_MEM 2
+#define ITYPE_BRA 3
+#define ITYPE_OP 4
+#define ITYPE_FOP 5
+
+static struct { int op; char *name; int itype; } ops[] = {
+ { 0x00, "", ITYPE_UNDEF},
+ { 0x01, "", ITYPE_UNDEF},
+ { 0x02, "", ITYPE_UNDEF},
+ { 0x03, "", ITYPE_UNDEF},
+ { 0x04, "", ITYPE_UNDEF},
+ { 0x05, "", ITYPE_UNDEF},
+ { 0x06, "", ITYPE_UNDEF},
+ { 0x07, "", ITYPE_UNDEF},
+ { 0x08, "LDA ", ITYPE_MEM},
+ { 0x09, "LDAH ", ITYPE_MEM},
+ { 0x0a, "LDB ", ITYPE_MEM},
+ { 0x0b, "LDQ_U ", ITYPE_MEM},
+ { 0x0c, "LDW ", ITYPE_MEM},
+ { 0x0d, "STW ", ITYPE_MEM},
+ { 0x0e, "STB ", ITYPE_MEM},
+ { 0x0f, "STQ_U ", ITYPE_MEM},
+ { 0x10, "OP ", ITYPE_OP},
+ { 0x11, "OP ", ITYPE_OP},
+ { 0x12, "OP ", ITYPE_OP},
+ { 0x13, "OP ", ITYPE_OP},
+ { 0x14, "", ITYPE_UNDEF},
+ { 0x15, "", ITYPE_UNDEF},
+ { 0x16, "FOP ", ITYPE_FOP},
+ { 0x17, "FOP ", ITYPE_FOP},
+ { 0x18, "MEMFMT ", ITYPE_MEM},
+ { 0x19, "", ITYPE_UNDEF},
+ { 0x1a, "JMP ", ITYPE_JMP},
+ { 0x1b, "", ITYPE_UNDEF},
+ { 0x1c, "OP ", ITYPE_OP},
+ { 0x1d, "", ITYPE_UNDEF},
+ { 0x1e, "", ITYPE_UNDEF},
+ { 0x1f, "", ITYPE_UNDEF},
+ { 0x20, "LDF ", ITYPE_MEM},
+ { 0x21, "LDG ", ITYPE_MEM},
+ { 0x22, "LDS ", ITYPE_MEM},
+ { 0x23, "LDT ", ITYPE_MEM},
+ { 0x24, "STF ", ITYPE_MEM},
+ { 0x25, "STG ", ITYPE_MEM},
+ { 0x26, "STS ", ITYPE_MEM},
+ { 0x27, "STT ", ITYPE_MEM},
+ { 0x28, "LDL ", ITYPE_MEM},
+ { 0x29, "LDQ ", ITYPE_MEM},
+ { 0x2a, "LDL_L ", ITYPE_MEM},
+ { 0x2b, "LDQ_L ", ITYPE_MEM},
+ { 0x2c, "STL ", ITYPE_MEM},
+ { 0x2d, "STQ ", ITYPE_MEM},
+ { 0x2e, "STL_C ", ITYPE_MEM},
+ { 0x2f, "STQ_C ", ITYPE_MEM},
+ { 0x30, "BR ", ITYPE_BRA},
+ { 0x31, "FBEQ ", ITYPE_BRA},
+ { 0x32, "FBLT ", ITYPE_BRA},
+ { 0x33, "FBLE ", ITYPE_BRA},
+ { 0x34, "BSR ", ITYPE_BRA},
+ { 0x35, "FBNE ", ITYPE_BRA},
+ { 0x36, "FBGE ", ITYPE_BRA},
+ { 0x37, "FBGT ", ITYPE_BRA},
+ { 0x38, "BLBC ", ITYPE_BRA},
+ { 0x39, "BEQ ", ITYPE_BRA},
+ { 0x3a, "BLT ", ITYPE_BRA},
+ { 0x3b, "BLE ", ITYPE_BRA},
+ { 0x3c, "BLBS ", ITYPE_BRA},
+ { 0x3d, "BNE ", ITYPE_BRA},
+ { 0x3e, "BGE ", ITYPE_BRA},
+ { 0x3f, "BGT ", ITYPE_BRA}
+};
+
+static struct { u2 op,fun; char *name; } op3s[] = {
+ { 0x10, 0x00, "ADDL " },
+ { 0x10, 0x40, "ADDL/V " },
+ { 0x10, 0x20, "ADDQ " },
+ { 0x10, 0x60, "ADDQ/V " },
+ { 0x10, 0x09, "SUBL " },
+ { 0x10, 0x49, "SUBL/V " },
+ { 0x10, 0x29, "SUBQ " },
+ { 0x10, 0x69, "SUBQ/V " },
+ { 0x10, 0x2D, "CMPEQ " },
+ { 0x10, 0x4D, "CMPLT " },
+ { 0x10, 0x6D, "CMPLE " },
+ { 0x10, 0x1D, "CMPULT " },
+ { 0x10, 0x3D, "CMPULE " },
+ { 0x10, 0x0F, "CMPBGE " },
+ { 0x10, 0x02, "S4ADDL " },
+ { 0x10, 0x0b, "S4SUBL " },
+ { 0x10, 0x22, "S4ADDQ " },
+ { 0x10, 0x2b, "S4SUBQ " },
+ { 0x10, 0x12, "S8ADDL " },
+ { 0x10, 0x1b, "S8SUBL " },
+ { 0x10, 0x32, "S8ADDQ " },
+ { 0x10, 0x3b, "S8SUBQ " },
+ { 0x11, 0x00, "AND " },
+ { 0x11, 0x20, "OR " },
+ { 0x11, 0x40, "XOR " },
+ { 0x11, 0x08, "ANDNOT " },
+ { 0x11, 0x28, "ORNOT " },
+ { 0x11, 0x48, "XORNOT " },
+ { 0x11, 0x24, "CMOVEQ " },
+ { 0x11, 0x44, "CMOVLT " },
+ { 0x11, 0x64, "CMOVLE " },
+ { 0x11, 0x26, "CMOVNE " },
+ { 0x11, 0x46, "CMOVGE " },
+ { 0x11, 0x66, "CMOVGT " },
+ { 0x11, 0x14, "CMOVLBS" },
+ { 0x11, 0x16, "CMOVLBC" },
+ { 0x12, 0x39, "SLL " },
+ { 0x12, 0x3C, "SRA " },
+ { 0x12, 0x34, "SRL " },
+ { 0x12, 0x30, "ZAP " },
+ { 0x12, 0x31, "ZAPNOT " },
+ { 0x12, 0x06, "EXTBL " },
+ { 0x12, 0x16, "EXTWL " },
+ { 0x12, 0x26, "EXTLL " },
+ { 0x12, 0x36, "EXTQL " },
+ { 0x12, 0x5a, "EXTWH " },
+ { 0x12, 0x6a, "EXTLH " },
+ { 0x12, 0x7a, "EXTQH " },
+ { 0x12, 0x0b, "INSBL " },
+ { 0x12, 0x1b, "INSWL " },
+ { 0x12, 0x2b, "INSLL " },
+ { 0x12, 0x3b, "INSQL " },
+ { 0x12, 0x57, "INSWH " },
+ { 0x12, 0x67, "INSLH " },
+ { 0x12, 0x77, "INSQH " },
+ { 0x12, 0x02, "MSKBL " },
+ { 0x12, 0x12, "MSKWL " },
+ { 0x12, 0x22, "MSKLL " },
+ { 0x12, 0x32, "MSKQL " },
+ { 0x12, 0x52, "MSKWH " },
+ { 0x12, 0x62, "MSKLH " },
+ { 0x12, 0x72, "MSKQH " },
+ { 0x13, 0x00, "MULL " },
+ { 0x13, 0x60, "MULQ/V " },
+ { 0x13, 0x40, "MULL/V " },
+ { 0x13, 0x30, "UMULH " },
+ { 0x16, 0x080, "FADD " },
+ { 0x16, 0x0a0, "DADD " },
+ { 0x16, 0x081, "FSUB " },
+ { 0x16, 0x0a1, "DSUB " },
+ { 0x16, 0x082, "FMUL " },
+ { 0x16, 0x0a2, "DMUL " },
+ { 0x16, 0x083, "FDIV " },
+ { 0x16, 0x0a3, "DDIV " },
+ { 0x16, 0x580, "FADDS " },
+ { 0x16, 0x5a0, "DADDS " },
+ { 0x16, 0x581, "FSUBS " },
+ { 0x16, 0x5a1, "DSUBS " },
+ { 0x16, 0x582, "FMULS " },
+ { 0x16, 0x5a2, "DMULS " },
+ { 0x16, 0x583, "FDIVS " },
+ { 0x16, 0x5a3, "DDIVS " },
+ { 0x16, 0x0ac, "CVTDF " },
+ { 0x16, 0x0bc, "CVTLF " },
+ { 0x16, 0x0be, "CVTLD " },
+ { 0x16, 0x0af, "CVTDL " },
+ { 0x16, 0x02f, "CVTDLC " },
+ { 0x16, 0x5ac, "CVTDFS " },
+ { 0x16, 0x5af, "CVTDLS " },
+ { 0x16, 0x52f, "CVTDLCS" },
+ { 0x16, 0x0a4, "FCMPUN " },
+ { 0x16, 0x0a5, "FCMPEQ " },
+ { 0x16, 0x0a6, "FCMPLT " },
+ { 0x16, 0x0a7, "FCMPLE " },
+ { 0x16, 0x5a4, "FCMPUNS" },
+ { 0x16, 0x5a5, "FCMPEQS" },
+ { 0x16, 0x5a6, "FCMPLTS" },
+ { 0x16, 0x5a7, "FCMPLES" },
+ { 0x17, 0x020, "FMOV " },
+ { 0x17, 0x021, "FMOVN " },
+ { 0x1c, 0x0, "BSEXT " },
+ { 0x1c, 0x1, "WSEXT " },
+
+ { 0x00, 0x00, NULL }
+};
+
+
+static void disasscmd (int c, int pos)
+{
+ int op, opfun, fopfun, i;
+ int ra, rb, rc, lit, disp;
+
+ op = (c>>26) & 0x3f;
+ opfun = (c>>5) & 0x7f;
+ fopfun = (c>>5) & 0x7ff;
+ ra = (c>>21) & 0x1f;
+ rb = (c>>16) & 0x1f;
+ rc = (c>>0) & 0x1f;
+ lit = (c>>13) & 0xff;
+ disp = (c<<16) >> 16;
+
+ printf ("%6x: %8x ", pos, c);
+
+ switch ( ops[op].itype ) {
+ case ITYPE_JMP:
+ switch ((c>>14) & 3) {
+ case 0:
+ printf ("JMP ");
+ break;
+ case 1:
+ printf ("JSR ");
+ break;
+ case 2:
+ printf ("RET ");
+ break;
+ case 3:
+ printf ("JSR_CO ");
+ break;
+ }
+ printf ("$%d,$%d\n", ra, rb);
+ break;
+
+ case ITYPE_MEM:
+ if (op == 0x18 && ra == 0 && ra == 0 && disp == 0)
+ printf ("TRAPB\n");
+ else
+ printf ("%s $%d,$%d,%d\n", ops[op].name, ra, rb, disp);
+ break;
+
+ case ITYPE_BRA:
+ printf ("%s $%d,%x\n", ops[op].name, ra, pos + 4 + ((c << 11) >> 9));
+ break;
+
+ case ITYPE_FOP:
+ if (op == 0x17 && fopfun == 0x020 && ra == rb) {
+ if (ra == 31 && rc == 31)
+ printf ("FNOP\n");
+ else
+ printf ("FMOV $f%d,$f%d\n", ra, rc);
+ return;
+ }
+ for (i = 0; op3s[i].name; i++)
+ if (op3s[i].op == op && op3s[i].fun == fopfun) {
+ printf ("%s $f%d,$f%d,$f%d\n", op3s[i].name, ra, rb, rc);
+ return;
+ }
+ printf ("%s%x $f%d,$f%d,$f%d\n", ops[op].name, fopfun, ra, rb, rc);
+ break;
+
+ case ITYPE_OP:
+ if (op == 0x11 && opfun == 0x20 && ra == rb && ~(c&0x1000)) {
+ if (ra == 31 && rc == 31)
+ printf ("NOP\n");
+ else
+ printf ("MOV $%d,$%d\n", ra, rc);
+ return;
+ }
+ for (i = 0; op3s[i].name; i++) {
+ if (op3s[i].op == op && op3s[i].fun == opfun) {
+ if (c&0x1000)
+ printf ("%s $%d,#%d,$%d\n", op3s[i].name, ra, lit, rc);
+ else
+ printf ("%s $%d,$%d,$%d\n", op3s[i].name, ra, rb, rc);
+ return;
+ }
+ }
+ /* fall through */
+ default:
+ if (c&0x1000)
+ printf ("UNDEF %x(%x) $%d,#%d,$%d\n", op, opfun, ra, lit, rc);
+ else
+ printf ("UNDEF %x(%x) $%d,$%d,$%d\n", op, opfun, ra, rb, rc);
+ }
+}
+
+
+/*********************** funktion disassemble **********************************
+
+ outputs a disassembler listing of some machine code on 'stdout'
+
+*******************************************************************************/
+
+static void disassemble (int *code, int len)
+{
+ int p;
+
+ printf (" --- disassembler listing ---\n");
+ for (p = 0; p < len; p += 4, code++)
+ disasscmd (*code, p);
+}
--- /dev/null
+/***************************** alpha/gen.c *************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Contains the codegenerator for an Alpha processor.
+ This module generates Alpha machine code for a sequence of
+ pseudo commands (PCMDs).
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+ Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1997/10/22
+
+*******************************************************************************/
+
+
+
+/*******************************************************************************
+
+Datatypes and Register Allocations:
+-----------------------------------
+
+On 64-bit-machines (like the Alpha) all operands are stored in the
+registers in a 64-bit form, even when the correspondig JavaVM
+operands only need 32 bits.
+This is done by a canonical representation:
+
+32-bit integers are allways stored as sign-extended 64-bit values
+(this approach is directly supported by the Alpha architecture and
+is very easy to implement).
+
+32-bit-floats are stored in a 64-bit doubleprecision register by
+simply expanding the exponent and mantissa with zeroes.
+(also supported by the architecture)
+
+
+Stackframes:
+
+The calling conventions and the layout of the stack is
+explained in detail in the documention file: calling.doc
+
+*******************************************************************************/
+
+
+/************************ Preallocated registers ******************************/
+
+/* integer registers */
+
+#define REG_RESULT 0 /* to deliver method results */
+#define REG_EXCEPTION 1 /* to throw an exception across method bounds */
+
+#define REG_RA 26 /* return address */
+#define REG_PV 27 /* procedure vector, must be provided by caller */
+#define REG_METHODPTR 28 /* pointer to the place from where the procedure */
+ /* vector has been fetched */
+#define REG_ITMP1 25 /* temporary register */
+#define REG_ITMP2 28 /* temporary register */
+#define REG_ITMP3 29 /* temporary register */
+
+#define REG_SP 30 /* stack pointer */
+#define REG_ZERO 31 /* allways zero */
+
+/* floating point registers */
+
+#define REG_FRESULT 0 /* to deliver floating point method results */
+#define REG_FTMP1 28 /* temporary floating point register */
+#define REG_FTMP2 29 /* temporary floating point register */
+#define REG_FTMP3 30 /* temporary floating point register */
+
+
+/******************** register descripton - array *****************************/
+
+/* #define REG_RES 0 reserved register for OS or code generator */
+/* #define REG_RET 1 return value register */
+/* #define REG_EXC 2 exception value register */
+/* #define REG_SAV 3 (callee) saved register */
+/* #define REG_TMP 4 scratch temporary register (caller saved) */
+/* #define REG_ARG 5 argument register (caller saved) */
+
+/* #define REG_END -1 last entry in tables */
+
+int regdescint[] = {
+ REG_RET, REG_EXC, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
+ REG_TMP, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
+ REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP,
+ REG_TMP, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
+ REG_END };
+
+#define INT_SAV_FST 9 /* first int callee saved register */
+#define INT_SAV_CNT 7 /* number of int callee saved registers */
+#define INT_ARG_FST 16 /* first int callee saved register */
+#define INT_ARG_CNT 6 /* number of int callee saved registers */
+
+/* for use of reserved registers, see comment above */
+
+int regdescfloat[] = {
+ REG_RET, REG_TMP, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
+ REG_SAV, REG_SAV, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
+ REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP,
+ REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_RES, REG_RES, REG_RES, REG_RES,
+ REG_END };
+
+#define FLT_SAV_FST 2 /* first int callee saved register */
+#define FLT_SAV_CNT 8 /* number of int callee saved registers */
+#define FLT_ARG_FST 16 /* first int callee saved register */
+#define FLT_ARG_CNT 6 /* number of int callee saved registers */
+
+/* for use of reserved registers, see comment above */
+
+
+/*** parameter allocation mode ***/
+
+int reg_parammode = PARAMMODE_NUMBERED;
+
+ /* parameter-registers will be allocated by assigning the
+ 1. parameter: int/float-reg 16
+ 2. parameter: int/float-reg 17
+ 3. parameter: int/float-reg 18 ....
+ */
+
+
+/************************** stackframe-infos **********************************/
+
+int localvars_base; /* offset in stackframe for the local variables */
+int savedregs_base; /* offset in stackframe for the save area */
+int parentargs_base; /* offset in stackframe for the parameter from the caller*/
+
+/* -> see file 'calling.doc' */
+
+
+/******************** macros to create code ***********************************/
+
+/* 3-address-operations: M_OP3
+ op ..... opcode
+ fu ..... function-number
+ a ..... register number source 1
+ b ..... register number or constant integer source 2
+ c ..... register number destination
+ const .. switch to use b as constant integer
+ (0 means: use b as register number)
+ (1 means: use b as constant 8-bit-integer)
+*/
+#define M_OP3(op,fu,a,b,c,const) \
+ mcode_adds4 ( (((s4)(op))<<26)|((a)<<21)|((b)<<(16-3*(const)))| \
+ ((const)<<12)|((fu)<<5)|((c)) )
+
+/* 3-address-floating-point-operation: M_FOP3
+ op .... opcode
+ fu .... function-number
+ a,b ... source floating-point registers
+ c ..... destination register
+*/
+#define M_FOP3(op,fu,a,b,c) \
+ mcode_adds4 ( (((s4)(op))<<26)|((a)<<21)|((b)<<16)|((fu)<<5)|(c) )
+
+/* branch instructions: M_BRA
+ op ..... opcode
+ a ...... register to be tested
+ disp ... relative address to be jumped to (divided by 4)
+*/
+#define M_BRA(op,a,disp) \
+ mcode_adds4 ( (((s4)(op))<<26)|((a)<<21)|((disp)&0x1fffff) )
+
+
+/* memory operations: M_MEM
+ op ..... opcode
+ a ...... source/target register for memory access
+ b ...... base register
+ disp ... displacement (16 bit signed) to be added to b
+*/
+#define M_MEM(op,a,b,disp) \
+ mcode_adds4 ( (((s4)(op))<<26)|((a)<<21)|((b)<<16)|((disp)&0xffff) )
+
+
+/***** macros for all used commands (see an Alpha-manual for description) *****/
+
+#define M_LDA(a,b,disp) M_MEM (0x08,a,b,disp) /* low const */
+#define M_LDAH(a,b,disp) M_MEM (0x09,a,b,disp) /* high const */
+#define M_BLDU(a,b,disp) M_MEM (0x0a,a,b,disp) /* 8 load */
+#define M_SLDU(a,b,disp) M_MEM (0x0c,a,b,disp) /* 16 load */
+#define M_ILD(a,b,disp) M_MEM (0x28,a,b,disp) /* 32 load */
+#define M_LLD(a,b,disp) M_MEM (0x29,a,b,disp) /* 64 load */
+#define M_BST(a,b,disp) M_MEM (0x0e,a,b,disp) /* 8 store */
+#define M_SST(a,b,disp) M_MEM (0x0d,a,b,disp) /* 16 store */
+#define M_IST(a,b,disp) M_MEM (0x2c,a,b,disp) /* 32 store */
+#define M_LST(a,b,disp) M_MEM (0x2d,a,b,disp) /* 64 store */
+
+#define M_BSEXT(b,c) M_OP3 (0x1c,0x0,REG_ZERO,b,c,0) /* 8 signext */
+#define M_SSEXT(b,c) M_OP3 (0x1c,0x1,REG_ZERO,b,c,0) /* 16 signext */
+
+#define M_BR(disp) M_BRA (0x30,REG_ZERO,disp) /* branch */
+#define M_BSR(ra,disp) M_BRA (0x34,ra,disp) /* branch sbr */
+#define M_BEQZ(a,disp) M_BRA (0x39,a,disp) /* br a == 0 */
+#define M_BLTZ(a,disp) M_BRA (0x3a,a,disp) /* br a < 0 */
+#define M_BLEZ(a,disp) M_BRA (0x3b,a,disp) /* br a <= 0 */
+#define M_BNEZ(a,disp) M_BRA (0x3d,a,disp) /* br a != 0 */
+#define M_BGEZ(a,disp) M_BRA (0x3e,a,disp) /* br a >= 0 */
+#define M_BGTZ(a,disp) M_BRA (0x3f,a,disp) /* br a > 0 */
+
+#define M_JMP(a,b) M_MEM (0x1a,a,b,0x0000) /* jump */
+#define M_JSR(a,b) M_MEM (0x1a,a,b,0x4000) /* call sbr */
+#define M_RET(a,b) M_MEM (0x1a,a,b,0x8000) /* return */
+
+#define M_IADD(a,b,c,const) M_OP3 (0x10,0x0, a,b,c,const) /* 32 add */
+#define M_LADD(a,b,c,const) M_OP3 (0x10,0x20, a,b,c,const) /* 64 add */
+#define M_ISUB(a,b,c,const) M_OP3 (0x10,0x09, a,b,c,const) /* 32 sub */
+#define M_LSUB(a,b,c,const) M_OP3 (0x10,0x29, a,b,c,const) /* 64 sub */
+#define M_IMUL(a,b,c,const) M_OP3 (0x13,0x00, a,b,c,const) /* 32 mul */
+#define M_LMUL(a,b,c,const) M_OP3 (0x13,0x20, a,b,c,const) /* 64 mul */
+
+#define M_CMPEQ(a,b,c,const) M_OP3 (0x10,0x2d, a,b,c,const) /* c = a == b */
+#define M_CMPLT(a,b,c,const) M_OP3 (0x10,0x4d, a,b,c,const) /* c = a < b */
+#define M_CMPLE(a,b,c,const) M_OP3 (0x10,0x6d, a,b,c,const) /* c = a <= b */
+
+#define M_CMPULE(a,b,c,const) M_OP3 (0x10,0x3d, a,b,c,const) /* c = a <= b */
+
+#define M_AND(a,b,c,const) M_OP3 (0x11,0x00, a,b,c,const) /* c = a & b */
+#define M_OR(a,b,c,const) M_OP3 (0x11,0x20, a,b,c,const) /* c = a | b */
+#define M_XOR(a,b,c,const) M_OP3 (0x11,0x40, a,b,c,const) /* c = a ^ b */
+
+#define M_SLL(a,b,c,const) M_OP3 (0x12,0x39, a,b,c,const) /* c = a << b */
+#define M_SRA(a,b,c,const) M_OP3 (0x12,0x3c, a,b,c,const) /* c = a >> b */
+#define M_SRL(a,b,c,const) M_OP3 (0x12,0x34, a,b,c,const) /* c = a >>>b */
+
+#define M_FLD(a,b,disp) M_MEM (0x22,a,b,disp) /* load flt */
+#define M_DLD(a,b,disp) M_MEM (0x23,a,b,disp) /* load dbl */
+#define M_FST(a,b,disp) M_MEM (0x26,a,b,disp) /* store flt */
+#define M_DST(a,b,disp) M_MEM (0x27,a,b,disp) /* store dbl */
+
+#define M_FADD(a,b,c) M_FOP3 (0x16, 0x080, a,b,c) /* flt add */
+#define M_DADD(a,b,c) M_FOP3 (0x16, 0x0a0, a,b,c) /* dbl add */
+#define M_FSUB(a,b,c) M_FOP3 (0x16, 0x081, a,b,c) /* flt sub */
+#define M_DSUB(a,b,c) M_FOP3 (0x16, 0x0a1, a,b,c) /* dbl sub */
+#define M_FMUL(a,b,c) M_FOP3 (0x16, 0x082, a,b,c) /* flt mul */
+#define M_DMUL(a,b,c) M_FOP3 (0x16, 0x0a2, a,b,c) /* dbl mul */
+#define M_FDIV(a,b,c) M_FOP3 (0x16, 0x083, a,b,c) /* flt div */
+#define M_DDIV(a,b,c) M_FOP3 (0x16, 0x0a3, a,b,c) /* dbl div */
+
+#define M_CVTLF(a,b,c) M_FOP3 (0x16, 0x0bc, a,b,c) /* long2flt */
+#define M_CVTLD(a,b,c) M_FOP3 (0x16, 0x0be, a,b,c) /* long2dbl */
+#define M_CVTDL(a,b,c) M_FOP3 (0x16, 0x0af, a,b,c) /* dbl2long */
+#define M_CVTDL_C(a,b,c) M_FOP3 (0x16, 0x02f, a,b,c) /* dbl2long */
+
+#define M_FCMPEQ(a,b,c) M_FOP3 (0x16, 0x0a5, a,b,c) /* c = a==b */
+#define M_FCMPLT(a,b,c) M_FOP3 (0x16, 0x0a6, a,b,c) /* c = a<b */
+
+#define M_FMOV(fa,fb) M_FOP3 (0x17, 0x020, fa,fa,fb) /* b = a */
+#define M_FMOVN(fa,fb) M_FOP3 (0x17, 0x021, fa,fa,fb) /* b = -a */
+
+#define M_FBEQZ(fa,disp) M_BRA (0x31,fa,disp) /* br a == 0.0*/
+
+/****** macros for special commands (see an Alpha-manual for description) *****/
+
+#define M_S4ADDL(a,b,c,const) M_OP3 (0x10,0x02, a,b,c,const) /* c = a*4 + b */
+#define M_S4ADDQ(a,b,c,const) M_OP3 (0x10,0x22, a,b,c,const) /* c = a*4 + b */
+#define M_S4SUBL(a,b,c,const) M_OP3 (0x10,0x0b, a,b,c,const) /* c = a*4 - b */
+#define M_S4SUBQ(a,b,c,const) M_OP3 (0x10,0x2b, a,b,c,const) /* c = a*4 - b */
+#define M_S8ADDL(a,b,c,const) M_OP3 (0x10,0x12, a,b,c,const) /* c = a*8 + b */
+#define M_S8ADDQ(a,b,c,const) M_OP3 (0x10,0x32, a,b,c,const) /* c = a*8 + b */
+#define M_S8SUBL(a,b,c,const) M_OP3 (0x10,0x1b, a,b,c,const) /* c = a*8 - b */
+#define M_S8SUBQ(a,b,c,const) M_OP3 (0x10,0x3b, a,b,c,const) /* c = a*8 - b */
+
+#define M_LLD_U(a,b,disp) M_MEM (0x0b,a,b,disp) /* unalign ld */
+#define M_LST_U(a,b,disp) M_MEM (0x0f,a,b,disp) /* unalign st */
+
+#define M_ZAP(a,b,c,const) M_OP3 (0x12,0x30, a,b,c,const)
+#define M_ZAPNOT(a,b,c,const) M_OP3 (0x12,0x31, a,b,c,const)
+#define M_EXTBL(a,b,c,const) M_OP3 (0x12,0x06, a,b,c,const)
+#define M_EXTWL(a,b,c,const) M_OP3 (0x12,0x16, a,b,c,const)
+#define M_EXTLL(a,b,c,const) M_OP3 (0x12,0x26, a,b,c,const)
+#define M_EXTQL(a,b,c,const) M_OP3 (0x12,0x36, a,b,c,const)
+#define M_EXTWH(a,b,c,const) M_OP3 (0x12,0x5a, a,b,c,const)
+#define M_EXTLH(a,b,c,const) M_OP3 (0x12,0x6a, a,b,c,const)
+#define M_EXTQH(a,b,c,const) M_OP3 (0x12,0x7a, a,b,c,const)
+#define M_INSBL(a,b,c,const) M_OP3 (0x12,0x0b, a,b,c,const)
+#define M_INSWL(a,b,c,const) M_OP3 (0x12,0x1b, a,b,c,const)
+#define M_INSLL(a,b,c,const) M_OP3 (0x12,0x2b, a,b,c,const)
+#define M_INSQL(a,b,c,const) M_OP3 (0x12,0x3b, a,b,c,const)
+#define M_INSWH(a,b,c,const) M_OP3 (0x12,0x57, a,b,c,const)
+#define M_INSLH(a,b,c,const) M_OP3 (0x12,0x67, a,b,c,const)
+#define M_INSQH(a,b,c,const) M_OP3 (0x12,0x77, a,b,c,const)
+#define M_MSKBL(a,b,c,const) M_OP3 (0x12,0x02, a,b,c,const)
+#define M_MSKWL(a,b,c,const) M_OP3 (0x12,0x12, a,b,c,const)
+#define M_MSKLL(a,b,c,const) M_OP3 (0x12,0x22, a,b,c,const)
+#define M_MSKQL(a,b,c,const) M_OP3 (0x12,0x32, a,b,c,const)
+#define M_MSKWH(a,b,c,const) M_OP3 (0x12,0x52, a,b,c,const)
+#define M_MSKLH(a,b,c,const) M_OP3 (0x12,0x62, a,b,c,const)
+#define M_MSKQH(a,b,c,const) M_OP3 (0x12,0x72, a,b,c,const)
+
+
+/****** macros for unused commands (see an Alpha-manual for description) ******/
+
+#define M_ANDNOT(a,b,c,const) M_OP3 (0x11,0x08, a,b,c,const) /* c = a &~ b */
+#define M_ORNOT(a,b,c,const) M_OP3 (0x11,0x28, a,b,c,const) /* c = a |~ b */
+#define M_XORNOT(a,b,c,const) M_OP3 (0x11,0x48, a,b,c,const) /* c = a ^~ b */
+
+#define M_CMOVEQ(a,b,c,const) M_OP3 (0x11,0x24, a,b,c,const) /* a==0 ? c=b */
+#define M_CMOVNE(a,b,c,const) M_OP3 (0x11,0x26, a,b,c,const) /* a!=0 ? c=b */
+#define M_CMOVLT(a,b,c,const) M_OP3 (0x11,0x44, a,b,c,const) /* a< 0 ? c=b */
+#define M_CMOVGE(a,b,c,const) M_OP3 (0x11,0x46, a,b,c,const) /* a>=0 ? c=b */
+#define M_CMOVLE(a,b,c,const) M_OP3 (0x11,0x64, a,b,c,const) /* a<=0 ? c=b */
+#define M_CMOVGT(a,b,c,const) M_OP3 (0x11,0x66, a,b,c,const) /* a> 0 ? c=b */
+
+#define M_CMPULT(a,b,c,const) M_OP3 (0x10,0x1d, a,b,c,const)
+#define M_CMPBGE(a,b,c,const) M_OP3 (0x10,0x0f, a,b,c,const)
+
+#define M_FCMPUN(a,b,c) M_FOP3 (0x16, 0x0a4, a,b,c) /* unordered */
+#define M_FCMPLE(a,b,c) M_FOP3 (0x16, 0x0a7, a,b,c) /* c = a<=b */
+
+#define M_FBNEZ(fa,disp) M_BRA (0x35,fa,disp)
+#define M_FBLEZ(fa,disp) M_BRA (0x33,fa,disp)
+
+#define M_JMP_CO(a,b) M_MEM (0x1a,a,b,0xc000) /* call cosub */
+
+
+/******************** system independent macros *******************************/
+
+
+
+/************** additional functions to generate code *************************/
+
+
+/* M_INTMOVE:
+ generates an integer-move from register a to b.
+ if a and b are the same int-register, no code will be generated.
+*/
+
+static void M_INTMOVE(int a, int b)
+{
+ if (a == b) return;
+ M_OR (a,a,b, 0);
+}
+
+
+/* M_FLTMOVE:
+ generates a floating-point-move from register a to b.
+ if a and b are the same float-register, no code will be generated
+*/
+
+static void M_FLTMOVE(int a, int b)
+{
+ if (a == b) return;
+ M_FMOV (a, b);
+}
+
+
+/* var_to_reg_xxx:
+ this function generates code to fetch data from a pseudo-register
+ into a real register.
+ If the pseudo-register has actually been assigned to a real
+ register, no code will be emitted, since following operations
+ can use this register directly.
+
+ v: pseudoregister to be fetched from
+ tempregnum: temporary register to be used if v is actually spilled to ram
+
+ return: the register number, where the operand can be found after
+ fetching (this wil be either tempregnum or the register
+ number allready given to v)
+*/
+
+static int var_to_reg_int (varid v, int tempregnum)
+{
+ reginfo *ri = v->reg;
+
+ if (!(ri->typeflags & REG_INMEMORY))
+ return ri->num;
+#ifdef STATISTICS
+ count_spills++;
+#endif
+ M_LLD (tempregnum, REG_SP, 8 * (localvars_base + ri->num) );
+ return tempregnum;
+}
+
+
+static int var_to_reg_flt (varid v, int tempregnum)
+{
+ reginfo *ri = v->reg;
+
+
+ if (!(ri->typeflags & REG_INMEMORY))
+ return ri->num;
+#ifdef STATISTICS
+ count_spills++;
+#endif
+ M_DLD (tempregnum, REG_SP, 8 * (localvars_base + ri->num) );
+ return tempregnum;
+}
+
+
+/* reg_of_var:
+ This function determines a register, to which the result of an
+ operation should go, when it is ultimatively intended to store the result
+ in pseudoregister v.
+ If v is assigned to an actual register, this register will be
+ returned.
+ Otherwise (when v is spilled) this function returns tempregnum.
+*/
+
+static int reg_of_var(varid v, int tempregnum)
+{
+ if (!(v->reg->typeflags & REG_INMEMORY))
+ return v->reg->num;
+ return tempregnum;
+}
+
+
+/* store_reg_to_var_xxx:
+ This function generates the code to store the result of an operation
+ back into a spilled pseudo-variable.
+ If the pseudo-variable has not been spilled in the first place, this
+ function will generate nothing.
+
+ v ............ Pseudovariable
+ tempregnum ... Number of the temporary registers as returned by
+ reg_of_var.
+*/
+
+static void store_reg_to_var_int (varid v, int tempregnum)
+{
+ reginfo *ri = v->reg;
+
+ if (!(ri->typeflags & REG_INMEMORY))
+ return;
+#ifdef STATISTICS
+ count_spills++;
+#endif
+ M_LST (tempregnum, REG_SP, 8 * (localvars_base + ri->num) );
+}
+
+static void store_reg_to_var_flt (varid v, int tempregnum)
+{
+ reginfo *ri = v->reg;
+
+ if (!(ri->typeflags & REG_INMEMORY))
+ return;
+#ifdef STATISTICS
+ count_spills++;
+#endif
+ M_DST (tempregnum, REG_SP, 8 * (localvars_base + ri->num) );
+}
+
+
+/***************** functions to process the pseudo commands *******************/
+
+/* gen_method:
+ function to generate method-call
+*/
+
+static void gen_method (pcmd *c)
+{
+ int p, pa, r;
+ s4 a;
+ reginfo *ri;
+ classinfo *ci;
+
+ for (p = 0; p < c->u.method.paramnum; p++) {
+ ri = c->u.method.params[p]->reg;
+
+ if (p < INT_ARG_CNT) { /* arguments that go into registers */
+ if (IS_INT_LNG_REG(ri->typeflags)) {
+ if (!(ri->typeflags & REG_INMEMORY))
+ M_INTMOVE(ri->num, INT_ARG_FST+p);
+ else
+ M_LLD(INT_ARG_FST+p, REG_SP, 8*(localvars_base + ri->num));
+ }
+ else {
+ if (!(ri->typeflags & REG_INMEMORY))
+ M_FLTMOVE (ri->num, FLT_ARG_FST+p);
+ else
+ M_DLD(FLT_ARG_FST+p, REG_SP, 8*(localvars_base + ri->num));
+ }
+ }
+ else { /* arguments that go into memory */
+ pa = p - INT_ARG_CNT;
+ if (pa >= arguments_num)
+ panic ("invalid stackframe structure");
+
+ if (IS_INT_LNG_REG(ri->typeflags)) {
+ r = var_to_reg_int (c->u.method.params[p], REG_ITMP1);
+ M_LST(r, REG_SP, 8 * (0 + pa));
+ }
+ else {
+ r = var_to_reg_flt (c->u.method.params[p], REG_FTMP1);
+ M_DST (r, REG_SP, 8 * (0 + pa));
+ }
+ }
+ } /* end of for */
+
+ switch (c->opcode) {
+ case CMD_BUILTIN:
+ a = dseg_addaddress ( (void*) (c->u.method.builtin) );
+
+ M_LLD (REG_PV, REG_PV, a); /* Pointer to built-in-function */
+ goto makeactualcall;
+
+ case CMD_INVOKESTATIC:
+ case CMD_INVOKESPECIAL:
+ a = dseg_addaddress ( c->u.method.method->stubroutine );
+
+ M_LLD (REG_PV, REG_PV, a ); /* Method-Pointer in r27 */
+
+ goto makeactualcall;
+
+ case CMD_INVOKEVIRTUAL:
+
+ M_LLD (REG_METHODPTR, 16, OFFSET(java_objectheader, vftbl));
+ M_LLD (REG_PV, REG_METHODPTR,
+ OFFSET(vftbl,table[0]) +
+ sizeof(methodptr) * c->u.method.method->vftblindex );
+
+ goto makeactualcall;
+
+ case CMD_INVOKEINTERFACE:
+ ci = c->u.method.method->class;
+
+ M_LLD (REG_METHODPTR, 16, OFFSET(java_objectheader, vftbl));
+ M_LLD (REG_METHODPTR, REG_METHODPTR, OFFSET(vftbl, interfacevftbl));
+ M_LLD (REG_METHODPTR, REG_METHODPTR, sizeof(methodptr*) * ci->index);
+ M_LLD (REG_PV, REG_METHODPTR, sizeof(methodptr) * (c->u.method.method - ci->methods) );
+
+ goto makeactualcall;
+
+ default:
+ sprintf (logtext, "Unkown PCMD-Command: %d", c->opcode);
+ error ();
+ }
+
+
+makeactualcall:
+
+
+ M_JSR (REG_RA, REG_PV);
+ if (mcodelen<=32768) M_LDA (REG_PV, REG_RA, -mcodelen);
+ else {
+ s4 ml=-mcodelen, mh=0;
+ while (ml<-32768) { ml+=65536; mh--; }
+ M_LDA (REG_PV, REG_RA, ml );
+ M_LDAH (REG_PV, REG_PV, mh );
+ }
+
+ if ( c->dest ) {
+ ri = c->dest->reg;
+
+ if (IS_INT_LNG_REG(ri->typeflags)) {
+ if (!(ri->typeflags & REG_INMEMORY))
+ M_INTMOVE (REG_RESULT, ri->num);
+ else M_LST (REG_RESULT, REG_SP, 8 * (localvars_base + ri->num) );
+ }
+ else {
+ if (!(ri->typeflags & REG_INMEMORY))
+ M_FLTMOVE (REG_RESULT, ri->num);
+ else M_DST (REG_RESULT, REG_SP, 8 * (localvars_base + ri->num) );
+ }
+ }
+
+ if (c->u.method.exceptionvar) {
+ ri = c->u.method.exceptionvar->reg;
+ if (!(ri->typeflags & REG_INMEMORY))
+ M_INTMOVE (REG_EXCEPTION, ri->num);
+ else M_LST (REG_EXCEPTION, REG_SP, 8 *(localvars_base + ri->num) );
+ }
+}
+
+
+/************************ function block_genmcode ******************************
+
+ generates machine code for a complete basic block
+
+*******************************************************************************/
+
+
+static void block_genmcode(basicblock *b)
+{
+ int s1, s2, s3, d;
+ s4 a;
+ pcmd *c;
+
+ mcode_blockstart (b);
+
+ for(c = list_first(&(b->pcmdlist));
+ c != NULL;
+ c = list_next(&(b->pcmdlist), c))
+
+ switch (c->opcode) {
+
+ case CMD_TRACEBUILT:
+ M_LDA (REG_SP, REG_SP, -8);
+ a = dseg_addaddress (c->u.a.value);
+ M_LLD(REG_ITMP1, REG_PV, a);
+ M_LST(REG_ITMP1, REG_SP, 0);
+ a = dseg_addaddress ((void*) (builtin_trace_args));
+ M_LLD(REG_PV, REG_PV, a);
+ M_JSR (REG_RA, REG_PV);
+ if (mcodelen<=32768) M_LDA (REG_PV, REG_RA, -mcodelen);
+ else {
+ s4 ml=-mcodelen, mh=0;
+ while (ml<-32768) { ml+=65536; mh--; }
+ M_LDA (REG_PV, REG_RA, ml );
+ M_LDAH (REG_PV, REG_PV, mh );
+ }
+ M_LDA (REG_SP, REG_SP, 8);
+ b -> mpc = mcodelen;
+ break;
+
+
+ /*********************** constant operations **************************/
+
+ case CMD_LOADCONST_I:
+ d = reg_of_var(c->dest, REG_ITMP1);
+ if ( (c->u.i.value >= -32768) && (c->u.i.value <= 32767) ) {
+ M_LDA (d, REG_ZERO, c->u.i.value);
+ }
+ else {
+ a = dseg_adds4 (c->u.i.value);
+ M_ILD (d, REG_PV, a);
+ }
+ store_reg_to_var_int(c->dest, d);
+ break;
+
+ case CMD_LOADCONST_L:
+ d = reg_of_var(c->dest, REG_ITMP1);
+#if U8_AVAILABLE
+ if ((c->u.l.value >= -32768) && (c->u.l.value <= 32767) ) {
+ M_LDA (d, REG_ZERO, c->u.l.value);
+ }
+ else {
+ a = dseg_adds8 (c->u.l.value);
+ M_LLD (d, REG_PV, a);
+ }
+#else
+ a = dseg_adds8 (c->u.l.value);
+ M_LLD (d, REG_PV, a);
+#endif
+ store_reg_to_var_int(c->dest, d);
+ break;
+
+ case CMD_LOADCONST_F:
+ d = reg_of_var (c->dest, REG_FTMP1);
+ a = dseg_addfloat (c->u.f.value);
+ M_FLD (d, REG_PV, a);
+ store_reg_to_var_flt (c->dest, d);
+ break;
+
+ case CMD_LOADCONST_D:
+ d = reg_of_var (c->dest, REG_FTMP1);
+ a = dseg_adddouble (c->u.d.value);
+ M_DLD (d, REG_PV, a);
+ store_reg_to_var_flt (c->dest, d);
+ break;
+
+
+ case CMD_LOADCONST_A:
+ d = reg_of_var(c->dest, REG_ITMP1);
+ if (c->u.a.value) {
+ a = dseg_addaddress (c->u.a.value);
+ M_LLD (d, REG_PV, a);
+ }
+ else {
+ M_INTMOVE (REG_ZERO, d);
+ }
+ store_reg_to_var_int(c->dest, d);
+ break;
+
+ /************************* move operation *****************************/
+
+ case CMD_MOVE:
+ if (IS_INT_LNG_REG(c->source1->reg->typeflags)) {
+ d = reg_of_var(c->dest, REG_ITMP1);
+ s1 = var_to_reg_int(c->source1, d);
+ M_INTMOVE(s1,d);
+ store_reg_to_var_int(c->dest, d);
+ }
+ else {
+ d = reg_of_var(c->dest, REG_FTMP1);
+ s1 = var_to_reg_flt(c->source1, d);
+ M_FLTMOVE(s1,d);
+ store_reg_to_var_flt(c->dest, d);
+ }
+ break;
+
+
+ /********************* integer operations *****************************/
+
+ case CMD_IINC:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ d = reg_of_var(c->dest, REG_ITMP3);
+ if ((c->u.i.value >= 0) && (c->u.i.value <= 256)) {
+ M_IADD (s1, c->u.i.value, d, 1);
+ }
+ else if ((c->u.i.value >= -256) && (c->u.i.value < 0)) {
+ M_ISUB (s1, (-c->u.i.value), d, 1);
+ }
+ else {
+ M_LDA (d, s1, c->u.i.value);
+ M_IADD (d, REG_ZERO, d, 0);
+ }
+ store_reg_to_var_int(c->dest, d);
+ break;
+
+ case CMD_INEG:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ d = reg_of_var(c->dest, REG_ITMP3);
+ M_ISUB (REG_ZERO, s1, d, 0);
+ store_reg_to_var_int(c->dest, d);
+ break;
+
+ case CMD_LNEG:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ d = reg_of_var(c->dest, REG_ITMP3);
+ M_LSUB (REG_ZERO, s1, d, 0);
+ store_reg_to_var_int(c->dest, d);
+ break;
+
+ case CMD_I2L:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ d = reg_of_var(c->dest, REG_ITMP3);
+ M_INTMOVE (s1, d);
+ store_reg_to_var_int(c->dest, d);
+ break;
+
+ case CMD_L2I:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ d = reg_of_var(c->dest, REG_ITMP3);
+ M_IADD (s1, REG_ZERO, d , 0);
+ store_reg_to_var_int(c->dest, d);
+ break;
+
+ case CMD_INT2BYTE:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ d = reg_of_var(c->dest, REG_ITMP3);
+ if (has_ext_instr_set) {
+ M_BSEXT (s1, d);
+ }
+ else {
+ M_SLL (s1,56, d, 1);
+ M_SRA ( d,56, d, 1);
+ }
+ store_reg_to_var_int(c->dest, d);
+ break;
+
+ case CMD_INT2CHAR:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ d = reg_of_var(c->dest, REG_ITMP3);
+ M_ZAPNOT (s1, 0x03, d, 1);
+ store_reg_to_var_int(c->dest, d);
+ break;
+
+ case CMD_INT2SHORT:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ d = reg_of_var(c->dest, REG_ITMP3);
+ if (has_ext_instr_set) {
+ M_SSEXT (s1, d);
+ }
+ else {
+ M_SLL ( s1, 48, d, 1);
+ M_SRA ( d, 48, d, 1);
+ }
+ store_reg_to_var_int(c->dest, d);
+ break;
+
+ case CMD_IADD:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ s2 = var_to_reg_int(c->source2, REG_ITMP2);
+ d = reg_of_var(c->dest, REG_ITMP3);
+ M_IADD (s1, s2, d, 0);
+ store_reg_to_var_int(c->dest, d);
+ break;
+ case CMD_LADD:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ s2 = var_to_reg_int(c->source2, REG_ITMP2);
+ d = reg_of_var(c->dest, REG_ITMP3);
+ M_LADD (s1, s2, d, 0);
+ store_reg_to_var_int(c->dest, d);
+ break;
+
+ case CMD_ISUB:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ s2 = var_to_reg_int(c->source2, REG_ITMP2);
+ d = reg_of_var(c->dest, REG_ITMP3);
+ M_ISUB (s1, s2, d, 0);
+ store_reg_to_var_int(c->dest, d);
+ break;
+ case CMD_LSUB:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ s2 = var_to_reg_int(c->source2, REG_ITMP2);
+ d = reg_of_var(c->dest, REG_ITMP3);
+ M_LSUB (s1, s2, d, 0);
+ store_reg_to_var_int(c->dest, d);
+ break;
+
+ case CMD_IMUL:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ s2 = var_to_reg_int(c->source2, REG_ITMP2);
+ d = reg_of_var(c->dest, REG_ITMP3);
+ M_IMUL (s1, s2, d, 0);
+ store_reg_to_var_int(c->dest, d);
+ break;
+ case CMD_LMUL:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ s2 = var_to_reg_int(c->source2, REG_ITMP2);
+ d = reg_of_var(c->dest, REG_ITMP3);
+ M_LMUL (s1, s2, d, 0);
+ store_reg_to_var_int(c->dest, d);
+ break;
+
+
+ case CMD_ISHL:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ s2 = var_to_reg_int(c->source2, REG_ITMP2);
+ d = reg_of_var(c->dest, REG_ITMP3);
+ M_AND (s2, 0x1f, REG_ITMP3, 1);
+ M_SLL (s1, REG_ITMP3, d, 0);
+ M_IADD (d, REG_ZERO, d, 0);
+ store_reg_to_var_int(c->dest, d);
+ break;
+
+ case CMD_ISHR:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ s2 = var_to_reg_int(c->source2, REG_ITMP2);
+ d = reg_of_var(c->dest, REG_ITMP3);
+ M_AND (s2, 0x1f, REG_ITMP3, 1);
+ M_SRA (s1, REG_ITMP3, d, 0);
+ store_reg_to_var_int(c->dest, d);
+ break;
+
+ case CMD_IUSHR:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ s2 = var_to_reg_int(c->source2, REG_ITMP2);
+ d = reg_of_var(c->dest, REG_ITMP3);
+ M_AND (s2, 0x1f, REG_ITMP2, 1);
+ M_ZAPNOT (s1, 0x0f, d, 1);
+ M_SRL ( d, REG_ITMP2, d, 0);
+ M_IADD ( d, REG_ZERO, d, 0);
+ store_reg_to_var_int(c->dest, d);
+ break;
+
+ case CMD_LSHL:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ s2 = var_to_reg_int(c->source2, REG_ITMP2);
+ d = reg_of_var(c->dest, REG_ITMP3);
+ M_SLL (s1, s2, d, 0);
+ store_reg_to_var_int(c->dest, d);
+ break;
+
+ case CMD_LSHR:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ s2 = var_to_reg_int(c->source2, REG_ITMP2);
+ d = reg_of_var(c->dest, REG_ITMP3);
+ M_SRA (s1, s2, d, 0);
+ store_reg_to_var_int(c->dest, d);
+ break;
+
+ case CMD_LUSHR:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ s2 = var_to_reg_int(c->source2, REG_ITMP2);
+ d = reg_of_var(c->dest, REG_ITMP3);
+ M_SRL (s1, s2, d, 0);
+ store_reg_to_var_int(c->dest, d);
+ break;
+
+ case CMD_IAND:
+ case CMD_LAND:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ s2 = var_to_reg_int(c->source2, REG_ITMP2);
+ d = reg_of_var(c->dest, REG_ITMP3);
+ M_AND (s1, s2, d, 0);
+ store_reg_to_var_int(c->dest, d);
+ break;
+
+ case CMD_IOR:
+ case CMD_LOR:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ s2 = var_to_reg_int(c->source2, REG_ITMP2);
+ d = reg_of_var(c->dest, REG_ITMP3);
+ M_OR ( s1,s2, d, 0);
+ store_reg_to_var_int(c->dest, d);
+ break;
+
+ case CMD_IXOR:
+ case CMD_LXOR:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ s2 = var_to_reg_int(c->source2, REG_ITMP2);
+ d = reg_of_var(c->dest, REG_ITMP3);
+ M_XOR (s1, s2, d, 0);
+ store_reg_to_var_int(c->dest, d);
+ break;
+
+
+ case CMD_LCMP:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ s2 = var_to_reg_int(c->source2, REG_ITMP2);
+ d = reg_of_var(c->dest, REG_ITMP3);
+ M_CMPLT (s1, s2, REG_ITMP3, 0);
+ M_CMPLT (s2, s1, REG_ITMP1, 0);
+ M_LSUB (REG_ITMP1, REG_ITMP3, d, 0);
+ store_reg_to_var_int(c->dest, d);
+ break;
+
+
+ /*********************** floating operations **************************/
+
+ case CMD_FNEG:
+ s1 = var_to_reg_flt(c->source1, REG_FTMP1);
+ d = reg_of_var(c->dest, REG_FTMP3);
+ M_FMOVN (s1, d);
+ store_reg_to_var_flt(c->dest, d);
+ break;
+ case CMD_DNEG:
+ s1 = var_to_reg_flt(c->source1, REG_FTMP1);
+ d = reg_of_var(c->dest, REG_FTMP3);
+ M_FMOVN (s1, d);
+ store_reg_to_var_flt(c->dest, d);
+ break;
+
+ case CMD_FADD:
+ s1 = var_to_reg_flt(c->source1, REG_FTMP1);
+ s2 = var_to_reg_flt(c->source2, REG_FTMP2);
+ d = reg_of_var(c->dest, REG_FTMP3);
+ M_FADD ( s1,s2, d);
+ store_reg_to_var_flt(c->dest, d);
+ break;
+ case CMD_DADD:
+ s1 = var_to_reg_flt(c->source1, REG_FTMP1);
+ s2 = var_to_reg_flt(c->source2, REG_FTMP2);
+ d = reg_of_var(c->dest, REG_FTMP3);
+ M_DADD (s1, s2, d);
+ store_reg_to_var_flt(c->dest, d);
+ break;
+
+ case CMD_FSUB:
+ s1 = var_to_reg_flt(c->source1, REG_FTMP1);
+ s2 = var_to_reg_flt(c->source2, REG_FTMP2);
+ d = reg_of_var(c->dest, REG_FTMP3);
+ M_FSUB (s1, s2, d);
+ store_reg_to_var_flt(c->dest, d);
+ break;
+ case CMD_DSUB:
+ s1 = var_to_reg_flt(c->source1, REG_FTMP1);
+ s2 = var_to_reg_flt(c->source2, REG_FTMP2);
+ d = reg_of_var(c->dest, REG_FTMP3);
+ M_DSUB (s1, s2, d);
+ store_reg_to_var_flt(c->dest, d);
+ break;
+
+ case CMD_FMUL:
+ s1 = var_to_reg_flt(c->source1, REG_FTMP1);
+ s2 = var_to_reg_flt(c->source2, REG_FTMP2);
+ d = reg_of_var(c->dest, REG_FTMP3);
+ M_FMUL (s1, s2, d);
+ store_reg_to_var_flt(c->dest, d);
+ break;
+ case CMD_DMUL:
+ s1 = var_to_reg_flt(c->source1, REG_FTMP1);
+ s2 = var_to_reg_flt(c->source2, REG_FTMP2);
+ d = reg_of_var(c->dest, REG_FTMP3);
+ M_DMUL (s1, s2, d);
+ store_reg_to_var_flt(c->dest, d);
+ break;
+
+ case CMD_FDIV:
+ s1 = var_to_reg_flt(c->source1, REG_FTMP1);
+ s2 = var_to_reg_flt(c->source2, REG_FTMP2);
+ d = reg_of_var(c->dest, REG_FTMP3);
+ M_FDIV (s1, s2, d);
+ store_reg_to_var_flt(c->dest, d);
+ break;
+ case CMD_DDIV:
+ s1 = var_to_reg_flt(c->source1, REG_FTMP1);
+ s2 = var_to_reg_flt(c->source2, REG_FTMP2);
+ d = reg_of_var(c->dest, REG_FTMP3);
+ M_DDIV (s1, s2, d);
+ store_reg_to_var_flt(c->dest, d);
+ break;
+
+ case CMD_FREM:
+ s1 = var_to_reg_flt(c->source1, REG_FTMP1);
+ s2 = var_to_reg_flt(c->source2, REG_FTMP2);
+ d = reg_of_var(c->dest, REG_FTMP3);
+ M_FDIV ( s1,s2, REG_FTMP3 );
+ M_CVTDL_C ( REG_ZERO, REG_FTMP3, REG_FTMP3 ); /* round to integer */
+ M_CVTLF ( REG_ZERO, REG_FTMP3, REG_FTMP3 );
+ M_FMUL ( REG_FTMP3, s2, REG_FTMP3 );
+ M_FSUB ( s1, REG_FTMP3, d);
+ store_reg_to_var_flt(c->dest, d);
+ break;
+ case CMD_DREM:
+ s1 = var_to_reg_flt(c->source1, REG_FTMP1);
+ s2 = var_to_reg_flt(c->source2, REG_FTMP2);
+ d = reg_of_var(c->dest, REG_FTMP3);
+ M_DDIV ( s1,s2, REG_FTMP3 );
+ M_CVTDL_C ( REG_ZERO, REG_FTMP3, REG_FTMP3 ); /* round to integer */
+ M_CVTLD ( REG_ZERO, REG_FTMP3, REG_FTMP3 );
+ M_DMUL ( REG_FTMP3, s2, REG_FTMP3 );
+ M_DSUB ( s1, REG_FTMP3, d);
+ store_reg_to_var_flt(c->dest, d);
+ break;
+
+ case CMD_I2F:
+ case CMD_L2F:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ d = reg_of_var(c->dest, REG_FTMP3);
+ a = dseg_adddouble(0.0);
+ M_LST (s1, REG_PV, a);
+ M_DLD (d, REG_PV, a);
+ M_CVTLF ( REG_ZERO, d, d);
+ store_reg_to_var_flt(c->dest, d);
+ break;
+
+ case CMD_I2D:
+ case CMD_L2D:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ d = reg_of_var(c->dest, REG_FTMP3);
+ a = dseg_adddouble(0.0);
+ M_LST (s1, REG_PV, a);
+ M_DLD (d, REG_PV, a);
+ M_CVTLD ( REG_ZERO, d, d);
+ store_reg_to_var_flt(c->dest, d);
+ break;
+
+ case CMD_F2I:
+ case CMD_D2I:
+ s1 = var_to_reg_flt(c->source1, REG_FTMP1);
+ d = reg_of_var(c->dest, REG_ITMP3);
+ a = dseg_adddouble(0.0);
+ M_CVTDL_C (REG_ZERO, s1, REG_FTMP1);
+ M_DST (REG_FTMP1, REG_PV, a);
+ M_ILD (d, REG_PV, a);
+ store_reg_to_var_int(c->dest, d);
+ break;
+
+ case CMD_F2L:
+ case CMD_D2L:
+ s1 = var_to_reg_flt(c->source1, REG_FTMP1);
+ d = reg_of_var(c->dest, REG_ITMP3);
+ a = dseg_adddouble(0.0);
+ M_CVTDL_C (REG_ZERO, s1, REG_FTMP1);
+ M_DST (REG_FTMP1, REG_PV, a);
+ M_LLD (d, REG_PV, a);
+ store_reg_to_var_int(c->dest, d);
+ break;
+
+ case CMD_F2D:
+ s1 = var_to_reg_flt(c->source1, REG_FTMP1);
+ d = reg_of_var(c->dest, REG_FTMP3);
+ M_FLTMOVE (s1, d);
+ store_reg_to_var_flt(c->dest, d);
+ break;
+
+ case CMD_D2F:
+ s1 = var_to_reg_flt(c->source1, REG_FTMP1);
+ d = reg_of_var(c->dest, REG_FTMP3);
+ M_FADD (s1, REG_ZERO, d);
+ store_reg_to_var_flt(c->dest, d);
+ break;
+
+ case CMD_FCMPL:
+ case CMD_DCMPL:
+ s1 = var_to_reg_flt(c->source1, REG_FTMP1);
+ s2 = var_to_reg_flt(c->source2, REG_FTMP2);
+ d = reg_of_var(c->dest, REG_ITMP3);
+ M_LSUB (REG_ZERO, 1, d, 1);
+ M_FCMPEQ (s1, s2, REG_FTMP3);
+ M_FBEQZ (REG_FTMP3, 1); /* jump over next instructions */
+ M_OR (REG_ZERO, REG_ZERO, d, 0);
+ M_FCMPLT (s2, s1, REG_FTMP3);
+ M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
+ M_LADD (REG_ZERO, 1, d, 1);
+ store_reg_to_var_int(c->dest, d);
+ break;
+
+ case CMD_FCMPG:
+ case CMD_DCMPG:
+ s1 = var_to_reg_flt(c->source1, REG_FTMP1);
+ s2 = var_to_reg_flt(c->source2, REG_FTMP2);
+ d = reg_of_var(c->dest, REG_ITMP3);
+ M_LADD (REG_ZERO, 1, d, 1);
+ M_FCMPEQ (s1, s2, REG_FTMP3);
+ M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
+ M_OR (REG_ZERO, REG_ZERO, d, 0);
+ M_FCMPLT (s1, s2, REG_FTMP3);
+ M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
+ M_LSUB (REG_ZERO, 1, d, 1);
+ store_reg_to_var_int(c->dest, d);
+ break;
+
+
+ /********************** memory operations *****************************/
+
+ case CMD_ARRAYLENGTH:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ d = reg_of_var(c->dest, REG_ITMP3);
+ M_ILD (d, s1, OFFSET(java_arrayheader, size));
+ store_reg_to_var_int(c->dest, d);
+ break;
+
+ case CMD_AALOAD:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ s2 = var_to_reg_int(c->source2, REG_ITMP2);
+ d = reg_of_var(c->dest, REG_ITMP3);
+ M_S8ADDQ (s2, s1, REG_ITMP1, 0);
+ M_LLD ( d, REG_ITMP1, OFFSET (java_objectarray, data[0]));
+ store_reg_to_var_int(c->dest, d);
+ break;
+ case CMD_LALOAD:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ s2 = var_to_reg_int(c->source2, REG_ITMP2);
+ d = reg_of_var(c->dest, REG_ITMP3);
+ M_S8ADDQ (s2, s1, REG_ITMP1, 0);
+ M_LLD ( d, REG_ITMP1, OFFSET (java_longarray, data[0]));
+ store_reg_to_var_int(c->dest, d);
+ break;
+ case CMD_IALOAD:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ s2 = var_to_reg_int(c->source2, REG_ITMP2);
+ d = reg_of_var(c->dest, REG_ITMP3);
+ M_S4ADDQ (s2, s1, REG_ITMP1, 0);
+ M_ILD ( d, REG_ITMP1, OFFSET (java_intarray, data[0]));
+ store_reg_to_var_int(c->dest, d);
+ break;
+ case CMD_FALOAD:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ s2 = var_to_reg_int(c->source2, REG_ITMP2);
+ d = reg_of_var(c->dest, REG_FTMP3);
+ M_S4ADDQ (s2, s1, REG_ITMP1, 0);
+ M_FLD ( d, REG_ITMP1, OFFSET (java_floatarray, data[0]));
+ store_reg_to_var_flt(c->dest, d);
+ break;
+ case CMD_DALOAD:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ s2 = var_to_reg_int(c->source2, REG_ITMP2);
+ d = reg_of_var(c->dest, REG_FTMP3);
+ M_S8ADDQ (s2, s1, REG_ITMP1, 0);
+ M_DLD ( d, REG_ITMP1, OFFSET (java_doublearray, data[0]));
+ store_reg_to_var_flt(c->dest, d);
+ break;
+ case CMD_CALOAD:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ s2 = var_to_reg_int(c->source2, REG_ITMP2);
+ d = reg_of_var(c->dest, REG_ITMP3);
+ if (has_ext_instr_set) {
+ M_LADD (s2, s1, REG_ITMP1, 0);
+ M_LADD (s2, REG_ITMP1, REG_ITMP1, 0);
+ M_SLDU (d, REG_ITMP1, OFFSET (java_chararray, data[0]));
+ }
+ else {
+ M_LADD (s2, s1, REG_ITMP1, 0);
+ M_LADD (s2, REG_ITMP1, REG_ITMP1, 0);
+ M_LLD_U (REG_ITMP2, REG_ITMP1, OFFSET(java_chararray, data[0]));
+ M_LDA (REG_ITMP1, REG_ITMP1, OFFSET(java_chararray, data[0]));
+ M_EXTWL (REG_ITMP2, REG_ITMP1, d, 0);
+ }
+ store_reg_to_var_int(c->dest, d);
+ break;
+ case CMD_SALOAD:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ s2 = var_to_reg_int(c->source2, REG_ITMP2);
+ d = reg_of_var(c->dest, REG_ITMP3);
+ if (has_ext_instr_set) {
+ M_LADD (s2, s1, REG_ITMP1, 0);
+ M_LADD (s2, REG_ITMP1, REG_ITMP1, 0);
+ M_SLDU (d, REG_ITMP1, OFFSET (java_shortarray, data[0]));
+ M_SSEXT (d, d);
+ }
+ else {
+ M_LADD (s2, s1, REG_ITMP1, 0);
+ M_LADD (s2, REG_ITMP1, REG_ITMP1, 0);
+ M_LLD_U (REG_ITMP2, REG_ITMP1, OFFSET(java_shortarray, data[0]));
+ M_LDA (REG_ITMP1, REG_ITMP1, OFFSET(java_shortarray, data[0]) + 2);
+ M_EXTQH (REG_ITMP2, REG_ITMP1, d, 0);
+ M_SRA (d, 48, d, 1);
+ }
+ store_reg_to_var_int(c->dest, d);
+ break;
+ case CMD_BALOAD:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ s2 = var_to_reg_int(c->source2, REG_ITMP2);
+ d = reg_of_var(c->dest, REG_ITMP3);
+ if (has_ext_instr_set) {
+ M_LADD (s2, s1, REG_ITMP1, 0);
+ M_BLDU (d, REG_ITMP1, OFFSET (java_shortarray, data[0]));
+ M_BSEXT (d, d);
+ }
+ else {
+ M_LADD (s2, s1, REG_ITMP1, 0);
+ M_LLD_U (REG_ITMP2, REG_ITMP1, OFFSET(java_bytearray, data[0]));
+ M_LDA (REG_ITMP1, REG_ITMP1, OFFSET(java_bytearray, data[0]) + 1);
+ M_EXTQH (REG_ITMP2, REG_ITMP1, d, 0);
+ M_SRA (d, 56, d, 1);
+ }
+ store_reg_to_var_int(c->dest, d);
+ break;
+
+ case CMD_AASTORE:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ s2 = var_to_reg_int(c->source2, REG_ITMP2);
+ s3 = var_to_reg_int(c->source3, REG_ITMP3);
+ M_S8ADDQ (s2, s1, REG_ITMP1, 0);
+ M_LST (s3, REG_ITMP1, OFFSET (java_objectarray, data[0]));
+ break;
+ case CMD_LASTORE:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ s2 = var_to_reg_int(c->source2, REG_ITMP2);
+ s3 = var_to_reg_int(c->source3, REG_ITMP3);
+ M_S8ADDQ (s2, s1, REG_ITMP1, 0);
+ M_LST (s3, REG_ITMP1, OFFSET (java_longarray, data[0]));
+ break;
+ case CMD_IASTORE:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ s2 = var_to_reg_int(c->source2, REG_ITMP2);
+ s3 = var_to_reg_int(c->source3, REG_ITMP3);
+ M_S4ADDQ (s2, s1, REG_ITMP1, 0);
+ M_IST (s3, REG_ITMP1, OFFSET (java_intarray, data[0]));
+ break;
+ case CMD_FASTORE:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ s2 = var_to_reg_int(c->source2, REG_ITMP2);
+ s3 = var_to_reg_flt(c->source3, REG_FTMP3);
+ M_S4ADDQ (s2, s1, REG_ITMP1, 0);
+ M_FST (s3, REG_ITMP1, OFFSET (java_floatarray, data[0]));
+ break;
+ case CMD_DASTORE:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ s2 = var_to_reg_int(c->source2, REG_ITMP2);
+ s3 = var_to_reg_flt(c->source3, REG_FTMP3);
+ M_S8ADDQ (s2, s1, REG_ITMP1, 0);
+ M_DST (s3, REG_ITMP1, OFFSET (java_doublearray, data[0]));
+ break;
+ case CMD_CASTORE:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ s2 = var_to_reg_int(c->source2, REG_ITMP2);
+ s3 = var_to_reg_int(c->source3, REG_ITMP3);
+ if (has_ext_instr_set) {
+ M_LADD (s2, s1, REG_ITMP1, 0);
+ M_LADD (s2, REG_ITMP1, REG_ITMP1, 0);
+ M_SST (s3, REG_ITMP1, OFFSET (java_chararray, data[0]));
+ }
+ else {
+ M_LADD (s2, s1, REG_ITMP1, 0);
+ M_LADD (s2, REG_ITMP1, REG_ITMP1, 0);
+ M_LLD_U (REG_ITMP2, REG_ITMP1, OFFSET(java_chararray, data[0]));
+ M_LDA (REG_ITMP1, REG_ITMP1, OFFSET(java_chararray, data[0]));
+ M_INSWL (s3, REG_ITMP1, REG_ITMP3, 0);
+ M_MSKWL (REG_ITMP2, REG_ITMP1, REG_ITMP2, 0);
+ M_OR (REG_ITMP2, REG_ITMP3, REG_ITMP2, 0);
+ M_LST_U (REG_ITMP2, REG_ITMP1, 0);
+ }
+ break;
+ case CMD_SASTORE:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ s2 = var_to_reg_int(c->source2, REG_ITMP2);
+ s3 = var_to_reg_int(c->source3, REG_ITMP3);
+ if (has_ext_instr_set) {
+ M_LADD (s2, s1, REG_ITMP1, 0);
+ M_LADD (s2, REG_ITMP1, REG_ITMP1, 0);
+ M_SST (s3, REG_ITMP1, OFFSET (java_shortarray, data[0]));
+ }
+ else {
+ M_LADD (s2, s1, REG_ITMP1, 0);
+ M_LADD (s2, REG_ITMP1, REG_ITMP1, 0);
+ M_LLD_U (REG_ITMP2, REG_ITMP1, OFFSET(java_shortarray, data[0]));
+ M_LDA (REG_ITMP1, REG_ITMP1, OFFSET(java_shortarray, data[0]));
+ M_INSWL (s3, REG_ITMP1, REG_ITMP3, 0);
+ M_MSKWL (REG_ITMP2, REG_ITMP1, REG_ITMP2, 0);
+ M_OR (REG_ITMP2, REG_ITMP3, REG_ITMP2, 0);
+ M_LST_U (REG_ITMP2, REG_ITMP1, 0);
+ }
+ break;
+ case CMD_BASTORE:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ s2 = var_to_reg_int(c->source2, REG_ITMP2);
+ s3 = var_to_reg_int(c->source3, REG_ITMP3);
+ if (has_ext_instr_set) {
+ M_LADD (s2, s1, REG_ITMP1, 0);
+ M_BST (s3, REG_ITMP1, OFFSET (java_bytearray, data[0]));
+ }
+ else {
+ M_LADD (s2, s1, REG_ITMP1, 0);
+ M_LLD_U (REG_ITMP2, REG_ITMP1, OFFSET (java_bytearray, data[0]));
+ M_LDA (REG_ITMP1, REG_ITMP1, OFFSET (java_bytearray, data[0]));
+ M_INSBL (s3, REG_ITMP1, REG_ITMP3, 0);
+ M_MSKBL (REG_ITMP2, REG_ITMP1, REG_ITMP2, 0);
+ M_OR (REG_ITMP2, REG_ITMP3, REG_ITMP2, 0);
+ M_LST_U (REG_ITMP2, REG_ITMP1, 0);
+ }
+ break;
+
+
+ case CMD_PUTFIELD:
+ switch (c->u.mem.type) {
+ case TYPE_INT:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ s2 = var_to_reg_int(c->source2, REG_ITMP2);
+ M_IST (s2, s1, c->u.mem.offset);
+ break;
+ case TYPE_LONG:
+ case TYPE_ADDRESS:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ s2 = var_to_reg_int(c->source2, REG_ITMP2);
+ M_LST (s2, s1, c->u.mem.offset);
+ break;
+ case TYPE_FLOAT:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ s2 = var_to_reg_flt(c->source2, REG_FTMP2);
+ M_FST (s2, s1, c->u.mem.offset);
+ break;
+ case TYPE_DOUBLE:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ s2 = var_to_reg_flt(c->source2, REG_FTMP2);
+ M_DST (s2, s1, c->u.mem.offset);
+ break;
+ default: panic ("internal error");
+ }
+ break;
+
+ case CMD_GETFIELD:
+ switch (c->u.mem.type) {
+ case TYPE_INT:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ d = reg_of_var(c->dest, REG_ITMP3);
+ M_ILD (d, s1, c->u.mem.offset);
+ store_reg_to_var_int(c->dest, d);
+ break;
+ case TYPE_LONG:
+ case TYPE_ADDRESS:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ d = reg_of_var(c->dest, REG_ITMP3);
+ M_LLD (d, s1, c->u.mem.offset);
+ store_reg_to_var_int(c->dest, d);
+ break;
+ case TYPE_FLOAT:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ d = reg_of_var(c->dest, REG_FTMP1);
+ M_FLD (d, s1, c->u.mem.offset);
+ store_reg_to_var_flt(c->dest, d);
+ break;
+ case TYPE_DOUBLE:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ d = reg_of_var(c->dest, REG_FTMP1);
+ M_DLD (d, s1, c->u.mem.offset);
+ store_reg_to_var_flt(c->dest, d);
+ break;
+ default: panic ("internal error");
+ }
+ break;
+
+
+ /********************** branch operations *****************************/
+
+ case CMD_GOTO:
+ mcode_addreference (c->u.bra.target);
+ M_BR (0);
+ break;
+
+ case CMD_JSR: {
+ reginfo *di = c->dest->reg;
+
+ if (di->typeflags & REG_INMEMORY)
+ panic ("Can not put returnaddress into memory var");
+
+ mcode_addreference (c->u.bra.target);
+ M_BSR (di->num, 0);
+ }
+ break;
+
+ case CMD_RET:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ M_RET (REG_ZERO, s1);
+ break;
+
+ case CMD_IFEQ:
+ case CMD_IFEQL:
+ case CMD_IFNULL:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ mcode_addreference (c->u.bra.target);
+ M_BEQZ (s1, 0);
+ break;
+ case CMD_IFLT:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ mcode_addreference (c->u.bra.target);
+ M_BLTZ (s1, 0);
+ break;
+ case CMD_IFLE:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ mcode_addreference (c->u.bra.target);
+ M_BLEZ (s1, 0);
+ break;
+ case CMD_IFNE:
+ case CMD_IFNONNULL:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ mcode_addreference (c->u.bra.target);
+ M_BNEZ (s1, 0);
+ break;
+ case CMD_IFGT:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ mcode_addreference (c->u.bra.target);
+ M_BGTZ (s1, 0);
+ break;
+ case CMD_IFGE:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ mcode_addreference (c->u.bra.target);
+ M_BGEZ (s1, 0);
+ break;
+
+ case CMD_IF_ICMPEQ:
+ case CMD_IF_ACMPEQ:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ s2 = var_to_reg_int(c->source2, REG_ITMP2);
+ M_CMPEQ (s1, s2, REG_ITMP1, 0);
+ mcode_addreference (c->u.bra.target);
+ M_BNEZ (REG_ITMP1, 0);
+ break;
+ case CMD_IF_ICMPNE:
+ case CMD_IF_ACMPNE:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ s2 = var_to_reg_int(c->source2, REG_ITMP2);
+ M_CMPEQ (s1, s2, REG_ITMP1, 0);
+ mcode_addreference (c->u.bra.target);
+ M_BEQZ (REG_ITMP1, 0);
+ break;
+ case CMD_IF_ICMPLT:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ s2 = var_to_reg_int(c->source2, REG_ITMP2);
+ M_CMPLT (s1, s2, REG_ITMP1, 0);
+ mcode_addreference (c->u.bra.target);
+ M_BNEZ (REG_ITMP1, 0);
+ break;
+ case CMD_IF_ICMPGT:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ s2 = var_to_reg_int(c->source2, REG_ITMP2);
+ M_CMPLE (s1, s2, REG_ITMP1, 0);
+ mcode_addreference ( c->u.bra.target );
+ M_BEQZ (REG_ITMP1, 0);
+ break;
+ case CMD_IF_ICMPLE:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ s2 = var_to_reg_int(c->source2, REG_ITMP2);
+ M_CMPLE (s1, s2, REG_ITMP1, 0);
+ mcode_addreference (c->u.bra.target);
+ M_BNEZ (REG_ITMP1, 0);
+ break;
+ case CMD_IF_ICMPGE:
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ s2 = var_to_reg_int(c->source2, REG_ITMP2);
+ M_CMPLT (s1, s2, REG_ITMP1, 0);
+ mcode_addreference (c->u.bra.target);
+ M_BEQZ (REG_ITMP1, 0);
+ break;
+
+ case CMD_IF_UCMPGE: /* branch if the unsigned value of s1 is
+ greater that s2 (note, that s2 has
+ to be >= 0) */
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ s2 = var_to_reg_int(c->source2, REG_ITMP2);
+ M_CMPULE (s2, s1, REG_ITMP1, 0);
+ mcode_addreference (c->u.bra.target);
+ M_BNEZ (REG_ITMP1, 0);
+ break;
+
+
+ case CMD_IRETURN:
+ case CMD_LRETURN:
+ case CMD_ARETURN:
+ s1 = var_to_reg_int(c->source1, REG_RESULT);
+ M_INTMOVE (s1, REG_RESULT);
+ goto nowperformreturn;
+ case CMD_FRETURN:
+ case CMD_DRETURN:
+ s1 = var_to_reg_flt(c->source1, REG_FRESULT);
+ M_FLTMOVE (s1, REG_FRESULT);
+ goto nowperformreturn;
+
+ case CMD_RETURN:
+nowperformreturn:
+ {
+ int r, p;
+
+ s2 = var_to_reg_int(c->source2, REG_ITMP2);
+ M_INTMOVE (s2, REG_EXCEPTION);
+
+ p = parentargs_base;
+ if (!isleafmethod)
+ {p--; M_LLD (REG_RA, REG_SP, 8*p);}
+ for (r = INT_SAV_FST; r < INT_SAV_FST + INT_SAV_CNT; r++)
+ if (!(intregs[r].typeflags & REG_ISUNUSED))
+ {p--; M_LLD (r, REG_SP, 8*p);}
+ for (r = FLT_SAV_FST; r < FLT_SAV_FST + FLT_SAV_CNT; r++)
+ if (!(floatregs[r].typeflags & REG_ISUNUSED))
+ {p--; M_DLD (r, REG_SP, 8*p);}
+
+ if (parentargs_base)
+ {M_LDA (REG_SP, REG_SP, parentargs_base*8);}
+ if (runverbose) {
+ M_LDA (REG_SP, REG_SP, -32);
+ M_LST(REG_RA, REG_SP, 0);
+ M_LST(REG_RESULT, REG_SP, 8);
+ M_DST(REG_FRESULT, REG_SP,16);
+ M_LST(REG_EXCEPTION, REG_SP, 24);
+ a = dseg_addaddress (method);
+ M_LLD(INT_ARG_FST, REG_PV, a);
+ M_OR(REG_RESULT, REG_RESULT, INT_ARG_FST + 1, 0);
+ M_FLTMOVE(REG_FRESULT, FLT_ARG_FST + 2);
+ a = dseg_addaddress ((void*) (builtin_displaymethodstop));
+ M_LLD(REG_PV, REG_PV, a);
+ M_JSR (REG_RA, REG_PV);
+ if (mcodelen<=32768) M_LDA (REG_PV, REG_RA, -mcodelen);
+ else {
+ s4 ml=-mcodelen, mh=0;
+ while (ml<-32768) { ml+=65536; mh--; }
+ M_LDA (REG_PV, REG_RA, ml );
+ M_LDAH (REG_PV, REG_PV, mh );
+ }
+ M_LLD(REG_EXCEPTION, REG_SP, 24);
+ M_DLD(REG_FRESULT, REG_SP,16);
+ M_LLD(REG_RESULT, REG_SP, 8);
+ M_LLD(REG_RA, REG_SP, 0);
+ M_LDA (REG_SP, REG_SP, 32);
+ }
+ M_RET (REG_ZERO, REG_RA);
+ }
+ break;
+
+
+ case CMD_TABLEJUMP:
+ {
+ int i;
+
+ /* build jump table top down and use address of lowest entry */
+
+ a = 0;
+ for (i = c->u.tablejump.targetcount - 1; i >= 0; i--) {
+ a = dseg_addtarget (c->u.tablejump.targets[i]);
+ }
+ }
+
+ /* last offset a returned by dseg_addtarget is used by load */
+
+ s1 = var_to_reg_int(c->source1, REG_ITMP1);
+ M_S8ADDQ (s1, REG_PV, REG_ITMP2, 0);
+ M_LLD (REG_ITMP3, REG_ITMP2, a);
+ M_JMP (REG_ZERO, REG_ITMP3);
+ break;
+
+
+ case CMD_INVOKESTATIC:
+ case CMD_INVOKESPECIAL:
+ case CMD_INVOKEVIRTUAL:
+ case CMD_INVOKEINTERFACE:
+ case CMD_BUILTIN:
+ gen_method (c);
+ break;
+
+ case CMD_DROP:
+ case CMD_ACTIVATE:
+ break;
+
+ default: sprintf (logtext, "Unknown pseudo command: %d(%d)", c->opcode,
+ c->tag);
+ error();
+ }
+}
+
+
+/*********************** function input_args_prealloc **************************
+
+ preallocates the input arguments (on the Alpha only for leaf methods)
+
+*******************************************************************************/
+
+
+static void input_args_prealloc()
+{
+ int i, t;
+ varid p;
+ reginfo *r;
+
+ if (isleafmethod)
+ for (i = 0; (i < mparamnum) && (i < INT_ARG_CNT); i++) {
+ t = mparamtypes[i];
+ p = mparamvars[i];
+ p->saved = !isleafmethod;
+ if (t==TYPE_DOUBLE || t==TYPE_FLOAT)
+ r = &floatregs[FLT_ARG_FST + i];
+ else
+ r = &intregs[INT_ARG_FST + i];
+ r->typeflags &= ~REG_ISFREEUNUSED;
+ p->reg = r;
+ }
+}
+
+
+/********************* function gen_computestackframe **************************
+
+ computes the size and the layout of a stack frame.
+ The values of localvars_base, savedregs_base, parentargs_base
+ are numbers of 8-byte slots in the stackframe (every spilled or
+ saved register value will be stored in a 64-bit slot, regardless
+ of its type: INT/LONG/FLOAT/DOUBLE/ADDRESS)
+ (a detailed description of the stack frame is contained in 'calling.doc')
+
+
+*******************************************************************************/
+
+
+static void gen_computestackframe()
+{
+ int i;
+
+ savedregs_num = (isleafmethod) ? 0 : 1; /* space to save the RA */
+
+ /* space to save used callee saved registers */
+
+ for (i = INT_SAV_FST; i < INT_SAV_FST + INT_SAV_CNT; i++)
+ if (! (intregs[i].typeflags & REG_ISUNUSED))
+ savedregs_num++;
+ for (i = FLT_SAV_FST; i < FLT_SAV_FST + FLT_SAV_CNT; i++)
+ if (! (floatregs[i].typeflags & REG_ISUNUSED))
+ savedregs_num++;
+
+ localvars_base = arguments_num;
+ savedregs_base = localvars_base + localvars_num;
+ parentargs_base = savedregs_base + savedregs_num;
+}
+
+
+/******************** function gen_header **************************************
+
+ using the data computed by gen_computestackframe it generates a function
+ header which:
+
+ - saves the necessary registers
+ - copies arguments to registers or to stack slots
+
+*******************************************************************************/
+
+
+static void gen_header ()
+{
+ int p, pa, r;
+ reginfo *ri;
+
+
+ /* create stack frame (if necessary) */
+
+ if (parentargs_base)
+ {M_LDA (REG_SP, REG_SP, -parentargs_base * 8);}
+
+ /* save return address and used callee saved registers */
+
+ p = parentargs_base;
+ if (!isleafmethod)
+ {p--; M_LST (REG_RA, REG_SP, 8*p);}
+ for (r = INT_SAV_FST; r < INT_SAV_FST + INT_SAV_CNT; r++)
+ if (!(intregs[r].typeflags & REG_ISUNUSED))
+ {p--; M_LST (r, REG_SP, 8 * p);}
+ for (r = FLT_SAV_FST; r < FLT_SAV_FST + FLT_SAV_CNT; r++)
+ if (!(floatregs[r].typeflags & REG_ISUNUSED))
+ {p--; M_DST (r, REG_SP, 8 * p);}
+
+ /* take arguments out of register or stack frame */
+
+ for (p = 0; p < mparamnum; p++) {
+ ri = mparamvars[p]->reg;
+
+ if (p < INT_ARG_CNT) { /* register arguments */
+ if (IS_INT_LNG_REG(ri->typeflags)) { /* integer args */
+ if (!(ri->typeflags & REG_INMEMORY)) /* reg arg -> register */
+ M_INTMOVE (16+p, ri->num);
+ else /* reg arg -> spilled */
+ M_LST (16+p, REG_SP, 8 * (localvars_base + ri->num));
+ }
+ else { /* floating args */
+ if (!(ri->typeflags & REG_INMEMORY)) /* reg-arg -> register */
+ M_FLTMOVE (16+p, ri->num);
+ else /* reg-arg -> spilled */
+ M_DST (16+p, REG_SP, 8 * (localvars_base + ri->num));
+ }
+ }
+
+ else { /* stack arguments */
+ pa = p - INT_ARG_CNT;
+ if (IS_INT_LNG_REG(ri->typeflags)) { /* integer args */
+ if (!(ri->typeflags & REG_INMEMORY)) /* stack arg -> register */
+ M_LLD (ri->num, REG_SP, 8 * (parentargs_base + pa));
+ else { /* stack arg -> spilled */
+ M_LLD (REG_ITMP1, REG_SP, 8 * (parentargs_base + pa));
+ M_LST (REG_ITMP1, REG_SP, 8 * (localvars_base + ri->num));
+ }
+ }
+ else {
+ if (!(ri->typeflags & REG_INMEMORY)) /* stack-arg -> register */
+ M_DLD (ri->num, REG_SP, 8 * (parentargs_base + pa) );
+ else { /* stack-arg -> spilled */
+ M_DLD (REG_FTMP1, REG_SP, 8 * (parentargs_base + pa));
+ M_DST (REG_FTMP1, REG_SP, 8 * (localvars_base + ri->num));
+ }
+ }
+ }
+ } /* end for */
+} /* end gen_header */
+
+
+/************************ function gen_resolvebranch ***************************
+
+ backpatches a branch instruction; Alpha branch instructions are very
+ regular, so it is only necessary to overwrite some fixed bits in the
+ instruction.
+
+ parameters: mcodepiece .. start of code area
+ sourcepos ... offset of branch instruction
+ targetpos ... offset of branch target
+
+*******************************************************************************/
+
+
+static void gen_resolvebranch ( void* mcodepiece, s4 sourcepos, s4 targetpos)
+{
+ s4 *command = mcodepiece;
+ s4 offset = targetpos - (sourcepos+4);
+
+ (*command) |= ((offset >> 2) & ((s4) 0x1fffff) );
+}
+
+
+
+/******** redefinition of code generation makros (compilinf into array) *******/
+
+/*
+These macros are newly defined to allow code generation into an array.
+This is necessary, because the original M_.. macros generate code by
+calling 'mcode_adds4' that uses an additional data structure to
+receive the code.
+
+For a faster (but less flexible) version to generate code, these
+macros directly use the (s4* p) - pointer to put the code directly
+in a locally defined array.
+This makes sense only for the stub-generation-routines below.
+*/
+
+#undef M_OP3
+#define M_OP3(op,fu,a,b,c,const) \
+ *(p++) = ( (((s4)(op))<<26)|((a)<<21)|((b)<<(16-3*(const)))| \
+ ((const)<<12)|((fu)<<5)|((c)) )
+#undef M_FOP3
+#define M_FOP3(op,fu,a,b,c) \
+ *(p++) = ( (((s4)(op))<<26)|((a)<<21)|((b)<<16)|((fu)<<5)|(c) )
+#undef M_BRA
+#define M_BRA(op,a,disp) \
+ *(p++) = ( (((s4)(op))<<26)|((a)<<21)|((disp)&0x1fffff) )
+#undef M_MEM
+#define M_MEM(op,a,b,disp) \
+ *(p++) = ( (((s4)(op))<<26)|((a)<<21)|((b)<<16)|((disp)&0xffff) )
+
+
+/************************ function createcompilerstub **************************
+
+ creates a stub routine which calls the compiler
+
+*******************************************************************************/
+
+#define COMPSTUBSIZE 3
+
+u1 *createcompilerstub (methodinfo *m)
+{
+ u8 *s = CNEW (u8, COMPSTUBSIZE); /* memory to hold the stub */
+ s4 *p = (s4*) s; /* code generation pointer */
+
+ /* code for the stub */
+ M_LLD (REG_PV, REG_PV, 16); /* load pointer to the compiler */
+ M_JMP (0, REG_PV); /* jump to the compiler, return address
+ in reg 0 is used as method pointer */
+ s[1] = (u8) m; /* literals to be adressed */
+ s[2] = (u8) asm_call_jit_compiler; /* jump directly via PV from above */
+
+#ifdef STATISTICS
+ count_cstub_len += COMPSTUBSIZE * 8;
+#endif
+
+ return (u1*) s;
+}
+
+
+/************************* function removecompilerstub *************************
+
+ deletes a compilerstub from memory (simply by freeing it)
+
+*******************************************************************************/
+
+void removecompilerstub (u1 *stub)
+{
+ CFREE (stub, COMPSTUBSIZE * 8);
+}
+
+
+/********************* Funktion: createnativestub ******************************
+
+ creates a stub routine which calls a native method
+
+*******************************************************************************/
+
+#define NATIVESTUBSIZE 11
+
+u1 *createnativestub (functionptr f, methodinfo *m)
+{
+ u8 *s = CNEW (u8, NATIVESTUBSIZE); /* memory to hold the stub */
+ s4 *p = (s4*) s; /* code generation pointer */
+
+ M_LDA (REG_SP, REG_SP, -8); /* build up stackframe */
+ M_LST (REG_RA, REG_SP, 0); /* store return address */
+
+ M_LLD (REG_PV, REG_PV, 6*8); /* load adress of native method */
+ M_JSR (REG_RA, REG_PV); /* call native method */
+ M_LDA (REG_PV, REG_RA, -4*4); /* recompute pv from ra */
+
+ M_LLD (22, REG_PV, 7*8); /* get address of exceptionptr */
+ M_LLD (REG_EXCEPTION, 22, 0); /* load exception into reg. 1 */
+ M_LST (REG_ZERO, 22, 0); /* store NULL into exceptionptr */
+
+ M_LLD (REG_RA, REG_SP, 0); /* load return address */
+ M_LDA (REG_SP, REG_SP, 8); /* remove stackframe */
+
+ M_RET (REG_ZERO, REG_RA); /* return to caller */
+
+ s[6] = (u8) f; /* address of native method */
+ s[7] = (u8) (&exceptionptr); /* address of exceptionptr */
+
+#ifdef STATISTICS
+ count_nstub_len += NATIVESTUBSIZE * 8;
+#endif
+
+ return (u1*) s;
+}
+
+
+/************************ function: removenativestub ***************************
+
+ removes a previously created native-stub from memory
+
+*******************************************************************************/
+
+void removenativestub (u1 *stub)
+{
+ CFREE (stub, NATIVESTUBSIZE * 8);
+}
+
--- /dev/null
+/************************* alpha/native-math.h *********************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Contains the machine-specific floating point definitions.
+
+ Authors: Michael Gschwind EMAIL: cacao@complang.tuwien.ac.at
+ Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1997/10/21
+
+*******************************************************************************/
+
+/* include machine-specific math.h */
+
+#include <math.h>
+
+/* define infinity for floating point numbers */
+
+u4 flt_nan = 0xffffffff;
+u4 flt_posinf = 0x7f800000;
+u4 flt_neginf = 0xff800000;
+
+#define FLT_NAN (*((float*) (&flt_nan)))
+#define FLT_POSINF (*((float*) (&flt_posinf)))
+#define FLT_NEGINF (*((float*) (&flt_neginf)))
+
+/* define infinity for double floating point numbers */
+
+u8 dbl_nan = 0xffffffffffffffffL ;
+u8 dbl_posinf = 0x7ff0000000000000L ;
+u8 dbl_neginf = 0xfff0000000000000L ;
+
+#define DBL_NAN (*((double*) (&dbl_nan)))
+#define DBL_POSINF (*((double*) (&dbl_posinf)))
+#define DBL_NEGINF (*((double*) (&dbl_neginf)))
--- /dev/null
+/***************************** alpha/ngen.c ************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Contains the codegenerator for an Alpha processor.
+ This module generates Alpha machine code for a sequence of
+ pseudo commands (ICMDs).
+
+ Authors: Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
+ Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1998/08/10
+
+*******************************************************************************/
+
+
+
+/*******************************************************************************
+
+Datatypes and Register Allocations:
+-----------------------------------
+
+On 64-bit-machines (like the Alpha) all operands are stored in the
+registers in a 64-bit form, even when the correspondig JavaVM
+operands only need 32 bits.
+This is done by a canonical representation:
+
+32-bit integers are allways stored as sign-extended 64-bit values
+(this approach is directly supported by the Alpha architecture and
+is very easy to implement).
+
+32-bit-floats are stored in a 64-bit doubleprecision register by
+simply expanding the exponent and mantissa with zeroes.
+(also supported by the architecture)
+
+
+Stackframes:
+
+The calling conventions and the layout of the stack is
+explained in detail in the documention file: calling.doc
+
+*******************************************************************************/
+
+
+/*********** additional functions and macros to generate code *****************/
+
+#define BlockPtrOfPC(pc) block+block_index[pc]
+
+#ifdef STATISTICS
+#define COUNT_SPILLS count_spills++
+#else
+#define COUNT_SPILLS
+#endif
+
+
+/* gen_nullptr_check(objreg) */
+
+#ifdef SOFTNULLPTRCHECK
+#define gen_nullptr_check(objreg) \
+ if (checknull) {\
+ M_BEQZ((objreg), 0);\
+ mcode_addxnullrefs(mcodeptr);\
+ }
+#else
+#define gen_nullptr_check(objreg)
+#endif
+
+
+/* MCODECHECK(icnt) */
+
+#define MCODECHECK(icnt) \
+ if((mcodeptr+(icnt))>mcodeend)mcodeptr=mcode_increase((u1*)mcodeptr)
+
+/* M_INTMOVE:
+ generates an integer-move from register a to b.
+ if a and b are the same int-register, no code will be generated.
+*/
+
+#define M_INTMOVE(a,b) if(a!=b){M_OR(a,a,b,0);}
+
+
+/* M_FLTMOVE:
+ generates a floating-point-move from register a to b.
+ if a and b are the same float-register, no code will be generated
+*/
+
+#define M_FLTMOVE(a,b) if(a!=b){M_FMOV(a,b);}
+
+
+/* var_to_reg_xxx:
+ this function generates code to fetch data from a pseudo-register
+ into a real register.
+ If the pseudo-register has actually been assigned to a real
+ register, no code will be emitted, since following operations
+ can use this register directly.
+
+ v: pseudoregister to be fetched from
+ tempregnum: temporary register to be used if v is actually spilled to ram
+
+ return: the register number, where the operand can be found after
+ fetching (this wil be either tempregnum or the register
+ number allready given to v)
+*/
+
+#define var_to_reg_int(regnr,v,tempnr) { \
+ if ((v)->flags & INMEMORY) \
+ {COUNT_SPILLS;M_LLD(tempnr,REG_SP,8*(v)->regoff);regnr=tempnr;} \
+ else regnr=(v)->regoff; \
+}
+
+
+#define var_to_reg_flt(regnr,v,tempnr) { \
+ if ((v)->flags & INMEMORY) \
+ {COUNT_SPILLS;M_DLD(tempnr,REG_SP,8*(v)->regoff);regnr=tempnr;} \
+ else regnr=(v)->regoff; \
+}
+
+
+/* reg_of_var:
+ This function determines a register, to which the result of an
+ operation should go, when it is ultimatively intended to store the result
+ in pseudoregister v.
+ If v is assigned to an actual register, this register will be
+ returned.
+ Otherwise (when v is spilled) this function returns tempregnum.
+ If not already done, regoff and flags are set in the stack location.
+*/
+
+static int reg_of_var(stackptr v, int tempregnum)
+{
+ varinfo *var;
+
+ switch (v->varkind) {
+ case TEMPVAR:
+ if (!(v->flags & INMEMORY))
+ return(v->regoff);
+ break;
+ case STACKVAR:
+ var = &(interfaces[v->varnum][v->type]);
+ v->regoff = var->regoff;
+ if (!(var->flags & INMEMORY))
+ return(var->regoff);
+ break;
+ case LOCALVAR:
+ var = &(locals[v->varnum][v->type]);
+ v->regoff = var->regoff;
+ if (!(var->flags & INMEMORY))
+ return(var->regoff);
+ break;
+ case ARGVAR:
+ v->regoff = v->varnum;
+ if (IS_FLT_DBL_TYPE(v->type)) {
+ if (v->varnum < fltreg_argnum) {
+ v->regoff = argfltregs[v->varnum];
+ return(argfltregs[v->varnum]);
+ }
+ }
+ else
+ if (v->varnum < intreg_argnum) {
+ v->regoff = argintregs[v->varnum];
+ return(argintregs[v->varnum]);
+ }
+ v->regoff -= intreg_argnum;
+ break;
+ }
+ v->flags |= INMEMORY;
+ return tempregnum;
+}
+
+
+/* store_reg_to_var_xxx:
+ This function generates the code to store the result of an operation
+ back into a spilled pseudo-variable.
+ If the pseudo-variable has not been spilled in the first place, this
+ function will generate nothing.
+
+ v ............ Pseudovariable
+ tempregnum ... Number of the temporary registers as returned by
+ reg_of_var.
+*/
+
+#define store_reg_to_var_int(sptr, tempregnum) { \
+ if ((sptr)->flags & INMEMORY) { \
+ COUNT_SPILLS; \
+ M_LST(tempregnum, REG_SP, 8 * (sptr)->regoff); \
+ } \
+ }
+
+#define store_reg_to_var_flt(sptr, tempregnum) { \
+ if ((sptr)->flags & INMEMORY) { \
+ COUNT_SPILLS; \
+ M_DST(tempregnum, REG_SP, 8 * (sptr)->regoff); \
+ } \
+ }
+
+
+void asm_signal_exception(void *xptr, void *sigctx);
+
+void catch_NullPointerException(int sig, int code, void *sigctx)
+{
+ sigset_t nsig;
+
+ /* Reset signal handler - necessary for SysV, does no harm for BSD */
+
+ signal(sig, (void*) catch_NullPointerException);
+ sigemptyset(&nsig);
+ sigaddset(&nsig, sig);
+ sigprocmask(SIG_UNBLOCK, &nsig, 0);
+ asm_signal_exception(proto_java_lang_NullPointerException, sigctx);
+}
+
+#ifdef __osf__
+
+void init_exceptions(void)
+{
+
+#else
+
+#include <asm/fpu.h>
+
+extern unsigned long ieee_get_fp_control();
+extern void ieee_set_fp_control(unsigned long fp_control);
+
+void init_exceptions(void)
+{
+/* initialise floating point control */
+ieee_set_fp_control(ieee_get_fp_control()
+ & ~IEEE_TRAP_ENABLE_INV
+ & ~IEEE_TRAP_ENABLE_DZE
+/* & ~IEEE_TRAP_ENABLE_UNF */
+ & ~IEEE_TRAP_ENABLE_OVF);
+#endif
+
+ /* Catch signal we need to convert to exceptions */
+ if (!checknull) {
+#if defined(SIGSEGV)
+ signal(SIGSEGV, (void*) catch_NullPointerException);
+#endif
+#if defined(SIGBUS)
+ signal(SIGBUS, (void*) catch_NullPointerException);
+#endif
+ }
+}
+
+/*************************** function gen_mcode ********************************
+
+ generates machine code
+
+*******************************************************************************/
+
+#define MethodPointer -8
+#define FrameSize -12
+#define IsSync -16
+#define IsLeaf -20
+#define IntSave -24
+#define FltSave -28
+#define ExTableSize -32
+#define ExTableStart -32
+
+#define ExEntrySize -32
+#define ExStartPC -8
+#define ExEndPC -16
+#define ExHandlerPC -24
+#define ExCatchType -32
+
+static void gen_mcode()
+{
+ int len, s1, s2, s3, d, bbs;
+ s4 a;
+ s4 *mcodeptr;
+ stackptr src;
+ varinfo *var;
+ basicblock *bptr;
+ instruction *iptr;
+
+ {
+ int p, pa, t, l, r;
+
+ savedregs_num = (isleafmethod) ? 0 : 1; /* space to save the RA */
+
+ /* space to save used callee saved registers */
+
+ savedregs_num += (savintregcnt - maxsavintreguse);
+ savedregs_num += (savfltregcnt - maxsavfltreguse);
+
+ parentargs_base = maxmemuse + savedregs_num;
+
+#ifdef USE_THREADS
+ if (checksync && (method->flags & ACC_SYNCHRONIZED))
+ parentargs_base++;
+#endif
+
+ /* create method header */
+
+ (void) dseg_addaddress(method); /* MethodPointer */
+ (void) dseg_adds4(parentargs_base * 8); /* FrameSize */
+
+#ifdef USE_THREADS
+ if (checksync && (method->flags & ACC_SYNCHRONIZED))
+ (void) dseg_adds4((maxmemuse + 1) * 8); /* IsSync */
+ else
+#endif
+ (void) dseg_adds4(0); /* IsSync */
+
+ (void) dseg_adds4(isleafmethod); /* IsLeaf */
+ (void) dseg_adds4(savintregcnt - maxsavintreguse); /* IntSave */
+ (void) dseg_adds4(savfltregcnt - maxsavfltreguse); /* FltSave */
+ (void) dseg_adds4(exceptiontablelength); /* ExTableSize */
+
+ for (len = 0; len < exceptiontablelength; len++) {
+ dseg_addtarget(BlockPtrOfPC(extable[len].startpc));
+ dseg_addtarget(BlockPtrOfPC(extable[len].endpc));
+ dseg_addtarget(BlockPtrOfPC(extable[len].handlerpc));
+ (void) dseg_addaddress(extable[len].catchtype);
+ }
+
+ /* initialise mcode variables */
+
+ mcodeptr = (s4*) mcodebase;
+ mcodeend = (s4*) (mcodebase + mcodesize);
+ MCODECHECK(128);
+
+ /* create stack frame (if necessary) */
+
+ if (parentargs_base)
+ {M_LDA (REG_SP, REG_SP, -parentargs_base * 8);}
+
+ /* save return address and used callee saved registers */
+
+ p = parentargs_base;
+ if (!isleafmethod)
+ {p--; M_LST (REG_RA, REG_SP, 8*p);}
+ for (r = savintregcnt - 1; r >= maxsavintreguse; r--)
+ {p--; M_LST (savintregs[r], REG_SP, 8 * p);}
+ for (r = savfltregcnt - 1; r >= maxsavfltreguse; r--)
+ {p--; M_DST (savfltregs[r], REG_SP, 8 * p);}
+
+ /* save monitorenter argument */
+
+#ifdef USE_THREADS
+ if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
+ if (method->flags & ACC_STATIC) {
+ p = dseg_addaddress (class);
+ M_LLD(REG_ITMP1, REG_PV, p);
+ M_LST(REG_ITMP1, REG_SP, 8 * maxmemuse);
+ }
+ else {
+ M_LST (argintregs[0], REG_SP, 8 * maxmemuse);
+ }
+ }
+#endif
+
+ if (runverbose && isleafmethod) {
+ M_LDA (REG_SP, REG_SP, -(8*8));
+ M_LST(REG_RA, REG_SP, 1*8);
+ M_LST(argintregs[0], REG_SP, 2*8);
+ M_LST(argintregs[1], REG_SP, 3*8);
+ M_LST(argintregs[2], REG_SP, 4*8);
+ M_LST(argintregs[3], REG_SP, 5*8);
+ M_LST(argintregs[4], REG_SP, 6*8);
+ M_LST(argintregs[5], REG_SP, 7*8);
+ p = dseg_addaddress (method);
+ M_LLD(REG_ITMP1, REG_PV, p);
+ M_LST(REG_ITMP1, REG_SP, 0);
+ p = dseg_addaddress ((void*) (builtin_trace_args));
+ M_LLD(REG_PV, REG_PV, p);
+ M_JSR(REG_RA, REG_PV);
+ M_LDA(REG_PV, REG_RA, -(int)((u1*) mcodeptr - mcodebase));
+ M_LLD(REG_RA, REG_SP, 1*8);
+ M_LLD(argintregs[0], REG_SP, 2*8);
+ M_LLD(argintregs[1], REG_SP, 3*8);
+ M_LLD(argintregs[2], REG_SP, 4*8);
+ M_LLD(argintregs[3], REG_SP, 5*8);
+ M_LLD(argintregs[4], REG_SP, 6*8);
+ M_LLD(argintregs[5], REG_SP, 7*8);
+ M_LDA (REG_SP, REG_SP, 8*8);
+ }
+
+ /* take arguments out of register or stack frame */
+
+ for (p = 0, l = 0; p < mparamcount; p++) {
+ t = mparamtypes[p];
+ var = &(locals[l][t]);
+ l++;
+ if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
+ l++;
+ if (var->type < 0)
+ continue;
+ r = var->regoff;
+ if (IS_INT_LNG_TYPE(t)) { /* integer args */
+ if (p < INT_ARG_CNT) { /* register arguments */
+ if (!(var->flags & INMEMORY)) /* reg arg -> register */
+ {M_INTMOVE (argintregs[p], r);}
+ else /* reg arg -> spilled */
+ M_LST (argintregs[p], REG_SP, 8 * r);
+ }
+ else { /* stack arguments */
+ pa = p - INT_ARG_CNT;
+ if (!(var->flags & INMEMORY)) /* stack arg -> register */
+ M_LLD (r, REG_SP, 8 * (parentargs_base + pa));
+ else { /* stack arg -> spilled */
+ M_LLD (REG_ITMP1, REG_SP, 8 * (parentargs_base + pa));
+ M_LST (REG_ITMP1, REG_SP, 8 * r);
+ }
+ }
+ }
+ else { /* floating args */
+ if (p < FLT_ARG_CNT) { /* register arguments */
+ if (!(var->flags & INMEMORY)) /* reg arg -> register */
+ {M_FLTMOVE (argfltregs[p], r);}
+ else /* reg arg -> spilled */
+ M_DST (argfltregs[p], REG_SP, 8 * r);
+ }
+ else { /* stack arguments */
+ pa = p - FLT_ARG_CNT;
+ if (!(var->flags & INMEMORY)) /* stack-arg -> register */
+ M_DLD (r, REG_SP, 8 * (parentargs_base + pa) );
+ else { /* stack-arg -> spilled */
+ M_DLD (REG_FTMP1, REG_SP, 8 * (parentargs_base + pa));
+ M_DST (REG_FTMP1, REG_SP, 8 * r);
+ }
+ }
+ }
+ } /* end for */
+
+ if (runverbose && !isleafmethod) {
+ M_LDA (REG_SP, REG_SP, -8);
+ p = dseg_addaddress (method);
+ M_LLD(REG_ITMP1, REG_PV, p);
+ M_LST(REG_ITMP1, REG_SP, 0);
+ p = dseg_addaddress ((void*) (builtin_trace_args));
+ M_LLD(REG_PV, REG_PV, p);
+ M_JSR(REG_RA, REG_PV);
+ M_LDA(REG_PV, REG_RA, -(int)((u1*) mcodeptr - mcodebase));
+ M_LDA(REG_SP, REG_SP, 8);
+ }
+
+#ifdef USE_THREADS
+ if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
+ p = dseg_addaddress ((void*) (builtin_monitorenter));
+ M_LLD(REG_PV, REG_PV, p);
+ M_LLD(argintregs[0], REG_SP, 8 * maxmemuse);
+ M_JSR(REG_RA, REG_PV);
+ M_LDA(REG_PV, REG_RA, -(int)((u1*) mcodeptr - mcodebase));
+ }
+#endif
+ }
+
+ /* end of header generation */
+
+ for (bbs = block_count, bptr = block; --bbs >= 0; bptr++) {
+ bptr -> mpc = (int)((u1*) mcodeptr - mcodebase);
+
+ /* branch resolving */
+
+ {
+ branchref *brefs;
+ for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
+ gen_resolvebranch((u1*) mcodebase + brefs->branchpos,
+ brefs->branchpos, bptr->mpc);
+ }
+ }
+ src = bptr->instack;
+ len = bptr->indepth;
+ MCODECHECK(64+len);
+ while (src != NULL) {
+ len--;
+ if ((len == 0) && (bptr->type != BBTYPE_STD)) {
+ d = reg_of_var(src, REG_ITMP1);
+ M_INTMOVE(REG_ITMP1, d);
+ store_reg_to_var_int(src, d);
+ }
+ else {
+ d = reg_of_var(src, REG_IFTMP);
+ if ((src->varkind != STACKVAR)) {
+ s2 = src->type;
+ if (IS_FLT_DBL_TYPE(s2)) {
+ if (!(interfaces[len][s2].flags & INMEMORY)) {
+ s1 = interfaces[len][s2].regoff;
+ M_FLTMOVE(s1,d);
+ }
+ else {
+ M_DLD(d, REG_SP, 8 * interfaces[len][s2].regoff);
+ }
+ store_reg_to_var_flt(src, d);
+ }
+ else {
+ if (!(interfaces[len][s2].flags & INMEMORY)) {
+ s1 = interfaces[len][s2].regoff;
+ M_INTMOVE(s1,d);
+ }
+ else {
+ M_LLD(d, REG_SP, 8 * interfaces[len][s2].regoff);
+ }
+ store_reg_to_var_int(src, d);
+ }
+ }
+ }
+ src = src->prev;
+ }
+ s1 = bptr[0].ipc;
+ src = bptr->instack;
+ len = bptr[1].ipc - s1;
+ for (iptr = &instr[s1];
+ len > 0;
+ src = iptr->dst, len--, iptr++) {
+
+ MCODECHECK(64);
+ switch (iptr->opc) {
+
+ case ICMD_NOP:
+ break;
+
+ case ICMD_NULLCHECKPOP:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ gen_nullptr_check(s1);
+ break;
+
+ /*********************** constant operations **************************/
+
+ case ICMD_ICONST:
+ d = reg_of_var(iptr->dst, REG_ITMP1);
+ if ( (iptr->val.i >= -32768) && (iptr->val.i <= 32767) ) {
+ M_LDA(d, REG_ZERO, iptr->val.i);
+ }
+ else {
+ a = dseg_adds4 (iptr->val.i);
+ M_ILD(d, REG_PV, a);
+ }
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+
+ case ICMD_LCONST:
+ d = reg_of_var(iptr->dst, REG_ITMP1);
+ if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767) ) {
+ M_LDA(d, REG_ZERO, iptr->val.l);
+ }
+ else {
+ a = dseg_adds8 (iptr->val.l);
+ M_LLD(d, REG_PV, a);
+ }
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+
+ case ICMD_FCONST:
+ d = reg_of_var (iptr->dst, REG_FTMP1);
+ a = dseg_addfloat (iptr->val.f);
+ M_FLD(d, REG_PV, a);
+ store_reg_to_var_flt (iptr->dst, d);
+ break;
+
+ case ICMD_DCONST:
+ d = reg_of_var (iptr->dst, REG_FTMP1);
+ a = dseg_adddouble (iptr->val.d);
+ M_DLD(d, REG_PV, a);
+ store_reg_to_var_flt (iptr->dst, d);
+ break;
+
+
+ case ICMD_ACONST:
+ d = reg_of_var(iptr->dst, REG_ITMP1);
+ if (iptr->val.a) {
+ a = dseg_addaddress (iptr->val.a);
+ M_LLD(d, REG_PV, a);
+ }
+ else {
+ M_INTMOVE(REG_ZERO, d);
+ }
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+
+ /********************** load/store operations *************************/
+
+ case ICMD_ILOAD:
+ case ICMD_LLOAD:
+ case ICMD_ALOAD:
+ d = reg_of_var(iptr->dst, REG_ITMP1);
+ if ((iptr->dst->varkind == LOCALVAR) &&
+ (iptr->dst->varnum == iptr->op1))
+ break;
+ var = &(locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
+ if (var->flags & INMEMORY)
+ M_LLD(d, REG_SP, 8 * var->regoff);
+ else
+ {M_INTMOVE(var->regoff,d);}
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+
+ case ICMD_FLOAD:
+ case ICMD_DLOAD:
+ d = reg_of_var(iptr->dst, REG_FTMP1);
+ if ((iptr->dst->varkind == LOCALVAR) &&
+ (iptr->dst->varnum == iptr->op1))
+ break;
+ var = &(locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
+ if (var->flags & INMEMORY)
+ M_DLD(d, REG_SP, 8 * var->regoff);
+ else
+ {M_FLTMOVE(var->regoff,d);}
+ store_reg_to_var_flt(iptr->dst, d);
+ break;
+
+
+ case ICMD_ISTORE:
+ case ICMD_LSTORE:
+ case ICMD_ASTORE:
+ if ((src->varkind == LOCALVAR) &&
+ (src->varnum == iptr->op1))
+ break;
+ var = &(locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
+ if (var->flags & INMEMORY) {
+ var_to_reg_int(s1, src, REG_ITMP1);
+ M_LST(s1, REG_SP, 8 * var->regoff);
+ }
+ else {
+ var_to_reg_int(s1, src, var->regoff);
+ M_INTMOVE(s1, var->regoff);
+ }
+ break;
+
+ case ICMD_FSTORE:
+ case ICMD_DSTORE:
+ if ((src->varkind == LOCALVAR) &&
+ (src->varnum == iptr->op1))
+ break;
+ var = &(locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
+ if (var->flags & INMEMORY) {
+ var_to_reg_flt(s1, src, REG_FTMP1);
+ M_DST(s1, REG_SP, 8 * var->regoff);
+ }
+ else {
+ var_to_reg_flt(s1, src, var->regoff);
+ M_FLTMOVE(s1, var->regoff);
+ }
+ break;
+
+
+ /******************* pop/dup/swap operations **************************/
+
+ case ICMD_POP:
+ case ICMD_POP2:
+ break;
+
+#define M_COPY(from,to) \
+ d = reg_of_var(to, REG_IFTMP); \
+ if ((from->regoff != to->regoff) || \
+ ((from->flags ^ to->flags) & INMEMORY)) { \
+ if (IS_FLT_DBL_TYPE(from->type)) { \
+ var_to_reg_flt(s1, from, d); \
+ M_FLTMOVE(s1,d); \
+ store_reg_to_var_flt(to, d); \
+ }\
+ else { \
+ var_to_reg_int(s1, from, d); \
+ M_INTMOVE(s1,d); \
+ store_reg_to_var_int(to, d); \
+ }\
+ }
+
+ case ICMD_DUP:
+ M_COPY(src, iptr->dst);
+ break;
+
+ case ICMD_DUP_X1:
+ M_COPY(src, iptr->dst->prev->prev);
+ case ICMD_DUP2:
+ M_COPY(src, iptr->dst);
+ M_COPY(src->prev, iptr->dst->prev);
+ break;
+
+ case ICMD_DUP2_X1:
+ M_COPY(src->prev, iptr->dst->prev->prev->prev);
+ case ICMD_DUP_X2:
+ M_COPY(src, iptr->dst);
+ M_COPY(src->prev, iptr->dst->prev);
+ M_COPY(src->prev->prev, iptr->dst->prev->prev);
+ M_COPY(src, iptr->dst->prev->prev->prev);
+ break;
+
+ case ICMD_DUP2_X2:
+ M_COPY(src, iptr->dst);
+ M_COPY(src->prev, iptr->dst->prev);
+ M_COPY(src->prev->prev, iptr->dst->prev->prev);
+ M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
+ M_COPY(src, iptr->dst->prev->prev->prev->prev);
+ M_COPY(src->prev, iptr->dst->prev->prev->prev->prev->prev);
+ break;
+
+ case ICMD_SWAP:
+ M_COPY(src, iptr->dst->prev);
+ M_COPY(src->prev, iptr->dst);
+ break;
+
+
+ /********************* integer operations *****************************/
+
+ case ICMD_INEG:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ M_ISUB(REG_ZERO, s1, d, 0);
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+
+ case ICMD_LNEG:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ M_LSUB(REG_ZERO, s1, d, 0);
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+
+ case ICMD_I2L:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ M_INTMOVE(s1, d);
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+
+ case ICMD_L2I:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ M_IADD(s1, REG_ZERO, d , 0);
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+
+ case ICMD_INT2BYTE:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ if (has_ext_instr_set) {
+ M_BSEXT(s1, d);
+ }
+ else {
+ M_SLL(s1,56, d, 1);
+ M_SRA( d,56, d, 1);
+ }
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+
+ case ICMD_INT2CHAR:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ M_ZAPNOT(s1, 0x03, d, 1);
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+
+ case ICMD_INT2SHORT:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ if (has_ext_instr_set) {
+ M_SSEXT(s1, d);
+ }
+ else {
+ M_SLL( s1, 48, d, 1);
+ M_SRA( d, 48, d, 1);
+ }
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+
+#define ICONST(r,c) if(((c)>=-32768)&&((c)<= 32767)){M_LDA(r,REG_ZERO,c);} \
+ else{a=dseg_adds4(c);M_ILD(r,REG_PV,a);}
+
+#define LCONST(r,c) if(((c)>=-32768)&&((c)<= 32767)){M_LDA(r,REG_ZERO,c);} \
+ else{a=dseg_adds8(c);M_LLD(r,REG_PV,a);}
+
+
+ case ICMD_IADD:
+ var_to_reg_int(s1, src->prev, REG_ITMP1);
+ var_to_reg_int(s2, src, REG_ITMP2);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ M_IADD(s1, s2, d, 0);
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+ case ICMD_IADDCONST:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
+ M_IADD(s1, iptr->val.i, d, 1);
+ }
+ else {
+ ICONST(REG_ITMP2, iptr->val.i);
+ M_IADD(s1, REG_ITMP2, d, 0);
+ }
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+ case ICMD_LADD:
+ var_to_reg_int(s1, src->prev, REG_ITMP1);
+ var_to_reg_int(s2, src, REG_ITMP2);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ M_LADD(s1, s2, d, 0);
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+ case ICMD_LADDCONST:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
+ M_LADD(s1, iptr->val.l, d, 1);
+ }
+ else {
+ LCONST(REG_ITMP2, iptr->val.l);
+ M_LADD(s1, REG_ITMP2, d, 0);
+ }
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+
+ case ICMD_ISUB:
+ var_to_reg_int(s1, src->prev, REG_ITMP1);
+ var_to_reg_int(s2, src, REG_ITMP2);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ M_ISUB(s1, s2, d, 0);
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+ case ICMD_ISUBCONST:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
+ M_ISUB(s1, iptr->val.i, d, 1);
+ }
+ else {
+ ICONST(REG_ITMP2, iptr->val.i);
+ M_ISUB(s1, REG_ITMP2, d, 0);
+ }
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+ case ICMD_LSUB:
+ var_to_reg_int(s1, src->prev, REG_ITMP1);
+ var_to_reg_int(s2, src, REG_ITMP2);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ M_LSUB(s1, s2, d, 0);
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+ case ICMD_LSUBCONST:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
+ M_LSUB(s1, iptr->val.l, d, 1);
+ }
+ else {
+ LCONST(REG_ITMP2, iptr->val.l);
+ M_LSUB(s1, REG_ITMP2, d, 0);
+ }
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+
+ case ICMD_IMUL:
+ var_to_reg_int(s1, src->prev, REG_ITMP1);
+ var_to_reg_int(s2, src, REG_ITMP2);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ M_IMUL(s1, s2, d, 0);
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+ case ICMD_IMULCONST:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
+ M_IMUL(s1, iptr->val.i, d, 1);
+ }
+ else {
+ ICONST(REG_ITMP2, iptr->val.i);
+ M_IMUL(s1, REG_ITMP2, d, 0);
+ }
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+ case ICMD_LMUL:
+ var_to_reg_int(s1, src->prev, REG_ITMP1);
+ var_to_reg_int(s2, src, REG_ITMP2);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ M_LMUL (s1, s2, d, 0);
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+ case ICMD_LMULCONST:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
+ M_LMUL(s1, iptr->val.l, d, 1);
+ }
+ else {
+ LCONST(REG_ITMP2, iptr->val.l);
+ M_LMUL(s1, REG_ITMP2, d, 0);
+ }
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+
+
+ case ICMD_ISHL:
+ var_to_reg_int(s1, src->prev, REG_ITMP1);
+ var_to_reg_int(s2, src, REG_ITMP2);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ M_AND(s2, 0x1f, REG_ITMP3, 1);
+ M_SLL(s1, REG_ITMP3, d, 0);
+ M_IADD(d, REG_ZERO, d, 0);
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+ case ICMD_ISHLCONST:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ M_SLL(s1, iptr->val.i & 0x1f, d, 1);
+ M_IADD(d, REG_ZERO, d, 0);
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+
+ case ICMD_ISHR:
+ var_to_reg_int(s1, src->prev, REG_ITMP1);
+ var_to_reg_int(s2, src, REG_ITMP2);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ M_AND(s2, 0x1f, REG_ITMP3, 1);
+ M_SRA(s1, REG_ITMP3, d, 0);
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+ case ICMD_ISHRCONST:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ M_SRA(s1, iptr->val.i & 0x1f, d, 1);
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+
+ case ICMD_IUSHR:
+ var_to_reg_int(s1, src->prev, REG_ITMP1);
+ var_to_reg_int(s2, src, REG_ITMP2);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ M_AND (s2, 0x1f, REG_ITMP2, 1);
+ M_ZAPNOT(s1, 0x0f, d, 1);
+ M_SRL ( d, REG_ITMP2, d, 0);
+ M_IADD ( d, REG_ZERO, d, 0);
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+ case ICMD_IUSHRCONST:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ M_ZAPNOT(s1, 0x0f, d, 1);
+ M_SRL(d, iptr->val.i & 0x1f, d, 1);
+ M_IADD(d, REG_ZERO, d, 0);
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+
+ case ICMD_LSHL:
+ var_to_reg_int(s1, src->prev, REG_ITMP1);
+ var_to_reg_int(s2, src, REG_ITMP2);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ M_SLL(s1, s2, d, 0);
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+ case ICMD_LSHLCONST:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ M_SLL(s1, iptr->val.l & 0x3f, d, 1);
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+
+ case ICMD_LSHR:
+ var_to_reg_int(s1, src->prev, REG_ITMP1);
+ var_to_reg_int(s2, src, REG_ITMP2);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ M_SRA(s1, s2, d, 0);
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+ case ICMD_LSHRCONST:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ M_SRA(s1, iptr->val.l & 0x3f, d, 1);
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+
+ case ICMD_LUSHR:
+ var_to_reg_int(s1, src->prev, REG_ITMP1);
+ var_to_reg_int(s2, src, REG_ITMP2);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ M_SRL(s1, s2, d, 0);
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+ case ICMD_LUSHRCONST:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ M_SRL(s1, iptr->val.l & 0x3f, d, 1);
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+
+ case ICMD_IAND:
+ case ICMD_LAND:
+ var_to_reg_int(s1, src->prev, REG_ITMP1);
+ var_to_reg_int(s2, src, REG_ITMP2);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ M_AND(s1, s2, d, 0);
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+ case ICMD_IANDCONST:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
+ M_AND(s1, iptr->val.i, d, 1);
+ }
+ else {
+ ICONST(REG_ITMP2, iptr->val.i);
+ M_AND(s1, REG_ITMP2, d, 0);
+ }
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+ case ICMD_LANDCONST:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
+ M_AND(s1, iptr->val.l, d, 1);
+ }
+ else {
+ LCONST(REG_ITMP2, iptr->val.l);
+ M_AND(s1, REG_ITMP2, d, 0);
+ }
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+
+ case ICMD_IOR:
+ case ICMD_LOR:
+ var_to_reg_int(s1, src->prev, REG_ITMP1);
+ var_to_reg_int(s2, src, REG_ITMP2);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ M_OR( s1,s2, d, 0);
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+ case ICMD_IORCONST:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
+ M_OR(s1, iptr->val.i, d, 1);
+ }
+ else {
+ ICONST(REG_ITMP2, iptr->val.i);
+ M_OR(s1, REG_ITMP2, d, 0);
+ }
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+ case ICMD_LORCONST:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
+ M_OR(s1, iptr->val.l, d, 1);
+ }
+ else {
+ LCONST(REG_ITMP2, iptr->val.l);
+ M_OR(s1, REG_ITMP2, d, 0);
+ }
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+
+ case ICMD_IXOR:
+ case ICMD_LXOR:
+ var_to_reg_int(s1, src->prev, REG_ITMP1);
+ var_to_reg_int(s2, src, REG_ITMP2);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ M_XOR(s1, s2, d, 0);
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+ case ICMD_IXORCONST:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
+ M_XOR(s1, iptr->val.i, d, 1);
+ }
+ else {
+ ICONST(REG_ITMP2, iptr->val.i);
+ M_XOR(s1, REG_ITMP2, d, 0);
+ }
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+ case ICMD_LXORCONST:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
+ M_XOR(s1, iptr->val.l, d, 1);
+ }
+ else {
+ LCONST(REG_ITMP2, iptr->val.l);
+ M_XOR(s1, REG_ITMP2, d, 0);
+ }
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+
+
+ case ICMD_LCMP:
+ var_to_reg_int(s1, src->prev, REG_ITMP1);
+ var_to_reg_int(s2, src, REG_ITMP2);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ M_CMPLT(s1, s2, REG_ITMP3, 0);
+ M_CMPLT(s2, s1, REG_ITMP1, 0);
+ M_LSUB (REG_ITMP1, REG_ITMP3, d, 0);
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+
+
+ case ICMD_IINC:
+ var = &(locals[iptr->op1][TYPE_INT]);
+ if (var->flags & INMEMORY) {
+ s1 = REG_ITMP1;
+ M_LLD(s1, REG_SP, 8 * var->regoff);
+ }
+ else
+ s1 = var->regoff;
+ if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
+ M_IADD(s1, iptr->val.i, s1, 1);
+ }
+ else if ((iptr->val.i > -256) && (iptr->val.i < 0)) {
+ M_ISUB(s1, (-iptr->val.i), s1, 1);
+ }
+ else {
+ M_LDA (s1, s1, iptr->val.i);
+ M_IADD(s1, REG_ZERO, s1, 0);
+ }
+ if (var->flags & INMEMORY)
+ M_LST(s1, REG_SP, 8 * var->regoff);
+ break;
+
+
+ /*********************** floating operations **************************/
+
+ case ICMD_FNEG:
+ var_to_reg_flt(s1, src, REG_FTMP1);
+ d = reg_of_var(iptr->dst, REG_FTMP3);
+ M_FMOVN(s1, d);
+ store_reg_to_var_flt(iptr->dst, d);
+ break;
+ case ICMD_DNEG:
+ var_to_reg_flt(s1, src, REG_FTMP1);
+ d = reg_of_var(iptr->dst, REG_FTMP3);
+ M_FMOVN(s1, d);
+ store_reg_to_var_flt(iptr->dst, d);
+ break;
+
+ case ICMD_FADD:
+ var_to_reg_flt(s1, src->prev, REG_FTMP1);
+ var_to_reg_flt(s2, src, REG_FTMP2);
+ d = reg_of_var(iptr->dst, REG_FTMP3);
+ if (checkfloats) {
+ M_FADDS(s1, s2, d);
+ M_TRAPB;
+ }
+ else {
+ M_FADD(s1, s2, d);
+ }
+ store_reg_to_var_flt(iptr->dst, d);
+ break;
+ case ICMD_DADD:
+ var_to_reg_flt(s1, src->prev, REG_FTMP1);
+ var_to_reg_flt(s2, src, REG_FTMP2);
+ d = reg_of_var(iptr->dst, REG_FTMP3);
+ if (checkfloats) {
+ M_DADDS(s1, s2, d);
+ M_TRAPB;
+ }
+ else {
+ M_DADD(s1, s2, d);
+ }
+ store_reg_to_var_flt(iptr->dst, d);
+ break;
+
+ case ICMD_FSUB:
+ var_to_reg_flt(s1, src->prev, REG_FTMP1);
+ var_to_reg_flt(s2, src, REG_FTMP2);
+ d = reg_of_var(iptr->dst, REG_FTMP3);
+ if (checkfloats) {
+ M_FSUBS(s1, s2, d);
+ M_TRAPB;
+ }
+ else {
+ M_FSUB(s1, s2, d);
+ }
+ store_reg_to_var_flt(iptr->dst, d);
+ break;
+ case ICMD_DSUB:
+ var_to_reg_flt(s1, src->prev, REG_FTMP1);
+ var_to_reg_flt(s2, src, REG_FTMP2);
+ d = reg_of_var(iptr->dst, REG_FTMP3);
+ if (checkfloats) {
+ M_DSUBS(s1, s2, d);
+ M_TRAPB;
+ }
+ else {
+ M_DSUB(s1, s2, d);
+ }
+ store_reg_to_var_flt(iptr->dst, d);
+ break;
+
+ case ICMD_FMUL:
+ var_to_reg_flt(s1, src->prev, REG_FTMP1);
+ var_to_reg_flt(s2, src, REG_FTMP2);
+ d = reg_of_var(iptr->dst, REG_FTMP3);
+ if (checkfloats) {
+ M_FMULS(s1, s2, d);
+ M_TRAPB;
+ }
+ else {
+ M_FMUL(s1, s2, d);
+ }
+ store_reg_to_var_flt(iptr->dst, d);
+ break;
+ case ICMD_DMUL:
+ var_to_reg_flt(s1, src->prev, REG_FTMP1);
+ var_to_reg_flt(s2, src, REG_FTMP2);
+ d = reg_of_var(iptr->dst, REG_FTMP3);
+ if (checkfloats) {
+ M_DMULS(s1, s2, d);
+ M_TRAPB;
+ }
+ else {
+ M_DMUL(s1, s2, d);
+ }
+ store_reg_to_var_flt(iptr->dst, d);
+ break;
+
+ case ICMD_FDIV:
+ var_to_reg_flt(s1, src->prev, REG_FTMP1);
+ var_to_reg_flt(s2, src, REG_FTMP2);
+ d = reg_of_var(iptr->dst, REG_FTMP3);
+ if (checkfloats) {
+ M_FDIVS(s1, s2, d);
+ M_TRAPB;
+ }
+ else {
+ M_FDIV(s1, s2, d);
+ }
+ store_reg_to_var_flt(iptr->dst, d);
+ break;
+ case ICMD_DDIV:
+ var_to_reg_flt(s1, src->prev, REG_FTMP1);
+ var_to_reg_flt(s2, src, REG_FTMP2);
+ d = reg_of_var(iptr->dst, REG_FTMP3);
+ if (checkfloats) {
+ M_DDIVS(s1, s2, d);
+ M_TRAPB;
+ }
+ else {
+ M_DDIV(s1, s2, d);
+ }
+ store_reg_to_var_flt(iptr->dst, d);
+ break;
+
+ case ICMD_FREM:
+ var_to_reg_flt(s1, src->prev, REG_FTMP1);
+ var_to_reg_flt(s2, src, REG_FTMP2);
+ d = reg_of_var(iptr->dst, REG_FTMP3);
+ if (checkfloats) {
+ M_FDIVS(s1,s2, REG_FTMP3);
+ M_TRAPB;
+ M_CVTDL_CS(REG_ZERO, REG_FTMP3, REG_FTMP3); /* round to integer */
+ M_TRAPB;
+ M_CVTLF(REG_ZERO, REG_FTMP3, REG_FTMP3);
+ M_FMULS(REG_FTMP3, s2, REG_FTMP3);
+ M_TRAPB;
+ M_FSUBS(s1, REG_FTMP3, d);
+ M_TRAPB;
+ }
+ else {
+ M_FDIV(s1,s2, REG_FTMP3);
+ M_CVTDL_C(REG_ZERO, REG_FTMP3, REG_FTMP3); /* round to integer */
+ M_CVTLF(REG_ZERO, REG_FTMP3, REG_FTMP3);
+ M_FMUL(REG_FTMP3, s2, REG_FTMP3);
+ M_FSUB(s1, REG_FTMP3, d);
+ }
+ store_reg_to_var_flt(iptr->dst, d);
+ break;
+ case ICMD_DREM:
+ var_to_reg_flt(s1, src->prev, REG_FTMP1);
+ var_to_reg_flt(s2, src, REG_FTMP2);
+ d = reg_of_var(iptr->dst, REG_FTMP3);
+ if (checkfloats) {
+ M_DDIVS(s1,s2, REG_FTMP3);
+ M_TRAPB;
+ M_CVTDL_CS(REG_ZERO, REG_FTMP3, REG_FTMP3); /* round to integer */
+ M_TRAPB;
+ M_CVTLD(REG_ZERO, REG_FTMP3, REG_FTMP3);
+ M_DMULS(REG_FTMP3, s2, REG_FTMP3);
+ M_TRAPB;
+ M_DSUBS(s1, REG_FTMP3, d);
+ M_TRAPB;
+ }
+ else {
+ M_DDIV(s1,s2, REG_FTMP3);
+ M_CVTDL_C(REG_ZERO, REG_FTMP3, REG_FTMP3); /* round to integer */
+ M_CVTLD(REG_ZERO, REG_FTMP3, REG_FTMP3);
+ M_DMUL(REG_FTMP3, s2, REG_FTMP3);
+ M_DSUB(s1, REG_FTMP3, d);
+ }
+ store_reg_to_var_flt(iptr->dst, d);
+ break;
+
+ case ICMD_I2F:
+ case ICMD_L2F:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ d = reg_of_var(iptr->dst, REG_FTMP3);
+ a = dseg_adddouble(0.0);
+ M_LST (s1, REG_PV, a);
+ M_DLD (d, REG_PV, a);
+ M_CVTLF(REG_ZERO, d, d);
+ store_reg_to_var_flt(iptr->dst, d);
+ break;
+
+ case ICMD_I2D:
+ case ICMD_L2D:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ d = reg_of_var(iptr->dst, REG_FTMP3);
+ a = dseg_adddouble(0.0);
+ M_LST (s1, REG_PV, a);
+ M_DLD (d, REG_PV, a);
+ M_CVTLD(REG_ZERO, d, d);
+ store_reg_to_var_flt(iptr->dst, d);
+ break;
+
+ case ICMD_F2I:
+ case ICMD_D2I:
+ var_to_reg_flt(s1, src, REG_FTMP1);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ a = dseg_adddouble(0.0);
+ if (checkfloats) {
+ M_CVTDL_CS(REG_ZERO, s1, REG_FTMP1);
+ M_TRAPB;
+ M_CVTLIS(REG_FTMP1, REG_FTMP2);
+ M_TRAPB;
+ }
+ else {
+ M_CVTDL_C(REG_ZERO, s1, REG_FTMP1);
+ M_CVTLI(REG_FTMP1, REG_FTMP2);
+ }
+ M_DST (REG_FTMP1, REG_PV, a);
+ M_ILD (d, REG_PV, a);
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+
+ case ICMD_F2L:
+ case ICMD_D2L:
+ var_to_reg_flt(s1, src, REG_FTMP1);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ a = dseg_adddouble(0.0);
+ if (checkfloats) {
+ M_CVTDL_CS(REG_ZERO, s1, REG_FTMP1);
+ M_TRAPB;
+ }
+ else {
+ M_CVTDL_C(REG_ZERO, s1, REG_FTMP1);
+ }
+ M_DST (REG_FTMP1, REG_PV, a);
+ M_LLD (d, REG_PV, a);
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+
+ case ICMD_F2D:
+ var_to_reg_flt(s1, src, REG_FTMP1);
+ d = reg_of_var(iptr->dst, REG_FTMP3);
+ M_FLTMOVE(s1, d);
+ store_reg_to_var_flt(iptr->dst, d);
+ break;
+
+ case ICMD_D2F:
+ var_to_reg_flt(s1, src, REG_FTMP1);
+ d = reg_of_var(iptr->dst, REG_FTMP3);
+ if (checkfloats) {
+ M_CVTDFS(REG_ZERO, s1, d);
+ M_TRAPB;
+ }
+ else {
+ M_CVTDF(REG_ZERO, s1, d);
+ }
+ store_reg_to_var_flt(iptr->dst, d);
+ break;
+
+ case ICMD_FCMPL:
+ case ICMD_DCMPL:
+ var_to_reg_flt(s1, src->prev, REG_FTMP1);
+ var_to_reg_flt(s2, src, REG_FTMP2);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ if (checkfloats) {
+ M_LSUB (REG_ZERO, 1, d, 1);
+ M_FCMPEQS(s1, s2, REG_FTMP3);
+ M_TRAPB;
+ M_FBEQZ (REG_FTMP3, 1); /* jump over next instructions */
+ M_OR (REG_ZERO, REG_ZERO, d, 0);
+ M_FCMPLTS(s2, s1, REG_FTMP3);
+ M_TRAPB;
+ M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
+ M_LADD (REG_ZERO, 1, d, 1);
+ }
+ else {
+ M_LSUB (REG_ZERO, 1, d, 1);
+ M_FCMPEQ(s1, s2, REG_FTMP3);
+ M_FBEQZ (REG_FTMP3, 1); /* jump over next instructions */
+ M_OR (REG_ZERO, REG_ZERO, d, 0);
+ M_FCMPLT(s2, s1, REG_FTMP3);
+ M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
+ M_LADD (REG_ZERO, 1, d, 1);
+ }
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+
+ case ICMD_FCMPG:
+ case ICMD_DCMPG:
+ var_to_reg_flt(s1, src->prev, REG_FTMP1);
+ var_to_reg_flt(s2, src, REG_FTMP2);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ if (checkfloats) {
+ M_LADD (REG_ZERO, 1, d, 1);
+ M_FCMPEQS(s1, s2, REG_FTMP3);
+ M_TRAPB;
+ M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
+ M_OR (REG_ZERO, REG_ZERO, d, 0);
+ M_FCMPLTS(s1, s2, REG_FTMP3);
+ M_TRAPB;
+ M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
+ M_LSUB (REG_ZERO, 1, d, 1);
+ }
+ else {
+ M_LADD (REG_ZERO, 1, d, 1);
+ M_FCMPEQ(s1, s2, REG_FTMP3);
+ M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
+ M_OR (REG_ZERO, REG_ZERO, d, 0);
+ M_FCMPLT(s1, s2, REG_FTMP3);
+ M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
+ M_LSUB (REG_ZERO, 1, d, 1);
+ }
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+
+
+ /********************** memory operations *****************************/
+
+#define gen_bound_check \
+ if (checkbounds) {\
+ M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));\
+ M_CMPULT(s2, REG_ITMP3, REG_ITMP3, 0);\
+ M_BEQZ(REG_ITMP3, 0);\
+ mcode_addxboundrefs(mcodeptr);\
+ }
+
+ case ICMD_ARRAYLENGTH:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ gen_nullptr_check(s1);
+ M_ILD(d, s1, OFFSET(java_arrayheader, size));
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+
+ case ICMD_AALOAD:
+ var_to_reg_int(s1, src->prev, REG_ITMP1);
+ var_to_reg_int(s2, src, REG_ITMP2);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ gen_nullptr_check(s1);
+ gen_bound_check;
+ M_S8ADDQ(s2, s1, REG_ITMP1, 0);
+ M_LLD( d, REG_ITMP1, OFFSET(java_objectarray, data[0]));
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+ case ICMD_LALOAD:
+ var_to_reg_int(s1, src->prev, REG_ITMP1);
+ var_to_reg_int(s2, src, REG_ITMP2);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ gen_nullptr_check(s1);
+ gen_bound_check;
+ M_S8ADDQ(s2, s1, REG_ITMP1, 0);
+ M_LLD(d, REG_ITMP1, OFFSET(java_longarray, data[0]));
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+ case ICMD_IALOAD:
+ var_to_reg_int(s1, src->prev, REG_ITMP1);
+ var_to_reg_int(s2, src, REG_ITMP2);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ gen_nullptr_check(s1);
+ gen_bound_check;
+ M_S4ADDQ(s2, s1, REG_ITMP1, 0);
+ M_ILD(d, REG_ITMP1, OFFSET(java_intarray, data[0]));
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+ case ICMD_FALOAD:
+ var_to_reg_int(s1, src->prev, REG_ITMP1);
+ var_to_reg_int(s2, src, REG_ITMP2);
+ d = reg_of_var(iptr->dst, REG_FTMP3);
+ gen_nullptr_check(s1);
+ gen_bound_check;
+ M_S4ADDQ(s2, s1, REG_ITMP1, 0);
+ M_FLD(d, REG_ITMP1, OFFSET(java_floatarray, data[0]));
+ store_reg_to_var_flt(iptr->dst, d);
+ break;
+ case ICMD_DALOAD:
+ var_to_reg_int(s1, src->prev, REG_ITMP1);
+ var_to_reg_int(s2, src, REG_ITMP2);
+ d = reg_of_var(iptr->dst, REG_FTMP3);
+ gen_nullptr_check(s1);
+ gen_bound_check;
+ M_S8ADDQ(s2, s1, REG_ITMP1, 0);
+ M_DLD(d, REG_ITMP1, OFFSET(java_doublearray, data[0]));
+ store_reg_to_var_flt(iptr->dst, d);
+ break;
+ case ICMD_CALOAD:
+ var_to_reg_int(s1, src->prev, REG_ITMP1);
+ var_to_reg_int(s2, src, REG_ITMP2);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ gen_nullptr_check(s1);
+ gen_bound_check;
+ if (has_ext_instr_set) {
+ M_LADD(s2, s1, REG_ITMP1, 0);
+ M_LADD(s2, REG_ITMP1, REG_ITMP1, 0);
+ M_SLDU(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
+ }
+ else {
+ M_LADD (s2, s1, REG_ITMP1, 0);
+ M_LADD (s2, REG_ITMP1, REG_ITMP1, 0);
+ M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_chararray, data[0]));
+ M_LDA (REG_ITMP1, REG_ITMP1, OFFSET(java_chararray, data[0]));
+ M_EXTWL(REG_ITMP2, REG_ITMP1, d, 0);
+ }
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+ case ICMD_SALOAD:
+ var_to_reg_int(s1, src->prev, REG_ITMP1);
+ var_to_reg_int(s2, src, REG_ITMP2);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ gen_nullptr_check(s1);
+ gen_bound_check;
+ if (has_ext_instr_set) {
+ M_LADD(s2, s1, REG_ITMP1, 0);
+ M_LADD(s2, REG_ITMP1, REG_ITMP1, 0);
+ M_SLDU( d, REG_ITMP1, OFFSET (java_shortarray, data[0]));
+ M_SSEXT(d, d);
+ }
+ else {
+ M_LADD(s2, s1, REG_ITMP1, 0);
+ M_LADD(s2, REG_ITMP1, REG_ITMP1, 0);
+ M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_shortarray, data[0]));
+ M_LDA(REG_ITMP1, REG_ITMP1, OFFSET(java_shortarray, data[0])+2);
+ M_EXTQH(REG_ITMP2, REG_ITMP1, d, 0);
+ M_SRA(d, 48, d, 1);
+ }
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+ case ICMD_BALOAD:
+ var_to_reg_int(s1, src->prev, REG_ITMP1);
+ var_to_reg_int(s2, src, REG_ITMP2);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ gen_nullptr_check(s1);
+ gen_bound_check;
+ if (has_ext_instr_set) {
+ M_LADD (s2, s1, REG_ITMP1, 0);
+ M_BLDU (d, REG_ITMP1, OFFSET (java_shortarray, data[0]));
+ M_BSEXT (d, d);
+ }
+ else {
+ M_LADD(s2, s1, REG_ITMP1, 0);
+ M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_bytearray, data[0]));
+ M_LDA(REG_ITMP1, REG_ITMP1, OFFSET(java_bytearray, data[0])+1);
+ M_EXTQH(REG_ITMP2, REG_ITMP1, d, 0);
+ M_SRA(d, 56, d, 1);
+ }
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+
+ case ICMD_AASTORE:
+ var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
+ var_to_reg_int(s2, src->prev, REG_ITMP2);
+ gen_nullptr_check(s1);
+ gen_bound_check;
+ var_to_reg_int(s3, src, REG_ITMP3);
+ M_S8ADDQ(s2, s1, REG_ITMP1, 0);
+ M_LST (s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
+ break;
+ case ICMD_LASTORE:
+ var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
+ var_to_reg_int(s2, src->prev, REG_ITMP2);
+ gen_nullptr_check(s1);
+ gen_bound_check;
+ var_to_reg_int(s3, src, REG_ITMP3);
+ M_S8ADDQ(s2, s1, REG_ITMP1, 0);
+ M_LST (s3, REG_ITMP1, OFFSET(java_longarray, data[0]));
+ break;
+ case ICMD_IASTORE:
+ var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
+ var_to_reg_int(s2, src->prev, REG_ITMP2);
+ gen_nullptr_check(s1);
+ gen_bound_check;
+ var_to_reg_int(s3, src, REG_ITMP3);
+ M_S4ADDQ(s2, s1, REG_ITMP1, 0);
+ M_IST (s3, REG_ITMP1, OFFSET(java_intarray, data[0]));
+ break;
+ case ICMD_FASTORE:
+ var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
+ var_to_reg_int(s2, src->prev, REG_ITMP2);
+ gen_nullptr_check(s1);
+ gen_bound_check;
+ var_to_reg_flt(s3, src, REG_FTMP3);
+ M_S4ADDQ(s2, s1, REG_ITMP1, 0);
+ M_FST (s3, REG_ITMP1, OFFSET(java_floatarray, data[0]));
+ break;
+ case ICMD_DASTORE:
+ var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
+ var_to_reg_int(s2, src->prev, REG_ITMP2);
+ gen_nullptr_check(s1);
+ gen_bound_check;
+ var_to_reg_flt(s3, src, REG_FTMP3);
+ M_S8ADDQ(s2, s1, REG_ITMP1, 0);
+ M_DST (s3, REG_ITMP1, OFFSET(java_doublearray, data[0]));
+ break;
+ case ICMD_CASTORE:
+ var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
+ var_to_reg_int(s2, src->prev, REG_ITMP2);
+ gen_nullptr_check(s1);
+ gen_bound_check;
+ var_to_reg_int(s3, src, REG_ITMP3);
+ if (has_ext_instr_set) {
+ M_LADD(s2, s1, REG_ITMP1, 0);
+ M_LADD(s2, REG_ITMP1, REG_ITMP1, 0);
+ M_SST (s3, REG_ITMP1, OFFSET(java_chararray, data[0]));
+ }
+ else {
+ M_LADD (s2, s1, REG_ITMP1, 0);
+ M_LADD (s2, REG_ITMP1, REG_ITMP1, 0);
+ M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_chararray, data[0]));
+ M_LDA (REG_ITMP1, REG_ITMP1, OFFSET(java_chararray, data[0]));
+ M_INSWL(s3, REG_ITMP1, REG_ITMP3, 0);
+ M_MSKWL(REG_ITMP2, REG_ITMP1, REG_ITMP2, 0);
+ M_OR (REG_ITMP2, REG_ITMP3, REG_ITMP2, 0);
+ M_LST_U(REG_ITMP2, REG_ITMP1, 0);
+ }
+ break;
+ case ICMD_SASTORE:
+ var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
+ var_to_reg_int(s2, src->prev, REG_ITMP2);
+ gen_nullptr_check(s1);
+ gen_bound_check;
+ var_to_reg_int(s3, src, REG_ITMP3);
+ if (has_ext_instr_set) {
+ M_LADD(s2, s1, REG_ITMP1, 0);
+ M_LADD(s2, REG_ITMP1, REG_ITMP1, 0);
+ M_SST (s3, REG_ITMP1, OFFSET(java_shortarray, data[0]));
+ }
+ else {
+ M_LADD (s2, s1, REG_ITMP1, 0);
+ M_LADD (s2, REG_ITMP1, REG_ITMP1, 0);
+ M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_shortarray, data[0]));
+ M_LDA (REG_ITMP1, REG_ITMP1, OFFSET(java_shortarray, data[0]));
+ M_INSWL(s3, REG_ITMP1, REG_ITMP3, 0);
+ M_MSKWL(REG_ITMP2, REG_ITMP1, REG_ITMP2, 0);
+ M_OR (REG_ITMP2, REG_ITMP3, REG_ITMP2, 0);
+ M_LST_U(REG_ITMP2, REG_ITMP1, 0);
+ }
+ break;
+ case ICMD_BASTORE:
+ var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
+ var_to_reg_int(s2, src->prev, REG_ITMP2);
+ gen_nullptr_check(s1);
+ gen_bound_check;
+ var_to_reg_int(s3, src, REG_ITMP3);
+ if (has_ext_instr_set) {
+ M_LADD(s2, s1, REG_ITMP1, 0);
+ M_BST (s3, REG_ITMP1, OFFSET(java_bytearray, data[0]));
+ }
+ else {
+ M_LADD (s2, s1, REG_ITMP1, 0);
+ M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_bytearray, data[0]));
+ M_LDA (REG_ITMP1, REG_ITMP1, OFFSET(java_bytearray, data[0]));
+ M_INSBL(s3, REG_ITMP1, REG_ITMP3, 0);
+ M_MSKBL(REG_ITMP2, REG_ITMP1, REG_ITMP2, 0);
+ M_OR (REG_ITMP2, REG_ITMP3, REG_ITMP2, 0);
+ M_LST_U(REG_ITMP2, REG_ITMP1, 0);
+ }
+ break;
+
+
+ case ICMD_PUTSTATIC:
+ a = dseg_addaddress (iptr->val.a);
+ M_LLD(REG_ITMP1, REG_PV, a);
+ switch (iptr->op1) {
+ case TYPE_INT:
+ var_to_reg_int(s2, src, REG_ITMP2);
+ M_IST(s2, REG_ITMP1, 0);
+ break;
+ case TYPE_LNG:
+ case TYPE_ADR:
+ var_to_reg_int(s2, src, REG_ITMP2);
+ M_LST(s2, REG_ITMP1, 0);
+ break;
+ case TYPE_FLT:
+ var_to_reg_flt(s2, src, REG_FTMP2);
+ M_FST(s2, REG_ITMP1, 0);
+ break;
+ case TYPE_DBL:
+ var_to_reg_flt(s2, src, REG_FTMP2);
+ M_DST(s2, REG_ITMP1, 0);
+ break;
+ default: panic ("internal error");
+ }
+ break;
+
+ case ICMD_GETSTATIC:
+ a = dseg_addaddress (iptr->val.a);
+ M_LLD(REG_ITMP1, REG_PV, a);
+ switch (iptr->op1) {
+ case TYPE_INT:
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ M_ILD(d, REG_ITMP1, 0);
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+ case TYPE_LNG:
+ case TYPE_ADR:
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ M_LLD(d, REG_ITMP1, 0);
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+ case TYPE_FLT:
+ d = reg_of_var(iptr->dst, REG_FTMP1);
+ M_FLD(d, REG_ITMP1, 0);
+ store_reg_to_var_flt(iptr->dst, d);
+ break;
+ case TYPE_DBL:
+ d = reg_of_var(iptr->dst, REG_FTMP1);
+ M_DLD(d, REG_ITMP1, 0);
+ store_reg_to_var_flt(iptr->dst, d);
+ break;
+ default: panic ("internal error");
+ }
+ break;
+
+
+ case ICMD_PUTFIELD:
+ switch (iptr->op1) {
+ case TYPE_INT:
+ var_to_reg_int(s1, src->prev, REG_ITMP1);
+ var_to_reg_int(s2, src, REG_ITMP2);
+ gen_nullptr_check(s1);
+ M_IST(s2, s1, iptr->val.i);
+ break;
+ case TYPE_LNG:
+ case TYPE_ADR:
+ var_to_reg_int(s1, src->prev, REG_ITMP1);
+ var_to_reg_int(s2, src, REG_ITMP2);
+ gen_nullptr_check(s1);
+ M_LST(s2, s1, iptr->val.i);
+ break;
+ case TYPE_FLT:
+ var_to_reg_int(s1, src->prev, REG_ITMP1);
+ var_to_reg_flt(s2, src, REG_FTMP2);
+ gen_nullptr_check(s1);
+ M_FST(s2, s1, iptr->val.i);
+ break;
+ case TYPE_DBL:
+ var_to_reg_int(s1, src->prev, REG_ITMP1);
+ var_to_reg_flt(s2, src, REG_FTMP2);
+ gen_nullptr_check(s1);
+ M_DST(s2, s1, iptr->val.i);
+ break;
+ default: panic ("internal error");
+ }
+ break;
+
+ case ICMD_GETFIELD:
+ switch (iptr->op1) {
+ case TYPE_INT:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ gen_nullptr_check(s1);
+ M_ILD(d, s1, iptr->val.i);
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+ case TYPE_LNG:
+ case TYPE_ADR:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ d = reg_of_var(iptr->dst, REG_ITMP3);
+ gen_nullptr_check(s1);
+ M_LLD(d, s1, iptr->val.i);
+ store_reg_to_var_int(iptr->dst, d);
+ break;
+ case TYPE_FLT:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ d = reg_of_var(iptr->dst, REG_FTMP1);
+ gen_nullptr_check(s1);
+ M_FLD(d, s1, iptr->val.i);
+ store_reg_to_var_flt(iptr->dst, d);
+ break;
+ case TYPE_DBL:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ d = reg_of_var(iptr->dst, REG_FTMP1);
+ gen_nullptr_check(s1);
+ M_DLD(d, s1, iptr->val.i);
+ store_reg_to_var_flt(iptr->dst, d);
+ break;
+ default: panic ("internal error");
+ }
+ break;
+
+
+ /********************** branch operations *****************************/
+
+#define ALIGNCODENOP {if((int)((long)mcodeptr&7)){M_NOP;}}
+
+ case ICMD_ATHROW:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ M_INTMOVE(s1, REG_ITMP1_XPTR);
+ a = dseg_addaddress(asm_handle_exception);
+ M_LLD(REG_ITMP2, REG_PV, a);
+ M_JMP(REG_ITMP2_XPC, REG_ITMP2);
+ ALIGNCODENOP;
+ break;
+
+ case ICMD_GOTO:
+ M_BR(0);
+ mcode_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
+ ALIGNCODENOP;
+ break;
+
+ case ICMD_JSR:
+ M_BSR(REG_ITMP1, 0);
+ mcode_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
+ break;
+
+ case ICMD_RET:
+ var = &(locals[iptr->op1][TYPE_ADR]);
+ if (var->flags & INMEMORY) {
+ M_LLD(REG_ITMP1, REG_SP, 8 * var->regoff);
+ M_RET(REG_ZERO, REG_ITMP1);
+ }
+ else
+ M_RET(REG_ZERO, var->regoff);
+ ALIGNCODENOP;
+ break;
+
+ case ICMD_IFNULL:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ M_BEQZ(s1, 0);
+ mcode_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
+ break;
+ case ICMD_IFNONNULL:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ M_BNEZ(s1, 0);
+ mcode_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
+ break;
+
+ case ICMD_IFEQ:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ if (iptr->val.i == 0) {
+ M_BEQZ(s1, 0);
+ }
+ else {
+ if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
+ M_CMPEQ(s1, iptr->val.i, REG_ITMP1, 1);
+ }
+ else {
+ ICONST(REG_ITMP2, iptr->val.i);
+ M_CMPEQ(s1, REG_ITMP2, REG_ITMP1, 0);
+ }
+ M_BNEZ(REG_ITMP1, 0);
+ }
+ mcode_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
+ break;
+ case ICMD_IFLT:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ if (iptr->val.i == 0) {
+ M_BLTZ(s1, 0);
+ }
+ else {
+ if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
+ M_CMPLT(s1, iptr->val.i, REG_ITMP1, 1);
+ }
+ else {
+ ICONST(REG_ITMP2, iptr->val.i);
+ M_CMPLT(s1, REG_ITMP2, REG_ITMP1, 0);
+ }
+ M_BNEZ(REG_ITMP1, 0);
+ }
+ mcode_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
+ break;
+ case ICMD_IFLE:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ if (iptr->val.i == 0) {
+ M_BLEZ(s1, 0);
+ }
+ else {
+ if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
+ M_CMPLE(s1, iptr->val.i, REG_ITMP1, 1);
+ }
+ else {
+ ICONST(REG_ITMP2, iptr->val.i);
+ M_CMPLE(s1, REG_ITMP2, REG_ITMP1, 0);
+ }
+ M_BNEZ(REG_ITMP1, 0);
+ }
+ mcode_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
+ break;
+ case ICMD_IFNE:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ if (iptr->val.i == 0) {
+ M_BNEZ(s1, 0);
+ }
+ else {
+ if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
+ M_CMPEQ(s1, iptr->val.i, REG_ITMP1, 1);
+ }
+ else {
+ ICONST(REG_ITMP2, iptr->val.i);
+ M_CMPEQ(s1, REG_ITMP2, REG_ITMP1, 0);
+ }
+ M_BEQZ(REG_ITMP1, 0);
+ }
+ mcode_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
+ break;
+ case ICMD_IFGT:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ if (iptr->val.i == 0) {
+ M_BGTZ(s1, 0);
+ }
+ else {
+ if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
+ M_CMPLE(s1, iptr->val.i, REG_ITMP1, 1);
+ }
+ else {
+ ICONST(REG_ITMP2, iptr->val.i);
+ M_CMPLE(s1, REG_ITMP2, REG_ITMP1, 0);
+ }
+ M_BEQZ(REG_ITMP1, 0);
+ }
+ mcode_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
+ break;
+ case ICMD_IFGE:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ if (iptr->val.i == 0) {
+ M_BGEZ(s1, 0);
+ }
+ else {
+ if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
+ M_CMPLT(s1, iptr->val.i, REG_ITMP1, 1);
+ }
+ else {
+ ICONST(REG_ITMP2, iptr->val.i);
+ M_CMPLT(s1, REG_ITMP2, REG_ITMP1, 0);
+ }
+ M_BEQZ(REG_ITMP1, 0);
+ }
+ mcode_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
+ break;
+
+ case ICMD_IF_LEQ:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ if (iptr->val.l == 0) {
+ M_BEQZ(s1, 0);
+ }
+ else {
+ if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
+ M_CMPEQ(s1, iptr->val.l, REG_ITMP1, 1);
+ }
+ else {
+ LCONST(REG_ITMP2, iptr->val.l);
+ M_CMPEQ(s1, REG_ITMP2, REG_ITMP1, 0);
+ }
+ M_BNEZ(REG_ITMP1, 0);
+ }
+ mcode_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
+ break;
+ case ICMD_IF_LLT:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ if (iptr->val.l == 0) {
+ M_BLTZ(s1, 0);
+ }
+ else {
+ if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
+ M_CMPLT(s1, iptr->val.l, REG_ITMP1, 1);
+ }
+ else {
+ LCONST(REG_ITMP2, iptr->val.l);
+ M_CMPLT(s1, REG_ITMP2, REG_ITMP1, 0);
+ }
+ M_BNEZ(REG_ITMP1, 0);
+ }
+ mcode_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
+ break;
+ case ICMD_IF_LLE:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ if (iptr->val.l == 0) {
+ M_BLEZ(s1, 0);
+ }
+ else {
+ if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
+ M_CMPLE(s1, iptr->val.l, REG_ITMP1, 1);
+ }
+ else {
+ LCONST(REG_ITMP2, iptr->val.l);
+ M_CMPLE(s1, REG_ITMP2, REG_ITMP1, 0);
+ }
+ M_BNEZ(REG_ITMP1, 0);
+ }
+ mcode_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
+ break;
+ case ICMD_IF_LNE:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ if (iptr->val.l == 0) {
+ M_BNEZ(s1, 0);
+ }
+ else {
+ if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
+ M_CMPEQ(s1, iptr->val.l, REG_ITMP1, 1);
+ }
+ else {
+ LCONST(REG_ITMP2, iptr->val.l);
+ M_CMPEQ(s1, REG_ITMP2, REG_ITMP1, 0);
+ }
+ M_BEQZ(REG_ITMP1, 0);
+ }
+ mcode_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
+ break;
+ case ICMD_IF_LGT:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ if (iptr->val.l == 0) {
+ M_BGTZ(s1, 0);
+ }
+ else {
+ if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
+ M_CMPLE(s1, iptr->val.l, REG_ITMP1, 1);
+ }
+ else {
+ LCONST(REG_ITMP2, iptr->val.l);
+ M_CMPLE(s1, REG_ITMP2, REG_ITMP1, 0);
+ }
+ M_BEQZ(REG_ITMP1, 0);
+ }
+ mcode_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
+ break;
+ case ICMD_IF_LGE:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ if (iptr->val.l == 0) {
+ M_BGEZ(s1, 0);
+ }
+ else {
+ if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
+ M_CMPLT(s1, iptr->val.l, REG_ITMP1, 1);
+ }
+ else {
+ LCONST(REG_ITMP2, iptr->val.l);
+ M_CMPLT(s1, REG_ITMP2, REG_ITMP1, 0);
+ }
+ M_BEQZ(REG_ITMP1, 0);
+ }
+ mcode_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
+ break;
+
+ case ICMD_IF_ICMPEQ:
+ case ICMD_IF_LCMPEQ:
+ case ICMD_IF_ACMPEQ:
+ var_to_reg_int(s1, src->prev, REG_ITMP1);
+ var_to_reg_int(s2, src, REG_ITMP2);
+ M_CMPEQ(s1, s2, REG_ITMP1, 0);
+ M_BNEZ(REG_ITMP1, 0);
+ mcode_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
+ break;
+ case ICMD_IF_ICMPNE:
+ case ICMD_IF_LCMPNE:
+ case ICMD_IF_ACMPNE:
+ var_to_reg_int(s1, src->prev, REG_ITMP1);
+ var_to_reg_int(s2, src, REG_ITMP2);
+ M_CMPEQ(s1, s2, REG_ITMP1, 0);
+ M_BEQZ(REG_ITMP1, 0);
+ mcode_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
+ break;
+ case ICMD_IF_ICMPLT:
+ case ICMD_IF_LCMPLT:
+ var_to_reg_int(s1, src->prev, REG_ITMP1);
+ var_to_reg_int(s2, src, REG_ITMP2);
+ M_CMPLT(s1, s2, REG_ITMP1, 0);
+ M_BNEZ(REG_ITMP1, 0);
+ mcode_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
+ break;
+ case ICMD_IF_ICMPGT:
+ case ICMD_IF_LCMPGT:
+ var_to_reg_int(s1, src->prev, REG_ITMP1);
+ var_to_reg_int(s2, src, REG_ITMP2);
+ M_CMPLE(s1, s2, REG_ITMP1, 0);
+ M_BEQZ(REG_ITMP1, 0);
+ mcode_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
+ break;
+ case ICMD_IF_ICMPLE:
+ case ICMD_IF_LCMPLE:
+ var_to_reg_int(s1, src->prev, REG_ITMP1);
+ var_to_reg_int(s2, src, REG_ITMP2);
+ M_CMPLE(s1, s2, REG_ITMP1, 0);
+ M_BNEZ(REG_ITMP1, 0);
+ mcode_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
+ break;
+ case ICMD_IF_ICMPGE:
+ case ICMD_IF_LCMPGE:
+ var_to_reg_int(s1, src->prev, REG_ITMP1);
+ var_to_reg_int(s2, src, REG_ITMP2);
+ M_CMPLT(s1, s2, REG_ITMP1, 0);
+ M_BEQZ(REG_ITMP1, 0);
+ mcode_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
+ break;
+
+/* branch if the unsigned value of s1 is greater that s2 (note, that s2 has
+ to be >= 0) */
+
+/* case ICMD_IF_UCMPGE:
+ var_to_reg_int(s1, src->prev, REG_ITMP1);
+ var_to_reg_int(s2, src, REG_ITMP2);
+ M_CMPULE(s2, s1, REG_ITMP1, 0);
+ M_BNEZ(REG_ITMP1, 0);
+ mcode_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
+ break;
+*/
+
+ case ICMD_IRETURN:
+ case ICMD_LRETURN:
+ case ICMD_ARETURN:
+
+#ifdef USE_THREADS
+ if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
+ a = dseg_addaddress ((void*) (builtin_monitorexit));
+ M_LLD(REG_PV, REG_PV, a);
+ M_LLD(argintregs[0], REG_SP, 8 * maxmemuse);
+ M_JSR(REG_RA, REG_PV);
+ M_LDA(REG_PV, REG_RA, -(int)((u1*) mcodeptr - mcodebase));
+ }
+#endif
+ var_to_reg_int(s1, src, REG_RESULT);
+ M_INTMOVE(s1, REG_RESULT);
+ goto nowperformreturn;
+
+ case ICMD_FRETURN:
+ case ICMD_DRETURN:
+
+#ifdef USE_THREADS
+ if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
+ a = dseg_addaddress ((void*) (builtin_monitorexit));
+ M_LLD(REG_PV, REG_PV, a);
+ M_LLD(argintregs[0], REG_SP, 8 * maxmemuse);
+ M_JSR(REG_RA, REG_PV);
+ M_LDA(REG_PV, REG_RA, -(int)((u1*) mcodeptr - mcodebase));
+ }
+#endif
+ var_to_reg_flt(s1, src, REG_FRESULT);
+ M_FLTMOVE(s1, REG_FRESULT);
+ goto nowperformreturn;
+
+ case ICMD_RETURN:
+
+#ifdef USE_THREADS
+ if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
+ a = dseg_addaddress ((void*) (builtin_monitorexit));
+ M_LLD(REG_PV, REG_PV, a);
+ M_LLD(argintregs[0], REG_SP, 8 * maxmemuse);
+ M_JSR(REG_RA, REG_PV);
+ M_LDA(REG_PV, REG_RA, -(int)((u1*) mcodeptr - mcodebase));
+ }
+#endif
+
+nowperformreturn:
+ {
+ int r, p;
+
+ p = parentargs_base;
+ if (!isleafmethod)
+ {p--; M_LLD (REG_RA, REG_SP, 8 * p);}
+ for (r = savintregcnt - 1; r >= maxsavintreguse; r--)
+ {p--; M_LLD(savintregs[r], REG_SP, 8 * p);}
+ for (r = savfltregcnt - 1; r >= maxsavfltreguse; r--)
+ {p--; M_DLD(savfltregs[r], REG_SP, 8 * p);}
+
+ if (parentargs_base)
+ {M_LDA(REG_SP, REG_SP, parentargs_base*8);}
+ if (runverbose) {
+ M_LDA (REG_SP, REG_SP, -24);
+ M_LST(REG_RA, REG_SP, 0);
+ M_LST(REG_RESULT, REG_SP, 8);
+ M_DST(REG_FRESULT, REG_SP,16);
+ a = dseg_addaddress (method);
+ M_LLD(argintregs[0], REG_PV, a);
+ M_OR(REG_RESULT, REG_RESULT, argintregs[1], 0);
+ M_FLTMOVE(REG_FRESULT, argfltregs[2]);
+ a = dseg_addaddress ((void*) (builtin_displaymethodstop));
+ M_LLD(REG_PV, REG_PV, a);
+ M_JSR (REG_RA, REG_PV);
+ s1 = (int)((u1*) mcodeptr - mcodebase);
+ if (s1<=32768) M_LDA (REG_PV, REG_RA, -s1);
+ else {
+ s4 ml=-s1, mh=0;
+ while (ml<-32768) { ml+=65536; mh--; }
+ M_LDA (REG_PV, REG_RA, ml );
+ M_LDAH (REG_PV, REG_PV, mh );
+ }
+ M_DLD(REG_FRESULT, REG_SP,16);
+ M_LLD(REG_RESULT, REG_SP, 8);
+ M_LLD(REG_RA, REG_SP, 0);
+ M_LDA (REG_SP, REG_SP, 24);
+ }
+ M_RET(REG_ZERO, REG_RA);
+ ALIGNCODENOP;
+ }
+ break;
+
+
+ case ICMD_TABLESWITCH:
+ {
+ s4 i, l, *s4ptr;
+
+ s4ptr = iptr->val.a;
+ l = s4ptr[1]; /* low */
+ i = s4ptr[2]; /* high */
+
+ var_to_reg_int(s1, src, REG_ITMP1);
+ if (l == 0)
+ {M_INTMOVE(s1, REG_ITMP1);}
+ else
+ M_LDA(REG_ITMP1, s1, -l);
+ i = i - l + 1;
+
+ if (i <= 256)
+ M_CMPULE(REG_ITMP1, i - 1, REG_ITMP2, 1);
+ else {
+ M_LDA(REG_ITMP2, REG_ZERO, i - 1);
+ M_CMPULE(REG_ITMP1, REG_ITMP2, REG_ITMP2, 0);
+ }
+ M_BEQZ(REG_ITMP2, 0);
+ mcode_addreference(BlockPtrOfPC(s4ptr[0]), mcodeptr);
+
+ /* build jump table top down and use address of lowest entry */
+
+ s4ptr += 3 + i;
+ while (--i >= 0) {
+ dseg_addtarget(BlockPtrOfPC(*--s4ptr));
+ }
+ }
+
+ /* length of dataseg after last dseg_addtarget is used by load */
+
+ M_S8ADDQ(REG_ITMP1, REG_PV, REG_ITMP2, 0);
+ M_LLD(REG_ITMP2, REG_ITMP2, -dseglen);
+ M_JMP(REG_ZERO, REG_ITMP2);
+ ALIGNCODENOP;
+ break;
+
+
+ case ICMD_LOOKUPSWITCH:
+ {
+ s4 i, l, val, *s4ptr;
+
+ s4ptr = iptr->val.a;
+ l = s4ptr[0]; /* default */
+ i = s4ptr[1]; /* count */
+
+ MCODECHECK((i<<2)+8);
+ var_to_reg_int(s1, src, REG_ITMP1);
+ while (--i >= 0) {
+ s4ptr += 2;
+ val = s4ptr[0];
+ if ((val >= 0) && (val <= 255)) {
+ M_CMPEQ(s1, val, REG_ITMP2, 1);
+ }
+ else {
+ if ((val >= -32768) && (val <= 32767)) {
+ M_LDA(REG_ITMP2, REG_ZERO, val);
+ }
+ else {
+ a = dseg_adds4 (val);
+ M_ILD(REG_ITMP2, REG_PV, a);
+ }
+ M_CMPEQ(s1, REG_ITMP2, REG_ITMP2, 0);
+ }
+ M_BNEZ(REG_ITMP2, 0);
+ mcode_addreference(BlockPtrOfPC(s4ptr[1]), mcodeptr);
+ }
+
+ M_BR(0);
+ mcode_addreference(BlockPtrOfPC(l), mcodeptr);
+ ALIGNCODENOP;
+ break;
+ }
+
+
+ case ICMD_BUILTIN3:
+ s3 = 3;
+ goto gen_method;
+
+ case ICMD_BUILTIN2:
+ s3 = 2;
+ goto gen_method;
+
+ case ICMD_BUILTIN1:
+ s3 = 1;
+ goto gen_method;
+
+ case ICMD_INVOKESTATIC:
+ case ICMD_INVOKESPECIAL:
+ case ICMD_INVOKEVIRTUAL:
+ case ICMD_INVOKEINTERFACE:
+ s3 = iptr->op1;
+
+gen_method: {
+ methodinfo *m;
+ classinfo *ci;
+
+ MCODECHECK((s3 << 1) + 64);
+
+ for (; --s3 >= 0; src = src->prev) {
+ if (src->varkind == ARGVAR)
+ continue;
+ if (IS_INT_LNG_TYPE(src->type)) {
+ if (s3 < INT_ARG_CNT) {
+ s1 = argintregs[s3];
+ var_to_reg_int(d, src, s1);
+ M_INTMOVE(d, s1);
+ }
+ else {
+ var_to_reg_int(d, src, REG_ITMP1);
+ M_LST(d, REG_SP, 8 * (s3 - INT_ARG_CNT));
+ }
+ }
+ else
+ if (s3 < FLT_ARG_CNT) {
+ s1 = argfltregs[s3];
+ var_to_reg_flt(d, src, s1);
+ M_FLTMOVE(d, s1);
+ }
+ else {
+ var_to_reg_flt(d, src, REG_FTMP1);
+ M_DST(d, REG_SP, 8 * (s3 - FLT_ARG_CNT));
+ }
+ } /* end of for */
+
+ m = iptr->val.a;
+ switch (iptr->opc) {
+ case ICMD_BUILTIN3:
+ case ICMD_BUILTIN2:
+ case ICMD_BUILTIN1:
+ a = dseg_addaddress ((void*) (m));
+
+ M_LLD(REG_PV, REG_PV, a); /* Pointer to built-in-function */
+ d = iptr->op1;
+ goto makeactualcall;
+
+ case ICMD_INVOKESTATIC:
+ case ICMD_INVOKESPECIAL:
+ a = dseg_addaddress (m->stubroutine);
+
+ M_LLD(REG_PV, REG_PV, a ); /* Method-Pointer in r27 */
+
+ d = m->returntype;
+ goto makeactualcall;
+
+ case ICMD_INVOKEVIRTUAL:
+
+ gen_nullptr_check(argintregs[0]);
+ M_LLD(REG_METHODPTR, argintregs[0],
+ OFFSET(java_objectheader, vftbl));
+ M_LLD(REG_PV, REG_METHODPTR, OFFSET(vftbl, table[0]) +
+ sizeof(methodptr) * m->vftblindex);
+
+ d = m->returntype;
+ goto makeactualcall;
+
+ case ICMD_INVOKEINTERFACE:
+ ci = m->class;
+
+ gen_nullptr_check(argintregs[0]);
+ M_LLD(REG_METHODPTR, argintregs[0],
+ OFFSET(java_objectheader, vftbl));
+ M_LLD(REG_METHODPTR, REG_METHODPTR,
+ OFFSET(vftbl, interfacevftbl));
+ M_LLD(REG_METHODPTR, REG_METHODPTR,
+ sizeof(methodptr*) * ci->index);
+ M_LLD(REG_PV, REG_METHODPTR,
+ sizeof(methodptr) * (m - ci->methods));
+
+ d = m->returntype;
+ goto makeactualcall;
+
+ default:
+ d = 0;
+ sprintf (logtext, "Unkown ICMD-Command: %d", iptr->opc);
+ error ();
+ }
+
+makeactualcall:
+
+ M_JSR (REG_RA, REG_PV);
+ s1 = (int)((u1*) mcodeptr - mcodebase);
+ if (s1<=32768) M_LDA (REG_PV, REG_RA, -s1);
+ else {
+ s4 ml=-s1, mh=0;
+ while (ml<-32768) { ml+=65536; mh--; }
+ M_LDA (REG_PV, REG_RA, ml );
+ M_LDAH (REG_PV, REG_PV, mh );
+ }
+
+ if (d != TYPE_VOID) {
+ if (IS_INT_LNG_TYPE(iptr->dst->type)) {
+ s1 = reg_of_var(iptr->dst, REG_RESULT);
+ M_INTMOVE(REG_RESULT, s1);
+ store_reg_to_var_int(iptr->dst, s1);
+ }
+ else {
+ s1 = reg_of_var(iptr->dst, REG_FRESULT);
+ M_FLTMOVE(REG_FRESULT, s1);
+ store_reg_to_var_flt(iptr->dst, s1);
+ }
+ }
+ }
+ break;
+
+ case ICMD_CHECKASIZE:
+ var_to_reg_int(s1, src, REG_ITMP1);
+ M_BLTZ(s1, 0);
+ mcode_addxcheckarefs(mcodeptr);
+ break;
+
+ case ICMD_MULTIANEWARRAY:
+
+ /* check for negative sizes and copy sizes to stack if necessary */
+
+ MCODECHECK((iptr->op1 << 1) + 64);
+
+ for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
+ var_to_reg_int(s2, src, REG_ITMP1);
+ M_BLTZ(s2, 0);
+ mcode_addxcheckarefs(mcodeptr);
+
+ /* copy sizes to stack (argument numbers >= INT_ARG_CNT) */
+
+ if (src->varkind != ARGVAR) {
+ M_LST(s2, REG_SP, 8 * (s1 + INT_ARG_CNT));
+ }
+ }
+
+ /* a0 = dimension count */
+
+ M_LDA(argintregs[0], REG_ZERO, iptr->op1);
+
+ /* a1 = arraydescriptor */
+
+ a = dseg_addaddress(iptr->val.a);
+ M_LLD(argintregs[1], REG_PV, a);
+
+ /* a2 = pointer to dimensions = stack pointer */
+
+ M_INTMOVE(REG_SP, argintregs[2]);
+
+ a = dseg_addaddress((void*) (builtin_nmultianewarray));
+ M_LLD(REG_PV, REG_PV, a);
+ M_JSR(REG_RA, REG_PV);
+ s1 = (int)((u1*) mcodeptr - mcodebase);
+ if (s1 <= 32768)
+ M_LDA (REG_PV, REG_RA, -s1);
+ else {
+ s4 ml = -s1, mh = 0;
+ while (ml < -32768) {ml += 65536; mh--;}
+ M_LDA(REG_PV, REG_RA, ml);
+ M_LDAH(REG_PV, REG_PV, mh);
+ }
+ s1 = reg_of_var(iptr->dst, REG_RESULT);
+ M_INTMOVE(REG_RESULT, s1);
+ store_reg_to_var_int(iptr->dst, s1);
+ break;
+
+
+ default: sprintf (logtext, "Unknown pseudo command: %d", iptr->opc);
+ error();
+ } /* switch */
+ } /* for instruction */
+ src = bptr->outstack;
+ len = bptr->outdepth;
+ MCODECHECK(64+len);
+ while (src) {
+ len--;
+ if ((src->varkind != STACKVAR)) {
+ s2 = src->type;
+ if (IS_FLT_DBL_TYPE(s2)) {
+ var_to_reg_int(s1, src, REG_ITMP1);
+ if (!(interfaces[len][s2].flags & INMEMORY)) {
+ M_FLTMOVE(s1,interfaces[len][s2].regoff);
+ }
+ else {
+ M_DST(s1, REG_SP, 8 * interfaces[len][s2].regoff);
+ }
+ }
+ else {
+ var_to_reg_flt(s1, src, REG_FTMP1);
+ if (!(interfaces[len][s2].flags & INMEMORY)) {
+ M_INTMOVE(s1,interfaces[len][s2].regoff);
+ }
+ else {
+ M_LST(s1, REG_SP, 8 * interfaces[len][s2].regoff);
+ }
+ }
+ }
+ src = src->prev;
+ }
+ } /* for basic block */
+
+ {
+ s4 *xcodeptr = NULL;
+
+ for (; xboundrefs != NULL; xboundrefs = xboundrefs->next) {
+ if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
+ gen_resolvebranch((u1*) mcodebase + xboundrefs->branchpos,
+ xboundrefs->branchpos, (u1*) xcodeptr - (u1*) mcodebase - 4);
+ continue;
+ }
+
+ gen_resolvebranch((u1*) mcodebase + xboundrefs->branchpos,
+ xboundrefs->branchpos, (u1*) mcodeptr - mcodebase);
+
+ MCODECHECK(8);
+
+ M_LDA(REG_ITMP2_XPC, REG_PV, xboundrefs->branchpos);
+
+ if (xcodeptr != NULL) {
+ M_BR((xcodeptr-mcodeptr)-1);
+ }
+ else {
+ xcodeptr = mcodeptr;
+
+ a = dseg_addaddress(proto_java_lang_ArrayIndexOutOfBoundsException);
+ M_LLD(REG_ITMP1_XPTR, REG_PV, a);
+
+ a = dseg_addaddress(asm_handle_exception);
+ M_LLD(REG_ITMP3, REG_PV, a);
+
+ M_JMP(REG_ZERO, REG_ITMP3);
+ }
+ }
+
+ xcodeptr = NULL;
+
+ for (; xcheckarefs != NULL; xcheckarefs = xcheckarefs->next) {
+ if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
+ gen_resolvebranch((u1*) mcodebase + xcheckarefs->branchpos,
+ xcheckarefs->branchpos, (u1*) xcodeptr - (u1*) mcodebase - 4);
+ continue;
+ }
+
+ gen_resolvebranch((u1*) mcodebase + xcheckarefs->branchpos,
+ xcheckarefs->branchpos, (u1*) mcodeptr - mcodebase);
+
+ MCODECHECK(8);
+
+ M_LDA(REG_ITMP2_XPC, REG_PV, xcheckarefs->branchpos);
+
+ if (xcodeptr != NULL) {
+ M_BR((xcodeptr-mcodeptr)-1);
+ }
+ else {
+ xcodeptr = mcodeptr;
+
+ a = dseg_addaddress(proto_java_lang_NegativeArraySizeException);
+ M_LLD(REG_ITMP1_XPTR, REG_PV, a);
+
+ a = dseg_addaddress(asm_handle_exception);
+ M_LLD(REG_ITMP3, REG_PV, a);
+
+ M_JMP(REG_ZERO, REG_ITMP3);
+ }
+ }
+
+
+#ifdef SOFTNULLPTRCHECK
+
+ xcodeptr = NULL;
+
+ for (; xnullrefs != NULL; xnullrefs = xnullrefs->next) {
+ if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
+ gen_resolvebranch((u1*) mcodebase + xnullrefs->branchpos,
+ xnullrefs->branchpos, (u1*) xcodeptr - (u1*) mcodebase - 4);
+ continue;
+ }
+
+ gen_resolvebranch((u1*) mcodebase + xnullrefs->branchpos,
+ xnullrefs->branchpos, (u1*) mcodeptr - mcodebase);
+
+ MCODECHECK(8);
+
+ M_LDA(REG_ITMP2_XPC, REG_PV, xnullrefs->branchpos - 4);
+
+ if (xcodeptr != NULL) {
+ M_BR((xcodeptr-mcodeptr)-1);
+ }
+ else {
+ xcodeptr = mcodeptr;
+
+ a = dseg_addaddress(proto_java_lang_NullPointerException);
+ M_LLD(REG_ITMP1_XPTR, REG_PV, a);
+
+ a = dseg_addaddress(asm_handle_exception);
+ M_LLD(REG_ITMP3, REG_PV, a);
+
+ M_JMP(REG_ZERO, REG_ITMP3);
+ }
+ }
+
+#endif
+ }
+
+ mcode_finish((int)((u1*) mcodeptr - mcodebase));
+}
+
+
+/******** redefinition of code generation macros (compiling into array) *******/
+
+/*
+These macros are newly defined to allow code generation into an array.
+This is necessary, because the original M_.. macros generate code by
+calling 'mcode_adds4' that uses an additional data structure to
+receive the code.
+
+For a faster (but less flexible) version to generate code, these
+macros directly use the (s4* p) - pointer to put the code directly
+in a locally defined array.
+This makes sense only for the stub-generation-routines below.
+*/
+
+#undef M_OP3
+#define M_OP3(op,fu,a,b,c,const) \
+ *(p++) = ( (((s4)(op))<<26)|((a)<<21)|((b)<<(16-3*(const)))| \
+ ((const)<<12)|((fu)<<5)|((c)) )
+#undef M_FOP3
+#define M_FOP3(op,fu,a,b,c) \
+ *(p++) = ( (((s4)(op))<<26)|((a)<<21)|((b)<<16)|((fu)<<5)|(c) )
+#undef M_BRA
+#define M_BRA(op,a,disp) \
+ *(p++) = ( (((s4)(op))<<26)|((a)<<21)|((disp)&0x1fffff) )
+#undef M_MEM
+#define M_MEM(op,a,b,disp) \
+ *(p++) = ( (((s4)(op))<<26)|((a)<<21)|((b)<<16)|((disp)&0xffff) )
+
+
+#if 0
+
+/************************ function createcompilerstub **************************
+
+ creates a stub routine which calls the compiler
+
+*******************************************************************************/
+
+#define COMPSTUBSIZE 3
+
+u1 *createcompilerstub (methodinfo *m)
+{
+ u8 *s = CNEW (u8, COMPSTUBSIZE); /* memory to hold the stub */
+ s4 *p = (s4*) s; /* code generation pointer */
+
+ /* code for the stub */
+ M_LLD (REG_PV, REG_PV, 16); /* load pointer to the compiler */
+ M_JMP (0, REG_PV); /* jump to the compiler, return address
+ in reg 0 is used as method pointer */
+ s[1] = (u8) m; /* literals to be adressed */
+ s[2] = (u8) asm_call_jit_compiler; /* jump directly via PV from above */
+
+#ifdef STATISTICS
+ count_cstub_len += COMPSTUBSIZE * 8;
+#endif
+
+ return (u1*) s;
+}
+
+
+/************************* function removecompilerstub *************************
+
+ deletes a compilerstub from memory (simply by freeing it)
+
+*******************************************************************************/
+
+void removecompilerstub (u1 *stub)
+{
+ CFREE (stub, COMPSTUBSIZE * 8);
+}
+
+
+/************************ function: removenativestub ***************************
+
+ removes a previously created native-stub from memory
+
+*******************************************************************************/
+
+void removenativestub (u1 *stub)
+{
+ CFREE (stub, NATIVESTUBSIZE * 8);
+}
+
+#endif /* 0 */
+
+
+/********************* Funktion: ncreatenativestub *****************************
+
+ creates a stub routine which calls a native method
+
+*******************************************************************************/
+
+#define NATIVESTUBSIZE 11
+
+u1 *ncreatenativestub (functionptr f, methodinfo *m)
+{
+ u8 *s = CNEW (u8, NATIVESTUBSIZE); /* memory to hold the stub */
+ s4 *p = (s4*) s; /* code generation pointer */
+
+ M_LDA (REG_SP, REG_SP, -8); /* build up stackframe */
+ M_LST (REG_RA, REG_SP, 0); /* store return address */
+
+ M_LLD (REG_PV, REG_PV, 8*8); /* load adress of native method */
+ M_JSR (REG_RA, REG_PV); /* call native method */
+
+ M_LDA (REG_PV, REG_RA, -4*4); /* recompute pv from ra */
+ M_LLD (REG_ITMP3, REG_PV, 9*8); /* get address of exceptionptr */
+
+ M_LLD (REG_RA, REG_SP, 0); /* load return address */
+ M_LLD (REG_ITMP1, REG_ITMP3, 0); /* load exception into reg. itmp1 */
+
+ M_LDA (REG_SP, REG_SP, 8); /* remove stackframe */
+ M_BNEZ (REG_ITMP1, 1); /* if no exception then return */
+
+ M_RET (REG_ZERO, REG_RA); /* return to caller */
+
+ M_LST (REG_ZERO, REG_ITMP3, 0); /* store NULL into exceptionptr */
+ M_LDA (REG_ITMP2, REG_RA, -4); /* move fault address into reg. itmp2 */
+
+ M_LLD (REG_ITMP3, REG_PV,10*8); /* load asm exception handler address */
+ M_JMP (REG_ZERO, REG_ITMP3); /* jump to asm exception handler */
+
+
+ s[8] = (u8) f; /* address of native method */
+ s[9] = (u8) (&exceptionptr); /* address of exceptionptr */
+ s[10]= (u8) (asm_handle_nat_exception); /* addr of asm exception handler */
+
+#ifdef STATISTICS
+ count_nstub_len += NATIVESTUBSIZE * 8;
+#endif
+
+ return (u1*) s;
+}
+
--- /dev/null
+/***************************** alpha/ngen.h ************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Contains the machine dependent code generator definitions and macros for an
+ Alpha processor.
+
+ Authors: Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
+ Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1998/08/10
+
+*******************************************************************************/
+
+/************************ Preallocated registers ******************************/
+
+/* integer registers */
+
+#define REG_RESULT 0 /* to deliver method results */
+#define REG_EXCEPTION 1 /* to throw an exception across method bounds */
+
+#define REG_RA 26 /* return address */
+#define REG_PV 27 /* procedure vector, must be provided by caller */
+#define REG_METHODPTR 28 /* pointer to the place from where the procedure */
+ /* vector has been fetched */
+#define REG_ITMP1 25 /* temporary register */
+#define REG_ITMP2 28 /* temporary register */
+#define REG_ITMP3 29 /* temporary register */
+
+#define REG_ITMP1_XPTR 25 /* exception pointer = temporary register 1 */
+#define REG_ITMP2_XPC 28 /* exception pc = temporary register 2 */
+
+#define REG_SP 30 /* stack pointer */
+#define REG_ZERO 31 /* allways zero */
+
+/* floating point registers */
+
+#define REG_FRESULT 0 /* to deliver floating point method results */
+#define REG_FTMP1 28 /* temporary floating point register */
+#define REG_FTMP2 29 /* temporary floating point register */
+#define REG_FTMP3 30 /* temporary floating point register */
+
+#define REG_IFTMP 28 /* temporary integer and floating point register */
+
+/******************** register descripton - array *****************************/
+
+/* #define REG_RES 0 reserved register for OS or code generator */
+/* #define REG_RET 1 return value register */
+/* #define REG_EXC 2 exception value register */
+/* #define REG_SAV 3 (callee) saved register */
+/* #define REG_TMP 4 scratch temporary register (caller saved) */
+/* #define REG_ARG 5 argument register (caller saved) */
+
+/* #define REG_END -1 last entry in tables */
+
+int nregdescint[] = {
+ REG_RET, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
+ REG_TMP, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
+ REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP,
+ REG_TMP, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
+ REG_END };
+
+#define INT_SAV_CNT 7 /* number of int callee saved registers */
+#define INT_ARG_CNT 6 /* number of int argument registers */
+
+/* for use of reserved registers, see comment above */
+
+int nregdescfloat[] = {
+ REG_RET, REG_TMP, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
+ REG_SAV, REG_SAV, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
+ REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP,
+ REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_RES, REG_RES, REG_RES, REG_RES,
+ REG_END };
+
+#define FLT_SAV_CNT 8 /* number of flt callee saved registers */
+#define FLT_ARG_CNT 6 /* number of flt argument registers */
+
+/* for use of reserved registers, see comment above */
+
+
+/*** parameter allocation mode ***/
+
+int nreg_parammode = PARAMMODE_NUMBERED;
+
+ /* parameter-registers will be allocated by assigning the
+ 1. parameter: int/float-reg 16
+ 2. parameter: int/float-reg 17
+ 3. parameter: int/float-reg 18 ....
+ */
+
+
+/************************** stackframe-infos **********************************/
+
+int parentargs_base; /* offset in stackframe for the parameter from the caller*/
+
+/* -> see file 'calling.doc' */
+
+
+/******************** macros to create code ***********************************/
+
+/* 3-address-operations: M_OP3
+ op ..... opcode
+ fu ..... function-number
+ a ..... register number source 1
+ b ..... register number or constant integer source 2
+ c ..... register number destination
+ const .. switch to use b as constant integer
+ (0 means: use b as register number)
+ (1 means: use b as constant 8-bit-integer)
+*/
+#define M_OP3(op,fu,a,b,c,const) \
+ *(mcodeptr++) = ( (((s4)(op))<<26)|((a)<<21)|((b)<<(16-3*(const)))| \
+ ((const)<<12)|((fu)<<5)|((c)) )
+
+/* 3-address-floating-point-operation: M_FOP3
+ op .... opcode
+ fu .... function-number
+ a,b ... source floating-point registers
+ c ..... destination register
+*/
+#define M_FOP3(op,fu,a,b,c) \
+ *(mcodeptr++) = ( (((s4)(op))<<26)|((a)<<21)|((b)<<16)|((fu)<<5)|(c) )
+
+/* branch instructions: M_BRA
+ op ..... opcode
+ a ...... register to be tested
+ disp ... relative address to be jumped to (divided by 4)
+*/
+#define M_BRA(op,a,disp) \
+ *(mcodeptr++) = ( (((s4)(op))<<26)|((a)<<21)|((disp)&0x1fffff) )
+
+
+/* memory operations: M_MEM
+ op ..... opcode
+ a ...... source/target register for memory access
+ b ...... base register
+ disp ... displacement (16 bit signed) to be added to b
+*/
+#define M_MEM(op,a,b,disp) \
+ *(mcodeptr++) = ( (((s4)(op))<<26)|((a)<<21)|((b)<<16)|((disp)&0xffff) )
+
+
+/***** macros for all used commands (see an Alpha-manual for description) *****/
+
+#define M_LDA(a,b,disp) M_MEM (0x08,a,b,disp) /* low const */
+#define M_LDAH(a,b,disp) M_MEM (0x09,a,b,disp) /* high const */
+#define M_BLDU(a,b,disp) M_MEM (0x0a,a,b,disp) /* 8 load */
+#define M_SLDU(a,b,disp) M_MEM (0x0c,a,b,disp) /* 16 load */
+#define M_ILD(a,b,disp) M_MEM (0x28,a,b,disp) /* 32 load */
+#define M_LLD(a,b,disp) M_MEM (0x29,a,b,disp) /* 64 load */
+#define M_BST(a,b,disp) M_MEM (0x0e,a,b,disp) /* 8 store */
+#define M_SST(a,b,disp) M_MEM (0x0d,a,b,disp) /* 16 store */
+#define M_IST(a,b,disp) M_MEM (0x2c,a,b,disp) /* 32 store */
+#define M_LST(a,b,disp) M_MEM (0x2d,a,b,disp) /* 64 store */
+
+#define M_BSEXT(b,c) M_OP3 (0x1c,0x0,REG_ZERO,b,c,0) /* 8 signext */
+#define M_SSEXT(b,c) M_OP3 (0x1c,0x1,REG_ZERO,b,c,0) /* 16 signext */
+
+#define M_BR(disp) M_BRA (0x30,REG_ZERO,disp) /* branch */
+#define M_BSR(ra,disp) M_BRA (0x34,ra,disp) /* branch sbr */
+#define M_BEQZ(a,disp) M_BRA (0x39,a,disp) /* br a == 0 */
+#define M_BLTZ(a,disp) M_BRA (0x3a,a,disp) /* br a < 0 */
+#define M_BLEZ(a,disp) M_BRA (0x3b,a,disp) /* br a <= 0 */
+#define M_BNEZ(a,disp) M_BRA (0x3d,a,disp) /* br a != 0 */
+#define M_BGEZ(a,disp) M_BRA (0x3e,a,disp) /* br a >= 0 */
+#define M_BGTZ(a,disp) M_BRA (0x3f,a,disp) /* br a > 0 */
+
+#define M_JMP(a,b) M_MEM (0x1a,a,b,0x0000) /* jump */
+#define M_JSR(a,b) M_MEM (0x1a,a,b,0x4000) /* call sbr */
+#define M_RET(a,b) M_MEM (0x1a,a,b,0x8000) /* return */
+
+#define M_IADD(a,b,c,const) M_OP3 (0x10,0x0, a,b,c,const) /* 32 add */
+#define M_LADD(a,b,c,const) M_OP3 (0x10,0x20, a,b,c,const) /* 64 add */
+#define M_ISUB(a,b,c,const) M_OP3 (0x10,0x09, a,b,c,const) /* 32 sub */
+#define M_LSUB(a,b,c,const) M_OP3 (0x10,0x29, a,b,c,const) /* 64 sub */
+#define M_IMUL(a,b,c,const) M_OP3 (0x13,0x00, a,b,c,const) /* 32 mul */
+#define M_LMUL(a,b,c,const) M_OP3 (0x13,0x20, a,b,c,const) /* 64 mul */
+
+#define M_CMPEQ(a,b,c,const) M_OP3 (0x10,0x2d, a,b,c,const) /* c = a == b */
+#define M_CMPLT(a,b,c,const) M_OP3 (0x10,0x4d, a,b,c,const) /* c = a < b */
+#define M_CMPLE(a,b,c,const) M_OP3 (0x10,0x6d, a,b,c,const) /* c = a <= b */
+
+#define M_CMPULE(a,b,c,const) M_OP3 (0x10,0x3d, a,b,c,const) /* c = a <= b */
+#define M_CMPULT(a,b,c,const) M_OP3 (0x10,0x1d, a,b,c,const) /* c = a <= b */
+
+#define M_AND(a,b,c,const) M_OP3 (0x11,0x00, a,b,c,const) /* c = a & b */
+#define M_OR(a,b,c,const) M_OP3 (0x11,0x20, a,b,c,const) /* c = a | b */
+#define M_XOR(a,b,c,const) M_OP3 (0x11,0x40, a,b,c,const) /* c = a ^ b */
+
+#define M_NOP M_OR (31,31,31,0)
+
+#define M_SLL(a,b,c,const) M_OP3 (0x12,0x39, a,b,c,const) /* c = a << b */
+#define M_SRA(a,b,c,const) M_OP3 (0x12,0x3c, a,b,c,const) /* c = a >> b */
+#define M_SRL(a,b,c,const) M_OP3 (0x12,0x34, a,b,c,const) /* c = a >>>b */
+
+#define M_FLD(a,b,disp) M_MEM (0x22,a,b,disp) /* load flt */
+#define M_DLD(a,b,disp) M_MEM (0x23,a,b,disp) /* load dbl */
+#define M_FST(a,b,disp) M_MEM (0x26,a,b,disp) /* store flt */
+#define M_DST(a,b,disp) M_MEM (0x27,a,b,disp) /* store dbl */
+
+#define M_FADD(a,b,c) M_FOP3 (0x16, 0x080, a,b,c) /* flt add */
+#define M_DADD(a,b,c) M_FOP3 (0x16, 0x0a0, a,b,c) /* dbl add */
+#define M_FSUB(a,b,c) M_FOP3 (0x16, 0x081, a,b,c) /* flt sub */
+#define M_DSUB(a,b,c) M_FOP3 (0x16, 0x0a1, a,b,c) /* dbl sub */
+#define M_FMUL(a,b,c) M_FOP3 (0x16, 0x082, a,b,c) /* flt mul */
+#define M_DMUL(a,b,c) M_FOP3 (0x16, 0x0a2, a,b,c) /* dbl mul */
+#define M_FDIV(a,b,c) M_FOP3 (0x16, 0x083, a,b,c) /* flt div */
+#define M_DDIV(a,b,c) M_FOP3 (0x16, 0x0a3, a,b,c) /* dbl div */
+
+#define M_FADDS(a,b,c) M_FOP3 (0x16, 0x580, a,b,c) /* flt add */
+#define M_DADDS(a,b,c) M_FOP3 (0x16, 0x5a0, a,b,c) /* dbl add */
+#define M_FSUBS(a,b,c) M_FOP3 (0x16, 0x581, a,b,c) /* flt sub */
+#define M_DSUBS(a,b,c) M_FOP3 (0x16, 0x5a1, a,b,c) /* dbl sub */
+#define M_FMULS(a,b,c) M_FOP3 (0x16, 0x582, a,b,c) /* flt mul */
+#define M_DMULS(a,b,c) M_FOP3 (0x16, 0x5a2, a,b,c) /* dbl mul */
+#define M_FDIVS(a,b,c) M_FOP3 (0x16, 0x583, a,b,c) /* flt div */
+#define M_DDIVS(a,b,c) M_FOP3 (0x16, 0x5a3, a,b,c) /* dbl div */
+
+#define M_CVTDF(a,b,c) M_FOP3 (0x16, 0x0ac, a,b,c) /* dbl2long */
+#define M_CVTLF(a,b,c) M_FOP3 (0x16, 0x0bc, a,b,c) /* long2flt */
+#define M_CVTLD(a,b,c) M_FOP3 (0x16, 0x0be, a,b,c) /* long2dbl */
+#define M_CVTDL(a,b,c) M_FOP3 (0x16, 0x1af, a,b,c) /* dbl2long */
+#define M_CVTDL_C(a,b,c) M_FOP3 (0x16, 0x12f, a,b,c) /* dbl2long */
+#define M_CVTLI(a,b) M_FOP3 (0x17, 0x130, 31,a,b) /* long2int */
+
+#define M_CVTDFS(a,b,c) M_FOP3 (0x16, 0x5ac, a,b,c) /* dbl2long */
+#define M_CVTDLS(a,b,c) M_FOP3 (0x16, 0x5af, a,b,c) /* dbl2long */
+#define M_CVTDL_CS(a,b,c) M_FOP3 (0x16, 0x52f, a,b,c) /* dbl2long */
+#define M_CVTLIS(a,b) M_FOP3 (0x17, 0x530, 31,a,b) /* long2int */
+
+#define M_FCMPEQ(a,b,c) M_FOP3 (0x16, 0x0a5, a,b,c) /* c = a==b */
+#define M_FCMPLT(a,b,c) M_FOP3 (0x16, 0x0a6, a,b,c) /* c = a<b */
+
+#define M_FCMPEQS(a,b,c) M_FOP3 (0x16, 0x5a5, a,b,c) /* c = a==b */
+#define M_FCMPLTS(a,b,c) M_FOP3 (0x16, 0x5a6, a,b,c) /* c = a<b */
+
+#define M_FMOV(fa,fb) M_FOP3 (0x17, 0x020, fa,fa,fb) /* b = a */
+#define M_FMOVN(fa,fb) M_FOP3 (0x17, 0x021, fa,fa,fb) /* b = -a */
+
+#define M_FNOP M_FMOV (31,31)
+
+#define M_FBEQZ(fa,disp) M_BRA (0x31,fa,disp) /* br a == 0.0*/
+
+/****** macros for special commands (see an Alpha-manual for description) *****/
+
+#define M_TRAPB M_MEM (0x18,0,0,0x0000) /* trap barrier*/
+
+#define M_S4ADDL(a,b,c,const) M_OP3 (0x10,0x02, a,b,c,const) /* c = a*4 + b */
+#define M_S4ADDQ(a,b,c,const) M_OP3 (0x10,0x22, a,b,c,const) /* c = a*4 + b */
+#define M_S4SUBL(a,b,c,const) M_OP3 (0x10,0x0b, a,b,c,const) /* c = a*4 - b */
+#define M_S4SUBQ(a,b,c,const) M_OP3 (0x10,0x2b, a,b,c,const) /* c = a*4 - b */
+#define M_S8ADDL(a,b,c,const) M_OP3 (0x10,0x12, a,b,c,const) /* c = a*8 + b */
+#define M_S8ADDQ(a,b,c,const) M_OP3 (0x10,0x32, a,b,c,const) /* c = a*8 + b */
+#define M_S8SUBL(a,b,c,const) M_OP3 (0x10,0x1b, a,b,c,const) /* c = a*8 - b */
+#define M_S8SUBQ(a,b,c,const) M_OP3 (0x10,0x3b, a,b,c,const) /* c = a*8 - b */
+
+#define M_LLD_U(a,b,disp) M_MEM (0x0b,a,b,disp) /* unalign ld */
+#define M_LST_U(a,b,disp) M_MEM (0x0f,a,b,disp) /* unalign st */
+
+#define M_ZAP(a,b,c,const) M_OP3 (0x12,0x30, a,b,c,const)
+#define M_ZAPNOT(a,b,c,const) M_OP3 (0x12,0x31, a,b,c,const)
+#define M_EXTBL(a,b,c,const) M_OP3 (0x12,0x06, a,b,c,const)
+#define M_EXTWL(a,b,c,const) M_OP3 (0x12,0x16, a,b,c,const)
+#define M_EXTLL(a,b,c,const) M_OP3 (0x12,0x26, a,b,c,const)
+#define M_EXTQL(a,b,c,const) M_OP3 (0x12,0x36, a,b,c,const)
+#define M_EXTWH(a,b,c,const) M_OP3 (0x12,0x5a, a,b,c,const)
+#define M_EXTLH(a,b,c,const) M_OP3 (0x12,0x6a, a,b,c,const)
+#define M_EXTQH(a,b,c,const) M_OP3 (0x12,0x7a, a,b,c,const)
+#define M_INSBL(a,b,c,const) M_OP3 (0x12,0x0b, a,b,c,const)
+#define M_INSWL(a,b,c,const) M_OP3 (0x12,0x1b, a,b,c,const)
+#define M_INSLL(a,b,c,const) M_OP3 (0x12,0x2b, a,b,c,const)
+#define M_INSQL(a,b,c,const) M_OP3 (0x12,0x3b, a,b,c,const)
+#define M_INSWH(a,b,c,const) M_OP3 (0x12,0x57, a,b,c,const)
+#define M_INSLH(a,b,c,const) M_OP3 (0x12,0x67, a,b,c,const)
+#define M_INSQH(a,b,c,const) M_OP3 (0x12,0x77, a,b,c,const)
+#define M_MSKBL(a,b,c,const) M_OP3 (0x12,0x02, a,b,c,const)
+#define M_MSKWL(a,b,c,const) M_OP3 (0x12,0x12, a,b,c,const)
+#define M_MSKLL(a,b,c,const) M_OP3 (0x12,0x22, a,b,c,const)
+#define M_MSKQL(a,b,c,const) M_OP3 (0x12,0x32, a,b,c,const)
+#define M_MSKWH(a,b,c,const) M_OP3 (0x12,0x52, a,b,c,const)
+#define M_MSKLH(a,b,c,const) M_OP3 (0x12,0x62, a,b,c,const)
+#define M_MSKQH(a,b,c,const) M_OP3 (0x12,0x72, a,b,c,const)
+
+
+/****** macros for unused commands (see an Alpha-manual for description) ******/
+
+#define M_ANDNOT(a,b,c,const) M_OP3 (0x11,0x08, a,b,c,const) /* c = a &~ b */
+#define M_ORNOT(a,b,c,const) M_OP3 (0x11,0x28, a,b,c,const) /* c = a |~ b */
+#define M_XORNOT(a,b,c,const) M_OP3 (0x11,0x48, a,b,c,const) /* c = a ^~ b */
+
+#define M_CMOVEQ(a,b,c,const) M_OP3 (0x11,0x24, a,b,c,const) /* a==0 ? c=b */
+#define M_CMOVNE(a,b,c,const) M_OP3 (0x11,0x26, a,b,c,const) /* a!=0 ? c=b */
+#define M_CMOVLT(a,b,c,const) M_OP3 (0x11,0x44, a,b,c,const) /* a< 0 ? c=b */
+#define M_CMOVGE(a,b,c,const) M_OP3 (0x11,0x46, a,b,c,const) /* a>=0 ? c=b */
+#define M_CMOVLE(a,b,c,const) M_OP3 (0x11,0x64, a,b,c,const) /* a<=0 ? c=b */
+#define M_CMOVGT(a,b,c,const) M_OP3 (0x11,0x66, a,b,c,const) /* a> 0 ? c=b */
+
+#define M_CMPBGE(a,b,c,const) M_OP3 (0x10,0x0f, a,b,c,const)
+
+#define M_FCMPUN(a,b,c) M_FOP3 (0x16, 0x0a4, a,b,c) /* unordered */
+#define M_FCMPLE(a,b,c) M_FOP3 (0x16, 0x0a7, a,b,c) /* c = a<=b */
+
+#define M_FCMPUNS(a,b,c) M_FOP3 (0x16, 0x5a4, a,b,c) /* unordered */
+#define M_FCMPLES(a,b,c) M_FOP3 (0x16, 0x5a7, a,b,c) /* c = a<=b */
+
+#define M_FBNEZ(fa,disp) M_BRA (0x35,fa,disp)
+#define M_FBLEZ(fa,disp) M_BRA (0x33,fa,disp)
+
+#define M_JMP_CO(a,b) M_MEM (0x1a,a,b,0xc000) /* call cosub */
+
+
+/************************ function gen_resolvebranch ***************************
+
+ backpatches a branch instruction; Alpha branch instructions are very
+ regular, so it is only necessary to overwrite some fixed bits in the
+ instruction.
+
+ parameters: ip ... pointer to instruction after branch (void*)
+ so ... offset of instruction after branch (s4)
+ to ... offset of branch target (s4)
+
+*******************************************************************************/
+
+#define gen_resolvebranch(ip,so,to) ((s4*)(ip))[-1]|=((s4)(to)-(so))>>2&0x1fffff
+
+#define SOFTNULLPTRCHECK
--- /dev/null
+#ifndef _ASMAXP_SIGCONTEXT_H
+#define _ASMAXP_SIGCONTEXT_H
+
+struct sigcontext_struct {
+
+ /*
+ * what should we have here? I'd probably better use the same
+ * stack layout as OSF/1, just in case we ever want to try
+ * running their binaries..
+ *
+ * This is the basic layout, but I don't know if we'll ever
+ * actually fill in all the values..
+ */
+
+ long sc_onstack; /* sigstack state to restore */
+ long sc_mask; /* signal mask to restore */
+ long sc_pc; /* pc at time of signal */
+ long sc_ps; /* psl to retore */
+ long sc_regs[32]; /* processor regs 0 to 31 */
+ long sc_ownedfp; /* fp has been used */
+ long sc_fpregs[32]; /* fp regs 0 to 31 */
+ unsigned long sc_fpcr; /* floating point control register */
+ unsigned long sc_fp_control; /* software fpcr */
+ /* rest is unused */
+ unsigned long sc_reserved1, sc_reserved2;
+ unsigned long sc_ssize;
+ char *sc_sbase;
+ unsigned long sc_traparg_a0;
+ unsigned long sc_traparg_a1;
+ unsigned long sc_traparg_a2;
+ unsigned long sc_fp_trap_pc;
+ unsigned long sc_fp_trigger_sum;
+ unsigned long sc_fp_trigger_inst;
+ unsigned long sc_retcode[2];
+};
+
+#endif
--- /dev/null
+/*
+ * i386/threads.h
+ * i386 threading information.
+ *
+ * Copyright (c) 1996 T. J. Wilkinson & Associates, London, UK.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+ *
+ * See file COPYRIGHT for information on usage and disclaimer of warranties
+ *
+ * Written by Tim Wilkinson <tim@tjwassoc.demon.co.uk>, 1996.
+ */
+
+#ifndef __alpha_threads_h
+#define __alpha_threads_h
+
+/**/
+/* Thread handling */
+/**/
+
+#include "../threads/thread.h"
+
+void perform_alpha_threadswitch (u1 **from, u1 **to);
+u1* initialize_thread_stack (void *func, u1 *stack);
+u1* used_stack_top (void);
+
+#define THREADSTACKSIZE (64 * 1024)
+
+#define THREADSWITCH(to, from) perform_alpha_threadswitch(&(from)->restorePoint,\
+ &(to)->restorePoint)
+
+#define THREADINIT(to, func) (to)->restorePoint = \
+ initialize_thread_stack((u1*)(func), \
+ (to)->stackEnd)
+
+#define USEDSTACKTOP(top) (top) = used_stack_top()
+
+#define THREADINFO(ee) \
+ do { \
+ (ee)->restorePoint = 0; \
+ (ee)->flags = THREAD_FLAGS_NOSTACKALLOC;\
+ } while(0)
+
+/*
+ void* ptr; \
+ asm("addq $30,$31,%0" : "=r" (ptr)); \
+ (ee)->stackEnd = ptr; \
+ (ee)->stackBase = (ee)->stackEnd - threadStackSize;\
+*/
+
+/*
+#define THREADFRAMES(tid, cnt) \
+ do { \
+ void** ptr; \
+ cnt = 0; \
+ if (tid == currentThread) { \
+ asm("movl %%ebp,%0" : "=r" (ptr));\
+ } \
+ else { \
+ ptr = ((void***)tid->PrivateInfo->restorePoint)[2];\
+ } \
+ while (*ptr != 0) { \
+ cnt++; \
+ ptr = (void**)*ptr; \
+ } \
+ } while (0)
+*/
+
+#endif
--- /dev/null
+/*************************** alpha/types.h *************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ machine specific definitions for the Alpha processor
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+ Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
+ Michael Gschwind EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1997/09/22
+
+*******************************************************************************/
+
+#ifndef _CACAO_TYPES_H
+
+#define _CACAO_TYPES_H
+
+#define POINTERSIZE 8
+#define WORDS_BIGENDIAN 0
+
+#define SUPPORT_DIVISION 0
+#define SUPPORT_LONG 1
+#define SUPPORT_FLOAT 1
+#define SUPPORT_DOUBLE 1
+
+#define SUPPORT_LONG_ADD 1
+#define SUPPORT_LONG_CMP 1
+#define SUPPORT_LONG_LOG 1
+#define SUPPORT_LONG_SHIFT 1
+#define SUPPORT_LONG_MULDIV 1
+#define SUPPORT_LONG_ICVT 1
+#define SUPPORT_LONG_FCVT 1
+
+#define U8_AVAILABLE 1
+
+
+typedef signed char s1;
+typedef unsigned char u1;
+
+typedef signed short int s2;
+typedef unsigned short int u2;
+
+typedef signed int s4;
+typedef unsigned int u4;
+
+#if U8_AVAILABLE
+typedef signed long int s8;
+typedef unsigned long int u8;
+#else
+typedef struct {u4 low, high;} u8;
+#define s8 u8
+#endif
+
+#endif
+
--- /dev/null
+/****************************** asmpart.h **************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Headerfile for asmpart.S. asmpart.S contains the machine dependent
+ Java - C interface functions.
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+ Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1997/10/15
+
+*******************************************************************************/
+
+int has_no_x_instr_set();
+ /* determines if the byte support instruction set (21164a and higher)
+ is available. */
+
+void synchronize_caches();
+
+
+void asm_call_jit_compiler ();
+ /* invokes the compiler for untranslated JavaVM methods.
+ Register R0 contains a pointer to the method info structure
+ (prepared by createcompilerstub). */
+
+java_objectheader *asm_calljavamethod (methodinfo *m, void *arg1, void*arg2,
+ void*arg3, void*arg4);
+ /* This function calls a Java-method (which possibly needs compilation)
+ with up to 4 parameters. This function calls a Java-method (which
+ possibly needs compilation) with up to 4 parameters. */
+
+
+void asm_dumpregistersandcall ( functionptr f);
+ /* This funtion saves all callee saved registers and calls the function
+ which is passed as parameter.
+ This function is needed by the garbage collector, which needs to access
+ all registers which are stored on the stack. Unused registers are
+ cleared to avoid interferances with the GC. */
--- /dev/null
+/* -*- mode: c; tab-width: 4; c-basic-offset: 4 -*- */
+/****************************** builtin.c **************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Enthaelt die C-Funktionen fuer alle JavaVM-Befehle, die sich nicht direkt
+ auf Maschinencode "ubersetzen lassen. Im Code f"ur die Methoden steht
+ dann ein Funktionsaufruf (nat"urlich mit den Aufrufskonventionen von C).
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+ Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
+ Mark Probst EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1996/12/03
+
+*******************************************************************************/
+
+#include <assert.h>
+#include <values.h>
+
+#include "global.h"
+#include "builtin.h"
+
+#include "loader.h"
+#include "tables.h"
+
+#include "threads/thread.h"
+#include "threads/locks.h" /* schani */
+
+#include "sysdep/native-math.h"
+
+builtin_descriptor builtin_desc[] = {
+ {(functionptr) builtin_instanceof, "instanceof"},
+ {(functionptr) builtin_checkcast, "checkcast"},
+ {(functionptr) new_builtin_checkcast, "checkcast"},
+ {(functionptr) builtin_arrayinstanceof, "arrayinstanceof"},
+ {(functionptr) builtin_checkarraycast, "checkarraycast"},
+ {(functionptr) new_builtin_checkarraycast, "checkarraycast"},
+ {(functionptr) new_builtin_aastore, "aastore"},
+ {(functionptr) builtin_new, "new"},
+ {(functionptr) builtin_anewarray, "anewarray"},
+ {(functionptr) builtin_newarray_array, "newarray_array"},
+ {(functionptr) builtin_newarray_boolean, "newarray_boolean"},
+ {(functionptr) builtin_newarray_char, "newarray_char"},
+ {(functionptr) builtin_newarray_float, "newarray_float"},
+ {(functionptr) builtin_newarray_double, "newarray_double"},
+ {(functionptr) builtin_newarray_byte, "newarray_byte"},
+ {(functionptr) builtin_newarray_short, "newarray_short"},
+ {(functionptr) builtin_newarray_int, "newarray_int"},
+ {(functionptr) builtin_newarray_long, "newarray_long"},
+ {(functionptr) builtin_displaymethodstart, "displaymethodstart"},
+ {(functionptr) builtin_displaymethodstop, "displaymethodstop"},
+ {(functionptr) builtin_monitorenter, "monitorenter"},
+ {(functionptr) new_builtin_monitorenter, "monitorenter"},
+ {(functionptr) builtin_monitorexit, "monitorexit"},
+ {(functionptr) new_builtin_monitorexit, "monitorexit"},
+ {(functionptr) builtin_idiv, "idiv"},
+ {(functionptr) new_builtin_idiv, "idiv"},
+ {(functionptr) builtin_irem, "irem"},
+ {(functionptr) new_builtin_irem, "irem"},
+ {(functionptr) builtin_ladd, "ladd"},
+ {(functionptr) builtin_lsub, "lsub"},
+ {(functionptr) builtin_lmul, "lmul"},
+ {(functionptr) builtin_ldiv, "ldiv"},
+ {(functionptr) new_builtin_ldiv, "ldiv"},
+ {(functionptr) builtin_lrem, "lrem"},
+ {(functionptr) new_builtin_lrem, "lrem"},
+ {(functionptr) builtin_lshl, "lshl"},
+ {(functionptr) builtin_lshr, "lshr"},
+ {(functionptr) builtin_lushr, "lushr"},
+ {(functionptr) builtin_land, "land"},
+ {(functionptr) builtin_lor, "lor"},
+ {(functionptr) builtin_lxor, "lxor"},
+ {(functionptr) builtin_lneg, "lneg"},
+ {(functionptr) builtin_lcmp, "lcmp"},
+ {(functionptr) builtin_fadd, "fadd"},
+ {(functionptr) builtin_fsub, "fsub"},
+ {(functionptr) builtin_fmul, "fmul"},
+ {(functionptr) builtin_fdiv, "fdiv"},
+ {(functionptr) builtin_frem, "frem"},
+ {(functionptr) builtin_fneg, "fneg"},
+ {(functionptr) builtin_fcmpl, "fcmpl"},
+ {(functionptr) builtin_fcmpg, "fcmpg"},
+ {(functionptr) builtin_dadd, "dadd"},
+ {(functionptr) builtin_dsub, "dsub"},
+ {(functionptr) builtin_dmul, "dmul"},
+ {(functionptr) builtin_ddiv, "ddiv"},
+ {(functionptr) builtin_drem, "drem"},
+ {(functionptr) builtin_dneg, "dneg"},
+ {(functionptr) builtin_dcmpl, "dcmpl"},
+ {(functionptr) builtin_dcmpg, "dcmpg"},
+ {(functionptr) builtin_i2l, "i2l"},
+ {(functionptr) builtin_i2f, "i2f"},
+ {(functionptr) builtin_i2d, "i2d"},
+ {(functionptr) builtin_l2i, "l2i"},
+ {(functionptr) builtin_l2f, "l2f"},
+ {(functionptr) builtin_l2d, "l2d"},
+ {(functionptr) builtin_f2i, "f2i"},
+ {(functionptr) builtin_f2l, "f2l"},
+ {(functionptr) builtin_f2d, "f2d"},
+ {(functionptr) builtin_d2i, "d2i"},
+ {(functionptr) builtin_d2l, "d2l"},
+ {(functionptr) builtin_d2f, "d2f"},
+ {(functionptr) NULL, "unknown"}
+ };
+
+
+/*****************************************************************************
+ TYPCHECKS
+*****************************************************************************/
+
+
+
+/*************** interne Funktion: builtin_isanysubclass *********************
+
+ "uberpr"uft, ob eine Klasse eine Unterklasse einer anderen Klasse ist.
+ Dabei gelten auch Interfaces, die eine Klasse implementiert, als
+ deren Oberklassen.
+ R"uckgabewert: 1 ... es trifft zu
+ 0 ... es trifft nicht zu
+
+*****************************************************************************/
+
+static s4 builtin_isanysubclass (classinfo *sub, classinfo *super)
+{
+ if (super->flags & ACC_INTERFACE) {
+ u4 index = super->index;
+/* if (sub->vftbl == NULL) return 0; */
+ if (index >= sub->vftbl->interfacetablelength) return 0;
+ return ( sub->vftbl->interfacevftbl[index] ) ? 1 : 0;
+ }
+ else {
+ while (sub) {
+ if (sub==super) return 1;
+ sub = sub->super;
+ }
+ return 0;
+ }
+}
+
+
+/****************** Funktion: builtin_instanceof *****************************
+
+ "Uberpr"uft, ob ein Objekt eine Instanz einer Klasse (oder einer davon
+ abgeleiteten Klasse) ist, oder ob die Klasse des Objekts ein Interface
+ implementiert.
+ Return: 1, wenn ja
+ 0, wenn nicht, oder wenn Objekt ein NULL-Zeiger
+
+*****************************************************************************/
+
+s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
+{
+#ifdef DEBUG
+ log_text ("builtin_instanceof called");
+#endif
+
+ if (!obj) return 0;
+ return builtin_isanysubclass (obj->vftbl->class, class);
+}
+
+
+
+/**************** Funktion: builtin_checkcast *******************************
+
+ "Uberpr"uft, ob ein Objekt eine Instanz einer Klasse (oder einer davon
+ abgeleiteten Klasse ist).
+ Unterschied zu builtin_instanceof: Ein NULL-Zeiger ist immer richtig
+ Return: 1, wenn ja, oder wenn Objekt ein NULL-Zeiger
+ 0, wenn nicht
+
+****************************************************************************/
+
+s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
+{
+#ifdef DEBUG
+ log_text ("builtin_checkcast called");
+#endif
+
+ if (!obj) return 1;
+ if ( builtin_isanysubclass (obj->vftbl->class, class) ) {
+ return 1;
+ }
+#if DEBUG
+ printf ("#### checkcast failed ");
+ unicode_display (obj->vftbl->class->name);
+ printf (" -> ");
+ unicode_display (class->name);
+ printf ("\n");
+#endif
+
+ return 0;
+}
+
+
+
+/*********** interne Funktion: builtin_descriptorscompatible ******************
+
+ "uberpr"uft, ob zwei Array-Typdescriptoren compartible sind, d.h.,
+ ob ein Array vom Typ 'desc' gefahrlos einer Variblen vom Typ 'target'
+ zugewiesen werden kann.
+ Return: 1, wenn ja
+ 0, wenn nicht
+
+******************************************************************************/
+
+static s4 builtin_descriptorscompatible
+ (constant_arraydescriptor *desc, constant_arraydescriptor *target)
+{
+ if (desc==target) return 1;
+ if (desc->arraytype != target->arraytype) return 0;
+ switch (target->arraytype) {
+ case ARRAYTYPE_OBJECT:
+ return builtin_isanysubclass (desc->objectclass, target->objectclass);
+ case ARRAYTYPE_ARRAY:
+ return builtin_descriptorscompatible
+ (desc->elementdescriptor, target->elementdescriptor);
+ default: return 1;
+ }
+}
+
+
+
+/******************** Funktion: builtin_checkarraycast ***********************
+
+ "uberpr"uft, ob ein gegebenes Objekt tats"achlich von einem
+ Untertyp des geforderten Arraytyps ist.
+ Dazu muss das Objekt auf jeden Fall ein Array sein.
+ Bei einfachen Arrays (int,short,double,etc.) muss der Typ genau
+ "ubereinstimmen.
+ Bei Arrays von Objekten muss der Elementtyp des tats"achlichen Arrays
+ ein Untertyp (oder der selbe Typ) vom geforderten Elementtyp sein.
+ Bei Arrays vom Arrays (die eventuell wieder Arrays von Arrays
+ sein k"onnen) m"ussen die untersten Elementtypen in der entsprechenden
+ Unterklassenrelation stehen.
+
+ Return: 1, wenn Cast in Ordung ist
+ 0, wenn es nicht geht
+
+ Achtung: ein Cast mit einem NULL-Zeiger geht immer gut.
+
+*****************************************************************************/
+
+s4 builtin_checkarraycast(java_objectheader *o, constant_arraydescriptor *desc)
+{
+ java_arrayheader *a = (java_arrayheader*) o;
+
+ if (!o) return 1;
+ if (o->vftbl->class != class_array) {
+ return 0;
+ }
+
+ if (a->arraytype != desc->arraytype) {
+ return 0;
+ }
+
+ switch (a->arraytype) {
+ case ARRAYTYPE_OBJECT: {
+ java_objectarray *oa = (java_objectarray*) o;
+ return builtin_isanysubclass (oa->elementtype, desc->objectclass);
+ }
+ case ARRAYTYPE_ARRAY: {
+ java_arrayarray *aa = (java_arrayarray*) o;
+ return builtin_descriptorscompatible
+ (aa->elementdescriptor, desc->elementdescriptor);
+ }
+ default:
+ return 1;
+ }
+}
+
+
+s4 builtin_arrayinstanceof
+ (java_objectheader *obj, constant_arraydescriptor *desc)
+{
+ if (!obj) return 1;
+ return builtin_checkarraycast (obj, desc);
+}
+
+
+/************************** exception functions *******************************
+
+******************************************************************************/
+
+java_objectheader *builtin_throw_exception (java_objectheader *exceptionptr) {
+ unicode_display (exceptionptr->vftbl->class->name);
+ printf ("\n");
+ fflush (stdout);
+ return exceptionptr;
+}
+
+
+/******************* Funktion: builtin_canstore *******************************
+
+ "uberpr"uft, ob ein Objekt in einem Array gespeichert werden
+ darf.
+ Return: 1, wenn es geht
+ 0, wenn nicht
+
+******************************************************************************/
+
+
+s4 builtin_canstore (java_objectarray *a, java_objectheader *o)
+{
+ if (!o) return 1;
+
+ switch (a->header.arraytype) {
+ case ARRAYTYPE_OBJECT:
+ if ( ! builtin_checkcast (o, a->elementtype) ) {
+ return 0;
+ }
+ return 1;
+ break;
+
+ case ARRAYTYPE_ARRAY:
+ if ( ! builtin_checkarraycast
+ (o, ((java_arrayarray*)a)->elementdescriptor) ) {
+ return 0;
+ }
+ return 1;
+ break;
+
+ default:
+ panic ("builtin_canstore called with invalid arraytype");
+ return 0;
+ }
+}
+
+
+
+/*****************************************************************************
+ ARRAYOPERATIONEN
+*****************************************************************************/
+
+
+
+/******************** Funktion: builtin_new **********************************
+
+ Legt ein neues Objekt einer Klasse am Heap an.
+ Return: Der Zeiger auf das Objekt, oder NULL, wenn kein Speicher
+ mehr frei ist.
+
+*****************************************************************************/
+
+java_objectheader *builtin_new (classinfo *c)
+{
+ java_objectheader *o;
+
+ o = heap_allocate ( c->instancesize, true, c->finalizer );
+ if (!o) return NULL;
+
+ memset (o, 0, c->instancesize);
+
+ o -> vftbl = c -> vftbl;
+ return o;
+}
+
+
+
+/******************** Funktion: builtin_anewarray ****************************
+
+ Legt ein Array von Zeigern auf Objekte am Heap an.
+ Parameter:
+ size ......... Anzahl der Elemente
+ elementtype .. ein Zeiger auf die classinfo-Struktur des Typs
+ der Elemente
+
+ Return: Zeiger auf das Array, oder NULL (wenn kein Speicher frei)
+
+*****************************************************************************/
+
+java_objectarray *builtin_anewarray (s4 size, classinfo *elementtype)
+{
+ s4 i;
+ java_objectarray *a;
+
+ a = heap_allocate ( sizeof(java_objectarray) + (size-1) * sizeof(void*),
+ true, 0 /* FALSE */ );
+ if (!a) return NULL;
+
+ a -> header.objheader.vftbl = class_array -> vftbl;
+ a -> header.size = size;
+ a -> header.arraytype = ARRAYTYPE_OBJECT;
+ a -> elementtype = elementtype;
+ for (i=0; i<size; i++) a->data[i] = NULL;
+ return a;
+}
+
+
+
+/******************** Funktion: builtin_newarray_array ***********************
+
+ Legt ein Array von Zeigern auf Arrays am Heap an.
+ Paramter: size ......... Anzahl der Elemente
+ elementdesc .. Zeiger auf die Arraybeschreibungs-Struktur f"ur
+ die Element-Arrays.
+
+ Return: Zeiger auf das Array, oder NULL
+
+*****************************************************************************/
+
+java_arrayarray *builtin_newarray_array
+ (s4 size, constant_arraydescriptor *elementdesc)
+{
+ s4 i;
+ java_arrayarray *a;
+
+ a = heap_allocate ( sizeof(java_arrayarray) + (size-1) * sizeof(void*),
+ true, NULL );
+ if (!a) return NULL;
+
+ a -> header.objheader.vftbl = class_array -> vftbl;
+ a -> header.size = size;
+ a -> header.arraytype = ARRAYTYPE_ARRAY;
+ a -> elementdescriptor = elementdesc;
+ for (i=0; i<size; i++) a->data[i] = NULL;
+ return a;
+}
+
+
+/******************** Funktion: builtin_newarray_boolean ************************
+
+ Legt ein Array von Bytes am Heap an, das allerdings als Boolean-Array
+ gekennzeichnet wird (wichtig bei Casts!)
+
+ Return: Zeiger auf das Array, oder NULL
+
+*****************************************************************************/
+
+java_booleanarray *builtin_newarray_boolean (s4 size)
+{
+ java_booleanarray *a;
+
+ a = heap_allocate ( sizeof(java_booleanarray) + (size-1) * sizeof(u1),
+ false, NULL );
+ if (!a) return NULL;
+
+ a -> header.objheader.vftbl = class_array -> vftbl;
+ a -> header.size = size;
+ a -> header.arraytype = ARRAYTYPE_BOOLEAN;
+ memset (a->data, 0, sizeof(u1) * size);
+
+ return a;
+}
+
+/******************** Funktion: builtin_newarray_char ************************
+
+ Legt ein Array von 16-bit-Integers am Heap an.
+ Return: Zeiger auf das Array, oder NULL
+
+*****************************************************************************/
+
+java_chararray *builtin_newarray_char (s4 size)
+{
+ java_chararray *a;
+
+ a = heap_allocate ( sizeof(java_chararray) + (size-1) * sizeof(u2),
+ false, NULL );
+ if (!a) return NULL;
+
+ a -> header.objheader.vftbl = class_array -> vftbl;
+ a -> header.size = size;
+ a -> header.arraytype = ARRAYTYPE_CHAR;
+ memset (a->data, 0, sizeof(u2) * size);
+
+ return a;
+}
+
+
+/******************** Funktion: builtin_newarray_float ***********************
+
+ Legt ein Array von 32-bit-IEEE-float am Heap an.
+ Return: Zeiger auf das Array, oder NULL
+
+*****************************************************************************/
+
+java_floatarray *builtin_newarray_float (s4 size)
+{
+ s4 i;
+ java_floatarray *a;
+
+ a = heap_allocate ( sizeof(java_floatarray) + (size-1) * sizeof(float),
+ false, NULL );
+ if (!a) return NULL;
+
+ a -> header.objheader.vftbl = class_array -> vftbl;
+ a -> header.size = size;
+ a -> header.arraytype = ARRAYTYPE_FLOAT;
+ for (i=0; i<size; i++) a->data[i] = 0.0;
+ return a;
+}
+
+
+/******************** Funktion: builtin_newarray_double ***********************
+
+ Legt ein Array von 64-bit-IEEE-float am Heap an.
+ Return: Zeiger auf das Array, oder NULL
+
+*****************************************************************************/
+
+java_doublearray *builtin_newarray_double (s4 size)
+{
+ s4 i;
+ java_doublearray *a;
+
+ a = heap_allocate ( sizeof(java_doublearray) + (size-1) * sizeof(double),
+ false, NULL );
+ if (!a) return NULL;
+
+ a -> header.objheader.vftbl = class_array -> vftbl;
+ a -> header.size = size;
+ a -> header.arraytype = ARRAYTYPE_DOUBLE;
+ for (i=0; i<size; i++) a->data[i] = 0.0;
+ return a;
+}
+
+
+
+
+/******************** Funktion: builtin_newarray_byte ***********************
+
+ Legt ein Array von 8-bit-Integers am Heap an.
+ Return: Zeiger auf das Array, oder NULL
+
+*****************************************************************************/
+
+java_bytearray *builtin_newarray_byte (s4 size)
+{
+ java_bytearray *a;
+
+ a = heap_allocate ( sizeof(java_bytearray) + (size-1) * sizeof(s1),
+ false, NULL );
+ if (!a) return NULL;
+
+ a -> header.objheader.vftbl = class_array->vftbl;
+ a -> header.size = size;
+ a -> header.arraytype = ARRAYTYPE_BYTE;
+ memset (a->data, 0, sizeof(u1) * size);
+ return a;
+}
+
+
+/******************** Funktion: builtin_newarray_short ***********************
+
+ Legt ein Array von 16-bit-Integers am Heap an.
+ Return: Zeiger auf das Array, oder NULL
+
+*****************************************************************************/
+
+java_shortarray *builtin_newarray_short (s4 size)
+{
+ java_shortarray *a;
+
+ a = heap_allocate ( sizeof(java_shortarray) + (size-1) * sizeof(s2),
+ false, NULL );
+ if (!a) return NULL;
+
+ a -> header.objheader.vftbl = class_array -> vftbl;
+ a -> header.size = size;
+ a -> header.arraytype = ARRAYTYPE_SHORT;
+ memset (a->data, 0, sizeof(s2) * size);
+ return a;
+}
+
+
+/******************** Funktion: builtin_newarray_int ***********************
+
+ Legt ein Array von 32-bit-Integers am Heap an.
+ Return: Zeiger auf das Array, oder NULL
+
+*****************************************************************************/
+
+java_intarray *builtin_newarray_int (s4 size)
+{
+ java_intarray *a;
+
+ a = heap_allocate ( sizeof(java_intarray) + (size-1) * sizeof(s4),
+ false, NULL );
+ if (!a) return NULL;
+
+ a -> header.objheader.vftbl = class_array -> vftbl;
+ a -> header.size = size;
+ a -> header.arraytype = ARRAYTYPE_INT;
+ memset (a->data, 0, sizeof(s4) * size);
+ return a;
+}
+
+
+/******************** Funktion: builtin_newarray_long ***********************
+
+ Legt ein Array von 64-bit-Integers am Heap an.
+ Return: Zeiger auf das Array, oder NULL
+
+*****************************************************************************/
+
+java_longarray *builtin_newarray_long (s4 size)
+{
+ java_longarray *a;
+
+ a = heap_allocate ( sizeof(java_longarray) + (size-1) * sizeof(s8),
+ false, NULL );
+ if (!a) return NULL;
+
+ a -> header.objheader.vftbl = class_array -> vftbl;
+ a -> header.size = size;
+ a -> header.arraytype = ARRAYTYPE_LONG;
+ memset (a->data, 0, sizeof(s8) * size);
+ return a;
+}
+
+
+
+/***************** Funktion: builtin_multianewarray ***************************
+
+ Legt ein mehrdimensionales Array am Heap an.
+ Die Gr"ossen der einzelnen Dimensionen werden in einem Integerarray
+ "ubergeben. Der Typ es zu erzeugenden Arrays wird als
+ Referenz auf eine constant_arraydescriptor - Struktur "ubergeben.
+
+ Return: Ein Zeiger auf das Array, oder NULL, wenn kein Speicher mehr
+ vorhanden ist.
+
+******************************************************************************/
+
+ /* Hilfsfunktion */
+
+static java_arrayheader *multianewarray_part (java_intarray *dims, int thisdim,
+ constant_arraydescriptor *desc)
+{
+ u4 size,i;
+ java_arrayarray *a;
+
+ size = dims -> data[thisdim];
+
+ if (thisdim == (dims->header.size-1)) {
+ /* letzte Dimension schon erreicht */
+
+ switch (desc -> arraytype) {
+ case ARRAYTYPE_BOOLEAN:
+ return (java_arrayheader*) builtin_newarray_boolean (size);
+ case ARRAYTYPE_CHAR:
+ return (java_arrayheader*) builtin_newarray_char (size);
+ case ARRAYTYPE_FLOAT:
+ return (java_arrayheader*) builtin_newarray_float (size);
+ case ARRAYTYPE_DOUBLE:
+ return (java_arrayheader*) builtin_newarray_double (size);
+ case ARRAYTYPE_BYTE:
+ return (java_arrayheader*) builtin_newarray_byte (size);
+ case ARRAYTYPE_SHORT:
+ return (java_arrayheader*) builtin_newarray_short (size);
+ case ARRAYTYPE_INT:
+ return (java_arrayheader*) builtin_newarray_int (size);
+ case ARRAYTYPE_LONG:
+ return (java_arrayheader*) builtin_newarray_long (size);
+ case ARRAYTYPE_OBJECT:
+ return (java_arrayheader*) builtin_anewarray (size, desc->objectclass);
+
+ case ARRAYTYPE_ARRAY:
+ return (java_arrayheader*) builtin_newarray_array (size, desc->elementdescriptor);
+
+ default: panic ("Invalid arraytype in multianewarray");
+ }
+ }
+
+ /* wenn letzte Dimension noch nicht erreicht wurde */
+
+ if (desc->arraytype != ARRAYTYPE_ARRAY)
+ panic ("multianewarray with too many dimensions");
+
+ a = builtin_newarray_array (size, desc->elementdescriptor);
+ if (!a) return NULL;
+
+ for (i=0; i<size; i++) {
+ java_arrayheader *ea =
+ multianewarray_part (dims, thisdim+1, desc->elementdescriptor);
+ if (!ea) return NULL;
+
+ a -> data[i] = ea;
+ }
+
+ return (java_arrayheader*) a;
+}
+
+
+java_arrayheader *builtin_multianewarray (java_intarray *dims,
+ constant_arraydescriptor *desc)
+{
+ return multianewarray_part (dims, 0, desc);
+}
+
+
+static java_arrayheader *nmultianewarray_part (int n, long *dims, int thisdim,
+ constant_arraydescriptor *desc)
+{
+ int size, i;
+ java_arrayarray *a;
+
+ size = (int) dims[thisdim];
+
+ if (thisdim == (n - 1)) {
+ /* letzte Dimension schon erreicht */
+
+ switch (desc -> arraytype) {
+ case ARRAYTYPE_BOOLEAN:
+ return (java_arrayheader*) builtin_newarray_boolean(size);
+ case ARRAYTYPE_CHAR:
+ return (java_arrayheader*) builtin_newarray_char(size);
+ case ARRAYTYPE_FLOAT:
+ return (java_arrayheader*) builtin_newarray_float(size);
+ case ARRAYTYPE_DOUBLE:
+ return (java_arrayheader*) builtin_newarray_double(size);
+ case ARRAYTYPE_BYTE:
+ return (java_arrayheader*) builtin_newarray_byte(size);
+ case ARRAYTYPE_SHORT:
+ return (java_arrayheader*) builtin_newarray_short(size);
+ case ARRAYTYPE_INT:
+ return (java_arrayheader*) builtin_newarray_int(size);
+ case ARRAYTYPE_LONG:
+ return (java_arrayheader*) builtin_newarray_long(size);
+ case ARRAYTYPE_OBJECT:
+ return (java_arrayheader*) builtin_anewarray(size,
+ desc->objectclass);
+ case ARRAYTYPE_ARRAY:
+ return (java_arrayheader*) builtin_newarray_array(size,
+ desc->elementdescriptor);
+
+ default: panic ("Invalid arraytype in multianewarray");
+ }
+ }
+
+ /* wenn letzte Dimension noch nicht erreicht wurde */
+
+ if (desc->arraytype != ARRAYTYPE_ARRAY)
+ panic ("multianewarray with too many dimensions");
+
+ a = builtin_newarray_array(size, desc->elementdescriptor);
+ if (!a) return NULL;
+
+ for (i = 0; i < size; i++) {
+ java_arrayheader *ea =
+ nmultianewarray_part(n, dims, thisdim + 1, desc->elementdescriptor);
+ if (!ea) return NULL;
+
+ a -> data[i] = ea;
+ }
+
+ return (java_arrayheader*) a;
+}
+
+
+java_arrayheader *builtin_nmultianewarray (int size,
+ constant_arraydescriptor *desc, long *dims)
+{
+ (void) builtin_newarray_int(size); /* for compatibility with -old */
+ return nmultianewarray_part (size, dims, 0, desc);
+}
+
+
+
+
+/************************* Funktion: builtin_aastore *************************
+
+ speichert eine Referenz auf ein Objekt in einem Object-Array oder
+ in einem Array-Array.
+ Dabei wird allerdings vorher "uberpr"uft, ob diese Operation
+ zul"assig ist.
+
+ Return: 1, wenn alles OK ist
+ 0, wenn dieses Objekt nicht in dieses Array gespeichert werden
+ darf
+
+*****************************************************************************/
+
+s4 builtin_aastore (java_objectarray *a, s4 index, java_objectheader *o)
+{
+ if (builtin_canstore(a,o)) {
+ a->data[index] = o;
+ return 1;
+ }
+ return 0;
+}
+
+
+
+
+
+
+/*****************************************************************************
+ METHODEN-PROTOKOLLIERUNG
+
+ Verschiedene Funktionen, mit denen eine Meldung ausgegeben werden
+ kann, wann immer Methoden aufgerufen oder beendet werden.
+ (f"ur Debug-Zwecke)
+
+*****************************************************************************/
+
+
+u4 methodindent=0;
+
+java_objectheader *builtin_trace_exception (java_objectheader *exceptionptr,
+ methodinfo *method, int *pos, int noindent) {
+
+ if (!noindent)
+ methodindent--;
+ if (verbose || runverbose) {
+ printf("Exception ");
+ unicode_display (exceptionptr->vftbl->class->name);
+ printf(" thrown in ");
+ if (method) {
+ unicode_display (method->class->name);
+ printf(".");
+ unicode_display (method->name);
+ if (method->flags & ACC_SYNCHRONIZED)
+ printf("(SYNC)");
+ else
+ printf("(NOSYNC)");
+ printf("(%p) at position %p\n", method->entrypoint, pos);
+ }
+ else
+ printf("call_java_method\n");
+ fflush (stdout);
+ }
+ return exceptionptr;
+}
+
+
+void builtin_trace_args(long a0, long a1, long a2, long a3, long a4, long a5,
+ methodinfo *method)
+{
+ sprintf (logtext, " ");
+ sprintf (logtext+methodindent, "called: ");
+ unicode_sprint (logtext+strlen(logtext), method->class->name);
+ sprintf (logtext+strlen(logtext), ".");
+ unicode_sprint (logtext+strlen(logtext), method->name);
+ unicode_sprint (logtext+strlen(logtext), method->descriptor);
+ sprintf (logtext+strlen(logtext), "(");
+ switch (method->paramcount) {
+ case 6:
+ sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
+ a0, a1, a2, a3, a4, a5);
+ break;
+ case 5:
+ sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
+ a0, a1, a2, a3, a4);
+ break;
+ case 4:
+ sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
+ a0, a1, a2, a3);
+ break;
+ case 3:
+ sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0, a1, a2);
+ break;
+ case 2:
+ sprintf(logtext+strlen(logtext), "%lx, %lx", a0, a1);
+ break;
+ case 1:
+ sprintf(logtext+strlen(logtext), "%lx", a0);
+ break;
+ }
+ sprintf (logtext+strlen(logtext), ")");
+
+ dolog ();
+ methodindent++;
+}
+
+void builtin_displaymethodstart(methodinfo *method)
+{
+ sprintf (logtext, " ");
+ sprintf (logtext+methodindent, "called: ");
+ unicode_sprint (logtext+strlen(logtext), method->class->name);
+ sprintf (logtext+strlen(logtext), ".");
+ unicode_sprint (logtext+strlen(logtext), method->name);
+ unicode_sprint (logtext+strlen(logtext), method->descriptor);
+ dolog ();
+ methodindent++;
+}
+
+void builtin_displaymethodstop(methodinfo *method, long l, double d)
+{
+ methodindent--;
+ sprintf (logtext, " ");
+ sprintf (logtext+methodindent, "finished: ");
+ unicode_sprint (logtext+strlen(logtext), method->class->name);
+ sprintf (logtext+strlen(logtext), ".");
+ unicode_sprint (logtext+strlen(logtext), method->name);
+ unicode_sprint (logtext+strlen(logtext), method->descriptor);
+ switch (method->returntype) {
+ case TYPE_INT:
+ case TYPE_LONG:
+ sprintf (logtext+strlen(logtext), "->%ld", l);
+ break;
+ case TYPE_FLOAT:
+ case TYPE_DOUBLE:
+ sprintf (logtext+strlen(logtext), "->%g", d);
+ break;
+ case TYPE_ADDRESS:
+ sprintf (logtext+strlen(logtext), "->%p", (void*) l);
+ break;
+ }
+ dolog ();
+}
+
+void builtin_displaymethodexception(methodinfo *method)
+{
+ sprintf (logtext, " ");
+ sprintf (logtext+methodindent, "exception abort: ");
+ unicode_sprint (logtext+strlen(logtext), method->class->name);
+ sprintf (logtext+strlen(logtext), ".");
+ unicode_sprint (logtext+strlen(logtext), method->name);
+ unicode_sprint (logtext+strlen(logtext), method->descriptor);
+ dolog ();
+}
+
+
+/****************************************************************************
+ SYNCHRONIZATION FUNCTIONS
+*****************************************************************************/
+
+/*
+ * Lock the mutex of an object.
+ */
+#ifdef USE_THREADS
+void
+internal_lock_mutex_for_object (java_objectheader *object)
+{
+ mutexHashEntry *entry;
+ int hashValue;
+
+ assert(object != 0);
+
+ hashValue = MUTEX_HASH_VALUE(object);
+ entry = &mutexHashTable[hashValue];
+
+ if (entry->object != 0)
+ {
+ if (entry->mutex.count == 0 && entry->conditionCount == 0)
+ {
+ entry->object = 0;
+ entry->mutex.holder = 0;
+ entry->mutex.count = 0;
+ entry->mutex.muxWaiters = 0;
+ }
+ else
+ {
+ while (entry->next != 0 && entry->object != object)
+ entry = entry->next;
+
+ if (entry->object != object)
+ {
+ entry->next = firstFreeOverflowEntry;
+ firstFreeOverflowEntry = firstFreeOverflowEntry->next;
+
+ entry = entry->next;
+ entry->object = 0;
+ entry->next = 0;
+ assert(entry->conditionCount == 0);
+ }
+ }
+ }
+ else
+ {
+ entry->mutex.holder = 0;
+ entry->mutex.count = 0;
+ entry->mutex.muxWaiters = 0;
+ }
+
+ if (entry->object == 0)
+ entry->object = object;
+
+ internal_lock_mutex(&entry->mutex);
+}
+#endif
+
+
+/*
+ * Unlocks the mutex of an object.
+ */
+#ifdef USE_THREADS
+void
+internal_unlock_mutex_for_object (java_objectheader *object)
+{
+ int hashValue;
+ mutexHashEntry *entry;
+
+ hashValue = MUTEX_HASH_VALUE(object);
+ entry = &mutexHashTable[hashValue];
+
+ if (entry->object == object)
+ internal_unlock_mutex(&entry->mutex);
+ else
+ {
+ while (entry->next != 0 && entry->next->object != object)
+ entry = entry->next;
+
+ assert(entry->next != 0);
+
+ internal_unlock_mutex(&entry->next->mutex);
+
+ if (entry->next->mutex.count == 0 && entry->conditionCount == 0)
+ {
+ mutexHashEntry *unlinked = entry->next;
+
+ entry->next = unlinked->next;
+ unlinked->next = firstFreeOverflowEntry;
+ firstFreeOverflowEntry = unlinked;
+ }
+ }
+}
+#endif
+
+void
+builtin_monitorenter (java_objectheader *o)
+{
+#ifdef USE_THREADS
+ int hashValue;
+
+ assert(blockInts == 0);
+
+ ++blockInts;
+
+ hashValue = MUTEX_HASH_VALUE(o);
+ if (mutexHashTable[hashValue].object == o
+ && mutexHashTable[hashValue].mutex.holder == currentThread)
+ ++mutexHashTable[hashValue].mutex.count;
+ else
+ internal_lock_mutex_for_object(o);
+
+ --blockInts;
+
+ assert(blockInts == 0);
+#endif
+}
+
+void builtin_monitorexit (java_objectheader *o)
+{
+#ifdef USE_THREADS
+ int hashValue;
+
+ assert(blockInts == 0);
+
+ ++blockInts;
+
+ hashValue = MUTEX_HASH_VALUE(o);
+ if (mutexHashTable[hashValue].object == o)
+ {
+ if (mutexHashTable[hashValue].mutex.count == 1
+ && mutexHashTable[hashValue].mutex.muxWaiters != 0)
+ internal_unlock_mutex_for_object(o);
+ else
+ --mutexHashTable[hashValue].mutex.count;
+ }
+ else
+ internal_unlock_mutex_for_object(o);
+
+ --blockInts;
+
+ assert(blockInts == 0);
+#endif
+}
+
+
+/*****************************************************************************
+ DIVERSE HILFSFUNKTIONEN
+*****************************************************************************/
+
+
+
+/*********** Funktionen f"ur die Integerdivision *****************************
+
+ Auf manchen Systemen (z.B. DEC ALPHA) wird durch die CPU keine Integer-
+ division unterst"utzt.
+ Daf"ur gibt es dann diese Hilfsfunktionen
+
+******************************************************************************/
+
+s4 builtin_idiv (s4 a, s4 b) { return a/b; }
+s4 builtin_irem (s4 a, s4 b) { return a%b; }
+
+
+/************** Funktionen f"ur Long-Arithmetik *******************************
+
+ Auf Systemen, auf denen die CPU keine 64-Bit-Integers unterst"utzt,
+ werden diese Funktionen gebraucht
+
+******************************************************************************/
+
+
+s8 builtin_ladd (s8 a, s8 b)
+{
+#if U8_AVAILABLE
+ return a+b;
+#else
+ return builtin_i2l(0);
+#endif
+}
+
+s8 builtin_lsub (s8 a, s8 b)
+{
+#if U8_AVAILABLE
+ return a-b;
+#else
+ return builtin_i2l(0);
+#endif
+}
+
+s8 builtin_lmul (s8 a, s8 b)
+{
+#if U8_AVAILABLE
+ return a*b;
+#else
+ return builtin_i2l(0);
+#endif
+}
+
+s8 builtin_ldiv (s8 a, s8 b)
+{
+#if U8_AVAILABLE
+ return a/b;
+#else
+ return builtin_i2l(0);
+#endif
+}
+
+s8 builtin_lrem (s8 a, s8 b)
+{
+#if U8_AVAILABLE
+ return a%b;
+#else
+ return builtin_i2l(0);
+#endif
+}
+
+s8 builtin_lshl (s8 a, s4 b)
+{
+#if U8_AVAILABLE
+ return a<<(b&63);
+#else
+ return builtin_i2l(0);
+#endif
+}
+
+s8 builtin_lshr (s8 a, s4 b)
+{
+#if U8_AVAILABLE
+ return a>>(b&63);
+#else
+ return builtin_i2l(0);
+#endif
+}
+
+s8 builtin_lushr (s8 a, s4 b)
+{
+#if U8_AVAILABLE
+ return ((u8)a)>>(b&63);
+#else
+ return builtin_i2l(0);
+#endif
+}
+
+s8 builtin_land (s8 a, s8 b)
+{
+#if U8_AVAILABLE
+ return a&b;
+#else
+ return builtin_i2l(0);
+#endif
+}
+
+s8 builtin_lor (s8 a, s8 b)
+{
+#if U8_AVAILABLE
+ return a|b;
+#else
+ return builtin_i2l(0);
+#endif
+}
+
+s8 builtin_lxor (s8 a, s8 b)
+{
+#if U8_AVAILABLE
+ return a^b;
+#else
+ return builtin_i2l(0);
+#endif
+}
+
+s8 builtin_lneg (s8 a)
+{
+#if U8_AVAILABLE
+ return -a;
+#else
+ return builtin_i2l(0);
+#endif
+}
+
+s4 builtin_lcmp (s8 a, s8 b)
+{
+#if U8_AVAILABLE
+ if (a<b) return -1;
+ if (a>b) return 1;
+ return 0;
+#else
+ return 0;
+#endif
+}
+
+
+
+
+
+/*********** Funktionen f"ur die Floating-Point-Operationen ******************/
+
+float builtin_fadd (float a, float b)
+{
+ if (isnanf(a)) return FLT_NAN;
+ if (isnanf(b)) return FLT_NAN;
+ if (finitef(a)) {
+ if (finitef(b)) return a+b;
+ else return b;
+ }
+ else {
+ if (finitef(b)) return a;
+ else {
+ if (copysignf(1.0, a)==copysignf(1.0, b)) return a;
+ else return FLT_NAN;
+ }
+ }
+}
+
+float builtin_fsub (float a, float b)
+{
+ return builtin_fadd (a, builtin_fneg(b));
+}
+
+float builtin_fmul (float a, float b)
+{
+ if (isnanf(a)) return FLT_NAN;
+ if (isnanf(b)) return FLT_NAN;
+ if (finitef(a)) {
+ if (finitef(b)) return a*b;
+ else {
+ if (a==0) return FLT_NAN;
+ else return copysignf(b, copysignf(1.0, b)*a);
+ }
+ }
+ else {
+ if (finitef(b)) {
+ if (b==0) return FLT_NAN;
+ else return copysignf(a, copysignf(1.0, a)*b);
+ }
+ else {
+ return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
+ }
+ }
+}
+
+float builtin_fdiv (float a, float b)
+{
+ if (finitef(a) && finitef(b)) {
+ if (b != 0)
+ return a / b;
+ else {
+ if (a > 0)
+ return FLT_POSINF;
+ else if (a < 0)
+ return FLT_NEGINF;
+ }
+ }
+ return FLT_NAN;
+}
+
+float builtin_frem (float a, float b)
+{
+
+/* return (float) builtin_drem((double) a, (double) b); */
+
+ float f;
+
+ if (finite((double) a) && finite((double) b)) {
+ f = a / b;
+ if (finite((double) f))
+ return fmodf(a, b);
+ return FLT_NAN;
+ }
+ if (isnan((double) b))
+ return FLT_NAN;
+ if (finite((double) a))
+ return a;
+ return FLT_NAN;
+
+/* float f;
+
+ if (finitef(a) && finitef(b)) {
+ f = a / b;
+ if (finitef(f))
+ return a - floorf(f) * b;
+ return FLT_NAN;
+ }
+ if (isnanf(b))
+ return FLT_NAN;
+ if (finitef(a))
+ return a;
+ return FLT_NAN; */
+}
+
+
+float builtin_fneg (float a)
+{
+ if (isnanf(a)) return a;
+ else {
+ if (finitef(a)) return -a;
+ else return copysignf(a,-copysignf(1.0, a));
+ }
+}
+
+s4 builtin_fcmpl (float a, float b)
+{
+ if (isnanf(a)) return -1;
+ if (isnanf(b)) return -1;
+ if (!finitef(a) || !finitef(b)) {
+ a = finitef(a) ? 0 : copysignf(1.0, a);
+ b = finitef(b) ? 0 : copysignf(1.0, b);
+ }
+ if (a>b) return 1;
+ if (a==b) return 0;
+ return -1;
+}
+
+s4 builtin_fcmpg (float a, float b)
+{
+ if (isnanf(a)) return 1;
+ if (isnanf(b)) return 1;
+ if (!finitef(a) || !finitef(b)) {
+ a = finitef(a) ? 0 : copysignf(1.0, a);
+ b = finitef(b) ? 0 : copysignf(1.0, b);
+ }
+ if (a>b) return 1;
+ if (a==b) return 0;
+ return -1;
+}
+
+
+
+/*********** Funktionen f"ur doppelt genaue Fliesskommazahlen ***************/
+
+double builtin_dadd (double a, double b)
+{
+ if (isnan(a)) return DBL_NAN;
+ if (isnan(b)) return DBL_NAN;
+ if (finite(a)) {
+ if (finite(b)) return a+b;
+ else return b;
+ }
+ else {
+ if (finite(b)) return a;
+ else {
+ if (copysign(1.0, a)==copysign(1.0, b)) return a;
+ else return DBL_NAN;
+ }
+ }
+}
+
+double builtin_dsub (double a, double b)
+{
+ return builtin_dadd (a, builtin_dneg(b));
+}
+
+double builtin_dmul (double a, double b)
+{
+ if (isnan(a)) return DBL_NAN;
+ if (isnan(b)) return DBL_NAN;
+ if (finite(a)) {
+ if (finite(b)) return a*b;
+ else {
+ if (a==0) return DBL_NAN;
+ else return copysign(b, copysign(1.0, b)*a);
+ }
+ }
+ else {
+ if (finite(b)) {
+ if (b==0) return DBL_NAN;
+ else return copysign(a, copysign(1.0, a)*b);
+ }
+ else {
+ return copysign(a, copysign(1.0, a)*copysign(1.0, b));
+ }
+ }
+}
+
+double builtin_ddiv (double a, double b)
+{
+ if (finite(a) && finite(b)) {
+ if (b != 0)
+ return a / b;
+ else {
+ if (a > 0)
+ return DBL_POSINF;
+ else if (a < 0)
+ return DBL_NEGINF;
+ }
+ }
+ return DBL_NAN;
+}
+
+double builtin_drem (double a, double b)
+{
+ double d;
+
+ if (finite(a) && finite(b)) {
+ d = a / b;
+ if (finite(d)) {
+ if ((d < 1.0) && (d > 0.0))
+ return a;
+ return fmod(a, b);
+ }
+ return DBL_NAN;
+ }
+ if (isnan(b))
+ return DBL_NAN;
+ if (finite(a))
+ return a;
+ return DBL_NAN;
+}
+
+double builtin_dneg (double a)
+{
+ if (isnan(a)) return a;
+ else {
+ if (finite(a)) return -a;
+ else return copysign(a,-copysign(1.0, a));
+ }
+}
+
+s4 builtin_dcmpl (double a, double b)
+{
+ if (isnan(a)) return -1;
+ if (isnan(b)) return -1;
+ if (!finite(a) || !finite(b)) {
+ a = finite(a) ? 0 : copysign(1.0, a);
+ b = finite(b) ? 0 : copysign(1.0, b);
+ }
+ if (a>b) return 1;
+ if (a==b) return 0;
+ return -1;
+}
+
+s4 builtin_dcmpg (double a, double b)
+{
+ if (isnan(a)) return 1;
+ if (isnan(b)) return 1;
+ if (!finite(a) || !finite(b)) {
+ a = finite(a) ? 0 : copysign(1.0, a);
+ b = finite(b) ? 0 : copysign(1.0, b);
+ }
+ if (a>b) return 1;
+ if (a==b) return 0;
+ return -1;
+}
+
+
+/*********************** Umwandlungsoperationen ****************************/
+
+s8 builtin_i2l (s4 i)
+{
+#if U8_AVAILABLE
+ return i;
+#else
+ s8 v; v.high = 0; v.low=i; return v;
+#endif
+}
+
+float builtin_i2f (s4 a)
+{
+float f = (float) a;
+return f;
+}
+
+double builtin_i2d (s4 a)
+{
+double d = (double) a;
+return d;
+}
+
+
+s4 builtin_l2i (s8 l)
+{
+#if U8_AVAILABLE
+ return (s4) l;
+#else
+ return l.low;
+#endif
+}
+
+float builtin_l2f (s8 a)
+{
+#if U8_AVAILABLE
+ float f = (float) a;
+ return f;
+#else
+ return 0.0;
+#endif
+}
+
+double builtin_l2d (s8 a)
+{
+#if U8_AVAILABLE
+ double d = (double) a;
+ return d;
+#else
+ return 0.0;
+#endif
+}
+
+
+s4 builtin_f2i(float a)
+{
+
+return builtin_d2i((double) a);
+
+/* float f;
+
+ if (isnanf(a))
+ return 0;
+ if (finitef(a)) {
+ if (a > 2147483647)
+ return 2147483647;
+ if (a < (-2147483648))
+ return (-2147483648);
+ return (s4) a;
+ }
+ f = copysignf((float) 1.0, a);
+ if (f > 0)
+ return 2147483647;
+ return (-2147483648); */
+}
+
+
+s8 builtin_f2l (float a)
+{
+
+return builtin_d2l((double) a);
+
+/* float f;
+
+ if (finitef(a)) {
+ if (a > 9223372036854775807L)
+ return 9223372036854775807L;
+ if (a < (-9223372036854775808L))
+ return (-9223372036854775808L);
+ return (s8) a;
+ }
+ if (isnanf(a))
+ return 0;
+ f = copysignf((float) 1.0, a);
+ if (f > 0)
+ return 9223372036854775807L;
+ return (-9223372036854775808L); */
+}
+
+
+double builtin_f2d (float a)
+{
+ if (finitef(a)) return (double) a;
+ else {
+ if (isnanf(a)) return DBL_NAN;
+ else return copysign(DBL_POSINF, (double) copysignf(1.0, a) );
+ }
+}
+
+
+s4 builtin_d2i (double a)
+{
+ double d;
+
+ if (finite(a)) {
+ if (a >= 2147483647)
+ return 2147483647;
+ if (a <= (-2147483648))
+ return (-2147483648);
+ return (s4) a;
+ }
+ if (isnan(a))
+ return 0;
+ d = copysign(1.0, a);
+ if (d > 0)
+ return 2147483647;
+ return (-2147483648);
+}
+
+
+s8 builtin_d2l (double a)
+{
+ double d;
+
+ if (finite(a)) {
+ if (a >= 9223372036854775807L)
+ return 9223372036854775807L;
+ if (a <= (-9223372036854775807L-1))
+ return (-9223372036854775807L-1);
+ return (s8) a;
+ }
+ if (isnan(a))
+ return 0;
+ d = copysign(1.0, a);
+ if (d > 0)
+ return 9223372036854775807L;
+ return (-9223372036854775807L-1);
+}
+
+
+float builtin_d2f (double a)
+{
+ if (finite(a)) return (float) a;
+ else {
+ if (isnan(a)) return FLT_NAN;
+ else return copysignf (FLT_POSINF, (float) copysign(1.0, a));
+ }
+}
+
--- /dev/null
+/****************************** builtin.h **************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Contains the prototypes for the functions of file builtin.c which has
+ a more detailed description.
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1996/11/14
+
+*******************************************************************************/
+
+
+/***************************** Prototypes *************************************/
+
+typedef struct builtin_descriptor {
+ functionptr bptr;
+ char *name;
+ } builtin_descriptor;
+
+extern builtin_descriptor builtin_desc[];
+
+s4 builtin_instanceof(java_objectheader *obj, classinfo *class);
+s4 builtin_checkcast(java_objectheader *obj, classinfo *class);
+s4 new_builtin_checkcast(java_objectheader *obj, classinfo *class);
+s4 builtin_arrayinstanceof
+ (java_objectheader *obj, constant_arraydescriptor *desc);
+s4 builtin_checkarraycast
+ (java_objectheader *obj, constant_arraydescriptor *desc);
+s4 new_builtin_checkarraycast
+ (java_objectheader *obj, constant_arraydescriptor *desc);
+
+java_objectheader *builtin_throw_exception (java_objectheader *exception);
+java_objectheader *builtin_trace_exception (java_objectheader *exceptionptr,
+ methodinfo *method, int *pos, int noindent);
+
+java_objectheader *builtin_new (classinfo *c);
+
+
+java_objectarray *builtin_anewarray (s4 size, classinfo *elementtype);
+java_arrayarray *builtin_newarray_array
+ (s4 size, constant_arraydescriptor *elementdesc);
+java_booleanarray *builtin_newarray_boolean (s4 size);
+java_chararray *builtin_newarray_char (s4 size);
+java_floatarray *builtin_newarray_float (s4 size);
+java_doublearray *builtin_newarray_double (s4 size);
+java_bytearray *builtin_newarray_byte (s4 size);
+java_shortarray *builtin_newarray_short (s4 size);
+java_intarray *builtin_newarray_int (s4 size);
+java_longarray *builtin_newarray_long (s4 size);
+java_arrayheader *builtin_multianewarray (java_intarray *dims,
+ constant_arraydescriptor *desc);
+java_arrayheader *builtin_nmultianewarray (int size,
+ constant_arraydescriptor *desc, long *dims);
+
+s4 builtin_canstore (java_objectarray *a, java_objectheader *o);
+s4 builtin_aastore (java_objectarray *a, s4 index, java_objectheader *o);
+void new_builtin_aastore (java_objectarray *a, s4 index, java_objectheader *o);
+
+void builtin_trace_args(long a0, long a1, long a2, long a3, long a4, long a5, methodinfo *method);
+void builtin_displaymethodstart(methodinfo *method);
+void builtin_displaymethodstop(methodinfo *method, long l, double d);
+/* void builtin_displaymethodstop(methodinfo *method); */
+void builtin_displaymethodexception(methodinfo *method);
+
+void builtin_monitorenter (java_objectheader *o);
+void new_builtin_monitorenter (java_objectheader *o);
+void builtin_monitorexit (java_objectheader *o);
+void new_builtin_monitorexit (java_objectheader *o);
+
+s4 builtin_idiv (s4 a, s4 b);
+s4 new_builtin_idiv (s4 a, s4 b);
+s4 builtin_irem (s4 a, s4 b);
+s4 new_builtin_irem (s4 a, s4 b);
+
+s8 builtin_ladd (s8 a, s8 b);
+s8 builtin_lsub (s8 a, s8 b);
+s8 builtin_lmul (s8 a, s8 b);
+s8 builtin_ldiv (s8 a, s8 b);
+s8 new_builtin_ldiv (s8 a, s8 b);
+s8 builtin_lrem (s8 a, s8 b);
+s8 new_builtin_lrem (s8 a, s8 b);
+s8 builtin_lshl (s8 a, s4 b);
+s8 builtin_lshr (s8 a, s4 b);
+s8 builtin_lushr (s8 a, s4 b);
+s8 builtin_land (s8 a, s8 b);
+s8 builtin_lor (s8 a, s8 b);
+s8 builtin_lxor (s8 a, s8 b);
+s8 builtin_lneg (s8 a);
+s4 builtin_lcmp (s8 a, s8 b);
+
+float builtin_fadd (float a, float b);
+float builtin_fsub (float a, float b);
+float builtin_fmul (float a, float b);
+float builtin_fdiv (float a, float b);
+float builtin_frem (float a, float b);
+float builtin_fneg (float a);
+s4 builtin_fcmpl (float a, float b);
+s4 builtin_fcmpg (float a, float b);
+
+double builtin_dadd (double a, double b);
+double builtin_dsub (double a, double b);
+double builtin_dmul (double a, double b);
+double builtin_ddiv (double a, double b);
+double builtin_drem (double a, double b);
+double builtin_dneg (double a);
+s4 builtin_dcmpl (double a, double b);
+s4 builtin_dcmpg (double a, double b);
+
+s8 builtin_i2l (s4 i);
+float builtin_i2f (s4 i);
+double builtin_i2d (s4 i);
+s4 builtin_l2i (s8 l);
+float builtin_l2f (s8 l);
+double builtin_l2d (s8 l);
+s4 builtin_f2i (float a);
+s8 builtin_f2l (float a);
+double builtin_f2d (float a);
+s4 builtin_d2i (double a);
+s8 builtin_d2l (double a);
+float builtin_d2f (double a);
+
--- /dev/null
+#define TRACECALLARGS
--- /dev/null
+/***************************** comp/block.c ************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Basic block handling functions.
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1997/01/18
+
+*******************************************************************************/
+
+
+static u2 creatornum; /* Fortlaufende Nummerierung f"ur vom Compiler
+ generierte BasicBlocks (nur zu Debug-Zwecken) */
+
+static subroutineinfo *actual_subroutine;
+static u2 subroutinecounter=0;
+
+
+/********************** Funktion: block_new ***********************************
+
+ erzeugt eine neue 'basicblock'-Struktur und initialisiert alle
+ Komponenten
+
+******************************************************************************/
+
+static basicblock *block_new (u2 type, u4 codepos)
+{
+ basicblock *b = DNEW (basicblock);
+
+ b -> type = type;
+ b -> reached = false;
+ b -> finished = false;
+ b -> subroutine = NULL;
+ b -> jpc = codepos;
+ b -> stack = NULL;
+ list_init (&(b->pcmdlist), OFFSET (pcmd, linkage) );
+ b -> mpc = 0;
+
+ b -> exproto = NULL;
+ b -> throwpos = 0;
+ return b;
+}
+
+
+
+/******************* Funktion: block_find *************************************
+
+ Sucht den Basicblock, der an einer gew"unschten Stelle im JavaVM-Code
+ anf"angt.
+ Wenn dort kein Block anf"angt -> Fehler
+
+******************************************************************************/
+
+static basicblock *block_find (u4 codepos)
+{
+ basicblock *b = blocks[codepos];
+ if (!b) panic ("Accessed JAVA-Command on no block boundary");
+ return b;
+}
+
+
+/****************** Funktion: block_isany *************************************
+
+ "uberpr"uft, ob an einer Stelle ein Basicblock anf"angt
+
+******************************************************************************/
+
+static bool block_isany (u4 codepos)
+{
+ return (blocks[codepos] != NULL);
+}
+
+
+/***************** Funktion: block_reach **************************************
+
+ H"angt einen Basicblock in die Liste der schon erreichten Bl"ocke ein,
+ und setzt seinen Blockeintrittsstack auf den aktuellen Stack und
+ setzt den Unterprogramminfoblock auf das aktuelle Unterprogramminfo
+
+ Wenn der Block bereits vorher als erreicht markiert war (und er deshalb
+ schon einen definierten Stack hatte), dann wird im derzeit vom
+ Parser durchlaufenen Block (also dort, von wo dieser Block aus
+ angesprungen wird) ein entsprechende Codest"uck hinzugef"ugt, der
+ die beiden Stacks aufeinander abstimmt.
+
+******************************************************************************/
+
+static void block_reach (basicblock *b)
+{
+ if (!b->reached) {
+ list_addlast (&reachedblocks, b);
+ b -> reached = true;
+ b -> subroutine = actual_subroutine;
+ b -> stack = stack_get();
+ }
+ else {
+ if (b->subroutine != actual_subroutine)
+ panic ("Try to merge different subroutines");
+ stack_addjoincode (b->stack);
+ }
+}
+
+/*********************** Funktion: subroutine_set *****************************
+
+ setzt den aktuellen Subroutine-Infoblock
+
+*******************************************************************************/
+
+static void subroutine_set (subroutineinfo *s)
+{
+ actual_subroutine = s;
+}
+
+
+
+/*********************** Funktion: subroutine_new *****************************
+
+ erzeugt einen neuen Subroutine-Infoblock
+
+*******************************************************************************/
+
+static subroutineinfo *subroutine_new ()
+{
+ subroutineinfo *s = DNEW (subroutineinfo);
+ s -> returnfinished = false;
+ s -> returnstack = NULL;
+ s -> callers = chain_dnew();
+ s -> counter = subroutinecounter++;
+ return s;
+}
+
+
+
+
+
+
+/********************** Funktion: block_insert ********************************
+
+ Erzeugt einen neuen Block, der an einer gew"unschten JavaVM-Code- Stelle
+ anf"angt.
+ Der Zeiger auf diesen Block wird im (globalen) 'blocks'-Array
+ abgelegt.
+
+******************************************************************************/
+
+static void block_insert (u4 codepos)
+{
+ if (codepos>=jcodelength) {
+ sprintf (logtext,"Basic block border (%d) out of bounds",(int) codepos);
+ error ();
+ }
+
+ if (blocks[codepos]) return;
+
+ blocks[codepos] = block_new (BLOCKTYPE_JAVA, codepos);
+}
+
+
+
+/******************** Funktion: block_createexcreator *************************
+
+ erzeugt einen neuen Basicblock vom Typ EXCREATOR (=Exception Creator)
+
+******************************************************************************/
+
+static basicblock *block_createexcreator (java_objectheader *exproto, u4 throwpos)
+{
+ basicblock *b;
+
+ b = block_new (BLOCKTYPE_EXCREATOR, creatornum++);
+
+ b -> reached = true;
+ list_addlast (&reachedblocks, b);
+ b -> subroutine = actual_subroutine;
+ b -> exproto = exproto;
+ b -> throwpos = throwpos;
+ return b;
+}
+
+
+/******************* Funktion: block_createexforwarder ***********************
+
+ erzeugt einen neuen Basicblock vom Typ EXFORWARDER (=Exception Forwarder)
+
+*****************************************************************************/
+
+static basicblock *block_createexforwarder (varid exvar, u4 throwpos)
+{
+ basicblock *b;
+
+ b = block_new (BLOCKTYPE_EXFORWARDER, creatornum++);
+
+ b -> reached = true;
+ list_addlast (&reachedblocks, b);
+ b -> subroutine = actual_subroutine;
+ b -> exvar = exvar;
+ b -> throwpos = throwpos;
+ return b;
+}
+
+
+/********************** Funktion: block_genmcode ******************************
+
+ generiert f"ur einen vom Parser fertig abgearbeiteten Block den
+ Maschinencode.
+ Hintereinanderliegende Bl"ocke durch die der Kontrollflu"s ohne
+ Sprungbefehle durchgeht, m"ussen hier auch hintereinander
+ abgearbeitet werden.
+
+******************************************************************************/
+
+/* definition of block_genmcode moved to gen.c for inlining by andi */
+
+
+/************************ Funktion: block_firstscann **************************
+
+ Liest den JavaVM-Code der ganzen Methode durch und erzeugt soviele
+ neue Bl"ocke, wie es verschiedene Sprungziele gibt.
+
+******************************************************************************/
+
+static void block_firstscann ()
+{
+ u4 p,nextp;
+ int i;
+ u1 opcode;
+ bool blockend;
+
+
+ creatornum=10001;
+
+
+ block_insert (0);
+
+ for (i=0; i<exceptiontablelength; i++) block_insert(extable[i].handlerpc);
+
+ p=0;
+ blockend = false;
+ while (p<jcodelength) {
+ if (blockend) {
+ block_insert (p);
+ blockend = false;
+ }
+
+ opcode = jcode[p];
+ nextp = p + jcommandsize[opcode];
+
+ switch ( opcode ) {
+ case CMD_IFEQ:
+ case CMD_IFNULL:
+ case CMD_IFLT:
+ case CMD_IFLE:
+ case CMD_IFNE:
+ case CMD_IFNONNULL:
+ case CMD_IFGT:
+ case CMD_IFGE:
+ case CMD_IF_ICMPEQ:
+ case CMD_IF_ICMPNE:
+ case CMD_IF_ICMPLT:
+ case CMD_IF_ICMPGT:
+ case CMD_IF_ICMPLE:
+ case CMD_IF_ICMPGE:
+ case CMD_IF_ACMPEQ:
+ case CMD_IF_ACMPNE:
+ block_insert ( p + code_get_s2 (p+1) );
+ break;
+
+ case CMD_GOTO:
+ block_insert ( p + code_get_s2 (p+1) );
+ blockend = true;
+ break;
+
+ case CMD_GOTO_W:
+ block_insert ( p + code_get_s4 (p+1) );
+ blockend = true;
+ break;
+
+ case CMD_JSR:
+ block_insert ( p + code_get_s2 (p+1) );
+ blockend = true;
+ break;
+
+ case CMD_JSR_W:
+ block_insert ( p + code_get_s4 (p+1) );
+ blockend = true;
+ break;
+
+ case CMD_RET:
+ blockend = true;
+ break;
+
+ case CMD_IRETURN:
+ case CMD_LRETURN:
+ case CMD_FRETURN:
+ case CMD_DRETURN:
+ case CMD_ARETURN:
+ case CMD_RETURN:
+ blockend = true;
+ break;
+
+ case CMD_ATHROW:
+ blockend = true;
+ break;
+
+
+ case CMD_WIDE:
+ switch (code_get_u1(p+1)) {
+ case CMD_RET: nextp = p+4;
+ blockend = true;
+ break;
+ case CMD_IINC: nextp = p+6;
+ break;
+ default: nextp = p+4;
+ break;
+ }
+ break;
+
+ case CMD_LOOKUPSWITCH:
+ { u4 num,p2,i;
+ p2 = ALIGN ((p+1),4);
+ num = code_get_u4 (p2+4);
+ nextp = p2 + 8 + 8*num;
+
+ block_insert ( p + code_get_s4(p2) );
+ for (i=0; i<num; i++)
+ block_insert ( p + code_get_s4(p2+12+8*i) );
+
+ blockend = true;
+ }
+ break;
+
+ case CMD_TABLESWITCH:
+ { u4 num,p2,i;
+ p2 = ALIGN ((p+1),4);
+ num= code_get_u4(p2+8) - code_get_u4 (p2+4) + 1;
+ nextp = p2 + 12 + 4*num;
+
+ block_insert ( p + code_get_s4(p2) );
+
+ for (i=0; i<num; i++)
+ block_insert ( p + code_get_s4(p2+12+4*i) );
+
+ blockend = true;
+ }
+ break;
+
+ case CMD_LDC1:
+ i = code_get_u1(p+1);
+ goto pushconstantitem;
+ case CMD_LDC2:
+ case CMD_LDC2W:
+ i = code_get_u2(p + 1);
+ pushconstantitem:
+ if (class_constanttype(class, i) == CONSTANT_String) {
+ unicode *s;
+ s = class_getconstant(class, i, CONSTANT_String);
+ (void) literalstring_new(s);
+ }
+ break;
+ }
+
+ if (nextp > jcodelength) panic ("Command-sequence crosses code-boundary");
+ p = nextp;
+ }
+
+ if (!blockend) panic ("Code does not end with branch/return/athrow - stmt");
+
+}
+
+
+
+/************* Funktion: block_display (nur zu Debug-Zwecken) ****************/
+
+void block_display (basicblock *b)
+{
+ pcmd *p;
+
+ if (b->subroutine) {
+ printf ("\n%ld in subroutine: %d", (long int) b->jpc, (int) b->subroutine->counter);
+ }
+ else {
+ printf ("\n%ld:", (long int) b->jpc);
+ }
+
+ switch (b->type) {
+ case BLOCKTYPE_JAVA: printf ("(JavaVM code)\n"); break;
+ case BLOCKTYPE_EXCREATOR: printf ("(Exception creator)\n"); break;
+ case BLOCKTYPE_EXFORWARDER: printf ("(Exception forwarder)\n"); break;
+ }
+
+ printf ("binding of stack: ");
+ stack_display (b->stack); printf ("\n");
+
+ p = list_first (&(b->pcmdlist));
+ while (p) {
+ pcmd_display (p);
+ p = list_next (&(b->pcmdlist), p);
+ }
+}
+
+
--- /dev/null
+/******************************** comp/defines.c *******************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ defines all the constants and data structures of the compiler
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+ Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
+ Michael Gschwind EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1997/09/22
+
+*******************************************************************************/
+
+#include "../sysdep/types.h"
+
+/*********************** resolve typedef-cycles *******************************/
+
+typedef struct stackinfo stackinfo;
+typedef struct basicblock basicblock;
+typedef struct varinfo varinfo;
+typedef struct subroutineinfo subroutineinfo;
+
+
+/***************************** basic block structure **************************/
+
+#define BLOCKTYPE_JAVA 1
+#define BLOCKTYPE_EXCREATOR 2
+#define BLOCKTYPE_EXFORWARDER 3
+
+/* there are three kinds of basic blocks:
+ JAVA ........ block which contains JavaVM code (normal case)
+ EXCREATOR ... block which creates an exception and calls the handler
+ EXFORWARDER .. block which does the dispatching to all possible handlers
+*/
+
+struct basicblock {
+ u2 type; /* block type */
+ bool reached; /* true, when block has been reached; the field stack
+ contains the stack valid before entering block */
+ bool finished; /* true, if 'pcmdlist' is finished */
+ subroutineinfo *subroutine; /* info about blocks reachable by JSR */
+ listnode linkage; /* list chaining */
+ u4 jpc; /* JavaVM program counter at start of block */
+ stackinfo *stack; /* stack description */
+ list pcmdlist; /* list of pseudo commands */
+ u4 mpc; /* program counter within compiled machine code */
+ java_objectheader *exproto;
+ /* if (type==EXCREATOR) contains pointer to exception
+ raising object */
+ varinfo *exvar; /* if (type==EXFORWARDER) contains exception variable */
+ u4 throwpos; /* if (type!=JAVA) contains position in program where
+ the exception was raised */
+ };
+
+
+/***************************** subroutine structure ***************************/
+
+struct subroutineinfo {
+ bool returnfinished; /* true if return allready has been processed */
+
+ stackinfo *returnstack; /* stack structure at position of return */
+ chain *callers; /* a list of all callers */
+ u2 counter;
+ };
+
+
+/************************** stack element structure ***************************/
+
+struct stackinfo {
+ stackinfo *prev; /* pointer to next element towards bootom */
+ varinfo *var; /* pointer to variable which contains this value */
+ };
+
+
+/************************* pseudo variable structure **************************/
+
+struct varinfo {
+ listnode linkage; /* list chaining */
+
+ u2 type; /* basic type of variable */
+ u2 number; /* sequential numbering (used for debugging) */
+
+ bool saved; /* true if variable sould survive subroutine calls */
+
+ struct reginfo *reg; /* registerused by variable */
+
+ /* temporary fields used during parsing */
+
+ list copies; /* list of all variables which are copies */
+ listnode copylink; /* chaining for copy list */
+ varinfo *original; /* pointer to original variable (self reference
+ is possible) */
+
+ bool globalscope; /* true if variable is activ in whole subroutine */
+ bool active; /* true if variable is currently active (parsing
+ a block where the variable is valid ) */
+ };
+
+
+typedef varinfo *varid;
+
+#define NOVAR NULL
+
+
+/************************** pseudo command structure **************************/
+
+/* pseudo command tags */
+
+#define TAG_LOADCONST_I 1 /* load integer constant */
+#define TAG_LOADCONST_L 2 /* load long constant */
+#define TAG_LOADCONST_F 3 /* load float constant */
+#define TAG_LOADCONST_D 4 /* load double constant */
+#define TAG_LOADCONST_A 5 /* load address constant */
+#define TAG_MOVE 6
+#define TAG_OP 7
+#define TAG_MEM 8
+#define TAG_BRA 9
+#define TAG_TABLEJUMP 10
+#define TAG_METHOD 11
+#define TAG_DROP 12
+#define TAG_ACTIVATE 13
+
+
+typedef struct pcmd {
+ listnode linkage; /* list chaining */
+ int tag; /* kind of pseudo command */
+ int opcode; /* opcode and kind of pseudo command */
+
+ varinfo *dest; /* optional destination operand */
+ varinfo *source1; /* 3 optional source operands */
+ varinfo *source2;
+ varinfo *source3;
+
+ union {
+ struct { /* load integer constant */
+ s4 value;
+ } i;
+ struct { /* load long constant */
+ s8 value;
+ } l;
+ struct { /* load float constant */
+ float value;
+ } f;
+ struct { /* load double constant */
+ double value;
+ } d;
+ struct { /* load address constant */
+ voidptr value;
+ } a;
+
+ struct { /* move */
+ u2 type; /* type of value */
+ } move;
+
+ struct { /* memory access (load/store) */
+ int type; /* access type */
+ u4 offset; /* offset relative to base register */
+ } mem;
+
+ struct { /* branch */
+ basicblock *target; /* branch target */
+ } bra;
+
+ struct { /* branch using table */
+ u4 targetcount; /* number of entries */
+ basicblock **targets; /* branch target */
+ } tablejump;
+
+ struct { /* method call */
+ methodinfo *method; /* pointer to 'methodinfo'-structure */
+ functionptr builtin; /* C function pointer or NULL */
+ u2 paramnum; /* number of parameters */
+ varid *params; /* table of parameter variables */
+ varid exceptionvar; /* exception variable */
+ } method;
+
+ } u;
+
+ } pcmd;
+
+
+
+
+
+
+/***************** forward references in branch instructions ******************/
+
+typedef struct mcodereference {
+ listnode linkage; /* list chaining */
+
+ bool incode; /* true if code address, false if data address */
+ s4 msourcepos; /* patching position in code/data segment */
+ basicblock *target; /* target basic block */
+ } mcodereference;
+
+
+
+
+/********** JavaVM operation codes (sortet) and instruction lengths ***********/
+
+u1 jcommandsize[256] = {
+
+#define CMD_NOP 0
+ 1,
+#define CMD_ACONST_NULL 1
+ 1,
+#define CMD_ICONST_M1 2
+ 1,
+#define CMD_ICONST_0 3
+ 1,
+#define CMD_ICONST_1 4
+ 1,
+#define CMD_ICONST_2 5
+ 1,
+#define CMD_ICONST_3 6
+ 1,
+#define CMD_ICONST_4 7
+ 1,
+#define CMD_ICONST_5 8
+ 1,
+#define CMD_LCONST_0 9
+ 1,
+#define CMD_LCONST_1 10
+ 1,
+#define CMD_FCONST_0 11
+ 1,
+#define CMD_FCONST_1 12
+ 1,
+#define CMD_FCONST_2 13
+ 1,
+#define CMD_DCONST_0 14
+ 1,
+#define CMD_DCONST_1 15
+ 1,
+#define CMD_BIPUSH 16
+ 2,
+#define CMD_SIPUSH 17
+ 3,
+#define CMD_LDC1 18
+ 2,
+#define CMD_LDC2 19
+ 3,
+#define CMD_LDC2W 20
+ 3,
+#define CMD_ILOAD 21
+ 2,
+#define CMD_LLOAD 22
+ 2,
+#define CMD_FLOAD 23
+ 2,
+#define CMD_DLOAD 24
+ 2,
+#define CMD_ALOAD 25
+ 2,
+#define CMD_ILOAD_0 26
+ 1,
+#define CMD_ILOAD_1 27
+ 1,
+#define CMD_ILOAD_2 28
+ 1,
+#define CMD_ILOAD_3 29
+ 1,
+#define CMD_LLOAD_0 30
+ 1,
+#define CMD_LLOAD_1 31
+ 1,
+#define CMD_LLOAD_2 32
+ 1,
+#define CMD_LLOAD_3 33
+ 1,
+#define CMD_FLOAD_0 34
+ 1,
+#define CMD_FLOAD_1 35
+ 1,
+#define CMD_FLOAD_2 36
+ 1,
+#define CMD_FLOAD_3 37
+ 1,
+#define CMD_DLOAD_0 38
+ 1,
+#define CMD_DLOAD_1 39
+ 1,
+#define CMD_DLOAD_2 40
+ 1,
+#define CMD_DLOAD_3 41
+ 1,
+#define CMD_ALOAD_0 42
+ 1,
+#define CMD_ALOAD_1 43
+ 1,
+#define CMD_ALOAD_2 44
+ 1,
+#define CMD_ALOAD_3 45
+ 1,
+#define CMD_IALOAD 46
+ 1,
+#define CMD_LALOAD 47
+ 1,
+#define CMD_FALOAD 48
+ 1,
+#define CMD_DALOAD 49
+ 1,
+#define CMD_AALOAD 50
+ 1,
+#define CMD_BALOAD 51
+ 1,
+#define CMD_CALOAD 52
+ 1,
+#define CMD_SALOAD 53
+ 1,
+#define CMD_ISTORE 54
+ 2,
+#define CMD_LSTORE 55
+ 2,
+#define CMD_FSTORE 56
+ 2,
+#define CMD_DSTORE 57
+ 2,
+#define CMD_ASTORE 58
+ 2,
+#define CMD_ISTORE_0 59
+ 1,
+#define CMD_ISTORE_1 60
+ 1,
+#define CMD_ISTORE_2 61
+ 1,
+#define CMD_ISTORE_3 62
+ 1,
+#define CMD_LSTORE_0 63
+ 1,
+#define CMD_LSTORE_1 64
+ 1,
+#define CMD_LSTORE_2 65
+ 1,
+#define CMD_LSTORE_3 66
+ 1,
+#define CMD_FSTORE_0 67
+ 1,
+#define CMD_FSTORE_1 68
+ 1,
+#define CMD_FSTORE_2 69
+ 1,
+#define CMD_FSTORE_3 70
+ 1,
+#define CMD_DSTORE_0 71
+ 1,
+#define CMD_DSTORE_1 72
+ 1,
+#define CMD_DSTORE_2 73
+ 1,
+#define CMD_DSTORE_3 74
+ 1,
+#define CMD_ASTORE_0 75
+ 1,
+#define CMD_ASTORE_1 76
+ 1,
+#define CMD_ASTORE_2 77
+ 1,
+#define CMD_ASTORE_3 78
+ 1,
+#define CMD_IASTORE 79
+ 1,
+#define CMD_LASTORE 80
+ 1,
+#define CMD_FASTORE 81
+ 1,
+#define CMD_DASTORE 82
+ 1,
+#define CMD_AASTORE 83
+ 1,
+#define CMD_BASTORE 84
+ 1,
+#define CMD_CASTORE 85
+ 1,
+#define CMD_SASTORE 86
+ 1,
+#define CMD_POP 87
+ 1,
+#define CMD_POP2 88
+ 1,
+#define CMD_DUP 89
+ 1,
+#define CMD_DUP_X1 90
+ 1,
+#define CMD_DUP_X2 91
+ 1,
+#define CMD_DUP2 92
+ 1,
+#define CMD_DUP2_X1 93
+ 1,
+#define CMD_DUP2_X2 94
+ 1,
+#define CMD_SWAP 95
+ 1,
+#define CMD_IADD 96
+ 1,
+#define CMD_LADD 97
+ 1,
+#define CMD_FADD 98
+ 1,
+#define CMD_DADD 99
+ 1,
+#define CMD_ISUB 100
+ 1,
+#define CMD_LSUB 101
+ 1,
+#define CMD_FSUB 102
+ 1,
+#define CMD_DSUB 103
+ 1,
+#define CMD_IMUL 104
+ 1,
+#define CMD_LMUL 105
+ 1,
+#define CMD_FMUL 106
+ 1,
+#define CMD_DMUL 107
+ 1,
+#define CMD_IDIV 108
+ 1,
+#define CMD_LDIV 109
+ 1,
+#define CMD_FDIV 110
+ 1,
+#define CMD_DDIV 111
+ 1,
+#define CMD_IREM 112
+ 1,
+#define CMD_LREM 113
+ 1,
+#define CMD_FREM 114
+ 1,
+#define CMD_DREM 115
+ 1,
+#define CMD_INEG 116
+ 1,
+#define CMD_LNEG 117
+ 1,
+#define CMD_FNEG 118
+ 1,
+#define CMD_DNEG 119
+ 1,
+#define CMD_ISHL 120
+ 1,
+#define CMD_LSHL 121
+ 1,
+#define CMD_ISHR 122
+ 1,
+#define CMD_LSHR 123
+ 1,
+#define CMD_IUSHR 124
+ 1,
+#define CMD_LUSHR 125
+ 1,
+#define CMD_IAND 126
+ 1,
+#define CMD_LAND 127
+ 1,
+#define CMD_IOR 128
+ 1,
+#define CMD_LOR 129
+ 1,
+#define CMD_IXOR 130
+ 1,
+#define CMD_LXOR 131
+ 1,
+#define CMD_IINC 132
+ 3,
+#define CMD_I2L 133
+ 1,
+#define CMD_I2F 134
+ 1,
+#define CMD_I2D 135
+ 1,
+#define CMD_L2I 136
+ 1,
+#define CMD_L2F 137
+ 1,
+#define CMD_L2D 138
+ 1,
+#define CMD_F2I 139
+ 1,
+#define CMD_F2L 140
+ 1,
+#define CMD_F2D 141
+ 1,
+#define CMD_D2I 142
+ 1,
+#define CMD_D2L 143
+ 1,
+#define CMD_D2F 144
+ 1,
+#define CMD_INT2BYTE 145
+ 1,
+#define CMD_INT2CHAR 146
+ 1,
+#define CMD_INT2SHORT 147
+ 1,
+#define CMD_LCMP 148
+ 1,
+#define CMD_FCMPL 149
+ 1,
+#define CMD_FCMPG 150
+ 1,
+#define CMD_DCMPL 151
+ 1,
+#define CMD_DCMPG 152
+ 1,
+#define CMD_IFEQ 153
+ 3,
+#define CMD_IFNE 154
+ 3,
+#define CMD_IFLT 155
+ 3,
+#define CMD_IFGE 156
+ 3,
+#define CMD_IFGT 157
+ 3,
+#define CMD_IFLE 158
+ 3,
+#define CMD_IF_ICMPEQ 159
+ 3,
+#define CMD_IF_ICMPNE 160
+ 3,
+#define CMD_IF_ICMPLT 161
+ 3,
+#define CMD_IF_ICMPGE 162
+ 3,
+#define CMD_IF_ICMPGT 163
+ 3,
+#define CMD_IF_ICMPLE 164
+ 3,
+#define CMD_IF_ACMPEQ 165
+ 3,
+#define CMD_IF_ACMPNE 166
+ 3,
+#define CMD_GOTO 167
+ 3,
+#define CMD_JSR 168
+ 3,
+#define CMD_RET 169
+ 2,
+#define CMD_TABLESWITCH 170
+ 0, /* length must be computed */
+#define CMD_LOOKUPSWITCH 171
+ 0, /* length must be computed */
+#define CMD_IRETURN 172
+ 1,
+#define CMD_LRETURN 173
+ 1,
+#define CMD_FRETURN 174
+ 1,
+#define CMD_DRETURN 175
+ 1,
+#define CMD_ARETURN 176
+ 1,
+#define CMD_RETURN 177
+ 1,
+#define CMD_GETSTATIC 178
+ 3,
+#define CMD_PUTSTATIC 179
+ 3,
+#define CMD_GETFIELD 180
+ 3,
+#define CMD_PUTFIELD 181
+ 3,
+#define CMD_INVOKEVIRTUAL 182
+ 3,
+#define CMD_INVOKESPECIAL 183
+ 3,
+#define CMD_INVOKESTATIC 184
+ 3,
+#define CMD_INVOKEINTERFACE 185
+ 5,
+ 1, /* unused */
+#define CMD_NEW 187
+ 3,
+#define CMD_NEWARRAY 188
+ 2,
+#define CMD_ANEWARRAY 189
+ 3,
+#define CMD_ARRAYLENGTH 190
+ 1,
+#define CMD_ATHROW 191
+ 1,
+#define CMD_CHECKCAST 192
+ 3,
+#define CMD_INSTANCEOF 193
+ 3,
+#define CMD_MONITORENTER 194
+ 1,
+#define CMD_MONITOREXIT 195
+ 1,
+#define CMD_WIDE 196
+ 0, /* length must be computed */
+#define CMD_MULTIANEWARRAY 197
+ 4,
+#define CMD_IFNULL 198
+ 3,
+#define CMD_IFNONNULL 199
+ 3,
+#define CMD_GOTO_W 200
+ 5,
+#define CMD_JSR_W 201
+ 5,
+#define CMD_BREAKPOINT 202
+ 1,
+
+ 1,1,1,1,1,1,1,1,1,1, /* unused */
+ 1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,
+ 1,1,1
+ };
+
+#define CMD_TRACEBUILT 253 /* internal opcode */
+#define CMD_IFEQL 254 /* internal opcode */
+#define CMD_IF_UCMPGE 255 /* internal opcode */
+
+#define CMD_LOADCONST_I (CMD_IF_UCMPGE+TAG_LOADCONST_I) /* internal opcodes */
+#define CMD_LOADCONST_L (CMD_IF_UCMPGE+TAG_LOADCONST_L)
+#define CMD_LOADCONST_F (CMD_IF_UCMPGE+TAG_LOADCONST_F)
+#define CMD_LOADCONST_D (CMD_IF_UCMPGE+TAG_LOADCONST_D)
+#define CMD_LOADCONST_A (CMD_IF_UCMPGE+TAG_LOADCONST_A)
+#define CMD_MOVE (CMD_IF_UCMPGE+TAG_MOVE)
+
+#define CMD_TABLEJUMP (CMD_IF_UCMPGE+TAG_TABLEJUMP)
+#define CMD_BUILTIN (CMD_IF_UCMPGE+TAG_METHOD)
+#define CMD_DROP (CMD_IF_UCMPGE+TAG_DROP)
+#define CMD_ACTIVATE (CMD_IF_UCMPGE+TAG_ACTIVATE)
+
+
+/******************* description of JavaVM instructions ***********************/
+
+typedef struct {
+ u1 opcode;
+ u1 type_s1;
+ u1 type_s2;
+ u1 type_d;
+ functionptr builtin;
+ bool supported;
+ bool isfloat;
+} stdopdescriptor;
+
+stdopdescriptor *stdopdescriptors[256];
+
+stdopdescriptor stdopdescriptortable[] = {
+ { CMD_IADD, TYPE_INT, TYPE_INT, TYPE_INT, NULL, true, false },
+ { CMD_ISUB, TYPE_INT, TYPE_INT, TYPE_INT, NULL, true, false },
+ { CMD_IMUL, TYPE_INT, TYPE_INT, TYPE_INT, NULL, true, false },
+ { CMD_ISHL, TYPE_INT, TYPE_INT, TYPE_INT, NULL, true, false },
+ { CMD_ISHR, TYPE_INT, TYPE_INT, TYPE_INT, NULL, true, false },
+ { CMD_IUSHR, TYPE_INT, TYPE_INT, TYPE_INT, NULL, true, false },
+ { CMD_IAND, TYPE_INT, TYPE_INT, TYPE_INT, NULL, true, false },
+ { CMD_IOR, TYPE_INT, TYPE_INT, TYPE_INT, NULL, true, false },
+ { CMD_IXOR, TYPE_INT, TYPE_INT, TYPE_INT, NULL, true, false },
+ { CMD_INEG, TYPE_INT, TYPE_VOID,TYPE_INT, NULL, true, false },
+
+ { CMD_LADD, TYPE_LONG, TYPE_LONG, TYPE_LONG,
+ (functionptr) builtin_ladd , SUPPORT_LONG && SUPPORT_LONG_ADD, false },
+ { CMD_LSUB, TYPE_LONG, TYPE_LONG, TYPE_LONG,
+ (functionptr) builtin_lsub , SUPPORT_LONG && SUPPORT_LONG_ADD, false },
+ { CMD_LMUL, TYPE_LONG, TYPE_LONG, TYPE_LONG,
+ (functionptr) builtin_lmul , SUPPORT_LONG && SUPPORT_LONG_MULDIV, false },
+ { CMD_LSHL, TYPE_LONG, TYPE_INT, TYPE_LONG,
+ (functionptr) builtin_lshl , SUPPORT_LONG && SUPPORT_LONG_SHIFT, false },
+ { CMD_LSHR, TYPE_LONG, TYPE_INT, TYPE_LONG,
+ (functionptr) builtin_lshr, SUPPORT_LONG && SUPPORT_LONG_SHIFT, false },
+ { CMD_LUSHR, TYPE_LONG, TYPE_INT, TYPE_LONG,
+ (functionptr) builtin_lushr, SUPPORT_LONG && SUPPORT_LONG_SHIFT, false },
+ { CMD_LAND, TYPE_LONG, TYPE_LONG, TYPE_LONG,
+ (functionptr) builtin_land, SUPPORT_LONG && SUPPORT_LONG_LOG, false },
+ { CMD_LOR, TYPE_LONG, TYPE_LONG, TYPE_LONG,
+ (functionptr) builtin_lor , SUPPORT_LONG && SUPPORT_LONG_LOG, false },
+ { CMD_LXOR, TYPE_LONG, TYPE_LONG, TYPE_LONG,
+ (functionptr) builtin_lxor, SUPPORT_LONG && SUPPORT_LONG_LOG, false },
+ { CMD_LNEG, TYPE_LONG, TYPE_VOID, TYPE_LONG,
+ (functionptr) builtin_lneg, SUPPORT_LONG && SUPPORT_LONG_ADD, false },
+ { CMD_LCMP, TYPE_LONG, TYPE_LONG, TYPE_INT,
+ (functionptr) builtin_lcmp, SUPPORT_LONG && SUPPORT_LONG_CMP, false },
+
+ { CMD_FADD, TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT,
+ (functionptr) builtin_fadd, SUPPORT_FLOAT, true },
+ { CMD_FSUB, TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT,
+ (functionptr) builtin_fsub, SUPPORT_FLOAT, true },
+ { CMD_FMUL, TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT,
+ (functionptr) builtin_fmul, SUPPORT_FLOAT, true },
+ { CMD_FDIV, TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT,
+ (functionptr) builtin_fdiv, SUPPORT_FLOAT, true },
+ { CMD_FREM, TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT,
+ (functionptr) builtin_frem, SUPPORT_FLOAT, true },
+ { CMD_FNEG, TYPE_FLOAT, TYPE_VOID, TYPE_FLOAT,
+ (functionptr) builtin_fneg, SUPPORT_FLOAT, true },
+ { CMD_FCMPL, TYPE_FLOAT, TYPE_FLOAT, TYPE_INT,
+ (functionptr) builtin_fcmpl, SUPPORT_FLOAT, true },
+ { CMD_FCMPG, TYPE_FLOAT, TYPE_FLOAT, TYPE_INT,
+ (functionptr) builtin_fcmpg, SUPPORT_FLOAT, true },
+
+ { CMD_DADD, TYPE_DOUBLE, TYPE_DOUBLE, TYPE_DOUBLE,
+ (functionptr) builtin_dadd, SUPPORT_DOUBLE, true },
+ { CMD_DSUB, TYPE_DOUBLE, TYPE_DOUBLE, TYPE_DOUBLE,
+ (functionptr) builtin_dsub, SUPPORT_DOUBLE, true },
+ { CMD_DMUL, TYPE_DOUBLE, TYPE_DOUBLE, TYPE_DOUBLE,
+ (functionptr) builtin_dmul, SUPPORT_DOUBLE, true },
+ { CMD_DDIV, TYPE_DOUBLE, TYPE_DOUBLE, TYPE_DOUBLE,
+ (functionptr) builtin_ddiv, SUPPORT_DOUBLE, true },
+ { CMD_DREM, TYPE_DOUBLE, TYPE_DOUBLE, TYPE_DOUBLE,
+ (functionptr) builtin_drem, SUPPORT_DOUBLE, true },
+ { CMD_DNEG, TYPE_DOUBLE, TYPE_VOID, TYPE_DOUBLE,
+ (functionptr) builtin_dneg, SUPPORT_DOUBLE, true },
+ { CMD_DCMPL, TYPE_DOUBLE, TYPE_DOUBLE, TYPE_INT,
+ (functionptr) builtin_dcmpl, SUPPORT_DOUBLE, true },
+ { CMD_DCMPG, TYPE_DOUBLE, TYPE_DOUBLE, TYPE_INT,
+ (functionptr) builtin_dcmpg, SUPPORT_DOUBLE, true },
+
+ { CMD_INT2BYTE, TYPE_INT, TYPE_VOID, TYPE_INT, NULL, true,false },
+ { CMD_INT2CHAR, TYPE_INT, TYPE_VOID, TYPE_INT, NULL, true,false },
+ { CMD_INT2SHORT, TYPE_INT, TYPE_VOID, TYPE_INT, NULL, true,false },
+ { CMD_I2L, TYPE_INT, TYPE_VOID, TYPE_LONG,
+ (functionptr) builtin_i2l, SUPPORT_LONG && SUPPORT_LONG_ICVT, false },
+ { CMD_I2F, TYPE_INT, TYPE_VOID, TYPE_FLOAT,
+ (functionptr) builtin_i2f, SUPPORT_FLOAT, true },
+ { CMD_I2D, TYPE_INT, TYPE_VOID, TYPE_DOUBLE,
+ (functionptr) builtin_i2d, SUPPORT_DOUBLE, true },
+ { CMD_L2I, TYPE_LONG, TYPE_VOID, TYPE_INT,
+ (functionptr) builtin_l2i, SUPPORT_LONG && SUPPORT_LONG_ICVT, false },
+ { CMD_L2F, TYPE_LONG, TYPE_VOID, TYPE_FLOAT,
+ (functionptr) builtin_l2f, SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_LONG_FCVT, true },
+ { CMD_L2D, TYPE_LONG, TYPE_VOID, TYPE_DOUBLE,
+ (functionptr) builtin_l2d, SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_LONG_FCVT, true },
+ { CMD_F2I, TYPE_FLOAT, TYPE_VOID, TYPE_INT,
+ (functionptr) builtin_f2i, SUPPORT_FLOAT, true },
+ { CMD_F2L, TYPE_FLOAT, TYPE_VOID, TYPE_LONG,
+ (functionptr) builtin_f2l, SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_LONG_FCVT, true },
+ { CMD_F2D, TYPE_FLOAT, TYPE_VOID, TYPE_DOUBLE,
+ (functionptr) builtin_f2d, SUPPORT_FLOAT && SUPPORT_DOUBLE, true },
+ { CMD_D2I, TYPE_DOUBLE, TYPE_VOID, TYPE_INT,
+ (functionptr) builtin_d2i, SUPPORT_DOUBLE, true },
+ { CMD_D2L, TYPE_DOUBLE, TYPE_VOID, TYPE_LONG,
+ (functionptr) builtin_d2l, SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_LONG_FCVT, true },
+ { CMD_D2F, TYPE_DOUBLE, TYPE_VOID, TYPE_FLOAT,
+ (functionptr) builtin_d2f, SUPPORT_DOUBLE && SUPPORT_FLOAT, true },
+
+};
+
+
+
+/***************************** register types *********************************/
+
+#define REG_RES 0 /* reserved register for OS or code generator */
+#define REG_RET 1 /* return value register */
+#define REG_EXC 2 /* exception value register */
+#define REG_SAV 3 /* (callee) saved register */
+#define REG_TMP 4 /* scratch temporary register (caller saved) */
+#define REG_ARG 5 /* argument register (caller saved) */
+
+#define REG_END -1 /* last entry in tables */
+
+#define PARAMMODE_NUMBERED 0
+#define PARAMMODE_STUFFED 1
+
+/***************************** register info block ****************************/
+
+extern int regdescint[]; /* description of integer registers */
+extern int regdescfloat[]; /* description of floating point registers */
+
+extern int reg_parammode;
+
--- /dev/null
+/**************************** comp/local.c *************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ behandeln der lokalen Java-Variablen
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1996/11/14
+
+*******************************************************************************/
+
+ /* es werden f"ur die lokalen Java-Variablen 5 Tabellen angelegt,
+ f"ur jeden m"oglichen Typ eine, weil mehrere Java-Variablen
+ verschiendenen Typs die selben Slots belegen k"onnen */
+
+varid *locals[5];
+
+
+/*********************** Funktion: local_get **********************************
+
+ erzeugt eine neue Pseudo-Variable f"ur einen JavaVM-Slot und einen
+ gew"unschten Typ, oder eine bereits vorhandene Variable.
+
+******************************************************************************/
+
+static varid local_get (int slot, int type)
+{
+ varid v;
+ int secondslot;
+
+ secondslot = ((type==TYPE_DOUBLE) || (type==TYPE_LONG)) ? 1 : 0;
+
+ if (slot+secondslot>=maxlocals)
+ panic ("Local-variable access out of bounds");
+ v = locals[type][slot];
+
+ if (v==NULL) {
+ v = var_createwithspecialnumber (type, slot);
+ v -> globalscope = true;
+ locals[type][slot] = v;
+ }
+
+ return v;
+}
+
+
+
+
+/************************* Funktion: local_init *******************************
+
+ legt die 5 Tabellen an, und erzeugt auch gleich die Belegungen
+ f"ur die Methodenparameter.
+
+******************************************************************************/
+
+static void local_init()
+{
+ int t, i, slot;
+
+ if (TYPE_INT != 0 || TYPE_ADDRESS != 4)
+ panic ("JAVA-Basictypes have been changed");
+
+ for (t=TYPE_INT; t<=TYPE_ADDRESS; t++) {
+ locals[t] = DMNEW (varid, maxlocals);
+ for (i=0; i<maxlocals; i++) locals[t][i] = NULL;
+ }
+
+
+ slot =0;
+ for (i=0; i<mparamnum; i++) {
+ t = mparamtypes[i];
+ mparamvars[i] = local_get (slot, t);
+ slot += ((t==TYPE_DOUBLE || t==TYPE_LONG) ? 2 : 1);
+ }
+}
+
+
+/************************ Funktion: local_regalloc ****************************
+
+ f"uhrt die Registerbelegung f"ur die lokalen Java-Variablen durch
+
+******************************************************************************/
+
+
+static void local_regalloc ()
+{
+ int s, t;
+ varid v;
+
+ for (s=0; s<maxlocals; s++)
+ for (t=TYPE_INT; t<=TYPE_ADDRESS; t++) {
+ v = locals[t][s];
+ if (v) {
+ if (! isleafmethod)
+ var_makesaved (v);
+ if (v->reg == NULL)
+ v->reg = reg_allocate (v->type, v->saved, true);
+ }
+ }
+}
+
--- /dev/null
+/***************************** comp/mcode.c ************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ This file is an include file for "compiler.c" . It contains (mostly)
+ architecture independent functions for writing instructions into the
+ code area and constants into the data area.
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+ Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
+ Changes: Micheal Gschwind EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1997/04/13
+
+
+ All functions assume the following code area / data area layout:
+
+ +-----------+
+ | |
+ | code area | code area grows to higher addresses
+ | |
+ +-----------+ <-- start of procedure
+ | |
+ | data area | data area grows to lower addresses
+ | |
+ +-----------+
+
+ The functions first write into a temporary code/data area allocated by
+ "mcode_init". "mcode_finish" copies the code and data area into permanent
+ memory. All functions writing values into the data area return the offset
+ relative the begin of the code area (start of procedure).
+
+*******************************************************************************/
+
+#include <sys/mman.h>
+#include <errno.h>
+
+#define MCODEINITSIZE (1<<15) /* 32 Kbyte code area initialization size */
+#define DSEGINITSIZE (1<<12) /* 4 Kbyte data area initialization size */
+
+static u1* mcodebase = NULL; /* base pointer of code area */
+static int mcodesize; /* complete size of code area (bytes) */
+static int mcodelen; /* used size of code area (bytes) */
+
+static u1* dsegtop = NULL; /* pointer to top (end) of data area */
+static int dsegsize; /* complete size of data area (bytes) */
+static int dseglen; /* used size of data area (bytes) */
+ /* data area grows from top to bottom */
+
+static list mcodereferences; /* list of branch instruction adresses */
+ /* and of jumptable target addresses */
+
+static void mcode_init(); /* allocates code and data area */
+static void mcode_close(); /* releases temporary storage */
+static void mcode_finish(); /* makes code and data area permanent and */
+ /* updates branch references to code/data */
+static void mcode_adds4(s4 code); /* adds an instruction to code area */
+
+static s4 dseg_adds4(s4 value); /* adds an int to data area */
+static s4 dseg_adds8(s8 value); /* adds an long to data area */
+static s4 dseg_addfloat (float value); /* adds an float to data area */
+static s4 dseg_adddouble(double value); /* adds an double to data area */
+
+/* s4 dseg_addaddress(void* value); */
+static s4 dseg_addtarget(basicblock *target);
+static void mcode_addreference(basicblock *target);
+static void dseg_display();
+
+/* mcode_init allocates and initialises code area, data area and references */
+
+static void mcode_init()
+{
+ if (!mcodebase) {
+ mcodebase = MNEW (u1, MCODEINITSIZE);
+ mcodesize = MCODEINITSIZE;
+ }
+
+ if (!dsegtop) {
+ dsegtop = MNEW (u1, DSEGINITSIZE);
+ dsegsize = DSEGINITSIZE;
+ dsegtop += dsegsize;
+ }
+
+ mcodelen = 0;
+ dseglen = 0;
+
+ list_init (&mcodereferences, OFFSET(mcodereference, linkage) );
+}
+
+
+/* mcode_close releases temporary code and data area */
+
+static void mcode_close()
+{
+ if (mcodebase) {
+ MFREE (mcodebase, u1, mcodesize);
+ mcodebase = NULL;
+ }
+ if (dsegtop) {
+ MFREE (dsegtop - dsegsize, u1, dsegsize);
+ dsegtop = NULL;
+ }
+}
+
+
+/* mcode_adds4_increase doubles code area and adds instruction */
+
+static void mcode_adds4_increase(s4 code)
+{
+ mcodebase = MREALLOC(mcodebase, u1, mcodesize, mcodesize * 2);
+ mcodesize *= 2;
+ *((s4 *) (mcodebase + mcodelen - 4)) = code;
+}
+
+
+/* mcode_adds4 checks code area size and adds instruction */
+
+static void mcode_adds4(s4 code)
+{
+ s4 *codeptr;
+
+ codeptr = (s4 *) (mcodebase + mcodelen);
+ mcodelen += 4;
+ if (mcodelen <= mcodesize)
+ *codeptr = code;
+ else
+ mcode_adds4_increase(code);
+}
+
+
+/* desg_increase doubles data area */
+
+static void dseg_increase() {
+ u1 *newstorage = MNEW (u1, dsegsize * 2);
+ memcpy ( newstorage + dsegsize, dsegtop - dsegsize, dsegsize);
+ MFREE (dsegtop - dsegsize, u1, dsegsize);
+ dsegtop = newstorage;
+ dsegsize *= 2;
+ dsegtop += dsegsize;
+}
+
+
+static s4 dseg_adds4_increase(s4 value)
+{
+ dseg_increase();
+ *((s4 *) (dsegtop - dseglen)) = value;
+ return -dseglen;
+}
+
+
+static s4 dseg_adds4(s4 value)
+{
+ s4 *dataptr;
+
+ dseglen += 4;
+ dataptr = (s4 *) (dsegtop - dseglen);
+ if (dseglen > dsegsize)
+ return dseg_adds4_increase(value);
+ *dataptr = value;
+ return -dseglen;
+}
+
+
+static s4 dseg_adds8_increase(s8 value)
+{
+ dseg_increase();
+ *((s8 *) (dsegtop - dseglen)) = value;
+ return -dseglen;
+}
+
+
+static s4 dseg_adds8(s8 value)
+{
+ s8 *dataptr;
+
+ dseglen = ALIGN (dseglen + 8, 8);
+ dataptr = (s8 *) (dsegtop - dseglen);
+ if (dseglen > dsegsize)
+ return dseg_adds8_increase(value);
+ *dataptr = value;
+ return -dseglen;
+}
+
+
+static s4 dseg_addfloat_increase(float value)
+{
+ dseg_increase();
+ *((float *) (dsegtop - dseglen)) = value;
+ return -dseglen;
+}
+
+
+static s4 dseg_addfloat(float value)
+{
+ float *dataptr;
+
+ dseglen += 4;
+ dataptr = (float *) (dsegtop - dseglen);
+ if (dseglen > dsegsize)
+ return dseg_addfloat_increase(value);
+ *dataptr = value;
+ return -dseglen;
+}
+
+
+static s4 dseg_adddouble_increase(double value)
+{
+ dseg_increase();
+ *((double *) (dsegtop - dseglen)) = value;
+ return -dseglen;
+}
+
+
+static s4 dseg_adddouble(double value)
+{
+ double *dataptr;
+
+ dseglen = ALIGN (dseglen + 8, 8);
+ dataptr = (double *) (dsegtop - dseglen);
+ if (dseglen > dsegsize)
+ return dseg_adddouble_increase(value);
+ *dataptr = value;
+ return -dseglen;
+}
+
+
+#if POINTERSIZE==8
+#define dseg_addaddress(value) dseg_adds8((s8)(value))
+#else
+#define dseg_addaddress(value) dseg_adds4((s4)(value))
+#endif
+
+
+static s4 dseg_addtarget(basicblock *target)
+{
+ mcodereference *cr = DNEW(mcodereference);
+
+ dseglen = ALIGN (dseglen + sizeof(void*), sizeof(void*));
+ if (dseglen > dsegsize)
+ dseg_increase();
+
+ cr -> incode = false;
+ cr -> msourcepos = -dseglen;
+ cr -> target = target;
+
+ list_addlast (&mcodereferences, cr);
+
+ return -dseglen;
+}
+
+
+static void mcode_addreference(basicblock *target)
+{
+ mcodereference *cr = DNEW(mcodereference);
+
+ cr -> incode = true;
+ cr -> msourcepos = mcodelen;
+ cr -> target = target;
+
+ list_addlast (&mcodereferences, cr);
+}
+
+
+
+static void mcode_blockstart (basicblock *b)
+{
+ b -> mpc = mcodelen;
+}
+
+
+
+static void gen_resolvebranch(void* mcodepiece, s4 sourcepos, s4 targetpos);
+
+static void mcode_finish()
+{
+ mcodereference *cr;
+
+ count_code_len += mcodelen;
+ count_data_len += dseglen;
+
+ dseglen = ALIGN(dseglen, MAX_ALIGN);
+
+ method->mcodelength = mcodelen + dseglen;
+ method->mcode = CNEW(u1, mcodelen + dseglen);
+
+ memcpy ( method->mcode, dsegtop - dseglen, dseglen);
+ memcpy ( method->mcode + dseglen, mcodebase, mcodelen);
+
+ method -> entrypoint = (u1*) (method->mcode + dseglen);
+
+ cr = list_first (&mcodereferences);
+ while (cr != NULL) {
+
+ if (cr->incode) { /* branch resolving */
+ gen_resolvebranch ( ((u1*)(method->entrypoint)) + cr->msourcepos,
+ cr->msourcepos,
+ cr->target->mpc);
+ }
+ else { /* jump table resolving */
+ void **p;
+ p = (void**) ( ((u1*)(method->entrypoint)) + cr->msourcepos);
+
+ *p = ((u1*)(method->entrypoint)) + cr->target->mpc;
+ }
+
+ cr = list_next (&mcodereferences, cr);
+ }
+
+#ifdef CACHE_FLUSH_BLOCK
+ synchronize_caches(method->mcode, (mcodelen>>2));
+#endif
+
+}
+
+
+static void dseg_display()
+{
+ int i;
+ printf (" --- dump of datasegment\n");
+ for (i = dseglen - 4; i >= 0 ; i -= 4) {
+ printf ("%6x: %8x\n", i, (int)(*((s4*)(dsegtop - i))));
+ }
+}
--- /dev/null
+/****************************** comp/parse.c ***********************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Enth"alt den Parser f"ur die Bytecode-Darstellung der Methoden
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+ Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1997/10/17
+
+*******************************************************************************/
+
+
+/* Kurzschreibweise f"ur oft verwendete Funktionen */
+
+#define LOADCONST_I pcmd_loadconst_i
+#define LOADCONST_L pcmd_loadconst_l
+#define LOADCONST_F pcmd_loadconst_f
+#define LOADCONST_D pcmd_loadconst_d
+#define LOADCONST_A pcmd_loadconst_a
+#define MOVE pcmd_move
+#define IINC pcmd_iinc
+#define OP pcmd_op
+#define MEM pcmd_mem
+#define BRA pcmd_bra
+#define TABLEJUMP pcmd_tablejump
+#define METHOD pcmd_method
+
+#define BUILTIN1 pcmd_builtin1
+#define BUILTIN2 pcmd_builtin2
+#define BUILTIN3 pcmd_builtin3
+
+#define DROP pcmd_drop
+#define ACTIVATE pcmd_activate
+#define BRA_N_DROP pcmd_bra_n_drop
+#define MOVE_N_DROP pcmd_move_n_drop
+
+#define OP1(opcode,s,d) OP(opcode,s,NOVAR,NOVAR,d)
+#define OP2(opcode,s1,s2,d) OP(opcode,s1,s2,NOVAR,d)
+#define OP3(opcode,s1,s2,s3,d) OP(opcode,s1,s2,s3,d)
+
+
+#define EXCREATOR(exclass) block_createexcreator (exclass, p)
+#define EXFORWARDER(exvar) block_createexforwarder (exvar, p)
+
+
+
+
+/****************** Funktion: addreturnlog ************************************
+
+ f"ugt in den Code einen Aufruf der Methoden-R"uckkehr-Protokollierung
+ ein.
+
+******************************************************************************/
+
+static void addreturnhandling()
+{
+ if (checksync && (method->flags & ACC_SYNCHRONIZED) ) {
+ stack_makesaved ();
+#ifdef USE_THREADS
+ if (method->flags & ACC_STATIC) {
+ varid v = var_create (TYPE_ADDRESS);
+ LOADCONST_A (class, v);
+ BUILTIN1 ( (functionptr) builtin_monitorexit, v, NOVAR);
+ }
+ else {
+ BUILTIN1 ( (functionptr) builtin_monitorexit,
+ local_get (0, TYPE_ADDRESS) , NOVAR);
+ }
+#endif
+ }
+}
+
+
+/*************** Funktion: addreturnexceptionlog *****************************
+
+ f"ugt in den Code einen Aufruf der Methoden-R"uckkehr-Protokollierung
+ mit Exception ein.
+
+******************************************************************************/
+
+static void addreturnexceptionhandling()
+{
+
+ if (runverbose) {
+ varid v;
+
+ stack_makesaved ();
+ v = var_create (TYPE_ADDRESS);
+ LOADCONST_A (method, v);
+ BUILTIN1 ( (functionptr) builtin_displaymethodexception, v, NOVAR);
+ }
+
+ if (checksync && (method->flags & ACC_SYNCHRONIZED) ) {
+ stack_makesaved ();
+#ifdef USE_THREADS
+ if (method->flags & ACC_STATIC) {
+ varid v = var_create (TYPE_ADDRESS);
+ LOADCONST_A (class, v);
+ BUILTIN1 ( (functionptr) builtin_monitorexit, v, NOVAR);
+ }
+ else {
+ BUILTIN1 ( (functionptr) builtin_monitorexit,
+ local_get (0, TYPE_ADDRESS) , NOVAR);
+ }
+#endif
+ }
+}
+
+
+
+/******************************************************************************
+*************** Funktion 'parse' zum Durcharbeiten des Bytecodes **************
+******************************************************************************/
+
+static void parse (basicblock *b)
+{
+ varid v,v1,v2,v3,ve;
+ u4 poolindex;
+ s4 type;
+ u4 p,i;
+ basicblock *target=NULL;
+ bool iswide=false;
+
+ stack_restore (b->stack);
+ subroutine_set (b->subroutine);
+
+
+ switch (b->type) {
+
+ /* Code fuer einen Exception-Forwarder generieren */
+
+
+ case BLOCKTYPE_EXFORWARDER:
+ if (!compileall) {
+ ACTIVATE (b->exvar);
+ stack_repush (b->exvar);
+ stack_makesaved ();
+
+ for (i=0; i<exceptiontablelength; i++) {
+ target = block_find (extable[i].handlerpc);
+ if ( extable[i].startpc <= b->throwpos
+ && extable[i].endpc > b->throwpos) {
+
+ if (!extable[i].catchtype) goto exceptionfits;
+
+ stack_makesaved();
+ v1 = var_create (TYPE_ADDRESS);
+ v2 = var_create (TYPE_ADDRESS);
+ v = var_create (TYPE_INT);
+ MOVE (TYPE_ADDRESS, b->exvar, v1);
+ LOADCONST_A (extable[i].catchtype, v2);
+ BUILTIN2 ((functionptr) builtin_instanceof, v1,v2, v);
+
+ block_reach (target);
+ BRA_N_DROP (CMD_IFNE, v,NOVAR, NOVAR, target);
+ }
+ }
+ target = NULL;
+ }
+ goto exceptionfits;
+
+
+ /* Code fuer einen Exception-Creator generieren */
+ case BLOCKTYPE_EXCREATOR:
+ if (!compileall) {
+ java_objectheader *o = b->exproto;
+ LOADCONST_A (o, stack_push(TYPE_ADDRESS) );
+
+ for (i=0; i<exceptiontablelength; i++) {
+ target = block_find (extable[i].handlerpc);
+ if ( extable[i].startpc <= b->throwpos
+ && extable[i].endpc > b->throwpos) {
+
+ if (!extable[i].catchtype) goto exceptionfits;
+ if (builtin_instanceof (o, extable[i].catchtype) ) goto exceptionfits;
+ }
+ }
+ target = NULL;
+ }
+
+ /*** Der Sprung zum Exception-Handler (oder Methodenbeendigung) ***/
+
+ exceptionfits:
+ if (!compileall) {
+ if (target) {
+ block_reach (target);
+ BRA (CMD_GOTO, NOVAR,NOVAR,NOVAR, target);
+ goto cleanup;
+ }
+
+#ifdef STATISTICS
+ count_pcmd_returnx++;
+#endif
+
+ switch (mreturntype) {
+ case TYPE_INT:
+ addreturnexceptionhandling();
+
+ v1 = var_create (TYPE_INT);
+ LOADCONST_I (0, v1);
+ BRA_N_DROP (CMD_IRETURN, v1,stack_pop(TYPE_ADDRESS), NOVAR, NULL);
+ break;
+ case TYPE_LONG:
+ addreturnexceptionhandling();
+
+ v1 = var_create (TYPE_LONG);
+ LOADCONST_I (0, v1);
+ BRA_N_DROP (CMD_LRETURN, v1,stack_pop(TYPE_ADDRESS), NOVAR, NULL);
+ break;
+ case TYPE_FLOAT:
+ addreturnexceptionhandling();
+
+ v1 = var_create (TYPE_FLOAT);
+ LOADCONST_F (0.0, v1);
+ BRA_N_DROP (CMD_FRETURN, v1,stack_pop(TYPE_ADDRESS), NOVAR, NULL);
+ break;
+ case TYPE_DOUBLE:
+ addreturnexceptionhandling();
+
+ v1 = var_create (TYPE_DOUBLE);
+ LOADCONST_D (0.0, v1);
+ BRA_N_DROP (CMD_DRETURN, v1,stack_pop(TYPE_ADDRESS), NOVAR, NULL);
+ break;
+ case TYPE_ADDRESS:
+ addreturnexceptionhandling();
+
+ v1 = var_create (TYPE_ADDRESS);
+ LOADCONST_A (NULL, v1);
+ BRA_N_DROP (CMD_ARETURN, v1,stack_pop(TYPE_ADDRESS), NOVAR, NULL);
+ break;
+ case TYPE_VOID:
+ addreturnexceptionhandling();
+
+ BRA (CMD_RETURN, NOVAR,stack_pop(TYPE_ADDRESS), NOVAR, NULL);
+ break;
+ }
+ }
+ goto cleanup;
+ }
+
+
+ /* Code fuer einen (normalen) JavaVM - Block generieren */
+
+ p = b->jpc;
+
+
+
+ if ( p==0) {
+ /* Method call protocolling */
+
+ if (runverbose) {
+ stack_makesaved();
+ pcmd_trace (method);
+ }
+
+ /* Synchronization */
+ if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
+ stack_makesaved();
+#ifdef USE_THREADS
+ if (method->flags & ACC_STATIC) {
+ varid v = var_create (TYPE_ADDRESS);
+ LOADCONST_A (class, v);
+ BUILTIN1 ( (functionptr) builtin_monitorenter, v, NOVAR);
+ }
+ else {
+ BUILTIN1 ( (functionptr) builtin_monitorenter,
+ local_get (0, TYPE_ADDRESS), NOVAR );
+ }
+#endif
+ }
+ }
+
+ for (;;) {
+ u1 opcode;
+ u4 nextp;
+
+ opcode = code_get_u1 (p);
+ nextp = p + jcommandsize[opcode];
+
+
+ count_javainstr++;
+
+
+ if (showstack) {
+ printf ("PC: %3d OPCODE: %3d Stack: ",(int) p, (int) opcode);
+ stack_display (stack_get());
+ printf ("\n");
+ }
+
+
+ switch (opcode) {
+
+
+ /*** Pushing constants onto the stack ***/
+
+ case CMD_BIPUSH:
+ LOADCONST_I (code_get_s1 (p+1), stack_push (TYPE_INT) );
+ break;
+
+ case CMD_SIPUSH:
+ LOADCONST_I (code_get_s2 (p+1), stack_push (TYPE_INT) );
+ break;
+
+ case CMD_LDC1: poolindex = code_get_u1 (p+1);
+ goto pushconstantitem;
+ case CMD_LDC2:
+ case CMD_LDC2W: poolindex = code_get_u2 (p+1);
+ pushconstantitem:
+ switch (class_constanttype(class, poolindex)) {
+ case CONSTANT_Integer:
+ { constant_integer *c;
+ c = class_getconstant (class, poolindex, CONSTANT_Integer);
+ LOADCONST_I (c->value, stack_push(TYPE_INT) );
+ }
+ break;
+ case CONSTANT_Long:
+ { constant_long *c;
+ c = class_getconstant (class, poolindex, CONSTANT_Long);
+ LOADCONST_L (c->value, stack_push(TYPE_LONG) );
+ }
+ break;
+ case CONSTANT_Float:
+ { constant_float *c;
+ c = class_getconstant (class, poolindex, CONSTANT_Float);
+ LOADCONST_F (c->value, stack_push(TYPE_FLOAT) );
+ }
+ break;
+ case CONSTANT_Double:
+ { constant_double *c;
+ c = class_getconstant (class, poolindex, CONSTANT_Double);
+ LOADCONST_D (c->value, stack_push(TYPE_DOUBLE) );
+ }
+ break;
+
+ case CONSTANT_String:
+ { unicode *s;
+
+ s = class_getconstant (class, poolindex, CONSTANT_String);
+
+ LOADCONST_A ( literalstring_new (s),
+ stack_push(TYPE_ADDRESS) );
+ }
+ break;
+
+ default: panic ("Invalid constant type to push");
+ }
+ break;
+
+
+ case CMD_ACONST_NULL:
+ LOADCONST_A (0, stack_push (TYPE_ADDRESS) );
+ break;
+
+ case CMD_ICONST_M1:
+ case CMD_ICONST_0:
+ case CMD_ICONST_1:
+ case CMD_ICONST_2:
+ case CMD_ICONST_3:
+ case CMD_ICONST_4:
+ case CMD_ICONST_5:
+ LOADCONST_I (opcode - CMD_ICONST_0, stack_push (TYPE_INT) );
+ break;
+
+ case CMD_LCONST_0:
+ case CMD_LCONST_1:
+#if U8_AVAILABLE
+ LOADCONST_L (opcode - CMD_LCONST_0, stack_push (TYPE_LONG) );
+#else
+ { u8 v;
+ v.low = opcode - CMD_LCONST_0;
+ v.high = 0;
+ LOADCONST_L (v, stack_push(TYPE_LONG) );
+ }
+#endif
+ break;
+
+ case CMD_FCONST_0:
+ case CMD_FCONST_1:
+ case CMD_FCONST_2:
+ LOADCONST_F (opcode - CMD_FCONST_0, stack_push (TYPE_FLOAT) );
+ break;
+
+ case CMD_DCONST_0:
+ case CMD_DCONST_1:
+ LOADCONST_D (opcode - CMD_DCONST_0, stack_push (TYPE_DOUBLE) );
+ break;
+
+
+ /*** Loading variables onto the Stack ***/
+
+ case CMD_ILOAD:
+ if (!iswide) {
+ MOVE ( TYPE_INT,
+ local_get (code_get_u1 (p+1), TYPE_INT),
+ stack_push (TYPE_INT) );
+ }
+ else {
+ MOVE ( TYPE_INT,
+ local_get (code_get_u2 (p+1), TYPE_INT),
+ stack_push (TYPE_INT) );
+ nextp = p+3;
+ iswide = false;
+ }
+ break;
+
+ case CMD_ILOAD_0:
+ case CMD_ILOAD_1:
+ case CMD_ILOAD_2:
+ case CMD_ILOAD_3:
+ MOVE ( TYPE_INT,
+ local_get (opcode - CMD_ILOAD_0, TYPE_INT),
+ stack_push (TYPE_INT) );
+ break;
+
+ case CMD_LLOAD:
+ if (!iswide) {
+ MOVE ( TYPE_LONG,
+ local_get (code_get_u1 (p+1), TYPE_LONG),
+ stack_push (TYPE_LONG) );
+ }
+ else {
+ MOVE ( TYPE_LONG,
+ local_get (code_get_u2 (p+1), TYPE_LONG),
+ stack_push (TYPE_LONG) );
+ nextp = p+3;
+ iswide = false;
+ }
+ break;
+
+ case CMD_LLOAD_0:
+ case CMD_LLOAD_1:
+ case CMD_LLOAD_2:
+ case CMD_LLOAD_3:
+ MOVE ( TYPE_LONG,
+ local_get (opcode - CMD_LLOAD_0, TYPE_LONG),
+ stack_push (TYPE_LONG) );
+ break;
+
+ case CMD_FLOAD:
+ if (!iswide) {
+ MOVE ( TYPE_FLOAT,
+ local_get (code_get_u1 (p+1), TYPE_FLOAT),
+ stack_push (TYPE_FLOAT) );
+ }
+ else {
+ MOVE ( TYPE_FLOAT,
+ local_get (code_get_u2 (p+1), TYPE_FLOAT),
+ stack_push (TYPE_FLOAT) );
+ nextp = p+3;
+ iswide = false;
+ }
+ break;
+
+ case CMD_FLOAD_0:
+ case CMD_FLOAD_1:
+ case CMD_FLOAD_2:
+ case CMD_FLOAD_3:
+ MOVE ( TYPE_FLOAT,
+ local_get (opcode - CMD_FLOAD_0, TYPE_FLOAT),
+ stack_push (TYPE_FLOAT) );
+ break;
+
+ case CMD_DLOAD:
+ if (!iswide) {
+ MOVE ( TYPE_DOUBLE,
+ local_get (code_get_u1 (p+1), TYPE_DOUBLE),
+ stack_push (TYPE_DOUBLE) );
+ }
+ else {
+ MOVE ( TYPE_DOUBLE,
+ local_get (code_get_u2 (p+1), TYPE_DOUBLE),
+ stack_push (TYPE_DOUBLE) );
+ nextp = p+3;
+ iswide = false;
+ }
+ break;
+
+ case CMD_DLOAD_0:
+ case CMD_DLOAD_1:
+ case CMD_DLOAD_2:
+ case CMD_DLOAD_3:
+ MOVE ( TYPE_DOUBLE,
+ local_get (opcode - CMD_DLOAD_0, TYPE_DOUBLE),
+ stack_push (TYPE_DOUBLE) );
+ break;
+
+ case CMD_ALOAD:
+ if (!iswide) {
+ MOVE ( TYPE_ADDRESS,
+ local_get (code_get_u1 (p+1), TYPE_ADDRESS),
+ stack_push (TYPE_ADDRESS) );
+ }
+ else {
+ MOVE ( TYPE_ADDRESS,
+ local_get (code_get_u2 (p+1), TYPE_ADDRESS),
+ stack_push (TYPE_ADDRESS) );
+ nextp = p+3;
+ iswide = false;
+ }
+ break;
+
+ case CMD_ALOAD_0:
+ case CMD_ALOAD_1:
+ case CMD_ALOAD_2:
+ case CMD_ALOAD_3:
+ MOVE ( TYPE_ADDRESS,
+ local_get (opcode - CMD_ALOAD_0, TYPE_ADDRESS),
+ stack_push (TYPE_ADDRESS) );
+ break;
+
+
+ /*** Storing Stack Values into Local Variables ***/
+
+ case CMD_ISTORE:
+ v = stack_pop (TYPE_INT);
+ if (!iswide) {
+ MOVE_N_DROP (TYPE_INT, v,
+ local_get (code_get_u1 (p+1), TYPE_INT) );
+ }
+ else {
+ MOVE_N_DROP (TYPE_INT, v,
+ local_get (code_get_u2 (p+1), TYPE_INT) );
+ iswide=false;
+ nextp = p+3;
+ }
+ break;
+
+ case CMD_ISTORE_0:
+ case CMD_ISTORE_1:
+ case CMD_ISTORE_2:
+ case CMD_ISTORE_3:
+ v = stack_pop (TYPE_INT);
+ MOVE_N_DROP (TYPE_INT,
+ v, local_get (opcode - CMD_ISTORE_0, TYPE_INT) );
+ break;
+
+ case CMD_LSTORE:
+ v = stack_pop (TYPE_LONG);
+ if (!iswide) {
+ MOVE_N_DROP (TYPE_LONG, v,
+ local_get (code_get_u1 (p+1), TYPE_LONG) );
+ }
+ else {
+ MOVE_N_DROP (TYPE_LONG, v,
+ local_get (code_get_u2 (p+1), TYPE_LONG) );
+ iswide=false;
+ nextp = p+3;
+ }
+ break;
+
+ case CMD_LSTORE_0:
+ case CMD_LSTORE_1:
+ case CMD_LSTORE_2:
+ case CMD_LSTORE_3:
+ v = stack_pop (TYPE_LONG);
+ MOVE_N_DROP (TYPE_LONG,
+ v, local_get (opcode - CMD_LSTORE_0, TYPE_LONG) );
+ break;
+
+ case CMD_FSTORE:
+ v = stack_pop (TYPE_FLOAT);
+ if (!iswide) {
+ MOVE_N_DROP (TYPE_FLOAT, v,
+ local_get (code_get_u1 (p+1), TYPE_FLOAT) );
+ }
+ else {
+ MOVE_N_DROP (TYPE_FLOAT, v,
+ local_get (code_get_u2 (p+1), TYPE_FLOAT) );
+ iswide=false;
+ nextp = p+3;
+ }
+ break;
+
+ case CMD_FSTORE_0:
+ case CMD_FSTORE_1:
+ case CMD_FSTORE_2:
+ case CMD_FSTORE_3:
+ v = stack_pop (TYPE_FLOAT);
+ MOVE_N_DROP (TYPE_FLOAT,
+ v, local_get (opcode - CMD_FSTORE_0, TYPE_FLOAT) );
+ break;
+
+ case CMD_DSTORE:
+ v = stack_pop (TYPE_DOUBLE);
+ if (!iswide) {
+ MOVE_N_DROP (TYPE_DOUBLE, v,
+ local_get (code_get_u1 (p+1), TYPE_DOUBLE) );
+ }
+ else {
+ MOVE_N_DROP (TYPE_DOUBLE, v,
+ local_get (code_get_u2 (p+1), TYPE_DOUBLE) );
+ iswide=false;
+ nextp = p+3;
+ }
+ break;
+
+ case CMD_DSTORE_0:
+ case CMD_DSTORE_1:
+ case CMD_DSTORE_2:
+ case CMD_DSTORE_3:
+ v = stack_pop (TYPE_DOUBLE);
+ MOVE_N_DROP (TYPE_DOUBLE,
+ v, local_get (opcode - CMD_DSTORE_0, TYPE_DOUBLE) );
+ break;
+
+ case CMD_ASTORE:
+ v = stack_pop (TYPE_ADDRESS);
+ if (!iswide) {
+ MOVE_N_DROP (TYPE_ADDRESS, v,
+ local_get (code_get_u1 (p+1), TYPE_ADDRESS) );
+ }
+ else {
+ MOVE_N_DROP (TYPE_ADDRESS, v,
+ local_get (code_get_u2 (p+1), TYPE_ADDRESS) );
+ iswide=false;
+ nextp = p+3;
+ }
+ break;
+
+ case CMD_ASTORE_0:
+ case CMD_ASTORE_1:
+ case CMD_ASTORE_2:
+ case CMD_ASTORE_3:
+ v = stack_pop (TYPE_ADDRESS);
+ MOVE_N_DROP (TYPE_ADDRESS,
+ v, local_get (opcode - CMD_ASTORE_0, TYPE_ADDRESS) );
+ break;
+
+
+ case CMD_IINC:
+ if (!iswide) {
+ v1 = local_get (code_get_u1 (p+1), TYPE_INT);
+ IINC (code_get_s1 (p+2), v1 );
+ DROP (v1);
+ }
+ else {
+ v1 = local_get (code_get_u2 (p+1), TYPE_INT);
+ IINC (code_get_s2 (p+3), v1 );
+ DROP (v1);
+ iswide = false;
+ nextp = p+5;
+ }
+ break;
+
+
+ /*** Wider index for Loading, Storing and Incrementing ***/
+
+ case CMD_WIDE:
+ iswide=true;
+ nextp = p+1;
+ break;
+
+
+ /******************** Managing Arrays **************************/
+
+ case CMD_NEWARRAY:
+ v1 = stack_pop (TYPE_INT);
+ BRA (CMD_IFLT, v1,NOVAR, NOVAR, EXCREATOR(proto_java_lang_NegativeArraySizeException) );
+
+ stack_makesaved ();
+ v = stack_push (TYPE_ADDRESS);
+ switch ( code_get_s1 (p+1) ) {
+ case 4: BUILTIN1 ((functionptr) builtin_newarray_boolean, v1, v);
+ break;
+ case 5: BUILTIN1 ((functionptr) builtin_newarray_char, v1, v);
+ break;
+ case 6: BUILTIN1 ((functionptr) builtin_newarray_float, v1, v);
+ break;
+ case 7: BUILTIN1 ((functionptr) builtin_newarray_double, v1, v);
+ break;
+ case 8: BUILTIN1 ((functionptr) builtin_newarray_byte, v1, v);
+ break;
+ case 9: BUILTIN1 ((functionptr) builtin_newarray_short, v1, v);
+ break;
+ case 10: BUILTIN1 ((functionptr) builtin_newarray_int, v1, v);
+ break;
+ case 11: BUILTIN1 ((functionptr) builtin_newarray_long, v1, v);
+ break;
+ default: panic ("Invalid array-type to create");
+ }
+
+ BRA (CMD_IFNULL, v,NOVAR, NOVAR, EXCREATOR(proto_java_lang_OutOfMemoryError) );
+
+ break;
+
+ case CMD_ANEWARRAY:
+ poolindex = code_get_u2(p+1);
+ if (class_constanttype (class, poolindex) == CONSTANT_Arraydescriptor) {
+ /* anewarray mit Array-Typ! */
+ constant_arraydescriptor *desc =
+ class_getconstant (class, poolindex, CONSTANT_Arraydescriptor);
+
+ v1 = stack_pop (TYPE_INT);
+ BRA (CMD_IFLT, v1,NOVAR, NOVAR, EXCREATOR(proto_java_lang_NegativeArraySizeException) );
+
+ v2 = var_create (TYPE_ADDRESS);
+ LOADCONST_A (desc, v2);
+
+ stack_makesaved ();
+ v = stack_push (TYPE_ADDRESS);
+ BUILTIN2 ((functionptr) builtin_newarray_array, v1,v2, v);
+ BRA (CMD_IFNULL, v,NOVAR, NOVAR, EXCREATOR(proto_java_lang_OutOfMemoryError) );
+ }
+ else {
+ classinfo *c = class_getconstant (class, poolindex, CONSTANT_Class);
+
+ v1 = stack_pop (TYPE_INT);
+ BRA (CMD_IFLT, v1,NOVAR, NOVAR, EXCREATOR(proto_java_lang_NegativeArraySizeException) );
+
+ v2 = var_create (TYPE_ADDRESS);
+ LOADCONST_A (c, v2);
+
+ stack_makesaved ();
+ v = stack_push (TYPE_ADDRESS);
+ BUILTIN2 ((functionptr) builtin_anewarray, v1,v2, v);
+ BRA (CMD_IFNULL, v,NOVAR, NOVAR, EXCREATOR(proto_java_lang_OutOfMemoryError) );
+ }
+
+ break;
+
+
+ case CMD_MULTIANEWARRAY:
+ { constant_arraydescriptor *desc =
+ class_getconstant (class, code_get_u2(p+1), CONSTANT_Arraydescriptor);
+ int i, n = code_get_u1 (p+3);
+ varid dims = var_create (TYPE_ADDRESS); /* array for dimensions */
+ varid dimsdim = var_create (TYPE_INT); /* groesse des arrays */
+
+ stack_makesaved ();
+ LOADCONST_I (n, dimsdim);
+ BUILTIN1 ((functionptr) builtin_newarray_int, dimsdim, dims);
+ BRA (CMD_IFNULL, dims,NOVAR, NOVAR, EXCREATOR(proto_java_lang_OutOfMemoryError) );
+
+ for (i=0; i<n; i++) {
+ varid dimn = stack_pop (TYPE_INT);
+ BRA (CMD_IFLT, dimn,NOVAR, NOVAR, EXCREATOR(proto_java_lang_NegativeArraySizeException) );
+
+ LOADCONST_I ((n-i)-1, dimsdim);
+ OP3 (CMD_IASTORE, dims, dimsdim, dimn, NOVAR);
+ DROP (dimsdim);
+ DROP (dimn);
+ }
+
+ v = stack_push (TYPE_ADDRESS);
+
+ v1 = var_create (TYPE_ADDRESS);
+ LOADCONST_A (desc, v1);
+
+ BUILTIN2 ((functionptr) builtin_multianewarray, dims, v1, v);
+ BRA (CMD_IFNULL, v,NOVAR, NOVAR, EXCREATOR(proto_java_lang_OutOfMemoryError) );
+
+ }
+ break;
+
+
+ case CMD_ARRAYLENGTH:
+ v = stack_pop (TYPE_ADDRESS);
+ if (checknull) {
+#ifdef STATISTICS
+ count_check_null++;
+#endif
+ BRA (CMD_IFNULL, v,NOVAR, NOVAR, EXCREATOR(proto_java_lang_NullPointerException) );
+ }
+ OP1 (opcode, v, stack_push (TYPE_INT) );
+ DROP (v);
+ break;
+
+ case CMD_AALOAD:
+ type = TYPE_ADDRESS; goto do_aXload;
+ case CMD_LALOAD:
+ type = TYPE_LONG; goto do_aXload;
+ case CMD_FALOAD:
+ type = TYPE_FLOAT; goto do_aXload;
+ case CMD_DALOAD:
+ type = TYPE_DOUBLE; goto do_aXload;
+ case CMD_IALOAD:
+ case CMD_BALOAD:
+ case CMD_CALOAD:
+ case CMD_SALOAD:
+ type = TYPE_INT; goto do_aXload;
+ do_aXload:
+ v2 = stack_pop (TYPE_INT);
+ v1 = stack_pop (TYPE_ADDRESS);
+ if (checknull) {
+#ifdef STATISTICS
+ count_check_null++;
+#endif
+ BRA (CMD_IFNULL, v1,NOVAR, NOVAR, EXCREATOR(proto_java_lang_NullPointerException) );
+ }
+ if (checkbounds) {
+#ifdef STATISTICS
+ count_check_bound++;
+#endif
+ v = var_create (TYPE_INT);
+ OP1 (CMD_ARRAYLENGTH, v1, v);
+ BRA (CMD_IF_UCMPGE, v2,v, NOVAR, EXCREATOR(proto_java_lang_ArrayIndexOutOfBoundsException) );
+ DROP (v);
+ }
+ OP2 (opcode, v1,v2, stack_push (type) );
+ DROP (v1);
+ DROP (v2);
+ break;
+
+ case CMD_AASTORE:
+ type = TYPE_ADDRESS; goto do_aXstore;
+ case CMD_LASTORE:
+ type = TYPE_LONG; goto do_aXstore;
+ case CMD_FASTORE:
+ type = TYPE_FLOAT; goto do_aXstore;
+ case CMD_DASTORE:
+ type = TYPE_DOUBLE; goto do_aXstore;
+ case CMD_IASTORE:
+ case CMD_BASTORE:
+ case CMD_CASTORE:
+ case CMD_SASTORE:
+ type = TYPE_INT; goto do_aXstore;
+ do_aXstore:
+ v3 = stack_pop (type);
+ v2 = stack_pop (TYPE_INT);
+ v1 = stack_pop (TYPE_ADDRESS);
+ if (checknull) {
+#ifdef STATISTICS
+ count_check_null++;
+#endif
+ BRA (CMD_IFNULL, v1,NOVAR, NOVAR, EXCREATOR(proto_java_lang_NullPointerException) );
+ }
+ if (checkbounds) {
+#ifdef STATISTICS
+ count_check_bound++;
+#endif
+ v = var_create (TYPE_INT);
+ OP1 (CMD_ARRAYLENGTH, v1, v);
+ BRA (CMD_IF_UCMPGE, v2,v, NOVAR, EXCREATOR(proto_java_lang_ArrayIndexOutOfBoundsException) );
+ DROP (v);
+ }
+
+ if (opcode!=CMD_AASTORE) {
+ OP3 (opcode, v1,v2,v3, NOVAR);
+ DROP (v1);
+ DROP (v2);
+ DROP (v3);
+ } else {
+ stack_makesaved ();
+
+ v = var_create (TYPE_INT);
+ BUILTIN3 ((functionptr) builtin_aastore, v1,v2,v3, v);
+ BRA (CMD_IFEQ, v,NOVAR, NOVAR, EXCREATOR(proto_java_lang_ArrayStoreException) );
+ DROP (v);
+ }
+
+ break;
+
+
+
+ /******************* Stack instructions **************************/
+
+ case CMD_NOP:
+ break;
+
+ case CMD_POP:
+ v1 = stack_popany (1);
+ DROP (v1);
+ break;
+
+ case CMD_POP2:
+ { int varcount, i;
+ varid vararray[2];
+
+ varcount = stack_popmany (vararray, 2);
+ for (i=0; i<varcount; i++) DROP(vararray[i]);
+ }
+ break;
+
+ case CMD_DUP:
+ v1 = stack_popany(1);
+ stack_repush (v1);
+ v = stack_push ( var_type (v1) );
+ MOVE (var_type(v1), v1,v);
+ break;
+
+ case CMD_DUP2:
+ { int varcount, i;
+ varid vararray[2];
+
+ varcount = stack_popmany (vararray, 2);
+ stack_repushmany (varcount, vararray);
+ for (i=0; i<varcount; i++) {
+ v = stack_push ( var_type(vararray[varcount-1-i]) );
+ MOVE ( var_type(v), vararray[varcount-1-i], v);
+ }
+ }
+ break;
+
+ case CMD_DUP_X1:
+ v1 = stack_popany(1);
+ v2 = stack_popany(1);
+
+ stack_repush (v1);
+ stack_repush (v2);
+ v = stack_push ( var_type (v1) );
+ MOVE (var_type(v1), v1,v);
+ break;
+
+ case CMD_DUP2_X1:
+ { int varcount, i;
+ varid vararray[2];
+
+ varcount = stack_popmany (vararray, 2);
+ v3 = stack_popany (1);
+ stack_repushmany (varcount, vararray);
+ stack_repush (v3);
+ for (i=0; i<varcount; i++) {
+ v = stack_push ( var_type(vararray[varcount-1-i]) );
+ MOVE ( var_type(v), vararray[varcount-1-i], v);
+ }
+ }
+ break;
+
+ case CMD_DUP_X2:
+ { int varcount;
+ varid vararray[2];
+
+ v1 = stack_popany(1);
+ varcount = stack_popmany (vararray, 2);
+ stack_repush (v1);
+ stack_repushmany (varcount, vararray);
+ MOVE (var_type(v1), v1, stack_push(var_type(v1)) );
+ }
+ break;
+
+ case CMD_DUP2_X2:
+ { int varcount1, varcount2, i;
+ varid vararray1[2],vararray2[2];
+
+ varcount1 = stack_popmany (vararray1, 2);
+ varcount2 = stack_popmany (vararray2, 2);
+ stack_repushmany (varcount2, vararray2);
+ stack_repushmany (varcount1, vararray1);
+ for (i=0; i<varcount1; i++) {
+ v = stack_push ( var_type(vararray1[varcount1-1-i]) );
+ MOVE ( var_type(v), vararray1[varcount1-1-i], v);
+ }
+ }
+ break;
+
+ case CMD_SWAP:
+ v1 = stack_popany (1);
+ v2 = stack_popany (1);
+ stack_repush (v1);
+ stack_repush (v2);
+
+ break;
+
+
+ /*** Arithmetic & logical instructions ***/
+
+ case CMD_IDIV:
+ case CMD_IREM:
+ v2 = stack_pop (TYPE_INT);
+ v1 = stack_pop (TYPE_INT);
+ BRA (CMD_IFEQ, v2,NOVAR, NOVAR, EXCREATOR(proto_java_lang_ArithmeticException) );
+
+ if (SUPPORT_DIVISION) {
+ OP2 (opcode, v1,v2, stack_push(TYPE_INT));
+ DROP (v1);
+ DROP (v2);
+ }
+ else {
+ stack_makesaved ();
+ BUILTIN2 (
+ (opcode == CMD_IDIV) ?
+ ((functionptr) builtin_idiv)
+ : ((functionptr) builtin_irem)
+ ,v1,v2, stack_push (TYPE_INT) );
+ }
+ break;
+
+ case CMD_LDIV:
+ case CMD_LREM:
+ v2 = stack_pop (TYPE_LONG);
+ v1 = stack_pop (TYPE_LONG);
+ BRA (CMD_IFEQL, v2,NOVAR, NOVAR, EXCREATOR(proto_java_lang_ArithmeticException) );
+
+ if (SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_MULDIV) {
+ OP2 (opcode, v1,v2, stack_push(TYPE_LONG));
+ DROP (v1);
+ DROP (v2);
+ }
+ else {
+ stack_makesaved ();
+ BUILTIN2 (
+ (opcode == CMD_LDIV) ?
+ ((functionptr) builtin_ldiv)
+ : ((functionptr) builtin_lrem)
+ ,v1,v2, stack_push (TYPE_LONG) );
+ }
+ break;
+
+
+ /*** Control transfer instructions ***/
+
+ case CMD_IFEQ:
+ case CMD_IFLT:
+ case CMD_IFLE:
+ case CMD_IFNE:
+ case CMD_IFGT:
+ case CMD_IFGE:
+ target = block_find (p + code_get_s2 (p+1) );
+ v = stack_pop (TYPE_INT);
+ block_reach (target);
+ BRA_N_DROP (opcode, v,NOVAR, NOVAR, target);
+ break;
+
+ case CMD_IFNULL:
+ case CMD_IFNONNULL:
+ target = block_find (p + code_get_s2 (p+1));
+ v = stack_pop (TYPE_ADDRESS);
+ block_reach (target);
+ BRA_N_DROP (opcode, v,NOVAR, NOVAR, target);
+ break;
+
+ case CMD_IF_ICMPEQ:
+ case CMD_IF_ICMPNE:
+ case CMD_IF_ICMPLT:
+ case CMD_IF_ICMPGT:
+ case CMD_IF_ICMPLE:
+ case CMD_IF_ICMPGE:
+ target = block_find (p + code_get_s2 (p+1) );
+ v2 = stack_pop (TYPE_INT);
+ v1 = stack_pop (TYPE_INT);
+ block_reach (target);
+ BRA_N_DROP (opcode, v1,v2, NOVAR, target );
+ break;
+
+ case CMD_IF_ACMPEQ:
+ case CMD_IF_ACMPNE:
+ target = block_find (p + code_get_s2 (p+1) );
+ v2 = stack_pop (TYPE_ADDRESS);
+ v1 = stack_pop (TYPE_ADDRESS);
+ block_reach (target);
+ BRA_N_DROP (opcode, v1,v2, NOVAR, target);
+ break;
+
+
+ case CMD_GOTO:
+ target = block_find (p + code_get_s2 (p+1) );
+ goto do_goto;
+ case CMD_GOTO_W:
+ target = block_find (p + code_get_s4 (p+1) );
+ do_goto:
+ block_reach (target);
+ BRA (CMD_GOTO, NOVAR,NOVAR, NOVAR, target );
+ goto cleanup;
+
+
+ case CMD_JSR:
+ target = block_find (p + code_get_s2 (p+1) );
+ goto do_jsr;
+ case CMD_JSR_W:
+ target = block_find (p + code_get_s4 (p+1) );
+ do_jsr:
+ {
+ subroutineinfo *sub;
+
+ ACTIVATE (stack_push (TYPE_ADDRESS) );
+
+ sub = target->subroutine;
+ if (!sub) {
+ sub = subroutine_new();
+ target->subroutine = sub;
+ }
+
+ subroutine_set (sub);
+ block_reach (target);
+ subroutine_set (b->subroutine);
+
+ BRA (CMD_JSR, NOVAR,NOVAR, stack_pop(TYPE_ADDRESS), target );
+
+ while (! stack_isempty() ) {
+ v = stack_popany ( stack_topslots() );
+ DROP (v);
+ }
+
+ if (sub->returnfinished) {
+ stackinfo *s = sub->returnstack;
+ stack_restore (s);
+ while (s) {
+ ACTIVATE (s->var);
+ s = s->prev;
+ }
+ block_reach ( block_find(nextp) );
+ }
+ else {
+ basicblock *n = block_find(nextp);
+ n -> subroutine = b->subroutine;
+
+ chain_addlast (sub->callers, n );
+ }
+
+ }
+ goto cleanup;
+
+
+ case CMD_RET:
+ if (!iswide) {
+ v = local_get (code_get_u1 (p+1), TYPE_ADDRESS);
+ }
+ else {
+ v = local_get (code_get_u2 (p+1), TYPE_ADDRESS);
+ nextp = p+3;
+ iswide = false;
+ }
+
+ {
+ subroutineinfo *sub;
+ basicblock *bb;
+
+ sub = b->subroutine;
+ if (!sub) panic ("RET outside of subroutine");
+ if (sub->returnfinished) panic ("Multiple RET in a subroutine");
+
+ sub->returnfinished = true;
+ sub->returnstack = stack_get() ;
+
+ while ( (bb = chain_first(sub->callers)) ) {
+ chain_remove (sub->callers);
+
+ subroutine_set (bb->subroutine);
+ block_reach ( bb );
+ subroutine_set (sub);
+ }
+
+ BRA (CMD_RET, v,NOVAR, NOVAR, NULL);
+ }
+ goto cleanup;
+
+
+
+ /*************** Function Return **************/
+
+ case CMD_IRETURN:
+ addreturnhandling();
+
+ v = stack_pop (TYPE_INT);
+ ve = var_create (TYPE_ADDRESS);
+ LOADCONST_A (NULL, ve);
+ BRA_N_DROP (opcode, v, ve, NOVAR, NULL);
+#ifdef STATISTICS
+ count_pcmd_return++;
+#endif
+ goto cleanup;
+
+ case CMD_LRETURN:
+ addreturnhandling();
+
+ v = stack_pop (TYPE_LONG);
+ var_proposereg (v, reg_parlistresult(TYPE_LONG) );
+ ve = var_create (TYPE_ADDRESS);
+ LOADCONST_A (NULL, ve);
+ var_proposereg (ve, reg_parlistexception() );
+ BRA_N_DROP (opcode, v, ve, NOVAR, NULL);
+#ifdef STATISTICS
+ count_pcmd_return++;
+#endif
+ goto cleanup;
+
+ case CMD_FRETURN:
+ addreturnhandling();
+
+ v = stack_pop (TYPE_FLOAT);
+ var_proposereg (v, reg_parlistresult(TYPE_FLOAT) );
+ ve = var_create (TYPE_ADDRESS);
+ LOADCONST_A (NULL, ve);
+ var_proposereg (ve, reg_parlistexception() );
+ BRA_N_DROP (opcode, v, ve, NOVAR, NULL);
+#ifdef STATISTICS
+ count_pcmd_return++;
+#endif
+ goto cleanup;
+
+ case CMD_DRETURN:
+ addreturnhandling();
+
+ v = stack_pop (TYPE_DOUBLE);
+ var_proposereg (v, reg_parlistresult(TYPE_DOUBLE) );
+ ve = var_create (TYPE_ADDRESS);
+ LOADCONST_A (NULL, ve);
+ var_proposereg (ve, reg_parlistexception() );
+ BRA_N_DROP (opcode, v, ve, NOVAR, NULL);
+#ifdef STATISTICS
+ count_pcmd_return++;
+#endif
+ goto cleanup;
+
+ case CMD_ARETURN:
+ addreturnhandling();
+
+ v = stack_pop (TYPE_ADDRESS);
+ var_proposereg (v, reg_parlistresult(TYPE_ADDRESS) );
+ ve = var_create (TYPE_ADDRESS);
+ LOADCONST_A (NULL, ve);
+ var_proposereg (ve, reg_parlistexception() );
+ BRA_N_DROP (opcode, v, ve, NOVAR, NULL);
+ goto cleanup;
+#ifdef STATISTICS
+ count_pcmd_return++;
+#endif
+
+ case CMD_RETURN:
+ addreturnhandling();
+
+ ve = var_create (TYPE_ADDRESS);
+ LOADCONST_A (NULL, ve);
+ var_proposereg (ve, reg_parlistexception() );
+ BRA_N_DROP (opcode, NOVAR,ve, NOVAR, NULL);
+#ifdef STATISTICS
+ count_pcmd_return++;
+#endif
+ goto cleanup;
+
+
+ case CMD_BREAKPOINT:
+ break;
+
+
+
+ /**************** Table Jumping *****************/
+
+ case CMD_LOOKUPSWITCH:
+ { u4 p2 = ALIGN((p+1), 4);
+ basicblock *defaulttarget;
+ u4 num, i;
+
+ defaulttarget = block_find (p + code_get_s4 (p2) );
+ num = code_get_s4 (p2+4);
+
+ v = stack_pop (TYPE_INT);
+ for (i=0; i<num; i++) {
+ s4 value = code_get_s4 (p2 + 8 + 8*i);
+ target = block_find (p + code_get_s4 (p2 + 8 + 4 + 8*i) );
+
+ v1 = var_create (TYPE_INT);
+ v2 = var_create (TYPE_INT);
+ MOVE (TYPE_INT, v, v1);
+ LOADCONST_I (value, v2);
+ block_reach (target);
+ BRA_N_DROP (CMD_IF_ICMPEQ, v1,v2, NOVAR, target );
+ }
+
+ DROP (v);
+ block_reach (defaulttarget);
+ BRA (CMD_GOTO, NOVAR,NOVAR, NOVAR, defaulttarget );
+
+ nextp = p2 + 8 + 8*num;
+ goto cleanup;
+ }
+ break;
+
+ case CMD_TABLESWITCH:
+ { u4 p2 = ALIGN((p+1), 4);
+ basicblock *target;
+ basicblock **targets;
+ s4 low,high, i;
+
+ low = code_get_s4 (p2+4);
+ high = code_get_s4 (p2+8);
+ if (high<low) panic ("Tablejump range invalid");
+
+ v = stack_pop (TYPE_INT);
+
+ target = block_find (p + code_get_s4 (p2) );
+ block_reach(target);
+
+ v1 = var_create (TYPE_INT);
+ LOADCONST_I (high, v1);
+ BRA (CMD_IF_ICMPGT, v,v1, NOVAR, target);
+ DROP (v1);
+
+ if (low!=0) {
+ v1 = var_create (TYPE_INT);
+ v2 = var_create (TYPE_INT);
+ LOADCONST_I (low, v1);
+ OP2 (CMD_ISUB, v,v1, v2);
+ DROP (v1);
+ DROP (v);
+ v = v2;
+ }
+ BRA (CMD_IFLT, v,NOVAR, NOVAR, target);
+
+ targets = DMNEW (basicblock*, (high-low)+1);
+ for (i=0; i < (high-low)+1; i++) {
+ target = block_find (p + code_get_s4 (p2 + 12 + 4*i) );
+ block_reach (target);
+
+ targets[i] = target;
+ }
+
+ TABLEJUMP (v, (high-low)+1, targets);
+ DROP (v);
+
+ nextp = p2 + 12 + 4 * ((high-low)+1);
+ goto cleanup;
+ }
+ break;
+
+
+ /************ Manipulating Object Fields ********/
+
+ case CMD_PUTSTATIC:
+ case CMD_GETSTATIC:
+ case CMD_PUTFIELD:
+ case CMD_GETFIELD:
+
+ poolindex = code_get_u2 (p+1);
+ { constant_FMIref *fr;
+ fieldinfo *fi;
+
+ fr = class_getconstant (class, poolindex, CONSTANT_Fieldref);
+ fi = class_findfield (fr->class, fr->name, fr->descriptor);
+
+ switch (opcode) {
+ case CMD_PUTSTATIC:
+ compiler_addinitclass (fr->class);
+
+ v1 = var_create (TYPE_ADDRESS);
+ v = stack_pop (fi->type);
+ LOADCONST_A (&(fi->value), v1);
+
+ MEM (CMD_PUTFIELD, fi->type, v1,v, NOVAR, 0);
+ DROP (v);
+ DROP (v1);
+ break;
+
+ case CMD_GETSTATIC:
+ compiler_addinitclass (fr->class);
+
+ v1 = var_create (TYPE_ADDRESS);
+ v = stack_push (fi->type);
+ LOADCONST_A (&(fi->value), v1);
+
+ MEM (CMD_GETFIELD, fi->type, v1,NOVAR, v, 0);
+ DROP (v1);
+ break;
+
+
+ case CMD_PUTFIELD:
+ v = stack_pop (fi->type);
+ v1 = stack_pop (TYPE_ADDRESS);
+ if (checknull) {
+#ifdef STATISTICS
+ count_check_null++;
+#endif
+ BRA (CMD_IFNULL, v1,NOVAR, NOVAR, EXCREATOR(proto_java_lang_NullPointerException) );
+ }
+ MEM (CMD_PUTFIELD, fi->type, v1,v, NOVAR, fi->offset);
+ DROP (v);
+ DROP (v1);
+ break;
+
+ case CMD_GETFIELD:
+ v1 = stack_pop (TYPE_ADDRESS);
+ v = stack_push (fi->type);
+ if (checknull) {
+#ifdef STATISTICS
+ count_check_null++;
+#endif
+ BRA (CMD_IFNULL, v1,NOVAR, NOVAR, EXCREATOR(proto_java_lang_NullPointerException) );
+ }
+ MEM (CMD_GETFIELD, fi->type, v1,NOVAR, v, fi->offset);
+ DROP (v1);
+ break;
+
+
+ }
+ }
+ break;
+
+
+ /*** Method invocation ***/
+
+ case CMD_INVOKEVIRTUAL:
+ case CMD_INVOKESPECIAL:
+ case CMD_INVOKESTATIC:
+ case CMD_INVOKEINTERFACE:
+
+ count_calls ++;
+
+ { constant_FMIref *mr;
+ methodinfo *mi;
+ u4 i;
+ s4 paramnum;
+ u1 *paramtypes;
+ s4 returntype;
+ varid *params;
+ bool stat = (opcode == CMD_INVOKESTATIC);
+
+ if (opcode==CMD_INVOKEINTERFACE) {
+ poolindex = code_get_u2 (p+1);
+ mr = class_getconstant (class, poolindex, CONSTANT_InterfaceMethodref);
+ }
+ else {
+ poolindex = code_get_u2 (p+1);
+ mr = class_getconstant (class, poolindex, CONSTANT_Methodref);
+ }
+
+ mi = class_findmethod (mr->class, mr->name, mr->descriptor);
+
+ if ( ((mi->flags & ACC_STATIC) != 0) != stat)
+ panic ("Static/Nonstatic mismatch on method call");
+
+ descriptor2types (mi->descriptor, stat,
+ ¶mnum, ¶mtypes, &returntype);
+ mi->paramcount = paramnum;
+
+ params = DMNEW (varid, paramnum);
+ for (i=0; i<paramnum; i++) {
+ params[paramnum-i-1] = stack_pop (paramtypes[paramnum-i-1]);
+ }
+
+ stack_makesaved();
+
+ if ((!stat) && checknull) {
+#ifdef STATISTICS
+ count_check_null++;
+#endif
+ BRA (CMD_IFNULL, params[0],NOVAR, NOVAR, EXCREATOR(proto_java_lang_NullPointerException) );
+ }
+
+ ve = var_create (TYPE_ADDRESS);
+ if (returntype != TYPE_VOID) {
+ v = stack_push (returntype);
+ METHOD (opcode, mi, NULL, paramnum, params, v, ve);
+ }
+ else {
+ METHOD (opcode, mi, NULL, paramnum, params, NOVAR, ve);
+ }
+
+ BRA (CMD_IFNONNULL, ve,NOVAR, NOVAR, EXFORWARDER(ve) );
+ DROP (ve);
+
+ }
+ break;
+
+
+ /********* Exception Handling *****************/
+
+ case CMD_ATHROW:
+ v = stack_pop (TYPE_ADDRESS);
+ if (checknull) {
+#ifdef STATISTICS
+ count_check_null++;
+#endif
+ BRA (CMD_IFNULL, v,NOVAR, NOVAR, EXCREATOR(proto_java_lang_NullPointerException) );
+ }
+ BRA (CMD_GOTO, NOVAR,NOVAR, NOVAR, EXFORWARDER (v) );
+ DROP (v);
+ goto cleanup;
+
+
+ /***** Miscellaneous Object Operations ****/
+
+ case CMD_NEW:
+ poolindex = code_get_u2 (p+1);
+ { classinfo *ci;
+
+ ci = class_getconstant (class, poolindex, CONSTANT_Class);
+
+ v1 = var_create (TYPE_ADDRESS);
+ LOADCONST_A (ci, v1);
+
+ stack_makesaved ();
+
+ v = stack_push (TYPE_ADDRESS);
+ BUILTIN1 ((functionptr) builtin_new, v1, v);
+ BRA (CMD_IFNULL, v,NOVAR, NOVAR, EXCREATOR(proto_java_lang_OutOfMemoryError) );
+
+ }
+ break;
+
+
+ case CMD_CHECKCAST:
+ poolindex = code_get_u2 (p+1);
+
+ if (class_constanttype (class, poolindex) == CONSTANT_Arraydescriptor) {
+ /* cast-check auf Array-Typ! */
+
+ constant_arraydescriptor *desc =
+ class_getconstant (class, poolindex, CONSTANT_Arraydescriptor);
+
+ v = stack_pop (TYPE_ADDRESS);
+ stack_repush (v);
+ v1 = var_create (TYPE_ADDRESS);
+ MOVE (TYPE_ADDRESS, v,v1);
+ v2 = var_create (TYPE_ADDRESS);
+ LOADCONST_A (desc, v2);
+
+ stack_makesaved ();
+ ve = var_create (TYPE_INT);
+ BUILTIN2 ((functionptr) builtin_checkarraycast, v1,v2, ve);
+
+ BRA (CMD_IFEQ,ve,NOVAR, NOVAR, EXCREATOR(proto_java_lang_ClassCastException) );
+ DROP (ve);
+ }
+ else {
+ /* cast-check auf Object-Typ */
+
+ classinfo *ci = class_getconstant (class, poolindex, CONSTANT_Class);
+
+ v = stack_pop (TYPE_ADDRESS);
+ stack_repush (v);
+ v1 = var_create (TYPE_ADDRESS);
+ MOVE (TYPE_ADDRESS, v, v1);
+ v2 = var_create (TYPE_ADDRESS);
+ LOADCONST_A (ci, v2);
+
+ stack_makesaved ();
+ ve = var_create (TYPE_INT);
+ BUILTIN2 ((functionptr) builtin_checkcast, v1,v2, ve);
+
+ BRA (CMD_IFEQ,ve,NOVAR, NOVAR, EXCREATOR(proto_java_lang_ClassCastException) );
+ DROP (ve);
+ }
+
+ break;
+
+
+ case CMD_INSTANCEOF:
+ poolindex = code_get_u2 (p+1);
+
+ if (class_constanttype (class, poolindex) == CONSTANT_Arraydescriptor) {
+ /* cast-check auf Array-Typ! */
+
+ constant_arraydescriptor *desc =
+ class_getconstant (class, poolindex, CONSTANT_Arraydescriptor);
+
+ v = stack_pop (TYPE_ADDRESS);
+ v1 = var_create (TYPE_ADDRESS);
+ LOADCONST_A (desc, v1);
+
+ stack_makesaved ();
+
+ BUILTIN2 ((functionptr) builtin_arrayinstanceof, v,v1,
+ stack_push (TYPE_INT) );
+ }
+ else {
+ classinfo *ci;
+ ci = class_getconstant (class, poolindex, CONSTANT_Class);
+
+ v = stack_pop (TYPE_ADDRESS);
+ v1 = var_create (TYPE_ADDRESS);
+ LOADCONST_A (ci, v1);
+
+ stack_makesaved ();
+
+ BUILTIN2 ((functionptr) builtin_instanceof, v,v1,
+ stack_push (TYPE_INT) );
+ }
+ break;
+
+
+
+
+ /*************** Monitors ************************/
+
+ case CMD_MONITORENTER:
+ if (checksync) {
+ v = stack_pop (TYPE_ADDRESS);
+ if (checknull) {
+#ifdef STATISTICS
+ count_check_null++;
+#endif
+ BRA (CMD_IFNULL, v, NOVAR, NOVAR,
+ EXCREATOR(proto_java_lang_NullPointerException));
+ }
+ BUILTIN1 ((functionptr) builtin_monitorenter, v, NOVAR);
+ } else {
+ DROP (stack_pop (TYPE_ADDRESS));
+ }
+ break;
+
+ case CMD_MONITOREXIT:
+ if (checksync) {
+ BUILTIN1 ((functionptr) builtin_monitorexit,
+ stack_pop(TYPE_ADDRESS), NOVAR );
+ } else {
+ DROP (stack_pop (TYPE_ADDRESS));
+ }
+ break;
+
+
+
+
+ /************** any other Basic-Operation **********/
+
+
+ default:
+ {
+ stdopdescriptor *s = stdopdescriptors[opcode];
+ if (s) {
+ v2 = NULL;
+ if (s->type_s2 != TYPE_VOID) v2 = stack_pop(s->type_s2);
+ v1 = stack_pop(s->type_s1);
+
+ if (s->supported) {
+ v = stack_push (s->type_d);
+ if (v2) {
+ OP2 (opcode, v1,v2, v);
+ DROP (v1);
+ DROP (v2);
+ }
+ else {
+ OP1 (opcode, v1, v);
+ DROP (v1);
+ }
+ }
+ else {
+ stack_makesaved ();
+ v = stack_push (s->type_d);
+ if (v2) {
+ BUILTIN2 (s->builtin, v1,v2, v);
+ }
+ else {
+ BUILTIN1 (s->builtin, v1, v);
+ }
+ }
+ }
+
+
+ /*************** invalid Opcode ***************/
+
+ else {
+ sprintf (logtext, "Invalid opcode %d at position %ld",
+ opcode, (long int) p);
+ error ();
+ }
+
+ }
+
+ break;
+
+
+ } /* end switch */
+
+
+ p = nextp;
+
+ if ( block_isany (p) ) {
+ block_reach ( block_find (p) );
+ goto cleanup;
+ }
+
+ } /* end for */
+
+
+cleanup:
+ pcmd_untieall();
+}
+
--- /dev/null
+/********************************** comp/pcmd.c ********************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ contains the parser functions which generate pseude commands and
+ eliminating unnecessary copy instructions
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+ Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1997/09/22
+
+*******************************************************************************/
+
+
+list *pcmdlist; /* list of pseudo commands */
+
+
+/***************************** support functions ******************************/
+
+static void pcmd_init (list *pl)
+{
+ pcmdlist = pl;
+}
+
+
+static void pcmd_realmove (u2 type, varid source, varid dest)
+{
+ pcmd *c = DNEW(pcmd);
+ c -> tag = TAG_MOVE;
+ c -> opcode = CMD_MOVE;
+ c -> source1 = source;
+ c -> source2 = NOVAR;
+ c -> source3 = NOVAR;
+ c -> dest = dest;
+ c -> u.move.type = type;
+ list_addlast (pcmdlist, c);
+#ifdef STATISTICS
+ count_pcmd_move++;
+#endif
+}
+
+
+static void pcmd_invalidatevar (varid v)
+{
+ varid c;
+
+ if (!var_isoriginal(v) ) {
+ var_unlinkcopy (v);
+ }
+ else {
+ while ( (c = var_nextcopy (v)) != NULL) {
+ pcmd_realmove (var_type(v), v,c);
+ var_unlinkcopy (c);
+ }
+
+ }
+}
+
+
+static void pcmd_untievar (varid v)
+{
+ varid c;
+
+ if (!var_isoriginal(v)) {
+ pcmd_realmove (var_type(v), var_findoriginal(v), v);
+ var_unlinkcopy (v);
+ }
+ else {
+ while ( (c = var_nextcopy(v)) != NULL) {
+ pcmd_realmove (var_type(v), v, c);
+ var_unlinkcopy (c);
+ }
+ }
+}
+
+
+static void pcmd_untieall ()
+{
+ varid v;
+
+ while ( (v = var_nextcopiedvar()) != NULL) {
+ pcmd_realmove (var_type(v), var_findoriginal(v), v);
+ var_unlinkcopy (v);
+ }
+}
+
+
+/********************** generation of pseudo commands *************************/
+
+static void pcmd_drop (varid var)
+{
+ pcmd *c = DNEW(pcmd);
+
+ if (var_isoriginal(var)) {
+ pcmd_invalidatevar (var);
+
+ c -> tag = TAG_DROP;
+ c -> opcode = CMD_DROP;
+ c -> dest = var;
+ c -> source1 = c -> source2 = c -> source3 = NOVAR;
+ list_addlast (pcmdlist, c);
+#ifdef STATISTICS
+ count_pcmd_drop++;
+#endif
+ }
+ else {
+ pcmd_invalidatevar (var);
+ }
+}
+
+
+static void pcmd_activate (varid var)
+{
+ pcmd *c = DNEW(pcmd);
+
+ pcmd_untieall();
+
+ c -> tag = TAG_ACTIVATE;
+ c -> opcode = CMD_ACTIVATE;
+ c -> dest = var;
+ c -> source1 = c -> source2 = c -> source3 = NOVAR;
+ list_addlast (pcmdlist, c);
+
+#ifdef STATISTICS
+ count_pcmd_activ++;
+#endif
+}
+
+
+static void pcmd_loadconst_i (s4 val, varid var)
+{
+ pcmd *c = DNEW (pcmd);
+ c -> tag = TAG_LOADCONST_I;
+ c -> opcode = CMD_LOADCONST_I;
+ c -> dest = var;
+ c -> source1 = c -> source2 = c -> source3 = NOVAR;
+ c -> u.i.value = val;
+
+ pcmd_invalidatevar (var);
+ list_addlast (pcmdlist, c);
+
+#ifdef STATISTICS
+ if (val == 0)
+ count_pcmd_zero++;
+ count_pcmd_load++;
+#endif
+}
+
+
+static void pcmd_loadconst_l (s8 val, varid var)
+{
+ pcmd *c = DNEW (pcmd);
+ c -> tag = TAG_LOADCONST_L;
+ c -> opcode = CMD_LOADCONST_L;
+ c -> dest = var;
+ c -> source1 = c -> source2 = c -> source3 = NOVAR;
+ c -> u.l.value = val;
+
+ pcmd_invalidatevar (var);
+ list_addlast (pcmdlist, c);
+
+#ifdef STATISTICS
+ if (val == 0)
+ count_pcmd_zero++;
+ count_pcmd_load++;
+#endif
+}
+
+
+static void pcmd_loadconst_f (float val, varid var)
+{
+ pcmd *c = DNEW (pcmd);
+ c -> tag = TAG_LOADCONST_F;
+ c -> opcode = CMD_LOADCONST_F;
+ c -> dest = var;
+ c -> source1 = c -> source2 = c -> source3 = NOVAR;
+ c -> u.f.value = val;
+
+ pcmd_invalidatevar (var);
+ list_addlast (pcmdlist, c);
+
+#ifdef STATISTICS
+ count_pcmd_load++;
+#endif
+}
+
+
+static void pcmd_loadconst_d (double val, varid var)
+{
+ pcmd *c = DNEW (pcmd);
+ c -> tag = TAG_LOADCONST_D;
+ c -> opcode = CMD_LOADCONST_D;
+ c -> dest = var;
+ c -> source1 = c -> source2 = c -> source3 = NOVAR;
+ c -> u.d.value = val;
+
+ pcmd_invalidatevar (var);
+ list_addlast (pcmdlist, c);
+
+#ifdef STATISTICS
+ count_pcmd_load++;
+#endif
+}
+
+
+static void pcmd_loadconst_a (void *val, varid var)
+{
+ pcmd *c = DNEW (pcmd);
+ c -> tag = TAG_LOADCONST_A;
+ c -> opcode = CMD_LOADCONST_A;
+ c -> dest = var;
+ c -> source1 = c -> source2 = c -> source3 = NOVAR;
+ c -> u.a.value = val;
+
+ pcmd_invalidatevar (var);
+ list_addlast (pcmdlist, c);
+
+#ifdef STATISTICS
+ if (val == NULL)
+ count_pcmd_zero++;
+ count_pcmd_load++;
+#endif
+}
+
+
+static void pcmd_move (u2 type, varid source, varid dest)
+{
+ pcmd_invalidatevar (dest);
+ var_makecopy ( var_findoriginal(source), dest);
+}
+
+
+static void pcmd_move_n_drop (u2 type, varid source, varid dest)
+{
+ pcmd *c;
+
+ pcmd_untievar (source);
+ pcmd_untievar (dest);
+
+#ifdef STATISTICS
+ count_pcmd_store++;
+#endif
+ c = list_last (pcmdlist);
+ while (c) {
+ switch (c->tag) {
+ case TAG_LOADCONST_I:
+ if (c->dest == source) { c->dest = dest; return; }
+#ifdef STATISTICS
+ count_pcmd_const_store++;
+#endif
+ goto nothingfound;
+ case TAG_LOADCONST_L:
+ if (c->dest == source) { c->dest = dest; return; }
+ goto nothingfound;
+ case TAG_LOADCONST_F:
+ if (c->dest == source) { c->dest = dest; return; }
+ goto nothingfound;
+ case TAG_LOADCONST_D:
+ if (c->dest == source) { c->dest = dest; return; }
+ goto nothingfound;
+ case TAG_LOADCONST_A:
+ if (c->dest == source) { c->dest = dest; return; }
+ goto nothingfound;
+ case TAG_OP:
+ if (c->dest == source) { c->dest = dest; return; }
+ goto nothingfound;
+ case TAG_MEM:
+ if (c->dest == source) { c->dest = dest; return; }
+ goto nothingfound;
+
+ case TAG_DROP:
+ break;
+ default:
+ goto nothingfound;
+ } /* end switch */
+
+ c = list_prev (pcmdlist, c);
+ }
+
+nothingfound:
+ var_makecopy ( source, dest);
+ pcmd_drop (source);
+#ifdef STATISTICS
+ count_pcmd_store_comb++;
+#endif
+}
+
+
+static void pcmd_iinc (s4 val, varid sourcedest)
+{
+ pcmd *c = DNEW (pcmd);
+
+ pcmd_invalidatevar (sourcedest);
+
+ c -> tag = TAG_OP;
+ c -> opcode = CMD_IINC;
+ c -> source1 = var_findoriginal(sourcedest);
+ c -> source2 = NOVAR;
+ c -> source3 = NOVAR;
+ c -> dest = sourcedest;
+ c -> u.i.value = val;
+
+ list_addlast (pcmdlist, c);
+
+#ifdef STATISTICS
+ count_pcmd_op++;
+#endif
+}
+
+
+static void pcmd_op (u1 opcode,
+ varid source1, varid source2, varid source3, varid dest)
+{
+ pcmd *c;
+
+#ifdef STATISTICS
+ c = list_last (pcmdlist);
+ if (c && (c->tag == TAG_LOADCONST_I))
+ switch (opcode) {
+ case CMD_IASTORE:
+ case CMD_BASTORE:
+ case CMD_CASTORE:
+ case CMD_SASTORE:
+ count_pcmd_const_store++;
+ break;
+ case CMD_IADD:
+ case CMD_ISUB:
+ case CMD_IMUL:
+ case CMD_ISHL:
+ case CMD_ISHR:
+ case CMD_IUSHR:
+ case CMD_IAND:
+ case CMD_IOR:
+ case CMD_IXOR:
+ count_pcmd_const_alu++;
+ }
+#endif
+ c = DNEW(pcmd);
+ if (dest) pcmd_invalidatevar (dest);
+
+ c -> tag = TAG_OP;
+ c -> opcode = opcode;
+ c -> source1 = source1 ? var_findoriginal(source1) : NOVAR;
+ c -> source2 = source2 ? var_findoriginal(source2) : NOVAR;
+ c -> source3 = source3 ? var_findoriginal(source3) : NOVAR;
+ c -> dest = dest;
+ list_addlast (pcmdlist, c);
+#ifdef STATISTICS
+ count_pcmd_op++;
+#endif
+}
+
+
+static void pcmd_mem (u1 opcode, u2 type, varid base, varid source,
+ varid dest, u2 offset)
+{
+ pcmd *c;
+
+#ifdef STATISTICS
+ c = list_last (pcmdlist);
+ if (c && (c->tag == TAG_LOADCONST_I) && (opcode == CMD_PUTFIELD))
+ count_pcmd_const_store++;
+#endif
+ c = DNEW(pcmd);
+ if (dest) pcmd_invalidatevar (dest);
+
+ c -> tag = TAG_MEM;
+ c -> opcode = opcode;
+ c -> source1 = base ? var_findoriginal(base) : NOVAR;
+ c -> source2 = source ? var_findoriginal(source) : NOVAR;
+ c -> source3 = NOVAR;
+ c -> dest = dest;
+ c -> u.mem.type = type;
+ c -> u.mem.offset = offset;
+ list_addlast (pcmdlist, c);
+
+#ifdef STATISTICS
+ count_pcmd_mem++;
+#endif
+}
+
+
+static void pcmd_bra (u1 opcode, varid s1, varid s2, varid dest, basicblock *target)
+{
+ pcmd *c;
+ varid or1,or2;
+
+#ifdef STATISTICS
+ c = list_last (pcmdlist);
+ if (c && (c->tag == TAG_LOADCONST_I))
+ switch (opcode) {
+ case CMD_IF_ICMPEQ:
+ case CMD_IF_ICMPNE:
+ case CMD_IF_ICMPLT:
+ case CMD_IF_ICMPGT:
+ case CMD_IF_ICMPLE:
+ case CMD_IF_ICMPGE:
+ count_pcmd_const_bra++;
+ }
+#endif
+ c = DNEW(pcmd);
+ or1 = s1 ? var_findoriginal (s1) : NOVAR;
+ or2 = s2 ? var_findoriginal (s2) : NOVAR;
+
+ pcmd_untieall();
+
+ c -> tag = TAG_BRA;
+ c -> opcode = opcode;
+ c -> source1 = or1;
+ c -> source2 = or2;
+ c -> source3 = NOVAR;
+ c -> dest = dest;
+ c -> u.bra.target = target;
+ list_addlast (pcmdlist, c);
+
+#ifdef STATISTICS
+ count_pcmd_bra++;
+#endif
+}
+
+
+static void pcmd_trace (void *method)
+{
+ pcmd *c;
+
+ isleafmethod = false;
+
+ c = DNEW(pcmd);
+ c -> tag = TAG_BRA;
+ c -> opcode = CMD_TRACEBUILT;
+ c -> source1 = NOVAR;
+ c -> source2 = NOVAR;
+ c -> source3 = NOVAR;
+ c -> dest = NOVAR;
+ c -> u.a.value = method;
+ list_addlast (pcmdlist, c);
+}
+
+
+static void pcmd_bra_n_drop (u1 opcode, varid s1, varid s2, varid dest, basicblock *target)
+{
+ pcmd *c;
+ varid or1=NOVAR,or2=NOVAR;
+ bool isor1=false,isor2=false;
+
+#ifdef STATISTICS
+ c = list_last (pcmdlist);
+ if (c && (c->tag == TAG_LOADCONST_I))
+ switch (opcode) {
+ case CMD_IF_ICMPEQ:
+ case CMD_IF_ICMPNE:
+ case CMD_IF_ICMPLT:
+ case CMD_IF_ICMPGT:
+ case CMD_IF_ICMPLE:
+ case CMD_IF_ICMPGE:
+ count_pcmd_const_bra++;
+ }
+#endif
+ c = DNEW(pcmd);
+ if (s1!=NOVAR) {
+ or1 = var_findoriginal (s1);
+ if (! (isor1 = var_isoriginal(s1)) ) var_unlinkcopy (s1);
+ }
+ if (s2!=NOVAR) {
+ or2 = var_findoriginal (s2);
+ if (! (isor2 = var_isoriginal (s2)) ) var_unlinkcopy (s2);
+ }
+
+ pcmd_untieall();
+
+ c -> tag = TAG_BRA;
+ c -> opcode = opcode;
+ c -> source1 = or1;
+ c -> source2 = or2;
+ c -> source3 = NOVAR;
+ c -> dest = dest;
+ c -> u.bra.target = target;
+ list_addlast (pcmdlist, c);
+
+ if (isor1) pcmd_drop (s1);
+ if (isor2) pcmd_drop (s2);
+
+#ifdef STATISTICS
+ count_pcmd_bra++;
+#endif
+}
+
+
+static void pcmd_tablejump (varid s, u4 targetcount, basicblock **targets)
+{
+ pcmd *c = DNEW(pcmd);
+
+ pcmd_untieall();
+
+ c -> tag = TAG_TABLEJUMP;
+ c -> opcode = CMD_TABLEJUMP;
+ c -> source1 = var_findoriginal(s);
+ c -> source2 = NOVAR;
+ c -> source3 = NOVAR;
+ c -> dest = NOVAR;
+ c -> u.tablejump.targetcount = targetcount;
+ c -> u.tablejump.targets = targets;
+ list_addlast (pcmdlist, c);
+
+#ifdef STATISTICS
+ count_pcmd_table++;
+#endif
+}
+
+
+/******* ATTENTION: Method does DROP automatically !!!!! ****/
+
+static void pcmd_method (int opcode, methodinfo *mi, functionptr builtin,
+ int paramnum, varid *params, varid result, varid exceptionvar)
+{
+ varid v;
+ int i;
+
+ pcmd *c = DNEW(pcmd);
+
+ pcmd_untieall();
+
+ isleafmethod = false;
+
+ reg_parlistinit();
+ for (i = 0; i < paramnum; i++) {
+ v = params[i];
+ var_proposereg(v, reg_parlistpar(var_type(v)));
+ }
+
+ if (result) {
+ var_proposereg(result, reg_parlistresult(var_type(result)));
+ }
+ if (exceptionvar) {
+ exceptionvar -> reg = reg_parlistexception();
+ }
+
+ c -> tag = TAG_METHOD;
+ c -> opcode = opcode;
+ c -> source1 = c -> source2 = c -> source3 = NULL;
+ c -> dest = result;
+ c -> u.method.method = mi;
+ c -> u.method.builtin = builtin;
+ c -> u.method.paramnum = paramnum;
+ c -> u.method.params = params;
+ c -> u.method.exceptionvar = exceptionvar;
+ list_addlast (pcmdlist, c);
+
+ for (i = 0; i < paramnum; i++) pcmd_drop(params[i]);
+
+#ifdef STATISTICS
+ count_pcmd_met++;
+#endif
+}
+
+
+
+static void pcmd_builtin1 (functionptr builtin, varid v1, varid result)
+{
+ varid *args = DMNEW (varid, 1);
+ args[0] = v1;
+ pcmd_method (CMD_BUILTIN, NULL, builtin, 1, args, result,NOVAR);
+}
+
+static void pcmd_builtin2 (functionptr builtin, varid v1, varid v2, varid result)
+{
+ varid *args = DMNEW (varid, 2);
+ args[0] = v1;
+ args[1] = v2;
+ pcmd_method (CMD_BUILTIN, NULL, builtin, 2, args, result, NOVAR);
+}
+
+static void pcmd_builtin3 (functionptr builtin, varid v1, varid v2, varid v3, varid result)
+{
+ varid *args = DMNEW (varid, 3);
+ args[0] = v1;
+ args[1] = v2;
+ args[2] = v3;
+ pcmd_method (CMD_BUILTIN, NULL, builtin, 3, args, result, NOVAR);
+}
+
+
+static void pcmd_display (pcmd *c)
+{
+ int i;
+
+ switch (c -> tag) {
+ case TAG_LOADCONST_I:
+ printf (" LOADCONST_I #%ld -> ",
+ (long int) c -> u.i.value);
+ var_display (c -> dest);
+ printf ("\n");
+ break;
+ case TAG_LOADCONST_L:
+#if U8_AVAILABLE
+ printf (" LOADCONST_L #%ld -> ", (long int) c -> u.l.value);
+#else
+ printf (" LOADCONST_L #HI: %ld LO: %ld -> ",
+ (long int) c->u.l.value.high, (long int) c->u.l.value.low );
+#endif
+ var_display (c -> dest);
+ printf ("\n");
+ break;
+ case TAG_LOADCONST_F:
+ printf (" LOADCONST_F #%f -> ", (double) c -> u.f.value);
+ var_display (c -> dest);
+ printf ("\n");
+ break;
+ case TAG_LOADCONST_D:
+ printf (" LOADCONST_D #%f -> ", c -> u.d.value);
+ var_display (c -> dest);
+ printf ("\n");
+ break;
+ case TAG_LOADCONST_A:
+ printf (" LOADCONST_A #%p -> ", c -> u.a.value);
+ var_display (c -> dest);
+ printf ("\n");
+ break;
+
+ case TAG_MOVE:
+ printf (" MOVE_%1d ", c -> u.move.type);
+ var_display (c-> source1);
+ printf (" -> ");
+ var_display (c -> dest);
+ printf ("\n");
+ break;
+
+ case TAG_OP:
+ printf (" OP%3d ", c -> opcode);
+ var_display (c -> source1);
+ printf (", ");
+ var_display (c -> source2);
+ printf (", ");
+ var_display (c -> source3);
+ printf (" -> ");
+ var_display (c -> dest );
+ printf ("\n");
+ break;
+
+ case TAG_BRA:
+ printf (" BRA%3d (", c -> opcode);
+ var_display (c -> source1);
+ printf (", ");
+ var_display (c -> source2);
+ printf (" -> ");
+ var_display (c -> dest);
+ if (c->u.bra.target) {
+ printf (") to pos %ld\n",
+ (long int) c -> u.bra.target -> jpc );
+ }
+ else printf (")\n");
+ break;
+
+ case TAG_TABLEJUMP:
+ printf (" TABLEJUMP ");
+ var_display (c -> source1);
+ printf ("\n");
+ for (i=0; i < (int) c->u.tablejump.targetcount; i++) {
+ printf (" %d: to pos %ld\n", (int) i,
+ (long int) c ->u.tablejump.targets[i] -> jpc );
+ }
+ break;
+
+ case TAG_MEM:
+ printf (" MEM%3d_%d ", c -> opcode, c -> u.mem.type);
+ var_display (c -> source2);
+ printf ("/");
+ var_display (c -> dest);
+ printf (" <-> ");
+ printf ("%d [", (int) (c -> u.mem.offset) );
+ var_display (c -> source1 );
+ printf ("]\n");
+ break;
+
+ case TAG_METHOD:
+ printf (" METHOD%3d ", c -> opcode);
+ for (i=0; i < c -> u.method.paramnum; i++) {
+ var_display (c -> u.method.params[i]);
+ }
+ printf (" -> ");
+ var_display (c -> dest);
+ printf ("/");
+ var_display (c->u.method.exceptionvar);
+ printf ("\n");
+ break;
+
+ case TAG_DROP:
+ printf (" [ DROP ");
+ var_display (c-> dest);
+ printf (" ]\n");
+ break;
+ case TAG_ACTIVATE:
+ printf (" [ ACTIVATE ");
+ var_display (c-> dest);
+ printf (" ]\n");
+ break;
+
+ default:
+ printf (" ???\n");
+ break;
+ }
+
+}
--- /dev/null
+/******************************* comp/reg.c ************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ The register-manager.
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+ Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1997/10/23
+
+*******************************************************************************/
+
+/*********************** Structure of a register info *************************/
+
+#define REG_TYPE_FLT 1 /* integer or floating point type */
+#define REG_SIZE_DBL 2 /* int/single or long/double */
+#define REG_INMEMORY 4 /* true if register is in memory */
+#define REG_ISFREE 8 /* true if register is currently free */
+#define REG_ISUNUSED 16 /* true if register never has been used */
+#define REG_ISFREEUNUSED 24
+
+#define IS_INT_LNG_REG(a) (!((a)®_TYPE_FLT))
+#define IS_FLT_DBL_REG(a) ((a)®_TYPE_FLT)
+
+#define REGTYPE_INT 0
+#define REGTYPE_FLT 1
+#define REGTYPE_LNG 2
+#define REGTYPE_DBL 3
+
+#define REGTYPE(a) ((a) & 3)
+
+typedef struct reginfo {
+ int typeflags; /* register type, size and flags */
+ int num; /* register number or stack offset */
+ list *waitlist; /* free list for register allocation */
+ listnode linkage;
+} reginfo;
+
+
+
+static reginfo *intregs = NULL; /* table for the integer registers */
+static reginfo *floatregs = NULL; /* table for the float registers */
+static int intregsnum; /* absolute number of integer registers */
+static int floatregsnum; /* absolute number of float registers */
+
+static int intreg_ret; /* register to return integer values */
+static int intreg_exc; /* register to return exception value */
+static int intreg_arg1; /* register for first integer argument */
+static int intreg_argnum; /* number of integer argument registers */
+
+static int floatreg_ret; /* register for return float values */
+static int floatreg_arg1; /* register for first float argument */
+static int floatreg_argnum; /* number of float argument registers */
+
+
+static list savedintslist; /* free saved int registers during allocation */
+static list savedfloatslist; /* free saved float registers during allocation*/
+static list scratchintslist; /* free temp int registers during allocation */
+static list scratchfloatslist; /* free temp float registers during allocation */
+static int *freeintregs; /* free int registers table */
+static int *freefloatregs; /* free float registers table */
+
+static int savedregs_num; /* total number of registers to be saved */
+static int localvars_num; /* total number of variables to spilled */
+static int arguments_num; /* size of parameter field in the stackframe */
+
+
+
+/****************** function reg_init ******************************************
+
+ initialises the register-allocator
+
+*******************************************************************************/
+
+static void reg_init()
+{
+ int n;
+
+ if (!intregs) {
+ for (intregsnum=0; regdescint[intregsnum] != REG_END; intregsnum++);
+ intregs = MNEW (reginfo, intregsnum);
+ freeintregs = MNEW (int, intregsnum + 2);
+ *freeintregs++ = 0;
+ freeintregs[intregsnum] = 0;
+
+ intreg_arg1 = -1;
+ for (n=0; n<intregsnum; n++) {
+ intregs[n].typeflags = 0;
+ intregs[n].num = n;
+ intregs[n].waitlist = NULL;
+ freeintregs[n] = 0;
+
+ switch (regdescint[n]) {
+ case REG_RES: break;
+ case REG_RET: intreg_ret = n;
+ break;
+ case REG_EXC: intreg_exc = n;
+ break;
+ case REG_SAV: intregs[n].waitlist = &(savedintslist);
+ freeintregs[n] = 1;
+ break;
+ case REG_TMP: intregs[n].waitlist = &(scratchintslist);
+ freeintregs[n] = 1;
+ break;
+ case REG_ARG: if (intreg_arg1 < 0) intreg_arg1 = n;
+ intreg_argnum++;
+ break;
+ }
+ }
+
+
+ for (floatregsnum=0; regdescfloat[floatregsnum] != REG_END; floatregsnum++);
+ floatregs = MNEW (reginfo, floatregsnum);
+ freefloatregs = MNEW (int, floatregsnum + 2);
+ *freefloatregs++ = 0;
+ freefloatregs[floatregsnum] = 0;
+
+ floatreg_arg1 = -1;
+ for (n=0; n<floatregsnum; n++) {
+ floatregs[n].typeflags = REG_TYPE_FLT;
+ floatregs[n].num = n;
+ floatregs[n].waitlist = NULL;
+ freefloatregs[n] = 0;
+
+ switch (regdescfloat[n]) {
+ case REG_RES: break;
+ case REG_RET: floatreg_ret = n;
+ break;
+ case REG_EXC: panic ("can not use floating-reg as exception");
+ break;
+ case REG_SAV: floatregs[n].waitlist = &(savedfloatslist);
+ freefloatregs[n] = 1;
+ break;
+ case REG_TMP: floatregs[n].waitlist = &(scratchfloatslist);
+ freefloatregs[n] = 1;
+ break;
+ case REG_ARG: if (floatreg_arg1 < 0) floatreg_arg1 = n;
+ floatreg_argnum++;
+ break;
+ }
+ }
+
+ }
+
+
+ list_init (&savedintslist, OFFSET(reginfo, linkage));
+ list_init (&savedfloatslist, OFFSET(reginfo, linkage));
+ list_init (&scratchintslist, OFFSET(reginfo, linkage));
+ list_init (&scratchfloatslist, OFFSET(reginfo, linkage));
+
+ for (n=0; n<intregsnum; n++) {
+ intregs[n].typeflags |= REG_ISFREE | REG_ISUNUSED;
+ if (intregs[n].waitlist)
+ list_addlast(intregs[n].waitlist, intregs+n);
+ }
+ for (n=0; n<floatregsnum; n++) {
+ floatregs[n].typeflags |= REG_ISFREE | REG_ISUNUSED;
+ if (floatregs[n].waitlist)
+ list_addlast(floatregs[n].waitlist, floatregs+n);
+ }
+
+
+ localvars_num = 0;
+ arguments_num = 0;
+}
+
+
+/********************** function reg_close *************************************
+
+ releases all allocated space for registers
+
+*******************************************************************************/
+
+static void reg_close ()
+{
+ if (intregs) MFREE (intregs, reginfo, intregsnum);
+ if (floatregs) MFREE (floatregs, reginfo, floatregsnum);
+}
+
+
+/********************* function reg_free ***************************************
+
+ put back a register which has been allocated by reg_allocate into the
+ corresponding free list
+
+*******************************************************************************/
+
+static void reg_free (reginfo *ri)
+{
+ ri -> typeflags |= REG_ISFREE;
+
+ if (ri->waitlist) {
+ if (ri->typeflags & REG_INMEMORY)
+ list_addlast (ri->waitlist, ri);
+ else {
+#if (WORDSIZE == 4)
+ reginfo *ri1;
+
+ if (ri->typeflags & REG_TYPE_FLT) {
+ if (ri->typeflags & REG_SIZE_DBL) {
+ freefloatregs[ri->num] = 0;
+ freefloatregs[ri->num + 1] = 0;
+ ri1 = &floatregs[ri->num + 1];
+ list_addfirst (ri1->waitlist, ri1);
+ }
+ else
+ freefloatregs[ri->num] = 0;
+ }
+ else {
+ if (ri->typeflags & REG_SIZE_DBL) {
+ freeintregs[ri->num] = 0;
+ freeintregs[ri->num + 1] = 0;
+ ri1 = &intregs[ri->num + 1];
+ list_addfirst (ri1->waitlist, ri1);
+ }
+ else
+ freeintregs[ri->num] = 0;
+ }
+#endif
+ list_addfirst (ri->waitlist, ri);
+ }
+ }
+}
+
+
+/******************* internal function reg_suckregister ************************
+
+ searches for the first register of a list which fullfills the requirements:
+ if argument isunused is true ri->typeflags®_ISUNUSED has to be true too
+ if register pairs are required two adjacent register are searched
+ if a register can be found it is removed from the free list and the
+ fields 'isunused' and 'isfree' are set to false
+
+*******************************************************************************/
+
+static reginfo *reg_remove (list *l, int num) {
+ reginfo *ri;
+
+ ri = list_first (l);
+ while (ri->num != num)
+ ri = list_next (l, ri);
+ if (ri->typeflags & REG_TYPE_FLT)
+ freefloatregs[num] = 0;
+ else
+ freeintregs[num] = 0;
+ list_remove (l, ri);
+ ri -> typeflags &= ~REG_ISFREEUNUSED;
+ return ri;
+}
+
+
+static reginfo *reg_suckregister (list *l, bool isunused)
+{
+ reginfo *ri;
+
+ ri = list_first (l);
+
+ while (ri) {
+ if ( (!isunused) || (ri->typeflags & REG_ISUNUSED)) {
+#if (WORDSIZE == 4)
+ reginfo *retreg = NULL;
+
+ if (ri->typeflags & REG_SIZE_DBL) {
+ if (ri->typeflags & REG_TYPE_FLT)
+ if (ri->num & 1) {
+ if(freefloatregs[ri->num - 1]) {
+ freefloatregs[ri->num] = 0;
+ retreg = reg_remove(l, ri->num - 1);
+ }
+ }
+ else {
+ if (freefloatregs[ri->num + 1]) {
+ freefloatregs[ri->num] = 0;
+ retreg = ri;
+ (void) reg_remove(l, ri->num + 1);
+ }
+ }
+ else if (freeintregs[ri->num + 1]) {
+ freeintregs[ri->num] = 0;
+ retreg = ri;
+ (void) reg_remove(l, ri->num + 1);
+ }
+ else if(freeintregs[ri->num - 1]) {
+ freeintregs[ri->num] = 0;
+ retreg = reg_remove(l, ri->num - 1);
+ }
+ if (retreg) {
+ list_remove (l, ri);
+ ri -> typeflags &= ~REG_ISFREEUNUSED;
+ return retreg;
+ }
+ }
+ else {
+ if (ri->typeflags & REG_TYPE_FLT)
+ freefloatregs[ri->num] = 0;
+ else
+ freeintregs[ri->num] = 0;
+ list_remove (l, ri);
+ ri -> typeflags &= ~REG_ISFREEUNUSED;
+ return ri;
+ }
+#else
+ list_remove (l, ri);
+ ri -> typeflags &= ~REG_ISFREEUNUSED;
+ return ri;
+#endif
+ }
+ ri = list_next (l, ri);
+ }
+ return NULL;
+}
+
+
+/******************** Funktion: reg_allocate **********************************
+
+ versucht, ein Register zu belegen, das vom richtigen Typ ist, und
+ allen gew"unschten Anforderungen entspricht.
+
+ Parameter:
+ type .... JAVA-Grundtyp (INT,LONG,DOUBLE,FLOAT,ADDRESS)
+ saved ... Das Register soll bei Methodenaufrufen nicht zerst"ort werden
+ new ..... Das Register soll noch nie vorher verwendet worden sein
+
+ Wenn es (aus verschiedenen Gr"unden) kein geeignetes freies Register f"ur
+ den Zweck mehr gibt, dann erzeugt diese Funktion einen Verweis auf
+ einen Platz am aktuellen Stackframe (diese Stackframe-Eintr"age erf"ullen
+ auf jeden Fall alle obigen Forderungen)
+
+*******************************************************************************/
+
+static reginfo *reg_allocate (u2 type, bool saved, bool new)
+{
+ u2 t;
+ reginfo *ri;
+
+ switch (type) {
+ case TYPE_LONG:
+ t = REG_SIZE_DBL;
+ break;
+ case TYPE_INT:
+ t = 0;
+ break;
+ case TYPE_FLOAT:
+ t = REG_TYPE_FLT;
+ break;
+ case TYPE_DOUBLE:
+ t = REG_TYPE_FLT | REG_SIZE_DBL;
+ break;
+ default:
+ t = 0;
+ }
+
+ if (!saved) {
+ if (IS_INT_LNG_REG(t))
+ ri = reg_suckregister (&scratchintslist, new);
+ else
+ ri = reg_suckregister (&scratchfloatslist, new);
+ if (ri) return ri;
+ }
+
+ if (IS_INT_LNG_REG(t))
+ ri = reg_suckregister (&savedintslist, new);
+ else
+ ri = reg_suckregister (&savedfloatslist, new);
+ if (ri) return ri;
+
+ ri = DNEW (reginfo);
+ ri -> typeflags = t | REG_INMEMORY;
+#if (WORDSIZE == 4)
+ ri -> num = localvars_num;
+ if (t & REG_SIZE_DBL)
+ localvars_num += 2;
+ else
+ localvars_num++;
+#else
+ ri -> num = (localvars_num++);
+#endif
+ ri -> waitlist = (IS_INT_LNG_REG(t)) ? &savedintslist : &savedfloatslist;
+ return ri;
+}
+
+
+/********************* Funktion: reg_reallocate *******************************
+
+ versucht, ein schon einmal angefordertes (aber in der Zwischenzeit
+ wieder freigegebenens) Register neuerlich anzufordern.
+ Wenn das Register immer noch unbenutzt ist, dann ist alles OK
+ (R"uckgabewert true), sonst wird 'false' zur"uckgeben, und aus der
+ neuerlichen Belegung wird nichts.
+
+******************************************************************************/
+
+static bool reg_reallocate (reginfo *ri)
+{
+ if (!(ri->typeflags & REG_ISFREE)) return false;
+
+ ri->typeflags &= ~REG_ISFREEUNUSED;
+
+ if (ri->waitlist) list_remove (ri->waitlist, ri);
+
+ return true;
+}
+
+
+
+/****************** Funktion: reg_parlistresult *******************************
+
+ Erzeugt eine Registerreferenz auf das Register, das vom System zur
+ R"uckgabe von Werten aus Methoden verwendet wird.
+ Parameter:
+ type ... Der JAVA-Grundtyp des R"uckgabewertes
+
+******************************************************************************/
+
+static reginfo *reg_parlistresult (u2 type)
+{
+ if (type==TYPE_FLOAT || type==TYPE_DOUBLE) return &(floatregs[floatreg_ret]);
+ else return &(intregs[intreg_ret]);
+}
+
+
+
+/*************** Funktion: reg_parlistexception ******************************
+
+ Erzeugt eine Registerreferenz auf das Register, in dem das System die
+ Zeiger auf allf"allige Exception-Objekte bei Methodenaufrufen
+ zur"uckliefert.
+
+******************************************************************************/
+
+static reginfo *reg_parlistexception ()
+{
+ return &(intregs[intreg_exc]);
+}
+
+
+
+/************************ Funktion: reg_parlistpar ****************************
+
+ Erzeugt eine Registerreferenz auf ein Register, in dem das n"achste
+ Argument (in der Z"ahlung ab dem Zeitpunkt von Aufruf von 'reg_parlistinit')
+ bei Methodenaufrufen eingetragen wird.
+ Wenn es in Summe mehr als die m"oglichen Parameter-Register werden, dann
+ wird auch noch Platz am Stack f"ur die "uberz"ahligen Werte reserviert
+
+******************************************************************************/
+
+static int usedintpar, usedfloatpar;
+static int usedparoverflow;
+
+static reginfo *reg_parlistpar (u2 type)
+{
+ reginfo *f;
+
+ if (type == TYPE_FLOAT || type == TYPE_DOUBLE) {
+ usedfloatpar++;
+ if (reg_parammode == PARAMMODE_NUMBERED) usedintpar++;
+
+ if (usedfloatpar <= floatreg_argnum) {
+ f = &floatregs[floatreg_arg1 + (usedfloatpar - 1) ];
+ f->typeflags &= ~REG_ISUNUSED;
+ return f;
+ }
+ else goto overflow;
+ }
+ else {
+ usedintpar++;
+ if (reg_parammode == PARAMMODE_NUMBERED) usedfloatpar++;
+
+ if (usedintpar <= intreg_argnum) {
+ f = &intregs[intreg_arg1 + (usedintpar - 1) ];
+ f->typeflags &= ~REG_ISUNUSED;
+ return f;
+ }
+ else goto overflow;
+ }
+
+
+
+overflow:
+ usedparoverflow++;
+ if (usedparoverflow > arguments_num) arguments_num = usedparoverflow;
+ return NULL;
+}
+
+
+/****************** Funktion: reg_parlistinit *********************************
+
+ initialisiert die Z"ahlung der Parameter-Register
+
+*******************************************************************************/
+
+static void reg_parlistinit()
+{
+ usedintpar = 0;
+ usedfloatpar = 0;
+ usedparoverflow = 0;
+}
+
+
+
+
+
+/***************** Funktion: reg_display *************************************
+
+ gibt eine Register-Referenz in lesbarer Form auf 'stdout' aus.
+
+******************************************************************************/
+
+static void reg_display (reginfo *ri)
+{
+ if (ri->typeflags & REG_INMEMORY) {
+ printf ("[%d]", (int) (ri->num) );
+ }
+ else {
+ printf ("%s%d",
+ (IS_INT_LNG_REG(ri->typeflags)) ? "$" : "f$",
+ (int) (ri->num) );
+ }
+}
+
+
--- /dev/null
+/************************** comp/regalloc.c ************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ The register-allocator.
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1997/03/05
+
+*******************************************************************************/
+
+
+/******************** Funktion: regalloc_doalloc ******************************
+
+ versucht f"ur ein Pseudoregister ein tats"achliches CPU-Register zu
+ belegen.
+ Wenn noch keine Belegung stattgefunden hat, dann wird ein passendes
+ gerade freies Register angefordert.
+ Wenn das Pseudoregsiter bereits vorher schon einmal ein Belegung
+ hatte, dann wird versucht, das selbe CPU-Register wie vorher wieder
+ anzufordern. Wenn es nicht gelingt (weil es schon wieder anderwertig
+ verwendet wird), wann wird eben ein ganz neues Register angefordert.
+
+******************************************************************************/
+
+static void regalloc_doalloc (varinfo *v)
+{
+ if (v->reg) {
+ if (! reg_reallocate (v->reg)) {
+ v->reg = reg_allocate (v->type, v->saved, true);
+ }
+ }
+ else {
+ v->reg = reg_allocate (v->type, v->saved, false);
+ }
+}
+
+
+
+/********************* Funktion: regalloc_activate ****************************
+
+ setzt ein Pseudoregister auf aktiv (wenn es nicht schon
+ bereits aktiv ist), und fordert gegebenenfalls gleich ein passendes
+ CPU-Register an
+ Diese Operation wird aber nur bei Variablen mit lokalen Scope
+ gemacht.
+
+******************************************************************************/
+
+static void regalloc_activate (varinfo *v)
+{
+ if (! v->globalscope) {
+ if (! var_isactive(v) ) {
+ regalloc_doalloc (v);
+ var_activate (v);
+ }
+ }
+}
+
+
+/******************** Funktion: regalloc_deactivate ***************************
+
+ setzt ein Pseudoregister auf inaktiv (wenn es nicht schon inaktiv war)
+
+******************************************************************************/
+
+static void regalloc_deactivate (varinfo *v)
+{
+ if (! v->globalscope) {
+ if (var_isactive(v) ) {
+ var_deactivate (v);
+ if (v->reg) reg_free (v->reg);
+ }
+ }
+}
+
+
+/******************** Funktion: regalloc_cmd **********************************
+
+ f"uhrt f"ur ein Pseudo-Command die Registerbelegung durch.
+ Wird von regalloc in einer Schleife aufgerufen.
+
+******************************************************************************/
+
+static void regalloc_cmd (pcmd *c)
+{
+ switch (c->tag) {
+ case TAG_DROP:
+ regalloc_deactivate (c->dest);
+ break;
+ case TAG_METHOD:
+ if (c->u.method.exceptionvar)
+ regalloc_activate (c->u.method.exceptionvar);
+ if (c->dest)
+ regalloc_activate (c->dest);
+ break;
+ default:
+ if (c->dest) regalloc_activate (c->dest);
+ break;
+ }
+}
+
+
+/******************** Funktion: regalloc **************************************
+
+ f"uhrt f"ur einen ganzen Block die Registerbelegung durch.
+
+******************************************************************************/
+
+static void regalloc (basicblock *b)
+{
+ stackinfo *tos;
+ pcmd *c;
+ varinfo *v;
+
+ /* alle Pseudoregister am Stack, die schon eine Belegung haben,
+ wieder aktivieren */
+ tos = b->stack;
+ while (tos) {
+ if (tos -> var -> reg) regalloc_activate(tos->var);
+ tos = tos->prev;
+ }
+
+ /* alle anderen Pseudoregister am Stack belegen */
+ tos = b->stack;
+ while (tos) {
+ regalloc_activate(tos->var);
+ tos = tos->prev;
+ }
+
+
+ /* alle Befehle abarbeiten und Registerbelegung machen */
+ c = list_first (&b->pcmdlist);
+ while (c) {
+ regalloc_cmd (c);
+ c = list_next (&b->pcmdlist, c);
+ }
+
+
+ /* alle noch aktiven Pseudoregister deaktivieren */
+ while ( (v = var_nextactive ()) != NULL) {
+ regalloc_deactivate (v);
+ }
+}
+
--- /dev/null
+/***************************** alpha/gen.c *************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ behandeln des Java-Stacks
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1996/11/14
+
+*******************************************************************************/
+
+
+static stackinfo *tos; /* Top of Stack */
+
+
+
+/********************* Verwaltungsfunktionen *********************************/
+
+static void stack_init() { tos = NULL; }
+
+static stackinfo *stack_get () { return tos; }
+
+static void stack_restore (stackinfo *s) { tos = s; }
+
+static bool stack_isempty () { return tos == NULL; }
+
+
+
+/********************** Funktion: stack_topslots ******************************
+
+ liefert die Anzahl der JavaVM-slots, die die oberste Pseudovariable am
+ Stack belegt (entweder 2 bei LONG und DOUBLE, oder 1 sonst)
+
+******************************************************************************/
+
+static u2 stack_topslots ()
+{
+ u2 t;
+ if (!tos) panic ("Stack is empty on attempt to determine top slots");
+
+ t = var_type (tos->var);
+ return ( (t==TYPE_LONG) || (t==TYPE_DOUBLE) ) ? 2 : 1;
+}
+
+
+/********************* Funktion: stack_push ***********************************
+
+ erzeugt eine neues Pseudoregister eines gew"unschten Typs und gibt
+ es oben auf den Stack.
+ Ausserdem liefert die Funktion den Zeiger auf dieses Pseudoregister
+
+******************************************************************************/
+
+static varinfo *stack_push (u2 type)
+{
+ stackinfo *s = DNEW (stackinfo);
+
+ s -> prev = tos;
+ s -> var = var_create (type);
+
+ tos = s;
+ return s -> var;
+}
+
+
+/********************** Funktion: stack_repush ********************************
+
+ Gibt ein bereits vorhandenen Pseudoregister auf den Stack
+
+******************************************************************************/
+
+static void stack_repush (varinfo *v)
+{
+ stackinfo *s = DNEW (stackinfo);
+
+ s -> prev = tos;
+ s -> var = v;
+
+ tos = s;
+}
+
+
+/********************** Funktion: stack_pop ***********************************
+
+ nimmt das oberste Pseudoregister vom Stack, dabei wird aber
+ "uberpr"uft, ob der Typ stimmt.
+
+******************************************************************************/
+
+static varinfo *stack_pop (u2 type)
+{
+ varinfo *v;
+
+ if (!tos) panic ("Stack is empty on attempt to pop");
+
+ v = tos -> var;
+ tos = tos -> prev;
+
+ if (var_type (v) != type) panic ("Popped invalid element from stack");
+ return v;
+}
+
+
+/********************* Funktion: stack_popany ********************************
+
+ nimmt das oberste Pseudoregister vom stack, ohne Typ"uberpr"ufung
+ durchzuf"uhren, wobei aber zumindest die Anzahl der notwendigen
+ Slots "ubereinstimmen muss.
+
+******************************************************************************/
+
+static varinfo *stack_popany (u2 slots)
+{
+ varinfo *v;
+
+ if (!tos) panic ("Stack is empty on attempt to pop");
+ if (slots != stack_topslots() )
+ panic ("Pop would tear LONG/DOUBLE-Datatype apart");
+
+ v = tos -> var;
+ tos = tos -> prev;
+
+ return v;
+}
+
+
+
+/********************** Funktion: stack_popmany *******************************
+
+ nimmt vom Stack soviele Pseudoregister, dass die Anzahl der von
+ ihnen belegten Slots die gew"unschte Menge ergeben.
+ Zeiger auf dieses Pseudoregister werden im Array vars gespeichert, und
+ deren tats"achliche Anzahl als Funktionswert zur"uckgeliefert.
+ (Haupts"achlich f"ur die Typneutralen DUP/POP.. Operationen)
+
+******************************************************************************/
+
+static u2 stack_popmany (varid *vars, u2 slots)
+{
+ u2 ts;
+ u2 varcount=0;
+
+ while (slots>0) {
+ ts=stack_topslots();
+ if (ts > slots) panic ("POP would tear LONG/DOUBLE-Datatype apart");
+ vars[(varcount)++] = stack_popany(ts);
+ slots -= ts;
+ }
+ return varcount;
+}
+
+
+/********************** Funktion: stack_pushmany ******************************
+
+ Gibt eine Anzahl von Pseudoregister auf den Stack.
+
+******************************************************************************/
+
+static void stack_repushmany (u2 varcount, varid *vars)
+{
+ u2 i;
+ for (i=0; i<varcount; i++) stack_repush(vars[(varcount-1)-i]);
+}
+
+
+/***************** Funktion: stack_addjoincode ********************************
+
+ erzeugt die passenden MOVE-Commandos, sodass alle Pseudoregisterinhalte
+ eines Stacks auf die Pseudoregister eines anderen Stacks kopiert
+ werden.
+ Dann wird der Zielstack als neuer aktueller Stack verwendet.
+ (F"ur allem f"ur Verzweigungs- und Sprungbefehle)
+
+*******************************************************************************/
+
+static void stack_jointail (stackinfo *now, stackinfo *then)
+{
+ varinfo *v1,*v2;
+ u2 t;
+
+ if (now==then) return;
+ if ( (now==NULL) || (then==NULL) )
+ panic ("Stacks of different length on join");
+
+ v1 = now->var;
+ v2 = then->var;
+ if (v1 != v2) {
+ t = var_type (v1);
+ if (t != var_type (v2))
+ panic ("Mismatching stack types on join of control flow");
+
+ pcmd_move_n_drop (t, v1,v2);
+ }
+
+ stack_jointail (now -> prev, then -> prev);
+ return;
+}
+
+static void stack_addjoincode (stackinfo *targetstack)
+{
+ stack_jointail (tos, targetstack);
+ tos = targetstack;
+}
+
+
+/******************* Funktion: stack_makesaved ********************************
+
+ Kennzeichnet alle am Stack befindlichen Pseudoregister als
+ zu sichernde Register.
+
+*******************************************************************************/
+
+static void stack_makesaved ()
+{
+ stackinfo *s = tos;
+ while (s) {
+ var_makesaved (s->var);
+ s = s->prev;
+ }
+}
+
+
+/******************* Funktion: stack_display **********************************
+
+ Gibt den Inhalt des Stacks aus (also die Pseudoregister, die am
+ Stack liegen)
+ (Nur zu Debug-Zwecken)
+
+******************************************************************************/
+
+static void stack_display (stackinfo *s)
+{
+ if (s) {
+ stack_display (s->prev);
+ var_display (s->var);
+ }
+}
+
--- /dev/null
+/***************************** comp/tools.c ************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Ein paar zus"atzlich notwendige Funktionen, die sonst nirgends
+ hinpassen.
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1996/11/14
+
+*******************************************************************************/
+
+
+/***************** Funktion: compiler_addinitclass ****************************
+
+ zum Eintragen einer Klasse in die Liste der noch zu initialisierenden
+ Klassen
+
+******************************************************************************/
+
+void compiler_addinitclass (classinfo *c)
+{
+ classinfo *cl;
+
+ if (c->initialized) return;
+
+ cl = chain_first(uninitializedclasses);
+ if (cl == c)
+ return;
+
+ if (cl == class)
+ cl = chain_next(uninitializedclasses);
+ for (;;) {
+ if (cl == c)
+ return;
+ if (cl == NULL) {
+ if (runverbose) {
+ sprintf(logtext, "compiler_addinitclass: ");
+ unicode_sprint(logtext+strlen(logtext), c->name);
+ dolog();
+ }
+ chain_addlast(uninitializedclasses, c);
+ return;
+ }
+ if (c < cl) {
+ if (runverbose) {
+ sprintf(logtext, "compiler_addinitclass: ");
+ unicode_sprint(logtext+strlen(logtext), c->name);
+ dolog();
+ }
+ chain_addbefore(uninitializedclasses, c);
+ return;
+ }
+ cl = chain_next(uninitializedclasses);
+ }
+}
+
+
+
+/***************** Hilfsfunktionen zum Decodieren des Bytecodes ***************
+
+ lesen ein Datum des gew"unschten Typs aus dem Bytecode an der
+ angegebenen Stelle
+
+******************************************************************************/
+
+static u1 code_get_u1 (u4 pos)
+{
+ return jcode[pos];
+}
+
+static s1 code_get_s1 (u4 pos)
+{
+ return code_get_u1 (pos);
+}
+
+static u2 code_get_u2 (u4 pos)
+{
+ return ( ((u2) jcode[pos]) << 8 ) + jcode[pos+1];
+}
+
+static s2 code_get_s2 (u4 pos)
+{
+ return code_get_u2 (pos);
+}
+
+static u4 code_get_u4 (u4 pos)
+{
+ return ( ((u4) jcode[pos]) << 24 )
+ + ( ((u4) jcode[pos+1]) << 16 )
+ + ( ((u4) jcode[pos+2]) << 8 )
+ + ( jcode[pos+3] );
+}
+
+static s4 code_get_s4 (u4 pos)
+{
+ return code_get_u4 (pos);
+}
+
+
+
+/******************** Funktion: descriptor2types *****************************
+
+ Decodiert einen Methoddescriptor.
+ Beim Aufruf dieser Funktion MUSS (!!!) der Descriptor ein
+ gueltiges Format haben (wird eh vorher vom loader ueberprueft).
+
+ Die Funktion erzeugt ein Array von integers (u2), in das die
+ Parametertypen eingetragen werden, und liefert einen Zeiger auf
+ das Array in einem Referenzparameter ('paramtypes') zur"uck.
+ Die L"ange dieses Arrays und der Methodenr"uckgabewert werden ebenfalls
+ in Referenzparametern zur"uckgeliefert.
+
+ Der Parameter 'isstatic' gibt an (wenn true), dass kein zus"atzlicher
+ erster Eintrag f"ur den this-Zeiger in das Array eingetragen
+ werden soll (sonst wird er n"amlich automatisch erzeugt, mit dem
+ Typ TYPE_ADDRESS).
+
+******************************************************************************/
+
+static void descriptor2types (unicode *desc, bool isstatic,
+ s4 *paramnum, u1 **paramtypes, s4 *returntype)
+{
+ u2 *text = desc->text;
+ s4 pos;
+ u1 *types;
+ s4 tnum;
+
+ tnum = (isstatic) ? 0 : 1;
+ pos=1;
+ while (text[pos] != ')') {
+ repeatcounting:
+
+ switch (text[pos]) {
+ case '[': pos++;
+ goto repeatcounting;
+ case 'L': while (text[pos]!=';') pos++;
+ break;
+ }
+ pos++;
+ tnum++;
+ }
+
+ types = DMNEW (u1, tnum);
+
+ if (isstatic) tnum=0;
+ else {
+ types[0] = TYPE_ADDRESS;
+ tnum = 1;
+ }
+ pos=1;
+ while (text[pos] != ')') {
+ switch (text[pos]) {
+ case 'B':
+ case 'C':
+ case 'I':
+ case 'S':
+ case 'Z': types[tnum++] = TYPE_INT;
+ break;
+ case 'J': types[tnum++] = TYPE_LONG;
+ break;
+ case 'F': types[tnum++] = TYPE_FLOAT;
+ break;
+ case 'D': types[tnum++] = TYPE_DOUBLE;
+ break;
+ case 'L': types[tnum++] = TYPE_ADDRESS;
+ while (text[pos] != ';') pos++;
+ break;
+ case '[': types[tnum++] = TYPE_ADDRESS;
+ while (text[pos] == '[') pos++;
+ if (text[pos] == 'L') while (text[pos] != ';') pos++;
+ break;
+ default: panic ("Ill formed methodtype-descriptor");
+ }
+ pos++;
+ }
+
+ pos++; /* ueberlesen von ')' */
+
+ switch (text[pos]) {
+ case 'B':
+ case 'C':
+ case 'I':
+ case 'S':
+ case 'Z': *returntype = TYPE_INT;
+ break;
+ case 'J': *returntype = TYPE_LONG;
+ break;
+ case 'F': *returntype = TYPE_FLOAT;
+ break;
+ case 'D': *returntype = TYPE_DOUBLE;
+ break;
+ case '[':
+ case 'L': *returntype = TYPE_ADDRESS;
+ break;
+ case 'V': *returntype = TYPE_VOID;
+ break;
+
+ default: panic ("Ill formed methodtype-descriptor");
+ }
+
+ *paramnum = tnum;
+ *paramtypes = types;
+}
+
--- /dev/null
+/****************************** comp/var.c *************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ verwaltet die Pseudoregister (die ich manchmal auch einfach nur
+ 'Variablen' nenne, daher der Namen des Programmteiles)
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1996/11/14
+
+*******************************************************************************/
+
+
+s4 varnum; /* Anzahl der bereits vergebenen Variablen
+ (eigentlich nur, um den Variablen forlaufende
+ Nummern zu geben, damit man sie beim Debuggen
+ eindeutig kennzeichnen kann) */
+
+list copiedvars; /* Liste aller Variablen die nur eine Kopie einer
+ anderen Variablen sind (w"ahrend der
+ Parse-Phase notwendig) */
+list activevars; /* Liste aller gerade aktiven Variablen
+ (f"ur die Registerbelegungs-phase notwendig) */
+
+list vars; /* Liste aller Variablen, die nicht in einer der
+ obigen Listen sind */
+
+
+/********************** Funktion: var_init ************************************
+
+ initialisiert die Listen und den Variablen-Index-Z"ahler
+
+******************************************************************************/
+
+static void var_init ()
+{
+ varnum = maxlocals;
+ list_init (&vars, OFFSET (varinfo, linkage) );
+ list_init (&copiedvars, OFFSET (varinfo, linkage) );
+ list_init (&activevars, OFFSET (varinfo, linkage) );
+}
+
+
+/********************* Funktion: var_type *************************************
+
+ Liefert den JavaVM-Grundtyp einer Variablen
+
+******************************************************************************/
+
+static u2 var_type (varid v)
+{
+ return v->type;
+}
+
+
+/********************* Funktion: var_create ***********************************
+
+ Erzeugt eine neue Variable des gew"unschten Typs
+
+******************************************************************************/
+
+static varid var_create (u2 type)
+{
+ varinfo *v = DNEW (varinfo);
+
+ list_addlast (&vars, v);
+
+ list_init (&(v -> copies), OFFSET (varinfo, copylink) );
+ v -> original = v;
+
+ v -> type = type;
+ v -> number = varnum++;
+ v -> active = false;
+ v -> globalscope = false;
+ v -> saved = false;
+
+ v -> reg = NULL;
+
+ return v;
+}
+
+
+/***************** Funktion: var_createwithspecialnumber **********************
+
+ Erzeugt eine neue Variable des gew"unschten Typs, dabei wird aber als
+ Kennzeichnungsnummer eine vorgegebene Zahl verwendet (das brauche ich
+ um die lokalen Java-Variablen mit der Nummer des ihres Slots zu
+ kennzeichnen).
+
+******************************************************************************/
+
+static varid var_createwithspecialnumber(u2 type, u4 num)
+{
+ varinfo *v = var_create (type);
+ varnum--;
+ v -> number = num;
+ return v;
+}
+
+
+/*************** Funktion: var_makesaved **************************************
+
+ Kennzeichnet eine Variable daf"ur, dass sie bei Methodenaufrufen nicht
+ zerst"ort werden darf.
+
+******************************************************************************/
+
+static void var_makesaved (varid v)
+{
+ v -> saved = true;
+ v -> reg = NULL;
+}
+
+
+/*************** Funktion: var_proposereg *************************************
+
+ Macht dem Regiserallokator einen Vorschlag, mit welchem Register
+ eine Variable belegt werden sollte (bei Methodenaufrufen k"onnen so
+ viele Umlade-Befehle in die Argumentregister vermieden werden).
+ Aber: Die Anforderung, dass ein Register gesichert sein soll, hat auf
+ jeden Fall Priorit"at "uber so einen Vorschlag.
+
+******************************************************************************/
+
+static void var_proposereg (varid v, reginfo *r)
+{
+ if (v -> saved) return;
+
+ v -> reg = r;
+}
+
+
+/******************** Funktion: var_makecopy **********************************
+
+ kennzeichnet eine Variable daf"ur, dass sie nur eine Kopie einer anderen
+ Variable enth"alt.
+
+******************************************************************************/
+
+static void var_makecopy (varid original, varid copy)
+{
+ list_addlast (&(original->copies), copy);
+ copy -> original = original;
+
+ list_remove (&vars, copy);
+ list_addlast (&copiedvars, copy);
+}
+
+
+/******************** Funktion: var_unlinkcopy ********************************
+
+ eine Variable, die bis jetzt in der Liste der Kopien eingetragen
+ war, wird wieder auf normalen Zustand gebracht.
+
+******************************************************************************/
+
+static void var_unlinkcopy (varid copy)
+{
+ list_remove (&(copy->original->copies), copy);
+ copy -> original = copy;
+
+ list_remove (&copiedvars, copy);
+ list_addlast (&vars, copy);
+}
+
+
+/******************* Funktion: var_isoriginal *********************************
+
+ Liefert true, wenn die Variable selber das Original ist, und keine
+ Kopie einer anderen Variablen (das heisst, wenn sie nicht in der Liste
+ der Kopien eingetragen ist)
+
+******************************************************************************/
+
+static bool var_isoriginal (varid copy)
+{
+ return (copy -> original == copy) ? true : false;
+}
+
+
+/******************* Funktion: var_findoriginal *******************************
+
+ Sucht zu einer Variablen das Original (wenn die Variable eine Kopie ist),
+ oder gibt die Variable selbst zur"uck (im anderen Fall).
+
+******************************************************************************/
+
+static varid var_findoriginal (varid v)
+{
+ return v->original;
+}
+
+
+/******************* Funktion: var_nextcopy ***********************************
+
+ Gibt die erste noch eingetragene Kopie einer Variablen zur"uck.
+ (oder NILL, wenn die Variable keine Kopien hat)
+
+******************************************************************************/
+
+static varid var_nextcopy (varid original)
+{
+ return list_first (&original->copies);
+}
+
+
+/******************* Funktion: var_nextcopiedvar ******************************
+
+ Gibt die erste "uberhaupt noch vorhandene Variable zu"uck, die eine
+ Kopie irgendeiner anderen Variablen ist.
+
+******************************************************************************/
+
+static varid var_nextcopiedvar ()
+{
+ return list_first (&copiedvars);
+}
+
+
+
+/*********************** Funktion: var_isactive *******************************
+
+ Lieftert true, wenn die Variable gerade aktiviert ist (d.h., wenn
+ irgendwann vorher 'var_activate' aufgerufen wurde)
+
+******************************************************************************/
+
+static bool var_isactive (varinfo *v)
+{
+ return v->active;
+}
+
+
+/******************** Funktion: var_activate **********************************
+
+ Aktiviert eine Variable, d.h. sie wird in die Liste der aktiven
+ Variablen eingetragen.
+
+******************************************************************************/
+
+static void var_activate (varinfo *v)
+{
+ list_remove (&vars, v);
+ list_addlast (&activevars, v);
+ v -> active = true;
+}
+
+
+/******************** Funktion: var_deactivate ********************************
+
+ Deaktiviert eine Variable (Gegenst"uck zu var_activate)
+
+******************************************************************************/
+
+static void var_deactivate (varinfo *v)
+{
+ list_remove (&activevars, v);
+ list_addlast (&vars, v);
+ v -> active = false;
+}
+
+
+/****************** Funktion: var_nextactive **********************************
+
+ Liefert die erste noch aktivierte Variable
+
+******************************************************************************/
+
+static varinfo *var_nextactive ()
+{
+ return list_first (&activevars);
+}
+
+
+
+/**************************** Funktion: var_display **************************
+
+ Gibt eine abdruckbare Darstellung einer Variablen aus.
+ (nur zu Debug-Zwecken)
+
+*****************************************************************************/
+
+static void var_display (varinfo *v)
+{
+ if (v==NOVAR) {
+ printf ("_ ");
+ return;
+ }
+
+ switch (v->type) {
+ case TYPE_INT: printf ("I"); break;
+ case TYPE_LONG: printf ("L"); break;
+ case TYPE_FLOAT: printf ("F"); break;
+ case TYPE_DOUBLE: printf ("D"); break;
+ case TYPE_ADDRESS: printf ("A"); break;
+ default: printf ("?");
+ }
+ printf ("%d", v->number);
+
+ if (v->reg) {
+ printf ("(=");
+ reg_display (v->reg);
+ printf (")");
+ }
+ printf (" ");
+}
+
+
+/************************ Funktion: var_displayall **************************
+
+ Gibt eine abdruckbare Darstellung aller Variablen aus.
+ (nur zu Debug-Zwecken)
+
+*****************************************************************************/
+
+void var_displayall ()
+{
+ varid v;
+ int num=0;
+ varid *sorted = DMNEW (varid, varnum);
+
+ printf ("\n Types of all pseudo-variables:\n");
+
+ for (num=0; num<varnum; num++) sorted[num] = NULL;
+ v = list_first (&vars);
+ while (v) {
+ if (sorted[v->number]) {
+ printf (" Local variable overlay: ");
+ if (v->saved) printf ("* ");
+ else printf (" ");
+
+ var_display (v);
+ printf ("\n");
+ }
+ else sorted[v->number] = v;
+
+ v = list_next (&vars, v);
+ }
+
+
+ for (num=0; num<varnum; num++) {
+ v = sorted[num];
+ if (v) {
+ if (v->saved) printf ("* ");
+ else printf (" ");
+
+ var_display (v);
+ if (!v->reg) printf (" ");
+
+ if ( (num%5) == 4 ) printf ("\n");
+ else printf ("\t");
+ }
+ }
+
+ printf ("\n");
+}
+
+
--- /dev/null
+/****************************** compiler.c *************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Enth"alt die Funktionen mit denen die JavaVM - Methoden in Maschinencode
+ "ubersetzt werden.
+ Ein Aufruf vom compiler_compile "ubersetzt genau eine Methode.
+ Alle in diesem Modul global definierten Variablen gelten nur f"ur
+ eben diese gerade in der "Ubersetzung befindlichen Methode.
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+ Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
+ Changes: Mark Probst EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1997/10/22
+
+*******************************************************************************/
+
+#include "global.h"
+#include "compiler.h"
+
+#include "loader.h"
+#include "tables.h"
+#include "builtin.h"
+#include "native.h"
+#include "asmpart.h"
+
+#include "threads/thread.h" /* schani */
+
+
+/*************************** globale Schalter ********************************/
+
+extern int newcompiler;
+methodptr new_compile (methodinfo *m); /* compile a method with new compiler */
+
+/************************** no all in newcomp.c
+
+bool compileverbose = false;
+bool showstack = false;
+bool showintermediate = false;
+bool showdisassemble = false;
+int optimizelevel = 0;
+
+bool checkbounds = true;
+bool checknull = true;
+bool checkfloats = true;
+bool checksync = true;
+
+bool getcompilingtime = false;
+long int compilingtime = 0;
+int has_ext_instr_set = 0;
+
+bool statistics = false;
+
+int count_jit_calls = 0;
+int count_methods = 0;
+int count_spills = 0;
+int count_pcmd_activ = 0;
+int count_pcmd_drop = 0;
+int count_pcmd_zero = 0;
+int count_pcmd_const_store = 0;
+int count_pcmd_const_alu = 0;
+int count_pcmd_const_bra = 0;
+int count_pcmd_load = 0;
+int count_pcmd_move = 0;
+int count_pcmd_store = 0;
+int count_pcmd_store_comb = 0;
+int count_pcmd_op = 0;
+int count_pcmd_mem = 0;
+int count_pcmd_met = 0;
+int count_pcmd_bra = 0;
+int count_pcmd_table = 0;
+int count_pcmd_return = 0;
+int count_pcmd_returnx = 0;
+int count_check_null = 0;
+int count_javainstr = 0;
+int count_javacodesize = 0;
+int count_javaexcsize = 0;
+int count_calls = 0;
+int count_tryblocks = 0;
+int count_code_len = 0;
+int count_data_len = 0;
+int count_cstub_len = 0;
+int count_nstub_len = 0;
+
+********************/
+
+
+/************************ die Datentypen f"ur den Compiler *******************/
+
+#include "comp/defines.c"
+
+
+
+/******************* globale Variablen fuer den Compiler *********************/
+
+static methodinfo *method; /* Zeiger auf die Methodenstruktur */
+static unicode *descriptor; /* Typbeschreibung der Methode */
+static classinfo *class; /* Klasse, in der die Methode steht */
+
+static s4 maxstack; /* maximale Gr"osse des JavaVM-Stacks */
+static s4 maxlocals; /* maximale Anzahl der JavaVM-Variablen */
+static u4 jcodelength; /* L"ange des JavaVM-Codes */
+static u1 *jcode; /* Zeiger auf den JavaVM-Code */
+static s4 exceptiontablelength; /* L"ange der Exceptiontable */
+static exceptiontable *extable; /* Zeiger auf die Exceptiontable */
+
+
+static list reachedblocks; /* Die Listenstruktur f"ur alle vom Parser
+ bereits irgendwie erreichten Bl"ocke */
+static list finishedblocks; /* Die Listenstruktur f"ur alle Bl"ocke, die
+ vom Parser bereits durchgearbeitet wurden */
+
+static basicblock **blocks; /* Eine Tabelle, so lang wie der JavaVM-Code, */
+ /* in der an jeder Stelle, an der ein */
+ /* Basicblock beginnt, der Zeiger auf die */
+ /* ensprechende Basicblock-Struktur einge- */
+ /* tragen ist. */
+
+static bool isleafmethod; /* true, wenn die Methode KEINE weiteren
+ Unterprogramme mehr aufruft */
+
+static s4 mparamnum; /* Die Anzahl der Parameter (incl. this) */
+static u1 *mparamtypes; /* Die Typen aller Parameter (TYPE_INT,...) */
+static s4 mreturntype; /* R"uckgabewert der Methode */
+static varinfo **mparamvars; /* Die PCMD-Variablen, die die Parameter */
+ /* zu Methodenstart enthalten sollen */
+
+
+static chain *uninitializedclasses;
+ /* Eine Tabelle aller von der Methode */
+ /* irgendwie ben"otigten Klassen, die */
+ /* vor dem Start der Methode initialisiert */
+ /* werden m"ussen (wenn sie es noch nicht */
+ /* sind) */
+
+
+/************************ Subsysteme des Compilers ***************************/
+
+
+#include "comp/tools.c" /* ein paar n"utzliche Hilfsfunktionen */
+#include "comp/mcode.c" /* systemUNabh"angiger Teil des Codegenerators */
+
+#include "comp/reg.c" /* Registerverwaltung */
+#include "comp/var.c" /* Die Verwaltung der PCMD-Variblen */
+#include "comp/pcmd.c" /* Funktionen f"ur die Pseudocommandos (=PCMD) */
+#include "comp/local.c" /* Verwaltung der lokalen JavaVM-Variablen */
+#include "comp/stack.c" /* Verwaltung des JavaVM-Stacks */
+#include "comp/regalloc.c" /* Registerallokator */
+
+#include "sysdep/gen.c" /* systemABh"angiger Codegenerator */
+#include "sysdep/disass.c" /* Disassembler (nur zu Debug-Zwecken) */
+
+#include "comp/block.c" /* Verwaltung der basic blocks */
+#include "comp/parse.c" /* JavaVM - parser */
+
+
+
+
+/****** Die Dummy-Function (wird verwendet, wenn kein Code vorhanden ist) ****/
+
+static void* do_nothing_function()
+{
+ return NULL;
+}
+
+
+
+
+/******************************************************************************/
+/*********************** eine Methode compilieren *****************************/
+/******************************************************************************/
+
+
+methodptr compiler_compile (methodinfo *m)
+{
+ u4 i;
+ basicblock *b;
+ long int starttime=0,stoptime=0;
+ long int dumpsize;
+
+ if (newcompiler) {
+ return new_compile(m);
+ }
+
+ /*** Wenn schon ein Maschinencode vorliegt, dann sofort beenden ****/
+
+ count_jit_calls++; /* andi */
+ if (m->entrypoint) return m->entrypoint;
+
+ intsDisable(); /* schani */
+
+
+ /**************** Marke fuer den DUMP-Speicher aufheben *****************/
+
+ dumpsize = dump_size ();
+
+
+ /**************** Zeit messen *******************************************/
+
+ count_methods++; /* andi */
+ if (getcompilingtime) starttime=getcputime();
+
+ /*** Meldung ausgeben. Wenn kein JavaVM-Code vorhanden ist, beenden ****/
+
+ if (m->jcode) {
+ if (compileverbose) {
+ sprintf (logtext, "Compiling: ");
+ unicode_sprint (logtext+strlen(logtext), m->class->name);
+ strcpy (logtext+strlen(logtext), ".");
+ unicode_sprint (logtext+strlen(logtext), m->name);
+ unicode_sprint (logtext+strlen(logtext), m->descriptor);
+ dolog ();
+ }
+ }
+ else {
+ sprintf (logtext, "No code given for: ");
+ unicode_sprint (logtext+strlen(logtext), m->class->name);
+ strcpy (logtext+strlen(logtext), ".");
+ unicode_sprint (logtext+strlen(logtext), m->name);
+ unicode_sprint (logtext+strlen(logtext), m->descriptor);
+ dolog ();
+ intsRestore(); /* schani */
+ return (methodptr) do_nothing_function;
+ }
+
+
+ /*********** Initialisieren der Variablen und Subsysteme *****************/
+
+ isleafmethod = true; /* bis sich das Gegenteil herausstellt */
+
+ method = m;
+ descriptor = m->descriptor;
+ class = m->class;
+
+ maxstack = m->maxstack;
+ maxlocals = m->maxlocals;
+ jcodelength = m->jcodelength;
+ jcode = m->jcode;
+ count_tryblocks += (exceptiontablelength = m->exceptiontablelength);
+ extable = m->exceptiontable;
+
+#ifdef STATISTICS
+ count_javacodesize += jcodelength + 18;
+ count_javaexcsize += exceptiontablelength * 8;
+#endif
+
+ list_init (&reachedblocks, OFFSET(basicblock, linkage) );
+ list_init (&finishedblocks, OFFSET(basicblock, linkage) );
+
+ blocks = DMNEW (basicblock*, jcodelength);
+ for (i=0; i<jcodelength; i++) blocks[i] = NULL;
+
+
+ descriptor2types (descriptor, (m->flags & ACC_STATIC) != 0,
+ &mparamnum, &mparamtypes, &mreturntype);
+ m->paramcount = mparamnum;
+ m->returntype = mreturntype;
+ mparamvars = DMNEW (varid, mparamnum);
+
+ reg_init ();
+ mcode_init ();
+ var_init();
+ local_init();
+
+ uninitializedclasses = chain_new();
+ /* aktuelle Klasse zur Liste der m"oglicherweise zu
+ initialisierenden Klassen dazugeben */
+ compiler_addinitclass (m->class);
+
+
+ /************************ Compilieren ************************/
+
+ /* Fuer jedes Sprungziel einen eigenen Block erzeugen */
+ block_firstscann ();
+
+ /* Den ersten Block als erreicht markieren, der Stack ist leer */
+ stack_init();
+ subroutine_set(NULL);
+ block_reach ( block_find(0) );
+
+ /* Alle schon erreichten Bl"ocke durchgehen und fertig machen */
+ while ( (b = list_first (&reachedblocks)) ) {
+ list_remove (&reachedblocks, b);
+ list_addlast (&finishedblocks, b);
+ b -> finished = true;
+
+ pcmd_init ( &(b->pcmdlist) );
+ parse (b);
+ }
+
+ input_args_prealloc ();
+
+ /* F"ur alle Bl"ocke die Registerbelegung durchfuehren */
+ b = list_first (&finishedblocks);
+ while (b) {
+ regalloc (b);
+ b = list_next (&finishedblocks, b);
+ }
+
+
+ /* Registerbelegung fuer die lokalen JAVA-Variablen */
+ local_regalloc ();
+
+
+
+
+ /**************** Maschinencode generieren **********************/
+
+ gen_computestackframe ();
+ gen_header ();
+
+
+ for (i=0; i<jcodelength; i++) {
+ b = blocks[i];
+ if (b) if (b->reached) block_genmcode (b);
+ }
+
+ b = list_first (&finishedblocks);
+ while (b) {
+ if (b->type != BLOCKTYPE_JAVA) block_genmcode (b);
+ b = list_next (&finishedblocks, b);
+ }
+
+
+ mcode_finish ();
+
+
+ /*********** Zwischendarstellungen auf Wunsch ausgeben **********/
+
+ if (showintermediate) {
+ printf ("Leaf-method: %s\n", isleafmethod ? "YES":"NO");
+ printf ("Parameters: ");
+ for (i=0; i<mparamnum; i++) var_display (mparamvars[i]);
+ printf ("\n");
+ printf ("Max locals: %d\n", (int) maxlocals);
+ printf ("Max stack: %d\n", (int) maxstack);
+
+ for (i=0; i<jcodelength; i++) {
+ b = blocks[i];
+ if (b) if (b->reached) block_display (b);
+ }
+ b = list_first (&finishedblocks);
+ while (b) {
+ if (b->type != BLOCKTYPE_JAVA) block_display (b);
+ b = list_next (&finishedblocks, b);
+ }
+
+ var_displayall();
+ fflush (stdout);
+ }
+
+ if (showdisassemble) {
+ dseg_display ();
+ disassemble ( (void*) (m->mcode + dseglen), mcodelen);
+ fflush (stdout);
+ }
+
+
+
+ /***************** Dump-Speicher zurueckgeben *************/
+
+ dump_release (dumpsize);
+
+
+ /******************* Zeit messen **************************/
+
+ if (getcompilingtime) {
+ stoptime = getcputime();
+ compilingtime += (stoptime-starttime);
+ }
+
+ /******** Alle Klassen initialisieren, die gebraucht wurden *******/
+
+ {
+ chain *u = uninitializedclasses; /* wegen reentrant-F"ahigkeit */
+ classinfo *c; /* d"urfen ab hier keine */
+ /* globalen Variablen verwendet */
+ while ( (c = chain_first(u)) ) { /* werden */
+ chain_remove (u);
+
+ class_init (c); /* ruft unter Umst"anden wieder */
+ /* den Compiler auf */
+ }
+ chain_free (u);
+ }
+
+ intsRestore(); /* schani */
+
+
+
+ /****** Return pointer to the methods entry point **********/
+
+ return m -> entrypoint;
+
+}
+
+
+
+/***************** Funktionen zum Initialisieren und Terminieren *************/
+
+void compiler_init ()
+{
+ u4 i;
+
+ has_ext_instr_set = ! has_no_x_instr_set();
+
+ for (i=0; i<256;i++) stdopdescriptors[i]=NULL;
+
+ for (i=0; i<sizeof(stdopdescriptortable)/sizeof(stdopdescriptor); i++) {
+
+ if (stdopdescriptortable[i].isfloat && checkfloats) {
+ stdopdescriptortable[i].supported = false;
+ }
+
+ stdopdescriptors[stdopdescriptortable[i].opcode] =
+ &(stdopdescriptortable[i]);
+ }
+}
+
+
+void compiler_close()
+{
+ reg_close ();
+ mcode_close();
+}
+
--- /dev/null
+/****************************** compiler.h *************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Contains the codegenerator for an Alpha processor.
+ This module generates Alpha machine code for a sequence of
+ pseudo commands (PCMDs).
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+ Changes: Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1997/10/22
+
+*******************************************************************************/
+
+/************** Compiler-switches (werden von main gesetzt) *****************/
+
+
+extern bool compileverbose;
+extern bool showstack;
+extern bool showdisassemble;
+extern bool showintermediate;
+extern int optimizelevel;
+
+extern bool checkbounds;
+extern bool checknull;
+extern bool checkfloats;
+extern bool checksync;
+
+extern int has_ext_instr_set;
+
+extern bool getcompilingtime;
+extern long int compilingtime;
+
+extern bool statistics;
+
+extern int count_jit_calls;
+extern int count_methods;
+extern int count_spills;
+extern int count_pcmd_activ;
+extern int count_pcmd_drop;
+extern int count_pcmd_zero;
+extern int count_pcmd_const_store;
+extern int count_pcmd_const_alu;
+extern int count_pcmd_const_bra;
+extern int count_pcmd_load;
+extern int count_pcmd_move;
+extern int count_pcmd_store;
+extern int count_pcmd_store_comb;
+extern int count_pcmd_op;
+extern int count_pcmd_mem;
+extern int count_pcmd_met;
+extern int count_pcmd_bra;
+extern int count_pcmd_table;
+extern int count_pcmd_return;
+extern int count_pcmd_returnx;
+extern int count_check_null;
+extern int count_check_bound;
+extern int count_javainstr;
+extern int count_javacodesize;
+extern int count_javaexcsize;
+extern int count_calls;
+extern int count_tryblocks;
+extern int count_code_len;
+extern int count_data_len;
+extern int count_cstub_len;
+extern int count_nstub_len;
+
+
+/******************************* Prototypes *********************************/
+
+methodptr compiler_compile (methodinfo *m);
+
+void compiler_init ();
+void compiler_close ();
+
+u1 *createcompilerstub (methodinfo *m);
+u1 *createnativestub (functionptr f, methodinfo *m);
+u1 *ncreatenativestub (functionptr f, methodinfo *m);
+
+void removecompilerstub (u1 *stub);
+void removenativestub (u1 *stub);
+
--- /dev/null
+/*************************** doc/collect.doc ***********************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Enth"alt die Beschreibung des Garbage Collectors
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1996/11/14
+
+*******************************************************************************/
+
+Generell:
+
+F"ur den CACAO habe ich einen recht einfachen Mark and Sweep - Collector
+implementiert, mit dem der Speicher immer dann ges"aubert wird, wenn
+eine Anforderung nicht zufriedenstellend durchgef"uhrt werden
+kann (im Klartext: der GC l"auft NICHT in einem eigenen Thread).
+
+Der Heap ist ein einziger Speicherblock, der gleich zu Programmstart
+angelegt wird, und dessen Gr"osse sich nicht mehr "andern kann.
+(also immer gleich gen"ugend Speicher anlegen! Bei Maschinen mit
+virtuellem Speicher sollte das kein Problem sein)
+
+Der Collector verschiebt keine Objekte im Speicher, und er kommt mit
+minimaler Information "uber die innere Struktur der Objekte aus
+(um es pr"aziser zu sagen: Der GC nimmt bei allen Daten einmal an,
+dass es sich dabei um Zeiger auf Objekte in den Heap handelt. Wenn
+irgendwelche Zahlen z"uf"allig einen g"ultigen Zeiger auf ein Objekt
+darstellen, dann wird dieses Objekt eben nicht freigeben.)
+
+Der Heap ist in kleine unteilbare Einheiten aufgeteilt, die nur immer
+als ganzen vergeben werden k"onnen (Heap-Bl"ocke), deren Gr"osse
+auf jeden Fall die in Java n"otigen Alignment-Bedingungen erf"ullt.
+
+
+Notwendige zus"atzliche Datenstrukturen
+---------------------------------------
+
+Der GC muss auf jeden Fall wissen, wo im Heap g"ultige Objekte stehen
+(damit die Markierung mit m"oglicher- (aber nicht notwendigerweise)
+g"ultigen Zeigern richtig funktioniert).
+
+Dazu verwaltet er ein Bitfeld ('startbits'), in dem f"ur jeden Heap-Block
+eintr"agt, ob an der Stelle ein Objekt anf"angt. Zu"atzlich werden auch
+alle FREIEN Speicherbereiche mit so einem Bit markiert.
+
+Ein zweites Bitfeld ('referencebits') gibt an, ob in dem Objekt, das
+an der Stelle anf"angt, noch weitere Referenzen auf andere Objekte
+gespeichert sein k"onnen.
+(Damit die Markierungsphase fr"uhzeitig abgebrochen werden kann)
+
+Beispiel:
+
+Heap: | Obj1 | Obj2 | frei | Obj3 | Obj3 | frei |
+ -------------------------------------------------------
+
+startbits: 100000010000000100000000000000100000010000001000000000
+
+referencebits: 100000000000000000000000000000100000000000000000000000
+
+
+(in obigem Beispiel k"onnten Obj1 und Obj3 noch weitere Referenzen
+enthalten)
+
+Man beachte: Die Bitfelder werden nur soweit benutzt, als tats"achlich
+schon Platz am Heap vergeben worden ist (wird mit Hilfe einer globalen
+Variable 'topofheap' gehandhabt). Alle dar"uberhausgehenden Bits sind
+noch 0. Das letzte Objekte im Heap (oder der freie Speicherbereich)
+wird also nicht mit so einem 1-Bit abgeschlossen.
+
+
+Vorgangsweise beim Anlegen eines neuen Objektes
+-----------------------------------------------
+
+In einer Freispeicherliste sind alle freien Bereiche eingetragen
+(die Freispeicherlisten verwenden dabei gleich den freien Speicher
+f"ur die notwendige Verkettung).
+Zuerst muss beliebiger passender Bereich gesucht werden.
+
+1. Fall: Bereich hat genau die richtige Gr"osse
+ - Aus der Freispeicherliste austragen
+ - gegebenenfalls das zugeh"orige Bit im Feld 'referencebits'
+ setzen
+ - fertig
+
+2. Fall: Bereich ist gr"osser als notwendig
+ - Aus der Freispeicherliste austragen.
+ - In Liste das Restst"uckchen eintragen
+ - Ein Bit im Bitfeld 'startbits' eintragen, wo der neue freie
+ Speicher anf"angt.
+ - gegebenenfalls das dem neuen Objete zugeh"orige Bit im Feld
+ 'referencebits' setzen
+ - fertig
+
+3. Fall: Es ist kein freier Bereich mehr in der Freispeicherliste
+ - das neue Objekte wird ganz oben am Heap angelegt
+ - Bit im Bitfeld 'startbits' am der Stelle 'topofheap' eintragen.
+ - den 'topofheap'-Z"ahler im die Objektel"ange erh"ohen
+ - eventuell ein Bit in 'referencebits' setzen
+ - fertig
+
+4. Fall: Es ist zuwenig Speicher mehr oben im Heap "ubrig
+ - Garbage Collection durchf"uhren
+ - alles nocheinmal probieren
+
+
+Vorgangsweise zur Garbage Collection
+------------------------------------
+
+Ein drittes Bitfeld ('markbits') wird ben"otigt, das zuerst mit
+0 initialisiert wird.
+
+In der Markierungsphase werden alle Objekte durchgegangen, die
+von irgendwo im Stack oder von globalen Variablen aus erreichbar
+sind.
+Ein Zeiger zeigt tats"achlich auf ein g"ultiges Objekt im Heap, wenn:
+ - Der Zeiger in den Bereich des Heap zeigt
+ - Der Zeiger richtiges Alignment hat (auf Blockgr"osse)
+ - Das zugeh"orige Bit in 'startbits' gesetzt ist
+
+Wenn das der Fall ist, und das Bit in 'markbits' noch nicht gesetzt ist,
+dann wird dieses Bit jetzt gesetzt, und wenn noch dazu das Bit in
+'referencebits' gesetzt ist, dann werden alle Referenzen vom Objekt
+rekuriv ebenfalls markiert.
+Die L"ange des Objektes erf"ahrt man aus dem 'startbits'-Feld. Man muss
+nur den n"achsten 1er suchen (oder vorher abbrechen, wenn man die
+Stelle 'topofheap' erreicht).
+
+
+Beispiel:
+
+Heap: | Obj1 | Obj2 | frei | Obj3 | Obj4 | frei |
+ -------------------------------------------------------
+
+startbits: 100000010000000100000000000000100000010000001000000000
+markbits: 000000010000000000000000000000100000010000000000000000
+
+referencebits: 100000000000000000000000000000100000000000000000000000
+
+In dem Beispiel wurden nur mehr Obj2 und Obj3 als erreichbar erkannt,
+die anderen Objekte wurden nicht erreicht.
+
+Anmerkung: Es k"onnte hier passieren, dass ein freier Speicherbereich
+ irrt"umlich als Objekte markiert und f"ur den folgenden
+ Sweep-Durchlauf blockiert wird. Das sollte aber nur SEHR selten
+ vorkommen.
+
+
+Nach der Markierungsphase sieht man schon, dass einige Objekte
+weggeworfen werden sollen. Damit die zu diesen Objekte geh"orenden
+'referencebits' ebenfalls gel"oscht werden, braucht man nur
+ein logisches UND der beiden Bitfelder 'markbits' und 'referencebits'
+durchf"uhren, und das Ergebnis in 'referencebits' speichern.
+
+Obiges Beispiel:
+
+markbits: 000000010000000000000000000000100000010000000000000000
+referencebits: 100000000000000000000000000000100000000000000000000000
+---------------------------------------------------------------------
+ UND 000000000000000000000000000000100000000000000000000000
+
+
+
+
+
+F"ur die Sweep-Phase wird der gesammte Bereich linear durchgegangen,
+und alle freien Bereiche in die Freispeicherliste eingeh"angt.
+
+Dazu wird der Anfang des ersten freien Bereiches gesucht, und zwar indem
+nach der erste Stelle gesucht wird, an der ein startbit GESETZT ist,
+aber das markbit NICHT gesetzt ist.
+Das Ende des freien Bereiches findet man dort, wo das n"achste
+markbit GESETZT ist.
+(dabei werden auch automatisch hintereinanderliegenden Speicherst"ucke
+zusammengefasst)
+Den gesammten Bereich kann man jetzt in die Freispeicherliste einh"angen,
+und gleichzeitig muss noch ds markbit, an dem der Bereich anf"angt,
+gesetzt werden (wozu, das wird weiter unten erkl"art)
+
+F"ur alle folgenden Bl"ocke geht man genauso vor, bis das Ende des
+Heaps erreicht ist.
+Die oben erw"ahnten Bit-Suche-Operationen gehen - wenn man sie gut
+implementiert - relativ rasch (z.B. mit 64-Bit-Operationen auf einer
+DEC-Alpha).
+
+
+Der Grund, warum man alle freien Bereiche mit einem zus"atzlichen
+Markierungsbit versieht ist der, dass jetzt zu Ende des Sweep in
+'markbits' genau diejenige Bits stehen, die eigentlich auch in
+'startbits' geh"oren, n"amlich eine Kennzeichnung aller lebenden
+Objekte und aller Freispeicherbereiche.
+
+
+Fortsetzung des obigen Beispiels:
+
+Heap: | frei | Obj2 | frei | Obj3 | frei |
+ -------------------------------------------------------
+
+startbits: 100000010000000100000000000000100000010000001000000000
+markbits: 100000010000000100000000000000100000010000000000000000
+
+referencebits: 000000000000000000000000000000100000000000000000000000
+
+
+Durch einfaches Umkopieren der 'markbits' auf die 'startbits'
+(oder noch besser: durch Austauschen der beiden Zeiger) ist der
+Garbage-Collection-Durchlauf abgeschlossen.
+
+
--- /dev/null
+/***************************** doc/gen.doc *************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Enth"alt die Beschreibung der Schnittstelle zwischen dem systemUNabh"angigen
+ und dem systemABh"angigen Teil des Compilers.
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1997/03/05
+
+*******************************************************************************/
+
+Der gr"osste Teil des Compilers ist maschinenunabh"angig programmiert,
+aber diejenigen Programmteile, die den tats"achlichen Maschinencode
+erzeugen, m"ussen f"ur jede Maschine extra implementiert werden.
+
+Alle diese abh"angigen Teile habe ich im Verzeichnis 'sysdep' zusammen-
+gefa"sst (und sysdep selbst ist ein symbolischer Link auf das entsprechende
+Verzeichnis der tats"achlichen Architektur, so dass nur mehr dieser Link
+umgesetzt werden muss, damit das Programm auf einem anderen Rechner
+compiliert werden kann).
+
+Im Verzeichnis 'comp' gibt es folgende systemabh"angige Programmteile:
+(diese Dateien sind als Links in das Verzeichnis 'sysdep' realisiert)
+
+ reg.c ..... Registerbelegung
+ gen.c ..... generieren von Maschinencode
+ disass.c .. Disassembler (nur f"ur Debug-Zwecke)
+
+
+-------------------------------------------------------------------------------
+1. Der Registerallokator (reg.c)
+-------------------------------------------------------------------------------
+
+Die Pseudoregister, die vom Compiler bei allen Operationen verwendet werden,
+m"ussen irgendwann mit tats"achlichen CPU-Registern belegt werden.
+
+Die Belegung funktioniert nach folgendem Prinzip:
+
+Immer, wenn der Compiler ein CPU-Register f"ur eines seiner
+Pseudoregister ben"otigt, ruft er eine entsprechende Funktion des
+Allokators auf. Diese erzeugt eine 'reginfo'-Struktur, die die
+Information f"ur ein Register enth"alt (Typ INT/FLOAT, Registernummer,
+Auslagerungsinformation...).
+Der Inhalt der 'reginfo'-Struktur ist f"ur den systemunabh"angigen
+Compiler nicht von Bedeutung (wird also sozusagen als opaker Datentyp
+behandelt).
+Wenn irgendwann nicht mehr genug CPU-Register zur Verf"ugung stehen,
+dann darf der Allokator Register auch in den Speicher (also auf den
+Stack) auslagern. Er muss dazu einfach eine entsprechende 'reginfo'-
+Struktur erzeugen, die dann eben den Offset im Stackframe und
+alle n"otigen Zusatzinformationen enth"alt.
+
+
+Die Funktionen im einzelnen sind:
+
+void reg_init ()
+ initialisiert den Registerallokator
+
+
+reginfo *reg_allocate(u2 type, bool saved, bool new)
+ erzeugt eine reginfo-Struktur mit den entsprechenden Eintr"agen.
+ (Diese Datenstruktur muss am DUMP-Speicher [siehe Toolbox-Beschreibung]
+ angelegt werden, damit sie irgendwann sp"ater automatisch freigegeben
+ wird)
+
+ Das so belegte Register muss verschiedene Voraussetzugen erf"ullen:
+ - Es muss ein Datum vom Java-Typ type
+ (= TYPE_INT/TYPE_LONG/TYPE_FLOAT/TYPE_DOUBLE/TYPE_ADDRESS)
+ aufnehmen k"onnen
+ - Wenn saved=true, dann darf das Register w"ahrend Funktionsaufrufen
+ nicht zerst"ort werden.
+ - Wenn new=true, dann darf das Register noch NIE vorher vergeben
+ worden sein.
+
+ Alle so mit 'reg_allocate' belegten Register werden f"ur nachfolgende
+ Aufrufe von 'reg_allocate' gesperrt, sie d"urfen also nicht zweimal
+ hintereinander vergeben werden (eh klar!).
+
+ Diese Funktion muss IMMER eine g"ultige 'reginfo'-Struktur erzeugen,
+ auch wenn vielleicht keine normalen Register mehr "ubrig sind. In
+ solchen F"allen muss eben ein auf den Speicher ausgelagertes
+ Register erzeugt werden.
+
+
+void *reg_free(reginfo *r)
+ Gibt ein durch reg_allocate angefordertes Register tempor"ar wieder
+ frei. Dabei darf die 'reginfo'-Struktur aber NICHT zerst"ort werden,
+ weil sie vom Compiler sp"ater wieder gebraucht wird.
+ Das solchermassen frei gewordene CPU-Register (nicht diese reginfo-
+ Struktur) darf aber bei einem folgendem Aufruf von reg_allocate
+ wieder vergeben werden.
+
+
+bool reg_reallocate (reginfo *r)
+ versucht ein schon einmal angefordertes (aber in der Zwischenzeit
+ wieder freigegebenens) Register neuerlich anzufordern.
+ Wenn das Register immer noch unbenutzt ist, dann ist alles OK
+ (R"uckgabewert true), sonst wird 'false' zur"uckgeben, und aus der
+ neuerlichen Belegung wird nichts. In diesem Falle wird der Compiler
+ versuchen, mit 'reg_allocate' ein ganz neues Register anzufordern.
+
+
+void reg_display (reginfo *r)
+ dient nur zu Debug-Zwecken, und gibt eine lesbare Darstellung des
+ mit 'reginfo' beschriebenen Registers auf 'stdout' aus.
+
+
+
+Die nachfolgenden Funktionen sind f"ur die Optimierung der Funktionsaufrufe,
+bzw. der Registerbenutzung im Zusammenhang mit Funktionsaufrufen bestimmt.
+Jede dieser Funktionen darf entweder NULL zur"ckliefern (als allererste
+nichtoptimierte Version), oder aber eine entsprechende 'reginfo'-Struktur.
+
+
+reginfo *reg_parlistresult(u2 type)
+ erzeugt eine 'reginfo'-Struktur (auf dem DUMP), die das CPU-Register
+ beschreibt, mit den normalerweise ein Datum vom Typ type von
+ Funktionen zur"uckgeliefert wird.
+ Diese Funktion wird auch schon vor dem Aufruf von 'reg_init' verwendet,
+ Diese Funktion selbst blockiert noch kein Register, und sie braucht auch
+ keine R"ucksicht auf irgendwelche schon durchgef"uhrten Registerbelegungen
+ nehmen. Die tats"achliche Allokation wird sp"ater mit einem Aufruf
+ von 'reg_reallocate' versucht.
+
+reginfo *reg_parlistexception()
+ erzeugt eine 'reginfo'-Struktur (auf dem DUMP), die das CPU-Register
+ beschreibt, mit den normalerweise der Zeiger auf eine Exception von
+ Funktionen zur"uckgeliefert wird.
+ Ansonsten v"ollig analog zu 'reg_parlistresult'
+
+reginfo *reg_parlistpar(u2 type)
+ erzeugt eine 'reginfo'-Struktur (auf dem DUMP), die das CPU-Register
+ beschreibt, mit dem normalerweise ein Datum vom Typ type als Parameter
+ an eine Funktion "ubergeben wird.
+ Diese Funktion wird im allgemeinen mehrmals hintereinander aufgerufen,
+ n"amlich f"ur jedes gew"unschte Parameterregister einmal.
+ Jede solche Sequenz wird mit 'reg_parlistinit' eingeleitet.
+ Ansonsten funktioniert diese Funktion wie 'reg_parlistresult'.
+ Achtung: Diese Funktion sollte gegebenenfalls auch maximale Anzahl
+ der Parameter bei Funktionsaufrufen notieren, wenn diese Information
+ sp"ater vom Codegenerator gebraucht wird.
+
+void reg_parlistinit ()
+ Setzt den Parameterz"ahler, den die Funktion 'reg_parlistpar' intern
+ ben"otigen wird, auf 0.
+
+
+-------------------------------------------------------------------------------
+2. Der Codegenerator (gen.c)
+-------------------------------------------------------------------------------
+
+Der Compiler erzeugt im ersten Durchgang eine systemunabh"angige Darstellung
+einer Methode (Operationen mit Quell- und Ziel(pseudo)registern).
+Im zweiten Durchgang werden alle Pseudoregister mit tats"achlichen Registern
+belegt (siehe oben), und
+im dritten Durchgang wird der tats"achliche Code erzeugt (eben durch
+den Codegenerator).
+
+Der Codegenerator besteht aus mehreren Teilen:
+
+
+void gen_computestackframe()
+ berechnet das Memory-Layout des Stackframe f"ur die Methode.
+ Dabei m"ussen alle Register, die vom Register-Allokator vergeben
+ worden, sind und die Anzahl der zu sichernden Register und
+ die maximale Anzahl der Parameter ber"ucksichtigt werden.
+
+void gen_header()
+ erzeugt den Kopf der Methode (Anlegen des Stackframes, sichern von
+ Registern, holen der Parameter vom Stack oder von Registern, etc..)
+
+void gen_pcmd (pcmd *c)
+ erzeugt zu einem Pseudo-Kommando den entsprechenden Maschinencode.
+ Eine Beschreibung der pcmd-Struktur und aller f"ur den Codegenerator
+ relevanten globalen Variablen und Funktionen sind weiter unten beschrieben.
+
+void gen_resolvebranch ( void* mcodepiece, u4 sourcepos, u4 targetpos)
+ tr"agt eine tats"achlien Sprungadresse in den vorher erzeuten
+ Maschinencode ein (Backpatching).
+ Parameter: mcodepiece ... Zeiger in den Speicher, wo der entsprechende
+ Sprungbefehl steht
+ sourcepos .... relative Adresse des Sprungbefehls in Byte
+ (vom Methodenbeginn an gerechnet)
+ targetpos .... relative Adresse des Sprungziels in Byte
+ (vom Methodenbeginn an gerechnet)
+
+
+Alle Literale, die der Codegenerator erzeugt (konstante Integers,
+Addressen,...) werden in einem direkt VOR dem Codesegment liegenden
+Datensegment gespeichert.
+Dabei w"achst das Datensegment von oben nach unten, und das Codesegment
+von unten nach oben.
+Die Addressierung sowohl des Codes, als auch der Daten kann dann
+"uber ein einziges Basisregister (auf der ALPHA ist das das Register
+ R27 = PV ).
+Der Codegenerator greift auf diese beiden Segmente nur "uber spezielle
+Funktionen zu, die den Speicher f"ur die Segmente gegebenenfalls
+vergr"ossern k"onnen.
+Am Ende der Generierung wird ein dann einziger Speicherblock angelegt,
+wo beide Segmente passgenau hineingeschrieben werden.
+
+
+3. Der Disassembler (disass.c)
+-------------------------------------------------------------------------------
+
+Der Disassembler dient nur zu Debug-Zwecken und kann durch eine Dummy-Funktion
+ersetzt werden.
+
+Der Disassembler hat nur eine Funktion:
+
+disassemble(u4 *code, u4 len)
+ erzeugt ein lesbares Listing der Maschinenbefehle, die im Speicher
+ an der angegebenen Stelle stehen. Die L"ange des Maschinenprogrammes
+ wird hier in BYTE angegeben.
+ Das Listing wird auf 'stdout' ausgegeben.
+
+
+
+------------------------------------------------------------------------------
+Beschreibung der globalen Variablen und Methoden
+------------------------------------------------------------------------------
+
+Der Codegenerator braucht f"ur seine Arbeit einige Funktionen und
+Variablen, die im systemUnabh"angigen Teil bereits zur Verf"ugung stehen.
+
+
+Funktionen
+----------
+
+mcode_addu4 (u4 codepiece)
+ f"ugt zum aktuell erzeugten Codesegment ein 32-Byte-Wort hinzu.
+ Damit sollten sich alle Maschinenbefehle (zumindest f"ur RISC)
+ erzeugen lassen.
+
+s4 dseg_adds4 (s4 value)
+s4 dseg_adds8 (s8 value)
+s4 dseg_addfloat (float value)
+s4 dseg_adddouble (double value)
+s4 dseg_addaddress (void *value)
+ diese Funktionen f"ugen das entsprechende Datum zum Datensegment
+ der Methode hinzu. Das Alignment wird auf jeden Fall richtig
+ behandelt.
+
+ Alle diese Funktionen liefern als R"uckgabewert den Offset des
+ Datenelements innerhalb des Datensegments zur"uck. Weil das Datensegment
+ direkt vor dem Codesegment liegt, und alle Addressierungen
+ relativ zum Methodenanfang (also zum Anfang des Codes) passieren,
+ sind diese Offsets immer negativ.
+
+s4 dseg_addtarget (basicblock *target)
+ funktioniert im Prinzip so wie die obigen Funktionen, allerdings
+ wird in das Datensegment ein Zeiger auf eine Codeposition (deren
+ genaue Adresse aber noch gar nicht feststeht) eingetragen.
+ Die tats"achliche Adresse wird ganz am Ende der Codeerzeugung
+ automatisch an die richtige Stelle geschrieben, so dass beim
+ Programmlauf auf jeden Fall der richtige Wert dort steht.
+ (Diese Funktion wird wahrscheinlich vor allem f"ur Sprungtabellen
+ von Bedeutung sein)
+
+
+void mcode_addreference (basicblock *target)
+ Mit dieser Funktion macht der Codegenerator einen Eintrag in die
+ Liste der der sp"ater zu vervollst"andigenden Sprungbefehle.
+ Die Vorgehensweise ist folgende:
+ - Wenn der Codegenerator ein (Vorw"arts-)Sprunganweisung erzeugen will,
+ dann ruft er VORHER mcode_addreference auf (als Parameter
+ die entsprechende basicblock-Struktur)
+ - Dann erzeugt der Codegenerator einen Sprungbefehl (mit mcode_addu4),
+ l"asst dabei aber die Zieladdresse leer (weil sie ja noch nicht
+ feststeht)
+ - sobald der Code fertig erzeugt worden ist (und alle Sprungziele
+ feststehen) wird f"ur jeden so vorbereiteten Sprungbefehl die
+ Funktion gen_resolvebranch (Dokumentation siehe dort) aufgerufen.
+
+
+
+Globale Variablen
+-----------------
+
+bool isleafmethod
+ zeigt an, dass die Methode eine Leaf-Methode ist, d.h, dass sie keine
+ weiteren Methoden oder Funktionen aufruft
+
+u2 mparamnum
+ die Anzahl der Parameter f"ur die Methode, inklusive dem
+ this-Zeiger (aber um den this-Zeiger braucht sich der Codegenerator
+ sowieso nicht extra k"ummern)
+
+u2 *mparatypes
+ ein Zeiger auf ein Array von Integers, die die Java-Grundtypen
+ (TYPE_INT, TYPE_LONG,...) der Parameter angeben
+
+u2 mreturntype
+ gibt den Java-Grundtyp des R"uckgabewertes an (TYPE_INT, TYPE_LONG)
+ oder bei Methoden ohne R"uckgabewert: TYPE_VOID
+
+varinfo **mparamvars
+ ein Zeiger auf ein Array von Zeigern auf die varinfo-Strukturen.
+ Diese varinfos geben die Pseudoregister an, in die die Parameter
+ der Methode nach dem Aufruf geschrieben werden sollen (der Code
+ f"ur dieses (eventuell n"otige) Umladen der Werte muss von
+ gen_header erzeugt werden).
+
+
+------------------------------------------------------------------------------
+die varinfo-Struktur
+------------------------------------------------------------------------------
+
+In den Pseudocommandos (pcmd) stehen als Operanden immer Verweise auf
+Pseudoregister, denen w"ahrend der Registerbelegungsphase echte
+Maschinenregister zugewiesen werden.
+F"ur den nachfolgenden Codegenerator ist dann nur mehr das entsprechende
+Maschinenregister von Bedeutung.
+Der Codegenerator darf in der varinfo-Struktur nur auf das Feld
+'reg' zugreifen, das einen Zeiger auf die entsprechende 'reginfo'-Struktur
+(wie sie vom Registerallokator erzeugt worden ist -> siehe oben) enth"alt.
+Der Codegenerator kann sich darauf verlassen, dass jeder varinfo-Struktur,
+die "uber ein pcmd erreichbar ist, auch ein entsprechendes reginfo zugewiesen
+wurde.
+
+
+
+------------------------------------------------------------------------------
+Die pcmd-Struktur
+------------------------------------------------------------------------------
+
+Hier finden sich alle Informationen, die die Funktion 'gen_pcmd'
+braucht, um damit Maschinencode f"ur ein Pseudokommando zu erzeugen.
+Die Syntax dieser Struktur (mit Kommentaren) befindet sich unter anderem
+in der Datei 'defines.c'.
+
+F"ur verschiedene Typen von Kommandos muss die Struktur verschiedene
+Daten enthalten, deshalb ist sie mit Hilfe einer 'union' realisiert,
+und ein tag-Feld gibt den tats"achlichen Typ der Struktur an (jaja, in
+C gibt es eben keine abgeleiteten Datentypen ...).
+Die Werte und Bezeichnung f"ur dieses Tag-Feld steht ebenfalls in der
+Datei 'defines.c'
+
+
+Beschreibung der allgemeinen Felder der 'pcmd'.
+
+ linkage ... interne Verkettung, f"ur den Codegenerator ohne Bedeutung)
+ tag ....... Kennzeichnung des Typs des Kommandos
+
+ dest ...... Pseudoregister f"ur eine optionalen Zieloperanden
+ source1 ... Pseudoregister f"ur den 1. optionalen Quelloperanden
+ source2 ... 2.
+ source3 ... 3.
+
+Alle Kommandos (ausser unbedingten Spr"ungen) haben in irgendeiner Form
+Operanden-Register. Dabei stehen Register aus denen ein Wert geholt wird
+in den Feldern source1-source3, und ein Register in das ein Wert geschrieben
+wird, steht im Feld dest. Alle unbenutzen Felder haben immer den
+Wert NULL.
+
+Alle Befehle haben eine genau definierte Anzahl von Operanden, deren
+Typ ausserdem auf jeden Fall stimmt (die Register wurden zuvor mit
+'reg_allocate' unter Angabe des richtigen Typs angefordert).
+
+
+Die Befehlstypen
+----------------
+
+ LOADCONST_I
+ LOADCONST_L
+ LOADCONST_F
+ LOADCONST_D
+ LOADCONST_A
+ Jeder dieser Befehle l"adt einen Wert vom entsprechenden
+ Typ in das Zielregister.
+ Diese konstanten Werte selber stehen in
+ pcmd->i.value, pcmd->l.value ...
+
+ MOVE
+ Kopiert einen Wert vom Quellregister 1 ins Zielregister.
+ Beide Register haben den Typ pcmd->move.type .
+
+ OP
+ F"uhrt eine JavaVM-Grundoperation aus.
+ Im Feld pcmd->op.opcode steht der JavaVM-Opcode des gew"unschten
+ Befehls.
+ Die Anzahl und die Typen der Operanden sind f"ur jede Operation
+ anders. Eine genaue Beschreibung der Semantik findet sich
+ in der JavaVM-Spezifikation. Dabei sind die Quelloperanden
+ in der Reihenfolge wie sie in der Spezifikation am Stack stehen
+ (von links nach rechts), in die Quellregister 1 bis 3 aufgeteilt.
+ Bei Operanden vom Typ LONG oder DOUBLE sind beide 'value-words'
+ in einem Register zusammengefasst.
+
+ MEM
+ L"adt entweder einen Wert aus dem Speicher, oder schreibt
+ einen Wert dorthin.
+ Das Feld pcmd->mem.opcode enth"alt dazu entweder CMD_GETFIELD
+ oder CMD_PUTFIELD.
+ In pcmd->mem.type steht der Java-Grunddatentyp dieses
+ Feldes, und in pcmd->mem.offset steht der konstante Offset (in Byte),
+ der zum Basisregister (pcmd->source1) addiert werden soll, um die
+ tats"achliche Speicheradresse des Felds zu bekommen.
+ Bei Ladeoperationen steht das Ergebnis nachher im Register
+ pcmd->dest, bei Speicheroperationen steht der zu speichernde
+ Wert im Register pcmd->source2.
+
+ BRA
+ F"uhrt bedingte oder unbedingte Spr"unge aus. Im Feld
+ pcmd->bra.opcode steht der entsprechende JavaVM-Opcode.
+ Die Operanden (die laut JavaVM-Spec am Stack stehen m"ussen)
+ sind in den Registern pcmd->source1 und pcmd-source2 zu finden
+ (ganz analog zu dene OP-Kommandos).
+ Spezielle Formen:
+ JSR: Hier soll die R"ucksprungadresse ins Register pcmd-dest
+ geschrieben werden.
+ RET: Obwohl laut JavaVM-Spec dieser Befehl den Stack nicht
+ beeinflusst, hat er dennoch einen Operanden: pcmd->source1
+ enth"alt die R"ucksprungadresse
+
+ IRETURN bis ARETURN
+ und RETURN:
+ in pcmd->source1 befindet sich der R"uckgabewert
+ (ausgenommen bei RETURN), und
+ in pcmd->source2 ist der Zeiger auf die zu werfende
+ Exception.
+
+ Das Sprungziel (insofern bei dem Befehl eines m"oglich ist) wird
+ als Zeiger auf eine basicblock-Struktur "ubergeben.
+ Zum Aufl"osen der Sprungziele siehe: mcode_addreference.
+
+ TABLEJUMP
+ Fu"hrt eine Programmverzweigung "uber eine Sprungtabelle durch.
+ Der einzige Operand (pcmd->source1) ist im Bereich von
+ i = 0 .. pcmd->tablejump.targetcount-1. Der Befehl soll an das
+ dementsprechende Sprungziel pcmd->tablejump.targets[i] verzweigen.
+ Zur Konstruktion einer Sprungtabelle siehe: dseg_addtarget.
+
+
+ METHOD
+ F"uhrt einen Methoden (bzw. C-Funktions-) -aufruf durch.
+ Die Felder pcmd->method.paramnum und pcmd->method.params[..]
+ geben die Anzahl und die Register an, in denen die Parameter
+ stehen. Unter (g"unstigen) Umst"anden sind einige der Register
+ schon diejenigen, die durch die Aufrufkonventionen die Parameter
+ enthalten sollen (wenn das nicht der Fall ist, dann m"ussen
+ die Werte vor dem Aufruf noch umgeladen werden).
+ Das Feld pcmd->method.exceptionvar enth"alt (wenn es nicht
+ NULL ist) die Variable, in der eine allf"allig aufgetretene
+ Exception zur"uckerwartet wird.
+ Der normale R"uckgabewert der Methode soll ins Register
+ pcmd->dest geschrieben werden.
+
+ Dieses Pseudokommando wird sowohl f"ur Aufrufe von normalen
+ C-Funktionen (dann steht im Feld pcmd->method->builtin der
+ Zeiger auf diese Funktion) als auch f"ur Aufrufe von Java-Methoden
+ verwendet (dann steht im Feld pcmd->method->builtin der
+ Wert NULL).
+
+ Im zweiten Fall enth"alt das Feld pcmd->method->method einen
+ Zeiger auf die methodinfo-Struktur der gew"unschten Methode.
+ Bei Aufrufen vom Typ INVOKESTATIC und INVOKESPECIAL
+ (der Typ steht in pcmd->method->opcode) braucht dazu nur
+ der Funktionszeiger von dort geladen werden.
+ Bei INVOKEVIRTUAL und INVOKEINTERFACE muss der Funktionszeiger
+ aus der Virtual Function Table der Klasse des tats"achlichen
+ Objektes geholt werden. Der Zeiger auf dieses Objekt ist immer
+ im Register pcmd->method->params[0] zu finden.
+ Eine Beschreibung dieser Tabellen steht in der Datei "global.h".
+
+ WICHTIG: Dieses System compiliert alle Methoden beim ersten
+ Aufruf, deshalb m"ussen alle Methodenaufrufe immer mit dem
+ Umweg "uber die methodinfo-Struktur passieren, weil nur dort
+ dann der tats"achliche Funktionszeiger eingetragen wird.
+ Wenn die Methode n"amlich noch nicht aufgerufen wurde, dann
+ steht dort ein Zeiger auf den Compiler selbst.
+ Der Compiler ben"otigt f"ur seine Arbeit aber noch zus"atzlich
+ den Zeiger auf die methodinfo-Struktur in einem fixen
+ Register. Auf der DEC-ALPHA verwende ich hier das Register 28.
+ Die Aufrufsequenz auf der DEC-ALPHA f"ur einen normalen
+ INVOKESTATIC-Aufruf w"urde ungef"ahr so aussehen:
+
+ LDQ (28, 27, position_des_methodinfo_zeigers_im_datensegment)
+ LDQ (27, 28, OFFSET(methodinfo, func) )
+ JSR (26, 27)
+ LDA (27, 26, -position_dieses_befehls_im_code)
+
+
+
+
+-------------------------------------------------------------------------------
+Anhang: Notwendige Opcodes
+
+F"ur die Befehle vom Typ OP m"ussen folgende Opcodes unterst"utzt werden:
+ CMD_INEG
+ CMD_LNEG
+ CMD_FNEG
+ CMD_DNEG
+ CMD_I2L
+ CMD_L2I
+ CMD_INT2BYTE
+ CMD_INT2CHAR
+ CMD_INT2SHORT
+ CMD_IADD
+ CMD_LADD
+ CMD_FADD
+ CMD_DADD
+ CMD_ISUB
+ CMD_LSUB
+ CMD_FSUB
+ CMD_DSUB
+ CMD_IMUL
+ CMD_LMUL
+ CMD_FMUL
+ CMD_DMUL
+ CMD_FDIV
+ CMD_DDIV
+ CMD_FREM
+ CMD_DREM
+ CMD_ISHL
+ CMD_ISHR
+ CMD_IUSHR
+ CMD_LSHL
+ CMD_LSHR
+ CMD_LUSHR
+ CMD_IAND
+ CMD_LAND
+ CMD_IOR
+ CMD_LOR
+ CMD_IXOR
+ CMD_LXOR
+ CMD_I2F
+ CMD_L2F
+ CMD_I2D
+ CMD_L2D
+ CMD_F2I
+ CMD_D2I
+ CMD_F2L
+ CMD_D2L
+ CMD_F2D
+ CMD_D2F
+ CMD_LCMP
+ CMD_FCMPL
+ CMD_DCMPL
+ CMD_FCMPG
+ CMD_DCMPG
+ CMD_ARRAYLENGTH
+ CMD_AALOAD
+ CMD_LALOAD
+ CMD_IALOAD
+ CMD_FALOAD
+ CMD_DALOAD
+ CMD_CALOAD
+ CMD_SALOAD
+ CMD_BALOAD
+ CMD_AASTORE
+ CMD_LASTORE
+ CMD_IASTORE
+ CMD_FASTORE
+ CMD_DASTORE
+ CMD_CASTORE
+ CMD_SASTORE
+ CMD_BASTORE
+
+F"ur die Befehle vom Typ MEM m"ussen folgende Opcodes unterst"utzt werden:
+ CMD_PUTFIELD:
+ CMD_GETFIELD:
+
+
+F"ur die Befehle vom Typ BRA m"ussen folgende Opcodes unterst"utzt werden:
+ CMD_GOTO
+ CMD_JSR
+ CMD_RET
+ CMD_IFEQ
+ CMD_IFNULL
+ CMD_IFLT
+ CMD_IFLE
+ CMD_IFNE
+ CMD_IFNONNULL
+ CMD_IFGT
+ CMD_IFGE
+ CMD_IF_ICMPEQ
+ CMD_IF_ACMPEQ
+ CMD_IF_ICMPNE
+ CMD_IF_ACMPNE
+ CMD_IF_ICMPLT
+ CMD_IF_ICMPGT
+ CMD_IF_ICMPLE
+ CMD_IF_ICMPGE
+ CMD_IRETURN
+ CMD_LRETURN
+ CMD_ARETURN
+ CMD_FRETURN
+ CMD_DRETURN
+ CMD_RETURN
+
+
+
+F"ur die Befehle vom Typ METHOD m"ussen folgene Opcodes unterst"utzt werden:
+ CMD_INVOKESTATIC
+ CMD_INVOKESPECIAL
+ CMD_INVOKEVIRTUAL
+ CMD_INVOKEINTERFACE
--- /dev/null
+/****************************** global.h ***************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Contains global definitions which are used in the whole program, includes
+ some files and contains global used macros.
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+ Chages: Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
+ Mark Probst EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1997/10/28
+
+*******************************************************************************/
+
+#ifndef __global_h_
+#define __global_h_ /* schani */
+
+#define STATISTICS /* andi */
+
+/***************************** standard includes ******************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "toolbox/memory.h"
+#include "toolbox/chain.h"
+#include "toolbox/list.h"
+#include "toolbox/loging.h"
+
+
+/**************************** system dependent types **************************/
+
+#include "sysdep/types.h"
+
+
+/**************************** additional data types ***************************/
+
+typedef void *voidptr; /* generic pointer */
+
+
+typedef u1 bool; /* boolean data type */
+
+#define true 1
+#define false 0
+
+typedef void (*functionptr) (); /* generic function pointer */
+
+
+#define MAX_ALIGN 8 /* most generic alignment for JavaVM values */
+
+
+/**************************** shutdown function *******************************/
+
+void cacao_shutdown(s4 status);
+
+
+/**************************** basic data types ********************************/
+
+#define TYPE_INT 0 /* the JavaVM types must numbered in the */
+#define TYPE_LONG 1 /* same order as the ICMD_Ixxx to ICMD_Axxx */
+#define TYPE_FLOAT 2 /* instructions (LOAD and STORE) */
+#define TYPE_DOUBLE 3 /* integer, long, float, double, address */
+#define TYPE_ADDRESS 4 /* all other types can be numbered arbitrarily*/
+
+#define TYPE_VOID 10
+
+
+/**************************** Java class file constants ***********************/
+
+#define MAGIC 0xcafebabe
+#define MINOR_VERSION 3
+#define MAJOR_VERSION 45
+
+#define CONSTANT_Class 7
+#define CONSTANT_Fieldref 9
+#define CONSTANT_Methodref 10
+#define CONSTANT_InterfaceMethodref 11
+#define CONSTANT_String 8
+#define CONSTANT_Integer 3
+#define CONSTANT_Float 4
+#define CONSTANT_Long 5
+#define CONSTANT_Double 6
+#define CONSTANT_NameAndType 12
+#define CONSTANT_Utf8 1
+
+#define CONSTANT_Arraydescriptor 13
+#define CONSTANT_UNUSED 0
+
+
+#define ACC_PUBLIC 0x0001
+#define ACC_PRIVATE 0x0002
+#define ACC_PROTECTED 0x0004
+#define ACC_STATIC 0x0008
+#define ACC_FINAL 0x0010
+#define ACC_SYNCHRONIZED 0x0020
+#define ACC_VOLATILE 0x0040
+#define ACC_TRANSIENT 0x0080
+#define ACC_NATIVE 0x0100
+#define ACC_INTERFACE 0x0200
+#define ACC_ABSTRACT 0x0400
+
+
+
+/**************************** resolve typedef-cycles **************************/
+
+typedef struct unicode unicode;
+typedef struct classinfo classinfo;
+typedef struct vftbl vftbl;
+typedef u1* methodptr;
+
+
+/********************** data structures of UNICODE symbol *********************/
+
+struct unicode {
+ unicode *hashlink; /* externe Verkettung f"ur die unicode-Hashtabelle */
+ u4 key; /* Hash-Schl"ussel (h"angt nur vom Text ab) */
+ int length; /* L"ange des Textes */
+ u2 *text; /* Zeiger auf den Text (jeder Buchstabe 16 Bit) */
+ classinfo *class; /* gegebenenfalls Referenz auf die Klasse dieses
+ Namens (oder NULL, wenn es keine solche gibt) */
+ struct java_objectheader *string;
+ /* gegebenenfalls Referenz auf einen konstanten
+ String mit dem entsprechenden Wert */
+ };
+
+ /* Alle Unicode-Symbole werden in einer einzigen globalen Tabelle
+ (Hashtabelle) verwaltet, jedes Symbol wird nur einmal angelegt.
+ -> Speicherersparnis, und "Uberpr"ufung auf Gleichheit durch einfachen
+ Zeigervergleich */
+
+
+/************ data structures of remaining constant pool entries **************/
+
+
+typedef struct {
+ classinfo *class;
+ unicode *name;
+ unicode *descriptor;
+ } constant_FMIref;
+
+
+typedef struct {
+ s4 value;
+ } constant_integer;
+
+typedef struct {
+ float value;
+ } constant_float;
+
+typedef struct {
+ s8 value;
+ } constant_long;
+
+typedef struct {
+ double value;
+ } constant_double;
+
+
+typedef struct {
+ unicode *name;
+ unicode *descriptor;
+ } constant_nameandtype;
+
+
+typedef struct constant_arraydescriptor {
+ int arraytype;
+ classinfo *objectclass;
+ struct constant_arraydescriptor *elementdescriptor;
+ } constant_arraydescriptor;
+
+ /* Mit einem Arraydescriptor kann ein Array-Typ dargestellt werden.
+ Bei normalen Arrays (z.B. Array von Bytes,...) gen"ugt dazu,
+ dass das Feld arraytype die entsprechende Kennzahl enth"alt
+ (z.B. ARRAYTYPE_BYTE).
+ Bei Arrays von Objekten (arraytype=ARRAYTYPE_OBJECT) muss das
+ Feld objectclass auf die Klassenstruktur der m"oglichen
+ Element-Objekte zeigen.
+ Bei Arrays von Arrays (arraytype=ARRAYTYPE_ARRAY) muss das
+ Feld elementdescriptor auf eine weiter arraydescriptor-Struktur
+ zeigen, die die Element-Typen beschreibt.
+ */
+
+
+
+/********* Anmerkungen zum Constant-Pool:
+
+ Die Typen der Eintr"age in den Constant-Pool werden durch die oben
+ definierten CONSTANT_.. Werte angegeben.
+ Bei allen Typen muss zus"atzlich noch eine Datenstruktur hinzugef"ugt
+ werden, die den wirklichen Wert angibt.
+ Bei manchen Typen reicht es, einen Verweis auf eine schon bereits
+ existierende Struktur (z.B. unicode-Texte) einzutragen, bei anderen
+ muss diese Struktur erst extra erzeugt werden.
+ Ich habe folgende Datenstrukturen f"ur diese Typen verwendet:
+
+ Typ Struktur extra erzeugt?
+ ----------------------------------------------------------------------
+ CONSTANT_Class classinfo nein
+ CONSTANT_Fieldref constant_FMIref ja
+ CONSTANT_Methodref constant_FMIref ja
+ CONSTANT_InterfaceMethodref constant_FMIref ja
+ CONSTANT_String unicode nein
+ CONSTANT_Integer constant_integer ja
+ CONSTANT_Float constant_float ja
+ CONSTANT_Long constant_long ja
+ CONSTANT_Double constant_double ja
+ CONSTANT_NameAndType constant_nameandtype ja
+ CONSTANT_Utf8 unicode nein
+ CONSTANT_Arraydescriptor constant_arraydescriptor ja
+ CONSTANT_UNUSED -
+
+*******************************/
+
+
+
+/***************** Die Datenstrukturen fuer das Laufzeitsystem ***************/
+
+
+ /********* Objekte **********
+
+ Alle Objekte (und Arrays), die am Heap gespeichert werden, m"ussen eine
+ folgende spezielle Datenstruktur ganz vorne stehen haben:
+
+ */
+
+typedef struct java_objectheader { /* Der Header f"ur alle Objekte */
+ vftbl *vftbl; /* Zeiger auf die Function Table */
+} java_objectheader;
+
+
+
+ /********* Arrays ***********
+
+ Alle Arrays in Java sind auch gleichzeitig Objekte (d.h. sie haben auch
+ den obligatorischen Object-Header und darin einen Verweis auf eine Klasse)
+ Es gibt aber (der Einfachheit halber) nur eine einzige Klasse f"ur alle
+ m"oglichen Typen von Arrays, deshalb wird der tats"achliche Typ in einem
+ Feld im Array-Objekt selbst gespeichert.
+ Die Typen sind: */
+
+#define ARRAYTYPE_INT 0
+#define ARRAYTYPE_LONG 1
+#define ARRAYTYPE_FLOAT 2
+#define ARRAYTYPE_DOUBLE 3
+#define ARRAYTYPE_BYTE 4
+#define ARRAYTYPE_CHAR 5
+#define ARRAYTYPE_SHORT 6
+#define ARRAYTYPE_BOOLEAN 7
+#define ARRAYTYPE_OBJECT 8
+#define ARRAYTYPE_ARRAY 9
+
+
+ /** Der Header f"ur ein Java-Array **/
+
+typedef struct java_arrayheader { /* Der Arrayheader f"ur alle Arrays */
+ java_objectheader objheader; /* Der Object-Header */
+ s4 size; /* Gr"osse des Arrays */
+ s4 arraytype; /* Typ der Elemente */
+} java_arrayheader;
+
+
+
+ /** Die Unterschiedlichen Strukturen f"ur alle Typen von Arrays **/
+
+typedef struct java_chararray {
+ java_arrayheader header;
+ u2 data[1];
+} java_chararray;
+
+typedef struct java_floatheader {
+ java_arrayheader header;
+ float data[1];
+} java_floatarray;
+
+typedef struct java_doublearray {
+ java_arrayheader header;
+ double data[1];
+} java_doublearray;
+
+
+ /* achtung: die beiden Stukturen booleanarray und bytearray m"ussen
+ identisches memory-layout haben, weil mit den selben Funktionen
+ darauf zugegriffen wird */
+
+typedef struct java_booleanarray {
+ java_arrayheader header;
+ u1 data[1];
+} java_booleanarray;
+
+typedef struct java_bytearray {
+ java_arrayheader header;
+ s1 data[1];
+} java_bytearray;
+
+typedef struct java_shortarray {
+ java_arrayheader header;
+ s2 data[1];
+} java_shortarray;
+
+typedef struct java_intarray {
+ java_arrayheader header;
+ s4 data[1];
+} java_intarray;
+
+typedef struct java_longarray {
+ java_arrayheader header;
+ s8 data[1];
+} java_longarray;
+
+
+ /* ACHTUNG: die beiden folgenden Strukturen m"ussen unbedingt gleiches
+ Memory-Layout haben, weil mit ein und der selben Funktion auf die
+ data-Eintr"age beider Typen zugegriffen wird !!!! */
+
+typedef struct java_objectarray {
+ java_arrayheader header;
+ classinfo *elementtype;
+ java_objectheader *data[1];
+} java_objectarray;
+
+typedef struct java_arrayarray {
+ java_arrayheader header;
+ constant_arraydescriptor *elementdescriptor;
+ java_arrayheader *data[1];
+} java_arrayarray;
+
+
+
+
+/************** Strukturen f"ur Klassen, Felder & Methoden *****************/
+
+
+ /*** Struktur: fieldinfo ***/
+
+typedef struct fieldinfo { /* Struktur f"ur ein Feld einer Klasse */
+ s4 flags; /* die ACC-Flags */
+ s4 type; /* Grunddatentyp */
+ unicode *name; /* Name des Felds */
+ unicode *descriptor; /* Typedescriptor in JavaVM-Form */
+
+ s4 offset; /* Offset vom Anfang des Objektes */
+ /* (bei Instanzvariablen) */
+
+ union { /* Speicher f"ur den Wert */
+ s4 i; /* (bei Klassenvariablen) */
+ s8 l;
+ float f;
+ double d;
+ void *a;
+ } value;
+
+ } fieldinfo;
+
+
+ /*** Struktur: exceptiontable ***/
+
+typedef struct exceptiontable { /* Exceptionhandler-Eintrag in einer Methode */
+ s4 startpc; /* Anfang des G"ultigkeitsbereichs */
+ s4 endpc; /* Ende des Bereichs (exklusive) */
+ s4 handlerpc; /* JavaVM-Position des Handlers */
+ classinfo *catchtype; /* Typ der behandelten Exceptions (oder
+ NULL, wenn alle behandelt werden sollen) */
+ } exceptiontable;
+
+
+
+ /*** Struktur: methodinfo ***/
+
+typedef struct methodinfo { /* Struktur f"ur eine Methode einer Klasse */
+ s4 flags; /* die ACC-Flags */
+ unicode *name; /* Name der Methode */
+ unicode *descriptor; /* der JavaVM-Descriptorstring f"ur Methoden */
+ s4 returntype; /* only temporary valid, return type */
+ s4 paramcount; /* only temporary valid, number of parameters */
+ u1 *paramtypes; /* only temporary valid, parameter types */
+ classinfo *class; /* Die Klasse, der die Methode geh"ort */
+ u4 vftblindex; /* Index dieser Methode f"ur die Virtual
+ Function Table (wenn es keine statische
+ Methode ist) */
+
+ s4 maxstack; /* maximale Stacktiefe des JavaVM-Codes */
+ s4 maxlocals; /* maximale Anzahl der JavaVM-Variablen */
+ u4 jcodelength; /* L"ange des JavaVM-Codes */
+ u1 *jcode; /* und Zeiger auf den JavaVM-Code */
+
+ s4 exceptiontablelength; /* L"ange der Exceptintable */
+ exceptiontable *exceptiontable; /* Die Exceptiontable selber */
+
+ u1 *stubroutine; /* STUB-Routine for compiling or calling
+ natives */
+ u4 mcodelength; /* L"ange des generierten Maschinencodes */
+ u1 *mcode; /* Zeiger auf den Maschinencode */
+ u1 *entrypoint; /* Entrypoint to the Maschine-Code */
+
+
+ } methodinfo;
+
+
+ /*** Struktur: classinfo ***/
+
+struct classinfo { /* Datenstruktur f"ur eine Klasse */
+ java_objectheader header; /* Weil auch Klassen als Objekte angesprochen
+ werden */
+
+ s4 flags; /* Die ACC-Flags */
+ unicode *name; /* Name der Klasse */
+
+ s4 cpcount; /* Anzahl der Eintr"age im Constant-Pool */
+ u1 *cptags; /* Die TAGs f"ur den Constant-Pool */
+ voidptr *cpinfos; /* Die Zeiger auf die Info-Strukturen */
+
+ classinfo *super; /* Zeiger auf die "ubergeordnete Klasse */
+
+ s4 interfacescount; /* Anzahl der Interfaces */
+ classinfo **interfaces; /* Zeiger auf die Interfaces */
+
+ s4 fieldscount; /* Anzahl der Felder */
+ fieldinfo *fields; /* Die Tabelle der Felder */
+
+ s4 methodscount; /* Anzahl der Methoden */
+ methodinfo *methods; /* Die Tabelle der Methoden */
+
+
+ listnode listnode; /* Verkettungsstruktur (f"ur Listen) */
+
+ bool initialized; /* true, wenn Klasse bereits Initialisiert */
+ bool linked; /* wird von `class_link` auf true gesetzt */
+ s4 index; /* Hierarchietiefe (bei normalen Klassen)
+ oder fortlaufende Nummer (bei Interfaces)*/
+ u4 instancesize; /* Gr"osse eines Objektes dieser Klasse */
+
+ vftbl *vftbl;
+
+ methodinfo *finalizer; /* Finalizer-Methode f"ur die Klasse */
+ };
+
+
+struct vftbl {
+ classinfo *class; /* Class, the function table belongs to */
+
+ s4 vftbllength; /* L"aenge der Virtual Function Table */
+
+ s4 interfacetablelength; /* L"ange der Interfacetable */
+ u4 *interfacevftbllength; /* -> siehe unten */
+ methodptr **interfacevftbl;
+
+ methodptr table[1];
+ };
+
+/*********** Anmerkungen zur Interfacetable:
+
+ "Ahnlich wie die 'normalen' virtuellen Methoden k"onnen auch die
+ Interface-Methoden mit Hilfe einer Art Virtual Function Table
+ aufgerufen werden.
+ Dazu werden alle Interfaces im System fortlaufend nummeriert (beginnend
+ bei 0), und f"ur jede Klasse wird eine ganze Tabelle von
+ Virtual Function Tables erzeugt, n"amlich zu jedem Interface, das die
+ Klasse implementiert, eine.
+
+ z.B. Nehmen wir an, eine Klasse implementiert zwei Interfaces (die durch
+ die Nummerierung die Indizes 0 und 3 bekommen haben)
+
+ Das sieht dann ungef"ahr so aus:
+ -------------- -------------
+ interfacevftbl ---> | Eintrag 0 |---------> | Methode 0 |---> Methode X
+ | Eintrag 1 |--> NULL | Methode 1 |---> Methode Y
+ | Eintrag 2 |--> NULL | Methode 2 |---> Methode Z
+ | Eintrag 3 |-----+ -------------
+ -------------- |
+ +---> -------------
+ | Methode 0 |---> Methode X
+ | Methode 1 |---> Methode A
+ -------------
+ ---------------
+ interfacevftlblength ---> | Wert 0 = 3 |
+ | Wert 1 = 0 |
+ | Wert 2 = 0 |
+ | Wert 3 = 2 |
+ ---------------
+
+ Der Aufruf einer Interface-Methode geht dann so vor sich:
+ Zur Compilezeit steht der Index (i) des Interfaces und die Stelle (s), wo
+ in der entsprechenden Untertabelle die Methode eingetragen ist, schon fest.
+ Also muss zur Laufzeit nur mehr der n-te Eintrag aus der Interfacetable
+ gelesen werden, von dieser Tabelle aus wird der s-te Eintrag geholt,
+ und diese Methode wird angesprungen.
+
+****************/
+
+
+
+/************************* Referenzen auf die wichtigen Systemklassen ********************/
+
+extern classinfo *class_java_lang_Object;
+extern classinfo *class_java_lang_String;
+extern classinfo *class_java_lang_ClassCastException;
+extern classinfo *class_java_lang_NullPointerException;
+extern classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
+extern classinfo *class_java_lang_NegativeArraySizeException;
+extern classinfo *class_java_lang_OutOfMemoryError;
+extern classinfo *class_java_lang_ArithmeticException;
+extern classinfo *class_java_lang_ArrayStoreException;
+extern classinfo *class_java_lang_ThreadDeath; /* schani */
+
+extern classinfo *class_array;
+
+
+/********************** Vorgefertigte Instanzen einiger Systemklassen ********************/
+
+extern java_objectheader *proto_java_lang_ClassCastException;
+extern java_objectheader *proto_java_lang_NullPointerException;
+extern java_objectheader *proto_java_lang_ArrayIndexOutOfBoundsException;
+extern java_objectheader *proto_java_lang_NegativeArraySizeException;
+extern java_objectheader *proto_java_lang_OutOfMemoryError;
+extern java_objectheader *proto_java_lang_ArithmeticException;
+extern java_objectheader *proto_java_lang_ArrayStoreException;
+extern java_objectheader *proto_java_lang_ThreadDeath; /* schani */
+
+
+/********************** flag variables *********************/
+
+extern bool compileall;
+extern bool runverbose;
+extern bool verbose;
+
+
+/********************** trace variables ********************/
+
+extern int count_class_infos;
+extern int count_const_pool_len;
+extern int count_vftbl_len;
+extern int count_unicode_len;
+extern int count_all_methods;
+extern int count_vmcode_len;
+extern int count_extable_len;
+
+#endif
--- /dev/null
+/* -*- mode: c; tab-width: 4; c-basic-offset: 4 -*- */
+/****************************** headers.c **************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Dieser Modul ersetzt f"ur den Headerfile-Betrieb den Modul 'main',
+ und 'f"alscht' einige Verweise auf externe Module (damit nicht schon
+ alle Module des eigentlichen Programmes fertig sein m"ussen, was ja
+ unm"oglich w"are, da die Headerfile-Tabellen ja erst hier und jetzt
+ generiert werden).
+
+ Dieser Modul ist ein ziemlich schneller Hack und dementsprechend
+ schlecht (nicht) kommentiert.
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+ Changes: Mark Probst EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1997/05/23
+
+*******************************************************************************/
+
+#include "global.h"
+
+#include "tables.h"
+#include "loader.h"
+
+
+/******* verschiedene externe Funktionen "faelschen" (=durch Dummys ersetzen),
+ damit der Linker zufrieden ist *********/
+
+functionptr native_findfunction
+ (unicode *cname, unicode *mname, unicode *desc, bool isstatic)
+{ return NULL; }
+
+java_objectheader *literalstring_new (unicode *text)
+{ return NULL; }
+
+java_objectheader *javastring_new (unicode *text) /* schani */
+{ return NULL; }
+
+void synchronize_caches() { }
+void asm_call_jit_compiler () { }
+void asm_calljavamethod () { }
+void asm_dumpregistersandcall () { }
+
+s4 new_builtin_idiv (s4 a, s4 b) {return 0;}
+s4 new_builtin_irem (s4 a, s4 b) {return 0;}
+s8 new_builtin_ldiv (s8 a, s8 b) {return 0;}
+s8 new_builtin_lrem (s8 a, s8 b) {return 0;}
+
+
+void new_builtin_monitorenter (java_objectheader *o) {}
+void new_builtin_monitorexit (java_objectheader *o) {}
+
+s4 new_builtin_checkcast(java_objectheader *o, classinfo *c)
+ {return 0;}
+s4 new_builtin_checkarraycast
+ (java_objectheader *o, constant_arraydescriptor *d)
+ {return 0;}
+
+void new_builtin_aastore (java_objectarray *a, s4 index, java_objectheader *o) {}
+
+u1 *createcompilerstub (methodinfo *m) {return NULL;}
+u1 *createnativestub (functionptr f, methodinfo *m) {return NULL;}
+u1 *ncreatenativestub (functionptr f, methodinfo *m) {return NULL;}
+
+void removecompilerstub (u1 *stub) {}
+void removenativestub (u1 *stub) {}
+
+void perform_alpha_threadswitch (u1 **from, u1 **to) {}
+u1* initialize_thread_stack (void *func, u1 *stack) { return NULL; }
+u1* used_stack_top (void) { return NULL; }
+
+java_objectheader *native_new_and_init (void *p) { return NULL; }
+
+/************************ globale Variablen **********************/
+
+java_objectheader *exceptionptr; /* schani */
+int newcompiler = true;
+bool verbose = false;
+
+static chain *nativechain;
+static FILE *file = NULL;
+
+static void printIDpart (int c)
+{
+ if ( (c>='a' && c<='z')
+ || (c>='A' && c<='Z')
+ || (c>='0' && c<='9')
+ || (c=='_') )
+ putc (c,file);
+ else putc ('_',file);
+
+}
+
+static void printID (unicode *name)
+{
+ int i;
+ for (i=0; i<name->length; i++) {
+ printIDpart (name->text[i]);
+ }
+}
+
+
+u4 outputsize;
+bool dopadding;
+
+static void addoutputsize (int len)
+{
+ u4 newsize,i;
+ if (!dopadding) return;
+
+ newsize = ALIGN (outputsize, len);
+
+ for (i=outputsize; i<newsize; i++) fprintf (file, " u1 pad%d\n",(int) i);
+ outputsize = newsize;
+}
+
+
+static u2 *printtype (u2 *desc)
+{
+ u2 c;
+
+ switch (*(desc++)) {
+ case 'V': fprintf (file, "void");
+ break;
+ case 'I':
+ case 'S':
+ case 'B':
+ case 'C':
+ case 'Z': addoutputsize (4);
+ fprintf (file, "s4");
+ break;
+ case 'J': addoutputsize (8);
+ fprintf (file, "s8");
+ break;
+ case 'F': addoutputsize (4);
+ fprintf (file, "float");
+ break;
+ case 'D': addoutputsize (8);
+ fprintf (file, "double");
+ break;
+ case '[':
+ addoutputsize ( sizeof(java_arrayheader*) );
+ switch (*(desc++)) {
+ case 'I': fprintf (file, "java_intarray*"); break;
+ case 'J': fprintf (file, "java_longarray*"); break;
+ case 'Z': fprintf (file, "java_booleanarray*"); break;
+ case 'B': fprintf (file, "java_bytearray*"); break;
+ case 'S': fprintf (file, "java_shortarray*"); break;
+ case 'C': fprintf (file, "java_chararray*"); break;
+ case 'F': fprintf (file, "java_floatarray*"); break;
+ case 'D': fprintf (file, "java_doublearray*"); break;
+
+ case '[': fprintf (file, "java_arrayarray*");
+ while ((*desc) == '[') desc++;
+ if ((*desc)!='L') desc++;
+ else while (*(desc++) != ';');
+ break;
+
+ case 'L': fprintf (file, "java_objectarray*");
+ while ( *(desc++) != ';');
+ break;
+ default: panic ("invalid type descriptor");
+ }
+ break;
+
+ case 'L':
+ addoutputsize ( sizeof(java_objectheader*));
+ fprintf (file, "struct ");
+ while ( (c = *(desc++)) != ';' ) printIDpart (c);
+ fprintf (file, "*");
+ break;
+
+ default: panic ("Unknown type in field descriptor");
+ }
+
+ return (desc);
+}
+
+
+
+static void printfields (classinfo *c)
+{
+ u4 i;
+ fieldinfo *f;
+
+ if (!c) {
+ addoutputsize ( sizeof(java_objectheader) );
+ fprintf (file, " java_objectheader header;\n");
+ return;
+ }
+
+ printfields (c->super);
+
+ for (i=0; i<c->fieldscount; i++) {
+ f = &(c->fields[i]);
+
+ if (! (f->flags & ACC_STATIC) ) {
+ fprintf (file," ");
+ printtype (f->descriptor->text);
+ fprintf (file, " ");
+ unicode_fprint (file, f->name);
+ fprintf (file, ";\n");
+ }
+ }
+}
+
+
+
+
+static void remembermethods (classinfo *c)
+{
+ u2 i;
+ methodinfo *m;
+
+ for (i=0; i<c->methodscount; i++) {
+ m = &(c->methods[i]);
+
+ if (m->flags & ACC_NATIVE) {
+ chain_addlast (nativechain, m);
+ }
+
+ }
+}
+
+
+
+
+static void printmethod (methodinfo *m)
+{
+ u2 *d;
+ u2 paramnum=1;
+
+ d = m->descriptor->text;
+ while (*(d++) != ')');
+
+ printtype (d);
+ fprintf (file," ");
+ printID (m->class->name);
+ fprintf (file,"_");
+ printID (m->name);
+ fprintf (file," (");
+
+ d = m->descriptor->text+1;
+
+ if (! (m->flags & ACC_STATIC) ) {
+ fprintf (file, "struct ");
+ printID (m->class->name);
+ fprintf (file, "* this");
+ if ((*d)!=')') fprintf (file, ", ");
+ }
+
+ while ((*d)!=')') {
+ d = printtype (d);
+ fprintf (file, " par%d", paramnum++);
+ if ((*d)!=')') fprintf (file, ", ");
+ }
+
+ fprintf (file, ");\n");
+}
+
+
+static void headers_generate (classinfo *c)
+{
+ fprintf (file, "/* Structure information for class: ");
+ unicode_fprint (file, c->name);
+ fprintf (file, " */\n\n");
+
+ fprintf (file, "typedef struct ");
+ printID (c->name);
+ fprintf (file, " {\n");
+
+ outputsize=0;
+ dopadding=true;
+ printfields (c);
+
+ fprintf (file, "} ");
+ printID (c->name);
+ fprintf (file, ";\n\n");
+
+ remembermethods (c);
+
+
+ fprintf (file, "\n\n");
+}
+
+
+
+static void printnativetableentry (methodinfo *m)
+{
+ fprintf (file, " { \"");
+ unicode_fprint (file, m->class->name);
+ fprintf (file, "\",\n \"");
+ unicode_fprint (file, m->name);
+ fprintf (file, "\",\n \"");
+ unicode_fprint (file, m->descriptor);
+ fprintf (file, "\",\n ");
+ if ( (m->flags & ACC_STATIC) !=0) fprintf (file, "true");
+ else fprintf (file, "false");
+ fprintf (file, ",\n ");
+ fprintf (file, "(functionptr) ");
+ printID (m->class->name);
+ fprintf (file,"_");
+ printID (m->name);
+ fprintf (file,"\n },\n");
+}
+
+
+
+
+
+static void headers_start ()
+{
+ file = fopen ("nativetypes.hh", "w");
+ if (!file) panic ("Can not open file 'native.h' to store header information");
+
+ fprintf (file, "/* Headerfile for native methods: nativetypes.hh */\n");
+ fprintf (file, "/* This file is machine generated, don't edit it !*/\n\n");
+
+ nativechain = chain_new ();
+}
+
+
+static void headers_finish ()
+{
+ methodinfo *m;
+
+ fprintf (file, "\n/* Prototypes for native methods */\n\n");
+
+ m = chain_first (nativechain);
+ while (m) {
+ dopadding=false;
+ printmethod (m);
+
+ m = chain_next (nativechain);
+ }
+
+
+ file = fopen ("nativetable.hh", "w");
+ if (!file) panic ("Can not open file 'nativetable' to store native-link-table");
+
+ fprintf (file, "/* Table of native methods: nativetables.hh */\n");
+ fprintf (file, "/* This file is machine generated, don't edit it !*/\n\n");
+
+ while ( (m = chain_first (nativechain)) != NULL) {
+ chain_remove (nativechain);
+
+ printnativetableentry (m);
+
+ }
+
+ chain_free (nativechain);
+ fclose (file);
+}
+
+
+
+
+
+/******************** interne Funktion: print_usage ************************
+
+Gibt die richtige Aufrufsyntax des JAVA-Header-Generators auf stdout aus.
+
+***************************************************************************/
+
+static void print_usage()
+{
+ printf ("USAGE: jch class [class..]\n");
+}
+
+
+
+
+/************************** Funktion: main *******************************
+
+ Das Hauptprogramm.
+ Wird vom System zu Programstart aufgerufen (eh klar).
+
+**************************************************************************/
+
+int main(int argc, char **argv)
+{
+ s4 i,a;
+ char *cp;
+ classinfo *topclass;
+ void *dummy;
+
+
+ /********** interne (nur fuer main relevante Optionen) **************/
+
+ char classpath[500] = "";
+ u4 heapsize = 100000;
+
+ /*********** Optionen, damit wirklich nur headers generiert werden ***/
+
+ makeinitializations=false;
+
+
+ /************ Infos aus der Environment lesen ************************/
+
+ cp = getenv ("CLASSPATH");
+ if (cp) {
+ strcpy (classpath + strlen(classpath), ":");
+ strcpy (classpath + strlen(classpath), cp);
+ }
+
+ if (argc < 2) {
+ print_usage ();
+ exit(10);
+ }
+
+
+ /**************************** Programmstart *****************************/
+
+ log_init (NULL);
+ log_text ("Java - header-generator started");
+
+
+ suck_init (classpath);
+
+ unicode_init ();
+ heap_init (heapsize, heapsize, &dummy);
+ loader_init ();
+
+
+ /*********************** JAVA-Klassen laden ***************************/
+
+ headers_start ();
+
+
+ for (a=1; a<argc; a++) {
+ cp = argv[a];
+ for (i=strlen(cp)-1; i>=0; i--) { /* Punkte im Klassennamen */
+ if (cp[i]=='.') cp[i]='/'; /* auf slashes umbauen */
+ }
+
+ topclass = loader_load ( unicode_new_char (cp) );
+
+ headers_generate (topclass);
+ }
+
+
+ headers_finish ();
+
+
+ /************************ Freigeben aller Resourcen *******************/
+
+ loader_close ();
+ heap_close ();
+ unicode_close (NULL);
+
+
+ /* Endemeldung ausgeben und mit entsprechendem exit-Status terminieren */
+
+ log_text ("Java - header-generator stopped");
+ log_cputime ();
+ mem_usagelog(1);
+
+ return 0;
+}
+
+
--- /dev/null
+/* -*- mode: c; tab-width: 4; c-basic-offset: 4 -*- */
+/****************************** loader.c ***************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Contains the functions of the class loader.
+
+ Author: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+ Changes: Mark Probst EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1997/06/03
+
+*******************************************************************************/
+
+
+#include <assert.h>
+
+#include "global.h"
+#include "loader.h"
+
+#include "tables.h"
+#include "native.h"
+#include "builtin.h"
+#include "compiler.h"
+#include "asmpart.h"
+
+#include "threads/thread.h" /* schani */
+
+
+/*************************** globale Variablen *******************************/
+
+extern bool newcompiler;
+
+int count_class_infos = 0;
+int count_const_pool_len = 0;
+int count_vftbl_len = 0;
+int count_all_methods = 0;
+int count_vmcode_len = 0;
+int count_extable_len = 0;
+
+bool loadverbose = false; /* Switches f"ur mehr Debug-Meldungen */
+bool linkverbose = false;
+bool initverbose = false;
+
+bool makeinitializations = true;
+
+bool getloadingtime = false;
+long int loadingtime = 0;
+
+
+static u4 interfaceindex; /* fortlaufende Nummer f"ur Interfaces */
+
+static list unloadedclasses; /* Liste alle referenzierten, aber noch nicht
+ geladenen Klassen */
+static list unlinkedclasses; /* Liste aller geladenen, aber noch nicht
+ gelinkten Klassen */
+ list linkedclasses; /* Liste aller fertig gelinkten Klassen */
+
+
+
+/***************** die Referenzen auf die wichtigen Systemklassen ************/
+
+classinfo *class_java_lang_Object;
+classinfo *class_java_lang_String;
+classinfo *class_java_lang_ClassCastException;
+classinfo *class_java_lang_NullPointerException;
+classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
+classinfo *class_java_lang_NegativeArraySizeException;
+classinfo *class_java_lang_OutOfMemoryError;
+classinfo *class_java_lang_ArithmeticException;
+classinfo *class_java_lang_ArrayStoreException;
+classinfo *class_java_lang_ThreadDeath; /* schani */
+
+classinfo *class_array;
+
+
+/************ einige vorgefertigte Instanzen wichtiger Systemklassen *********/
+
+java_objectheader *proto_java_lang_ClassCastException;
+java_objectheader *proto_java_lang_NullPointerException;
+java_objectheader *proto_java_lang_ArrayIndexOutOfBoundsException;
+java_objectheader *proto_java_lang_NegativeArraySizeException;
+java_objectheader *proto_java_lang_OutOfMemoryError;
+java_objectheader *proto_java_lang_ArithmeticException;
+java_objectheader *proto_java_lang_ArrayStoreException;
+java_objectheader *proto_java_lang_ThreadDeath; /* schani */
+
+
+
+
+/****************************************************************************/
+/******************* Einige Support-Funkionen *******************************/
+/****************************************************************************/
+
+
+/********** interne Funktion: printflags (nur zu Debug-Zwecken) ************/
+
+static void printflags (u2 f)
+{
+ if ( f & ACC_PUBLIC ) printf (" PUBLIC");
+ if ( f & ACC_PRIVATE ) printf (" PRIVATE");
+ if ( f & ACC_PROTECTED ) printf (" PROTECTED");
+ if ( f & ACC_STATIC ) printf (" STATIC");
+ if ( f & ACC_FINAL ) printf (" FINAL");
+ if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
+ if ( f & ACC_VOLATILE ) printf (" VOLATILE");
+ if ( f & ACC_TRANSIENT ) printf (" TRANSIENT");
+ if ( f & ACC_NATIVE ) printf (" NATIVE");
+ if ( f & ACC_INTERFACE ) printf (" INTERFACE");
+ if ( f & ACC_ABSTRACT ) printf (" ABSTRACT");
+}
+
+
+/************************* Funktion: skipattribute ****************************
+
+ "uberliest im ClassFile eine (1) 'attribute'-Struktur
+
+******************************************************************************/
+
+static void skipattribute ()
+{
+ u4 len;
+
+ suck_u2 ();
+ len = suck_u4 ();
+ skip_nbytes (len);
+}
+
+/********************** Funktion: skipattributebody ***************************
+
+ "uberliest im Classfile ein attribut, wobei die 16-bit - attribute_name -
+ Referenz schon gelesen worden ist.
+
+******************************************************************************/
+
+static void skipattributebody ()
+{
+ u4 len = suck_u4 ();
+ skip_nbytes (len);
+}
+
+
+/************************* Funktion: skipattributes ***************************
+
+ "uberliest im ClassFile eine gew"unschte Anzahl von attribute-Strukturen
+
+******************************************************************************/
+
+static void skipattributes (u4 num)
+{
+ u4 i;
+ for (i=0; i<num; i++) skipattribute();
+}
+
+
+
+/************************** Funktion: loadUtf8 ********************************
+
+ liest aus dem ClassFile einen Utf8-String (=komprimierter unicode-text)
+ und legt daf"ur ein unicode-Symbol an.
+ Return: Zeiger auf das Symbol
+
+******************************************************************************/
+
+#define MAXUNICODELEN 5000
+static u2 unicodebuffer[MAXUNICODELEN];
+
+static unicode *loadUtf8 ()
+{
+ u4 unicodelen;
+ u4 letter;
+
+ u4 utflen;
+ u4 b1,b2,b3;
+
+ unicodelen = 0;
+
+ utflen = suck_u2 ();
+ while (utflen > 0) {
+ b1 = suck_u1 ();
+ utflen --;
+ if (b1<0x80) letter = b1;
+ else {
+ b2 = suck_u1 ();
+ utflen --;
+ if (b1<0xe0) letter = ((b1 & 0x1f) << 6) | (b2 & 0x3f);
+ else {
+ b3 = suck_u1 ();
+ utflen --;
+ letter = ((b1 & 0x0f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f);
+ }
+ }
+
+
+ if (unicodelen >= MAXUNICODELEN) {
+ panic ("String constant too long");
+ }
+
+ unicodebuffer[unicodelen++] = letter;
+ }
+
+
+ return unicode_new_u2 (unicodebuffer, unicodelen);
+}
+
+
+
+/******************** interne Funktion: checkfieldtype ***********************/
+
+static void checkfieldtype (u2 *text, u4 *count, u4 length)
+{
+ u4 l;
+
+ if (*count >= length) panic ("Type-descriptor exceeds unicode length");
+
+ l = text[(*count)++];
+
+ switch (l) {
+ default: panic ("Invalid symbol in type descriptor");
+ return;
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'F':
+ case 'I':
+ case 'J':
+ case 'S':
+ case 'Z': return;
+
+ case '[': checkfieldtype (text, count, length);
+ return;
+
+ case 'L':
+ {
+ u4 tlen,tstart = *count;
+
+ if (*count >= length)
+ panic ("Objecttype descriptor of length zero");
+
+ while ( text[*count] != ';' ) {
+ (*count)++;
+ if (*count >= length)
+ panic ("Missing ';' in objecttype-descriptor");
+ }
+
+ tlen = (*count) - tstart;
+ (*count)++;
+
+ if (tlen == 0) panic ("Objecttype descriptor with empty name");
+
+ class_get ( unicode_new_u2 (text+tstart, tlen) );
+ }
+ }
+}
+
+
+/******************* Funktion: checkfielddescriptor ***************************
+
+ "uberpr"uft, ob ein Field-Descriptor ein g"ultiges Format hat.
+ Wenn nicht, dann wird das System angehalten.
+ Au"serdem werden alle Klassen, die hier referenziert werden,
+ in die Liste zu ladender Klassen eingetragen.
+
+******************************************************************************/
+
+void checkfielddescriptor (unicode *d)
+{
+ u4 count=0;
+ checkfieldtype (d->text, &count, d->length);
+ if (count != d->length) panic ("Invalid type-descritor encountered");
+}
+
+
+/******************* Funktion: checkmethoddescriptor **************************
+
+ "uberpr"uft, ob ein Method-Descriptor ein g"ultiges Format hat.
+ Wenn nicht, dann wird das System angehalten.
+ Au"serdem werden alle Klassen, die hier referenziert werden,
+ in die Liste zu ladender Klassen eingetragen.
+
+******************************************************************************/
+
+void checkmethoddescriptor (unicode *d)
+{
+ u2 *text=d->text;
+ u4 length=d->length;
+ u4 count=0;
+
+ if (length<2) panic ("Method descriptor too short");
+ if (text[0] != '(') panic ("Missing '(' in method descriptor");
+ count=1;
+
+ while (text[count] != ')') {
+ checkfieldtype (text,&count,length);
+ if ( count > length-2 ) panic ("Unexpected end of descriptor");
+ }
+
+ count++;
+ if (text[count] == 'V') count++;
+ else checkfieldtype (text, &count,length);
+
+ if (count != length) panic ("Method-descriptor has exceeding chars");
+}
+
+
+/******************** Funktion: buildarraydescriptor ****************************
+
+ erzeugt zu einem namentlich als u2-String vorliegenden Arraytyp eine
+ entsprechende constant_arraydescriptor - Struktur
+
+********************************************************************************/
+
+static constant_arraydescriptor * buildarraydescriptor(u2 *name, u4 namelen)
+{
+ constant_arraydescriptor *d;
+
+ if (name[0]!='[') panic ("Attempt to build arraydescriptor for non-array");
+ d = NEW (constant_arraydescriptor);
+ d -> objectclass = NULL;
+ d -> elementdescriptor = NULL;
+
+#ifdef STATISTICS
+ count_const_pool_len += sizeof(constant_arraydescriptor);
+#endif
+
+ switch (name[1]) {
+ case 'Z': d -> arraytype = ARRAYTYPE_BOOLEAN; break;
+ case 'B': d -> arraytype = ARRAYTYPE_BYTE; break;
+ case 'C': d -> arraytype = ARRAYTYPE_CHAR; break;
+ case 'D': d -> arraytype = ARRAYTYPE_DOUBLE; break;
+ case 'F': d -> arraytype = ARRAYTYPE_FLOAT; break;
+ case 'I': d -> arraytype = ARRAYTYPE_INT; break;
+ case 'J': d -> arraytype = ARRAYTYPE_LONG; break;
+ case 'S': d -> arraytype = ARRAYTYPE_SHORT; break;
+
+ case '[':
+ d -> arraytype = ARRAYTYPE_ARRAY;
+ d -> elementdescriptor = buildarraydescriptor (name+1, namelen-1);
+ break;
+
+ case 'L':
+ d -> arraytype = ARRAYTYPE_OBJECT;
+ d -> objectclass = class_get ( unicode_new_u2 (name+2, namelen-3) );
+ break;
+ }
+ return d;
+}
+
+
+/******************* Funktion: freearraydescriptor ****************************
+
+ entfernt eine mit buildarraydescriptor erzeugte Struktur wieder
+ aus dem Speicher
+
+*******************************************************************************/
+
+static void freearraydescriptor (constant_arraydescriptor *d)
+{
+ while (d) {
+ constant_arraydescriptor *n = d->elementdescriptor;
+ FREE (d, constant_arraydescriptor);
+ d = n;
+ }
+}
+
+/*********************** Funktion: displayarraydescriptor *********************/
+
+static void displayarraydescriptor (constant_arraydescriptor *d)
+{
+ switch (d->arraytype) {
+ case ARRAYTYPE_BOOLEAN: printf ("boolean[]"); break;
+ case ARRAYTYPE_BYTE: printf ("byte[]"); break;
+ case ARRAYTYPE_CHAR: printf ("char[]"); break;
+ case ARRAYTYPE_DOUBLE: printf ("double[]"); break;
+ case ARRAYTYPE_FLOAT: printf ("float[]"); break;
+ case ARRAYTYPE_INT: printf ("int[]"); break;
+ case ARRAYTYPE_LONG: printf ("long[]"); break;
+ case ARRAYTYPE_SHORT: printf ("short[]"); break;
+ case ARRAYTYPE_ARRAY: displayarraydescriptor(d->elementdescriptor); printf("[]"); break;
+ case ARRAYTYPE_OBJECT: unicode_display(d->objectclass->name); printf("[]"); break;
+ }
+}
+
+
+
+/*****************************************************************************/
+/******************** Funktionen fuer Fields *********************************/
+/*****************************************************************************/
+
+
+/************************ Funktion: field_load ********************************
+
+ l"adt alle Informationen f"ur eine Feld einer Methode aus dem ClassFile,
+ und f"ullt mit diesen Infos eine schon existierende 'fieldinfo'-Struktur.
+ Bei 'static'-Fields wird auch noch ein Platz auf dem Datensegment
+ reserviert.
+
+******************************************************************************/
+
+static void field_load (fieldinfo *f, classinfo *c)
+{
+ u4 attrnum,i;
+ u4 jtype;
+
+ f -> flags = suck_u2 ();
+ f -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
+ f -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
+ f -> type = jtype = desc_to_type (f->descriptor);
+ f -> offset = 0;
+
+ switch (f->type) {
+ case TYPE_INT: f->value.i = 0; break;
+ case TYPE_FLOAT: f->value.f = 0.0; break;
+ case TYPE_DOUBLE: f->value.d = 0.0; break;
+ case TYPE_ADDRESS: f->value.a = NULL;
+ heap_addreference (&(f->value.a));
+ break;
+ case TYPE_LONG:
+#if U8_AVAILABLE
+ f->value.l = 0; break;
+#else
+ f->value.l.low = 0; f->value.l.high = 0; break;
+#endif
+ }
+
+ attrnum = suck_u2();
+ for (i=0; i<attrnum; i++) {
+ u4 pindex;
+ unicode *aname;
+
+ aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
+
+ if ( aname != unicode_new_char ("ConstantValue") ) {
+ skipattributebody ();
+ }
+ else {
+ suck_u4();
+ pindex = suck_u2();
+
+ switch (jtype) {
+ case TYPE_INT: {
+ constant_integer *ci =
+ class_getconstant(c, pindex, CONSTANT_Integer);
+ f->value.i = ci -> value;
+ }
+ break;
+
+ case TYPE_LONG: {
+ constant_long *cl =
+ class_getconstant(c, pindex, CONSTANT_Long);
+
+ f->value.l = cl -> value;
+ }
+ break;
+
+ case TYPE_FLOAT: {
+ constant_float *cf =
+ class_getconstant(c, pindex, CONSTANT_Float);
+
+ f->value.f = cf->value;
+ }
+ break;
+
+ case TYPE_DOUBLE: {
+ constant_double *cd =
+ class_getconstant(c, pindex, CONSTANT_Double);
+
+ f->value.d = cd->value;
+ }
+ break;
+
+ case TYPE_ADDRESS: {
+ unicode *u =
+ class_getconstant(c, pindex, CONSTANT_String);
+ f->value.a = literalstring_new(u);
+ }
+ break;
+
+ default:
+ log_text ("Invalid Constant - Type");
+
+ }
+
+ }
+ }
+
+}
+
+
+/********************** Funktion: field_free *********************************/
+
+static void field_free (fieldinfo *f)
+{
+}
+
+
+/************** Funktion: field_display (nur zu Debug-Zwecken) ***************/
+
+static void field_display (fieldinfo *f)
+{
+ printf (" ");
+ printflags (f -> flags);
+ printf (" ");
+ unicode_display (f -> name);
+ printf (" ");
+ unicode_display (f -> descriptor);
+ printf (" offset: %ld\n", (long int) (f -> offset) );
+}
+
+
+
+
+/*****************************************************************************/
+/************************* Funktionen f"ur Methods ***************************/
+/*****************************************************************************/
+
+
+/*********************** Funktion: method_load ********************************
+
+ l"adt die Infos f"ur eine Methode aus dem ClassFile und f"ullt damit
+ eine schon existierende 'methodinfo'-Struktur aus.
+ Bei allen native-Methoden wird au"serdem gleich der richtige
+ Funktionszeiger eingetragen, bei JavaVM-Methoden einstweilen ein
+ Zeiger auf den Compiler
+
+******************************************************************************/
+
+static void method_load (methodinfo *m, classinfo *c)
+{
+ u4 attrnum,i,e;
+
+#ifdef STATISTICS
+ count_all_methods++;
+#endif
+
+ m -> class = c;
+
+ m -> flags = suck_u2 ();
+ m -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
+ m -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
+
+ m -> jcode = NULL;
+ m -> exceptiontable = NULL;
+ m -> entrypoint = NULL;
+ m -> mcode = NULL;
+ m -> stubroutine = NULL;
+
+ if (! (m->flags & ACC_NATIVE) ) {
+ m -> stubroutine = createcompilerstub (m);
+ }
+ else {
+ functionptr f = native_findfunction
+ (c->name, m->name, m->descriptor, (m->flags & ACC_STATIC) != 0);
+ if (f) {
+ if (newcompiler)
+ m -> stubroutine = ncreatenativestub (f, m);
+ else
+ m -> stubroutine = createnativestub (f, m);
+ }
+ }
+
+
+ attrnum = suck_u2();
+ for (i=0; i<attrnum; i++) {
+ unicode *aname;
+
+ aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
+
+ if ( aname != unicode_new_char("Code")) {
+ skipattributebody ();
+ }
+ else {
+ if (m -> jcode) panic ("Two code-attributes for one method!");
+
+ suck_u4();
+ m -> maxstack = suck_u2();
+ m -> maxlocals = suck_u2();
+ m -> jcodelength = suck_u4();
+ m -> jcode = MNEW (u1, m->jcodelength);
+ suck_nbytes (m->jcode, m->jcodelength);
+ m -> exceptiontablelength = suck_u2 ();
+ m -> exceptiontable =
+ MNEW (exceptiontable, m->exceptiontablelength);
+
+#ifdef STATISTICS
+ count_vmcode_len += m->jcodelength + 18;
+ count_extable_len += 8 * m->exceptiontablelength;
+#endif
+
+ for (e=0; e < m->exceptiontablelength; e++) {
+ u4 idx;
+ m -> exceptiontable[e].startpc = suck_u2();
+ m -> exceptiontable[e].endpc = suck_u2();
+ m -> exceptiontable[e].handlerpc = suck_u2();
+
+ idx = suck_u2();
+ if (!idx) m -> exceptiontable[e].catchtype = NULL;
+ else {
+ m -> exceptiontable[e].catchtype =
+ class_getconstant (c, idx, CONSTANT_Class);
+ }
+ }
+
+ skipattributes ( suck_u2() );
+ }
+
+ }
+
+
+}
+
+
+/********************* Funktion: method_free **********************************
+
+ gibt allen Speicher, der extra f"ur eine Methode angefordert wurde,
+ wieder frei
+
+******************************************************************************/
+
+static void method_free (methodinfo *m)
+{
+ if (m->jcode) MFREE (m->jcode, u1, m->jcodelength);
+ if (m->exceptiontable)
+ MFREE (m->exceptiontable, exceptiontable, m->exceptiontablelength);
+ if (m->mcode) CFREE (m->mcode, m->mcodelength);
+ if (m->stubroutine) {
+ if (m->flags & ACC_NATIVE) removenativestub (m->stubroutine);
+ else removecompilerstub (m->stubroutine);
+ }
+}
+
+
+/************** Funktion: method_display (nur zu Debug-Zwecken) *************/
+
+void method_display (methodinfo *m)
+{
+ printf (" ");
+ printflags (m -> flags);
+ printf (" ");
+ unicode_display (m -> name);
+ printf (" ");
+ unicode_display (m -> descriptor);
+ printf ("\n");
+}
+
+
+/******************** Funktion: method_canoverwrite ***************************
+
+ "uberpr"ft, ob eine Methode mit einer anderen typ- und namensidentisch
+ ist (also mit einer Methodendefinition eine andere "uberschrieben
+ werden kann).
+
+******************************************************************************/
+
+static bool method_canoverwrite (methodinfo *m, methodinfo *old)
+{
+ if (m->name != old->name) return false;
+ if (m->descriptor != old->descriptor) return false;
+ if (m->flags & ACC_STATIC) return false;
+ return true;
+}
+
+
+
+
+/*****************************************************************************/
+/************************ Funktionen fuer Class ******************************/
+/*****************************************************************************/
+
+
+/******************** Funktion: class_get *************************************
+
+ Sucht im System die Klasse mit dem gew"unschten Namen, oder erzeugt
+ eine neue 'classinfo'-Struktur (und h"angt sie in die Liste der zu
+ ladenen Klassen ein).
+
+******************************************************************************/
+
+classinfo *class_get (unicode *u)
+{
+ classinfo *c;
+
+ if (u->class) return u->class;
+
+#ifdef STATISTICS
+ count_class_infos += sizeof(classinfo);
+#endif
+
+ c = NEW (classinfo);
+ c -> flags = 0;
+ c -> name = u;
+ c -> cpcount = 0;
+ c -> cptags = NULL;
+ c -> cpinfos = NULL;
+ c -> super = NULL;
+ c -> interfacescount = 0;
+ c -> interfaces = NULL;
+ c -> fieldscount = 0;
+ c -> fields = NULL;
+ c -> methodscount = 0;
+ c -> methods = NULL;
+ c -> linked = false;
+ c -> index = 0;
+ c -> instancesize = 0;
+ c -> vftbl = NULL;
+ c -> initialized = false;
+
+ unicode_setclasslink (u,c);
+ list_addlast (&unloadedclasses, c);
+
+ return c;
+}
+
+
+
+/******************** Funktion: class_getconstant *****************************
+
+ holt aus dem ConstantPool einer Klasse den Wert an der Stelle 'pos'.
+ Der Wert mu"s vom Typ 'ctype' sein, sonst wird das System angehalten.
+
+******************************************************************************/
+
+voidptr class_getconstant (classinfo *c, u4 pos, u4 ctype)
+{
+ if (pos >= c->cpcount)
+ panic ("Attempt to access constant outside range");
+ if (c->cptags[pos] != ctype) {
+ sprintf (logtext, "Type mismatch on constant: %d requested, %d here",
+ (int) ctype, (int) c->cptags[pos] );
+ error();
+ }
+
+ return c->cpinfos[pos];
+}
+
+
+/********************* Funktion: class_constanttype ***************************
+
+ Findet heraus, welchen Typ ein Eintrag in den ConstantPool einer
+ Klasse hat.
+
+******************************************************************************/
+
+u4 class_constanttype (classinfo *c, u4 pos)
+{
+ if (pos >= c->cpcount)
+ panic ("Attempt to access constant outside range");
+ return c->cptags[pos];
+}
+
+
+/******************** Funktion: class_loadcpool *******************************
+
+ l"adt den gesammten ConstantPool einer Klasse.
+
+ Dabei werden die einzelnen Eintr"age in ein wesentlich einfachers
+ Format gebracht (Klassenreferenzen werden aufgel"ost, ...)
+ F"ur eine genaue "Ubersicht "uber das kompakte Format siehe: 'global.h'
+
+******************************************************************************/
+
+static void class_loadcpool (classinfo *c)
+{
+
+ typedef struct forward_class { /* Diese Strukturen dienen dazu, */
+ struct forward_class *next; /* die Infos, die beim ersten */
+ u2 thisindex; /* Durchgang durch den ConstantPool */
+ u2 name_index; /* gelesen werden, aufzunehmen. */
+ } forward_class; /* Erst nachdem der ganze Pool */
+ /* gelesen wurde, k"onnen alle */
+ typedef struct forward_string { /* Felder kompletiert werden */
+ struct forward_string *next; /* (und das auch nur in der richtigen */
+ u2 thisindex; /* Reihenfolge) */
+ u2 string_index;
+ } forward_string;
+
+ typedef struct forward_nameandtype {
+ struct forward_nameandtype *next;
+ u2 thisindex;
+ u2 name_index;
+ u2 sig_index;
+ } forward_nameandtype;
+
+ typedef struct forward_fieldmethint {
+ struct forward_fieldmethint *next;
+ u2 thisindex;
+ u1 tag;
+ u2 class_index;
+ u2 nameandtype_index;
+ } forward_fieldmethint;
+
+
+
+ u4 idx;
+ long int dumpsize = dump_size ();
+
+ forward_class *forward_classes = NULL;
+ forward_string *forward_strings = NULL;
+ forward_nameandtype *forward_nameandtypes = NULL;
+ forward_fieldmethint *forward_fieldmethints = NULL;
+
+ u4 cpcount = c -> cpcount = suck_u2();
+ u1 *cptags = c -> cptags = MNEW (u1, cpcount);
+ voidptr *cpinfos = c -> cpinfos = MNEW (voidptr, cpcount);
+
+#ifdef STATISTICS
+ count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
+#endif
+
+
+ for (idx=0; idx<cpcount; idx++) {
+ cptags[idx] = CONSTANT_UNUSED;
+ cpinfos[idx] = NULL;
+ }
+
+
+ /******* Erster Durchgang *******/
+ /* Alle Eintr"age, die nicht unmittelbar aufgel"ost werden k"onnen,
+ werden einmal `auf Vorrat' in tempor"are Strukturen eingelesen,
+ und dann am Ende nocheinmal durchgegangen */
+
+ idx = 1;
+ while (idx < cpcount) {
+ u4 t = suck_u1 ();
+ switch ( t ) {
+
+ case CONSTANT_Class: {
+ forward_class *nfc = DNEW(forward_class);
+
+ nfc -> next = forward_classes;
+ forward_classes = nfc;
+
+ nfc -> thisindex = idx;
+ nfc -> name_index = suck_u2 ();
+
+ idx++;
+ break;
+ }
+
+ case CONSTANT_Fieldref:
+ case CONSTANT_Methodref:
+ case CONSTANT_InterfaceMethodref: {
+ forward_fieldmethint *nff = DNEW (forward_fieldmethint);
+
+ nff -> next = forward_fieldmethints;
+ forward_fieldmethints = nff;
+
+ nff -> thisindex = idx;
+ nff -> tag = t;
+ nff -> class_index = suck_u2 ();
+ nff -> nameandtype_index = suck_u2 ();
+
+ idx ++;
+ break;
+ }
+
+ case CONSTANT_String: {
+ forward_string *nfs = DNEW (forward_string);
+
+ nfs -> next = forward_strings;
+ forward_strings = nfs;
+
+ nfs -> thisindex = idx;
+ nfs -> string_index = suck_u2 ();
+
+ idx ++;
+ break;
+ }
+
+ case CONSTANT_NameAndType: {
+ forward_nameandtype *nfn = DNEW (forward_nameandtype);
+
+ nfn -> next = forward_nameandtypes;
+ forward_nameandtypes = nfn;
+
+ nfn -> thisindex = idx;
+ nfn -> name_index = suck_u2 ();
+ nfn -> sig_index = suck_u2 ();
+
+ idx ++;
+ break;
+ }
+
+ case CONSTANT_Integer: {
+ constant_integer *ci = NEW (constant_integer);
+
+#ifdef STATISTICS
+ count_const_pool_len += sizeof(constant_integer);
+#endif
+
+ ci -> value = suck_s4 ();
+ cptags [idx] = CONSTANT_Integer;
+ cpinfos [idx] = ci;
+ idx ++;
+
+ break;
+ }
+
+ case CONSTANT_Float: {
+ constant_float *cf = NEW (constant_float);
+
+#ifdef STATISTICS
+ count_const_pool_len += sizeof(constant_float);
+#endif
+
+ cf -> value = suck_float ();
+ cptags [idx] = CONSTANT_Float;
+ cpinfos[idx] = cf;
+ idx ++;
+ break;
+ }
+
+ case CONSTANT_Long: {
+ constant_long *cl = NEW(constant_long);
+
+#ifdef STATISTICS
+ count_const_pool_len += sizeof(constant_long);
+#endif
+
+ cl -> value = suck_s8 ();
+ cptags [idx] = CONSTANT_Long;
+ cpinfos [idx] = cl;
+ idx += 2;
+ break;
+ }
+
+ case CONSTANT_Double: {
+ constant_double *cd = NEW(constant_double);
+
+#ifdef STATISTICS
+ count_const_pool_len += sizeof(constant_double);
+#endif
+
+ cd -> value = suck_double ();
+ cptags [idx] = CONSTANT_Double;
+ cpinfos [idx] = cd;
+ idx += 2;
+ break;
+ }
+
+ case CONSTANT_Utf8: {
+ unicode *u;
+
+ u = loadUtf8 ();
+
+ cptags [idx] = CONSTANT_Utf8;
+ cpinfos [idx] = u;
+ idx++;
+ break;
+ }
+
+ default:
+ sprintf (logtext, "Unkown constant type: %d",(int) t);
+ error ();
+
+ } /* end switch */
+
+ } /* end while */
+
+
+
+ /* Aufl"osen der noch unfertigen Eintr"age */
+
+ while (forward_classes) {
+ unicode *name =
+ class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8);
+
+ if ( (name->length>0) && (name->text[0]=='[') ) {
+ checkfielddescriptor (name);
+
+ cptags [forward_classes -> thisindex] = CONSTANT_Arraydescriptor;
+ cpinfos [forward_classes -> thisindex] =
+ buildarraydescriptor(name->text, name->length);
+
+ }
+ else {
+ cptags [forward_classes -> thisindex] = CONSTANT_Class;
+ cpinfos [forward_classes -> thisindex] = class_get (name);
+ }
+ forward_classes = forward_classes -> next;
+
+ }
+
+ while (forward_strings) {
+ unicode *text =
+ class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8);
+
+ cptags [forward_strings -> thisindex] = CONSTANT_String;
+ cpinfos [forward_strings -> thisindex] = text;
+
+ forward_strings = forward_strings -> next;
+ }
+
+ while (forward_nameandtypes) {
+ constant_nameandtype *cn = NEW (constant_nameandtype);
+
+#ifdef STATISTICS
+ count_const_pool_len += sizeof(constant_nameandtype);
+#endif
+
+ cn -> name = class_getconstant
+ (c, forward_nameandtypes -> name_index, CONSTANT_Utf8);
+ cn -> descriptor = class_getconstant
+ (c, forward_nameandtypes -> sig_index, CONSTANT_Utf8);
+
+ cptags [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
+ cpinfos [forward_nameandtypes -> thisindex] = cn;
+
+ forward_nameandtypes = forward_nameandtypes -> next;
+ }
+
+
+ while (forward_fieldmethints) {
+ constant_nameandtype *nat;
+ constant_FMIref *fmi = NEW (constant_FMIref);
+
+#ifdef STATISTICS
+ count_const_pool_len += sizeof(constant_FMIref);
+#endif
+
+ nat = class_getconstant
+ (c, forward_fieldmethints -> nameandtype_index, CONSTANT_NameAndType);
+
+ fmi -> class = class_getconstant
+ (c, forward_fieldmethints -> class_index, CONSTANT_Class);
+ fmi -> name = nat -> name;
+ fmi -> descriptor = nat -> descriptor;
+
+ cptags [forward_fieldmethints -> thisindex] = forward_fieldmethints -> tag;
+ cpinfos [forward_fieldmethints -> thisindex] = fmi;
+
+ switch (forward_fieldmethints -> tag) {
+ case CONSTANT_Fieldref: checkfielddescriptor (fmi->descriptor);
+ break;
+ case CONSTANT_InterfaceMethodref:
+ case CONSTANT_Methodref: checkmethoddescriptor (fmi->descriptor);
+ break;
+ }
+
+ forward_fieldmethints = forward_fieldmethints -> next;
+
+ }
+
+
+ dump_release (dumpsize);
+}
+
+
+/********************** Funktion: class_load **********************************
+
+ l"adt alle Infos f"ur eine ganze Klasse aus einem ClassFile. Die
+ 'classinfo'-Struktur mu"s bereits angelegt worden sein.
+
+ Die Superklasse und die Interfaces, die diese Klasse implementiert,
+ m"ussen zu diesem Zeitpunkt noch nicht geladen sein, die
+ Verbindung dazu wird sp"ater in der Funktion 'class_link' hergestellt.
+
+ Die gelesene Klasse wird dann aus der Liste 'unloadedclasses' ausgetragen
+ und in die Liste 'unlinkedclasses' eingh"angt.
+
+******************************************************************************/
+
+static void class_load (classinfo *c)
+{
+ u4 i;
+ u4 mi,ma;
+
+
+ if (loadverbose) {
+ sprintf (logtext, "Loading class: ");
+ unicode_sprint (logtext+strlen(logtext), c->name );
+ dolog();
+ }
+
+
+ suck_start (c->name);
+
+ if (suck_u4() != MAGIC) panic("Can not find class-file signature");
+ mi = suck_u2();
+ ma = suck_u2();
+ if (ma != MAJOR_VERSION) {
+ sprintf (logtext, "Can only support major version %d, but not %d",
+ MAJOR_VERSION, (int) ma);
+ error();
+ }
+ if (mi > MINOR_VERSION) {
+ sprintf (logtext, "Minor version %d is not yet supported.", (int) mi);
+ error();
+ }
+
+
+ class_loadcpool (c);
+
+ c -> flags = suck_u2 ();
+ suck_u2 (); /* this */
+
+ if ( (i = suck_u2 () ) ) {
+ c -> super = class_getconstant (c, i, CONSTANT_Class);
+ }
+ else {
+ c -> super = NULL;
+ }
+
+ c -> interfacescount = suck_u2 ();
+ c -> interfaces = MNEW (classinfo*, c -> interfacescount);
+ for (i=0; i < c -> interfacescount; i++) {
+ c -> interfaces [i] =
+ class_getconstant (c, suck_u2(), CONSTANT_Class);
+ }
+
+ c -> fieldscount = suck_u2 ();
+ c -> fields = MNEW (fieldinfo, c -> fieldscount);
+ for (i=0; i < c -> fieldscount; i++) {
+ field_load (&(c->fields[i]), c);
+ }
+
+ c -> methodscount = suck_u2 ();
+ c -> methods = MNEW (methodinfo, c -> methodscount);
+ for (i=0; i < c -> methodscount; i++) {
+ method_load (&(c -> methods [i]), c);
+ }
+
+#ifdef STATISTICS
+ count_class_infos += sizeof(classinfo*) * c -> interfacescount;
+ count_class_infos += sizeof(fieldinfo) * c -> fieldscount;
+ count_class_infos += sizeof(methodinfo) * c -> methodscount;
+#endif
+
+
+ skipattributes ( suck_u2() );
+
+
+ suck_stop ();
+
+ list_remove (&unloadedclasses, c);
+ list_addlast (&unlinkedclasses, c);
+}
+
+
+
+/************** interne Funktion: class_highestinterface **********************
+
+ wird von der Funktion class_link ben"otigt, um festzustellen, wie gro"s
+ die Interfacetable einer Klasse sein mu"s.
+
+******************************************************************************/
+
+static s4 class_highestinterface (classinfo *c)
+{
+ s4 h;
+ s4 i;
+
+ if ( ! (c->flags & ACC_INTERFACE) ) {
+ sprintf (logtext, "Interface-methods count requested for non-interface: ");
+ unicode_sprint (logtext+strlen(logtext), c->name);
+ error();
+ }
+
+ h = c->index;
+ for (i=0; i<c->interfacescount; i++) {
+ s4 h2 = class_highestinterface (c->interfaces[i]);
+ if (h2>h) h=h2;
+ }
+ return h;
+}
+
+
+/**************** Funktion: class_addinterface ********************************
+
+ wird von der Funktion class_link ben"otigt, um eine Virtual Function
+ Table f"ur ein Interface (und alle weiteren von diesem Interface
+ implementierten Interfaces) in eine Klasse einzutragen.
+
+******************************************************************************/
+
+static void class_addinterface (classinfo *c, classinfo *ic)
+{
+ u4 i = ic->index;
+ u4 j,m;
+ vftbl *vftbl = c->vftbl;
+
+ if (i>=vftbl->interfacetablelength) panic ("Interfacetable-Overflow");
+ if (vftbl->interfacevftbl[i]) return;
+
+ if (ic->methodscount==0) { /* wenn interface keine Methoden hat, dann
+ trotzdem eine Tabelle mit L"ange 1 anlegen,
+ wegen Subclass-Tests */
+ vftbl -> interfacevftbllength[i] = 1;
+ vftbl -> interfacevftbl[i] = MNEW(methodptr, 1);
+ vftbl -> interfacevftbl[i][0] = NULL;
+ }
+ else {
+ vftbl -> interfacevftbllength[i] = ic -> methodscount;
+ vftbl -> interfacevftbl[i] = MNEW(methodptr, ic -> methodscount);
+
+#ifdef STATISTICS
+ count_vftbl_len += sizeof(methodptr) * ic -> methodscount;
+#endif
+
+ for (j=0; j<ic->methodscount; j++) {
+ classinfo *sc = c;
+ while (sc) {
+ for (m=0; m<sc->methodscount; m++) {
+ methodinfo *mi = &(sc->methods[m]);
+ if (method_canoverwrite (mi, &(ic->methods[j])) ) {
+ vftbl->interfacevftbl[i][j] =
+ vftbl->table[mi->vftblindex];
+ goto foundmethod;
+ }
+ }
+ sc = sc->super;
+ }
+ foundmethod: ;
+ }
+ }
+
+ for (j=0; j<ic->interfacescount; j++)
+ class_addinterface(c, ic->interfaces[j]);
+}
+
+
+/********************** Funktion: class_link **********************************
+
+ versucht, eine Klasse in das System voll zu integrieren (linken). Dazu
+ m"ussen sowol die Superklasse, als auch alle implementierten
+ Interfaces schon gelinkt sein.
+ Diese Funktion berechnet sowohl die L"ange (in Bytes) einer Instanz
+ dieser Klasse, als auch die Virtual Function Tables f"ur normale
+ Methoden als auch Interface-Methoden.
+
+ Wenn die Klasse erfolgreich gelinkt werden kann, dann wird sie aus
+ der Liste 'unlinkedclasses' ausgeh"angt, und in die Klasse 'linkedclasses'
+ eingetragen.
+ Wenn nicht, dann wird sie ans Ende der Liste 'unlinkedclasses' gestellt.
+
+ Achtung: Bei zyklischen Klassendefinitionen ger"at das Programm hier in
+ eine Endlosschleife!! (Da muss ich mir noch was einfallen lassen)
+
+******************************************************************************/
+
+static void class_link (classinfo *c)
+{
+ u4 supervftbllength; /* L"ange der VFTBL der Superklasse */
+ u4 vftbllength; /* L"ange der VFTBL dieser Klasse */
+ classinfo *super = c->super;
+ classinfo *ic,*c2; /* Hilfsvariablen */
+ vftbl *v;
+ u4 i;
+
+
+ /* schauen, ob alle "ubergeordneten Klassen schon fertig sind,
+ und richtiges Initialisieren der lokalen Variablen */
+
+ for ( i=0; i<c->interfacescount; i++) {
+ ic = c->interfaces[i];
+ if ( !ic -> linked) {
+ list_remove (&unlinkedclasses,c );
+ list_addlast (&unlinkedclasses,c );
+ return;
+ }
+ }
+
+ if (! super) {
+ c -> index = 0;
+ c -> instancesize = sizeof (java_objectheader);
+
+ vftbllength = supervftbllength = 0;
+
+ c -> finalizer = NULL;
+ }
+ else {
+ if ( !super -> linked ) {
+ list_remove (&unlinkedclasses,c );
+ list_addlast (&unlinkedclasses,c );
+ return;
+ }
+
+ if ( c->flags & ACC_INTERFACE) c -> index = interfaceindex++;
+ else c -> index = super -> index + 1;
+
+ c -> instancesize = super -> instancesize;
+
+ vftbllength = supervftbllength = super -> vftbl -> vftbllength;
+
+ c -> finalizer = super -> finalizer;
+ }
+
+
+ if (linkverbose) {
+ sprintf (logtext, "Linking Class: ");
+ unicode_sprint (logtext+strlen(logtext), c->name );
+ dolog ();
+ }
+
+ /* Erstellen der Virtual Function Table */
+
+ for (i=0; i < c->methodscount; i++) {
+ methodinfo *m = &(c->methods[i]);
+
+ if (! (m->flags & ACC_STATIC) ) {
+ classinfo *sc = super;
+ while (sc) {
+ int j;
+ for (j=0; j < sc->methodscount; j++) {
+ if ( method_canoverwrite (m, &(sc->methods[j])) ) {
+ m -> vftblindex = sc->methods[j].vftblindex;
+ goto foundvftblindex;
+ }
+ }
+ sc = sc->super;
+ }
+ m -> vftblindex = (vftbllength++);
+ foundvftblindex: ;
+ }
+ }
+
+#ifdef STATISTICS
+ count_vftbl_len += sizeof(vftbl) + sizeof(methodptr)*(vftbllength-1);
+#endif
+
+ c -> vftbl = v = (vftbl*)
+ mem_alloc (sizeof(vftbl) + sizeof(methodptr)*(vftbllength-1));
+ v -> class = c;
+ v -> vftbllength = vftbllength;
+ v -> interfacetablelength = 0;
+
+ for (i=0; i < supervftbllength; i++)
+ v -> table[i] = super -> vftbl -> table[i];
+
+ for (i=0; i < c->methodscount; i++) {
+ methodinfo *m = &(c->methods[i]);
+ if ( ! (m->flags & ACC_STATIC) ) {
+ v -> table[m->vftblindex] = m -> stubroutine;
+ }
+ }
+
+
+ /* Berechnen der Instanzengr"o"se und der Offsets der einzelnen
+ Felder */
+
+ for (i=0; i < c->fieldscount; i++) {
+ u4 dsize;
+ fieldinfo *f = &(c -> fields[i]);
+
+ if ( ! (f->flags & ACC_STATIC) ) {
+ dsize = desc_typesize (f->descriptor);
+ c -> instancesize = ALIGN ( c->instancesize, dsize);
+ f -> offset = c -> instancesize;
+ c -> instancesize += dsize;
+ }
+
+ }
+
+
+ /* Berechnen der Virtual Function Tables f"ur alle Interfaces */
+
+ c2 = c;
+ while (c2) {
+ for (i=0; i<c2->interfacescount; i++) {
+ s4 h = class_highestinterface (c2->interfaces[i]) + 1;
+ if ( h > v->interfacetablelength) v->interfacetablelength = h;
+ }
+ c2 = c2->super;
+ }
+ v -> interfacevftbllength = MNEW (u4, v->interfacetablelength);
+ v -> interfacevftbl = MNEW (methodptr *, v->interfacetablelength);
+
+#ifdef STATISTICS
+ count_vftbl_len += (4 + sizeof(methodptr*)) * v->interfacetablelength;
+#endif
+
+ for (i=0; i < v->interfacetablelength; i++) {
+ v -> interfacevftbllength[i] = 0;
+ v -> interfacevftbl[i] = NULL;
+ }
+
+ c2 = c;
+ while (c2) {
+ for (i=0; i<c2->interfacescount; i++) {
+ class_addinterface (c, c2->interfaces[i]);
+ }
+ c2 = c2->super;
+ }
+
+
+
+ /* Die finalizer-Methode suchen und eintragen (wenn vorhanden),
+ aber nur bei Objekten ausser java.lang.Object */
+
+ if (super) {
+ methodinfo *fi;
+ static unicode *finame=NULL,*fidesc=NULL;
+
+ if (!finame) finame = unicode_new_char ("finalize");
+ if (!fidesc) fidesc = unicode_new_char ("()V");
+
+ fi = class_findmethod (c, finame, fidesc);
+ if (fi) {
+ if (! (fi->flags & ACC_STATIC) ) {
+ c -> finalizer = fi;
+ }
+ }
+ }
+
+
+ /* Abschlie"sende Aktionen */
+
+ c -> linked = true;
+
+ list_remove (&unlinkedclasses, c);
+ list_addlast (&linkedclasses, c);
+}
+
+
+/******************* Funktion: class_freepool *********************************
+
+ Gibt alle Resourcen, die der ConstantPool einer Klasse ben"otigt,
+ wieder frei.
+
+******************************************************************************/
+
+static void class_freecpool (classinfo *c)
+{
+ u4 idx;
+ u4 tag;
+ voidptr info;
+
+ for (idx=0; idx < c->cpcount; idx++) {
+ tag = c->cptags[idx];
+ info = c->cpinfos[idx];
+
+ if (info != NULL) {
+ switch (tag) {
+ case CONSTANT_Fieldref:
+ case CONSTANT_Methodref:
+ case CONSTANT_InterfaceMethodref:
+ FREE (info, constant_FMIref);
+ break;
+ case CONSTANT_Integer:
+ FREE (info, constant_integer);
+ break;
+ case CONSTANT_Float:
+ FREE (info, constant_float);
+ break;
+ case CONSTANT_Long:
+ FREE (info, constant_long);
+ break;
+ case CONSTANT_Double:
+ FREE (info, constant_double);
+ break;
+ case CONSTANT_NameAndType:
+ FREE (info, constant_nameandtype);
+ break;
+ case CONSTANT_Arraydescriptor:
+ freearraydescriptor (info);
+ break;
+ }
+ }
+ }
+
+ MFREE (c -> cptags, u1, c -> cpcount);
+ MFREE (c -> cpinfos, voidptr, c -> cpcount);
+}
+
+
+/*********************** Funktion: class_free *********************************
+
+ Gibt alle Resourcen, die eine ganze Klasse ben"otigt, frei
+
+******************************************************************************/
+
+static void class_free (classinfo *c)
+{
+ u4 i;
+ vftbl *v;
+
+ unicode_unlinkclass (c->name);
+
+ class_freecpool (c);
+
+ MFREE (c->interfaces, classinfo*, c->interfacescount);
+
+ for (i=0; i < c->fieldscount; i++) field_free ( &(c->fields[i]) );
+ MFREE (c->fields, fieldinfo, c->fieldscount);
+
+ for (i=0; i < c->methodscount; i++) method_free ( &(c->methods[i]) );
+ MFREE (c->methods, methodinfo, c->methodscount);
+
+ if ( (v = c->vftbl) ) {
+ for (i=0; i<v->interfacetablelength; i++) {
+ MFREE (v->interfacevftbl[i], methodptr, v->interfacevftbllength[i]);
+ }
+ MFREE (v->interfacevftbllength, u4, v->interfacetablelength);
+ MFREE (v->interfacevftbl, methodptr*, v->interfacetablelength);
+
+ mem_free (v, sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1));
+ }
+
+ FREE (c, classinfo);
+}
+
+
+/************************* Funktion: class_findfield *************************
+
+ sucht in einer 'classinfo'-Struktur nach einem Feld mit gew"unschtem
+ Namen und Typ.
+
+*****************************************************************************/
+
+fieldinfo *class_findfield (classinfo *c, unicode *name, unicode *desc)
+{
+ u4 i;
+ for (i=0; i < c->fieldscount; i++) {
+ if ( (c->fields[i].name == name) && (c->fields[i].descriptor == desc) )
+ return &(c->fields[i]);
+ }
+ panic ("Can not find field given in CONSTANT_Fieldref");
+ return NULL;
+}
+
+
+/************************* Funktion: class_findmethod *************************
+
+ sucht in einer 'classinfo'-Struktur nach einer Methode mit gew"unschtem
+ Namen und Typ.
+ Wenn als Typ NULL angegeben wird, dann ist der Typ egal.
+
+*****************************************************************************/
+
+methodinfo *class_findmethod (classinfo *c, unicode *name, unicode *desc)
+{
+ u4 i;
+ for (i=0; i < c->methodscount; i++) {
+ if ( (c->methods[i].name == name)
+ && ( (desc == NULL)
+ || (c->methods[i].descriptor == desc)
+ )
+ )
+ return &(c->methods[i]);
+ }
+ return NULL;
+}
+
+
+/************************* Funktion: class_resolvemethod *************************
+
+ sucht eine Klasse und alle Superklassen ab, um eine Methode zu finden.
+
+*****************************************************************************/
+
+
+methodinfo *class_resolvemethod (classinfo *c, unicode *name, unicode *desc)
+{
+ while (c) {
+ methodinfo *m = class_findmethod (c, name, desc);
+ if (m) return m;
+ c = c->super;
+ }
+ return NULL;
+}
+
+
+
+/************************* Funktion: class_issubclass ************************
+
+ "uberpr"uft, ob eine Klasse von einer anderen Klasse abgeleitet ist.
+
+*****************************************************************************/
+
+bool class_issubclass (classinfo *sub, classinfo *super)
+{
+ for (;;) {
+ if (!sub) return false;
+ if (sub==super) return true;
+ sub = sub -> super;
+ }
+}
+
+
+
+/****************** Initialisierungsfunktion f"ur eine Klasse ****************
+
+ In Java kann jede Klasse ein statische Initialisierungsfunktion haben.
+ Diese Funktion mu"s aufgerufen werden, BEVOR irgendwelche Methoden der
+ Klasse aufgerufen werden, oder auf statische Variablen zugegriffen
+ wird.
+
+******************************************************************************/
+
+#ifdef USE_THREADS
+extern int blockInts;
+#endif
+
+void class_init (classinfo *c)
+{
+ methodinfo *m;
+ java_objectheader *exceptionptr;
+ s4 i;
+ int b;
+
+ if (!makeinitializations) return;
+ if (c->initialized) return;
+ c -> initialized = true;
+
+ if (c->super) class_init (c->super);
+ for (i=0; i < c->interfacescount; i++) class_init(c->interfaces[i]);
+
+ m = class_findmethod (c,
+ unicode_new_char ("<clinit>"),
+ unicode_new_char ("()V"));
+ if (!m) {
+ if (initverbose) {
+ sprintf (logtext, "Class ");
+ unicode_sprint (logtext+strlen(logtext), c->name);
+ sprintf (logtext+strlen(logtext), " has no initializer");
+ dolog ();
+ }
+ return;
+ }
+
+ if (! (m->flags & ACC_STATIC)) panic ("Class initializer is not static!");
+
+ if (initverbose) {
+ sprintf (logtext, "Starting initializer for class: ");
+ unicode_sprint (logtext+strlen(logtext), c->name);
+ dolog ();
+ }
+
+#ifdef USE_THREADS
+ b = blockInts;
+ blockInts = 0;
+#endif
+
+ exceptionptr = asm_calljavamethod (m, NULL,NULL,NULL,NULL);
+
+#ifdef USE_THREADS
+ assert(blockInts == 0);
+ blockInts = b;
+#endif
+
+ if (exceptionptr) {
+ printf ("#### Initializer has thrown: ");
+ unicode_display (exceptionptr->vftbl->class->name);
+ printf ("\n");
+ fflush (stdout);
+ }
+
+ if (initverbose) {
+ sprintf (logtext, "Finished initializer for class: ");
+ unicode_sprint (logtext+strlen(logtext), c->name);
+ dolog ();
+ }
+
+}
+
+
+
+
+/********* Funktion: class_showconstantpool (nur f"ur Debug-Zwecke) ********/
+
+void class_showconstantpool (classinfo *c)
+{
+ u4 i;
+ voidptr e;
+
+ printf ("---- dump of constant pool ----\n");
+
+ for (i=0; i<c->cpcount; i++) {
+ printf ("#%d: ", (int) i);
+
+ e = c -> cpinfos [i];
+ if (e) {
+
+ switch (c -> cptags [i]) {
+ case CONSTANT_Class:
+ printf ("Classreference -> ");
+ unicode_display ( ((classinfo*)e) -> name );
+ break;
+
+ case CONSTANT_Fieldref:
+ printf ("Fieldref -> "); goto displayFMI;
+ case CONSTANT_Methodref:
+ printf ("Methodref -> "); goto displayFMI;
+ case CONSTANT_InterfaceMethodref:
+ printf ("InterfaceMethod -> "); goto displayFMI;
+ displayFMI:
+ {
+ constant_FMIref *fmi = e;
+ unicode_display ( fmi->class->name );
+ printf (".");
+ unicode_display ( fmi->name);
+ printf (" ");
+ unicode_display ( fmi->descriptor );
+ }
+ break;
+
+ case CONSTANT_String:
+ printf ("String -> ");
+ unicode_display (e);
+ break;
+ case CONSTANT_Integer:
+ printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
+ break;
+ case CONSTANT_Float:
+ printf ("Float -> %f", ((constant_float*)e) -> value);
+ break;
+ case CONSTANT_Double:
+ printf ("Double -> %f", ((constant_double*)e) -> value);
+ break;
+ case CONSTANT_Long:
+ {
+ u8 v = ((constant_long*)e) -> value;
+#if U8_AVAILABLE
+ printf ("Long -> %ld", (long int) v);
+#else
+ printf ("Long -> HI: %ld, LO: %ld\n",
+ (long int) v.high, (long int) v.low);
+#endif
+ }
+ break;
+ case CONSTANT_NameAndType:
+ { constant_nameandtype *cnt = e;
+ printf ("NameAndType: ");
+ unicode_display (cnt->name);
+ printf (" ");
+ unicode_display (cnt->descriptor);
+ }
+ break;
+ case CONSTANT_Utf8:
+ printf ("Utf8 -> ");
+ unicode_display (e);
+ break;
+ case CONSTANT_Arraydescriptor: {
+ printf ("Arraydescriptor: ");
+ displayarraydescriptor (e);
+ }
+ break;
+ default:
+ panic ("Invalid type of ConstantPool-Entry");
+ }
+
+ }
+
+ printf ("\n");
+ }
+
+}
+
+
+
+/********** Funktion: class_showmethods (nur f"ur Debug-Zwecke) ************/
+
+void class_showmethods (classinfo *c)
+{
+ u4 i;
+
+ printf ("--------- Fields and Methods ----------------\n");
+ printf ("Flags: "); printflags (c->flags); printf ("\n");
+
+ printf ("This: "); unicode_display (c->name); printf ("\n");
+ if (c->super) {
+ printf ("Super: "); unicode_display (c->super->name); printf ("\n");
+ }
+ printf ("Index: %d\n", c->index);
+
+ printf ("interfaces:\n");
+ for (i=0; i < c-> interfacescount; i++) {
+ printf (" ");
+ unicode_display (c -> interfaces[i] -> name);
+ printf (" (%d)\n", c->interfaces[i] -> index);
+ }
+
+ printf ("fields:\n");
+ for (i=0; i < c -> fieldscount; i++) {
+ field_display (&(c -> fields[i]));
+ }
+
+ printf ("methods:\n");
+ for (i=0; i < c -> methodscount; i++) {
+ methodinfo *m = &(c->methods[i]);
+ if ( !(m->flags & ACC_STATIC))
+ printf ("vftblindex: %d ", m->vftblindex);
+
+ method_display ( m );
+
+ }
+
+ printf ("Virtual function table:\n");
+ for (i=0; i<c->vftbl->vftbllength; i++) {
+ printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
+ }
+
+}
+
+
+
+/*****************************************************************************/
+/******************* Funktionen fuer den Class-loader generell ***************/
+/*****************************************************************************/
+
+
+/********************* Funktion: loader_load **********************************
+
+ l"adt und linkt die ge"unschte Klasse und alle davon
+ referenzierten Klassen und Interfaces
+ Return: Einen Zeiger auf diese Klasse
+
+******************************************************************************/
+
+classinfo *loader_load (unicode *topname)
+{
+ classinfo *top;
+ classinfo *c;
+ long int starttime=0,stoptime=0;
+
+ intsDisable(); /* schani */
+
+ if (getloadingtime) starttime = getcputime();
+
+
+ top = class_get (topname);
+
+ while ( (c = list_first(&unloadedclasses)) ) {
+ class_load (c);
+ }
+
+ while ( (c = list_first(&unlinkedclasses)) ) {
+ class_link (c);
+ }
+
+
+ synchronize_caches ();
+
+
+
+ if (getloadingtime) {
+ stoptime = getcputime();
+ loadingtime += (stoptime-starttime);
+ }
+
+ intsRestore(); /* schani */
+
+ return top;
+}
+
+
+/******************* interne Funktion: loader_createarrayclass ****************
+
+ Erzeugt (und linkt) eine Klasse f"ur die Arrays.
+
+******************************************************************************/
+
+static classinfo *loader_createarrayclass ()
+{
+ classinfo *c;
+ c = class_get ( unicode_new_char ("The_Array_Class") );
+
+ list_remove (&unloadedclasses, c);
+ list_addlast (&unlinkedclasses, c);
+ c -> super = class_java_lang_Object;
+
+ class_link (c);
+ return c;
+}
+
+
+
+/********************** Funktion: loader_init *********************************
+
+ Initialisiert alle Listen und l"adt alle Klassen, die vom System
+ und vom Compiler direkt ben"otigt werden.
+
+******************************************************************************/
+
+void loader_init ()
+{
+ interfaceindex = 0;
+
+ list_init (&unloadedclasses, OFFSET(classinfo, listnode) );
+ list_init (&unlinkedclasses, OFFSET(classinfo, listnode) );
+ list_init (&linkedclasses, OFFSET(classinfo, listnode) );
+
+
+ class_java_lang_Object =
+ loader_load ( unicode_new_char ("java/lang/Object") );
+ class_java_lang_String =
+ loader_load ( unicode_new_char ("java/lang/String") );
+ class_java_lang_ClassCastException =
+ loader_load ( unicode_new_char ("java/lang/ClassCastException") );
+ class_java_lang_NullPointerException =
+ loader_load ( unicode_new_char ("java/lang/NullPointerException") );
+ class_java_lang_ArrayIndexOutOfBoundsException = loader_load (
+ unicode_new_char ("java/lang/ArrayIndexOutOfBoundsException") );
+ class_java_lang_NegativeArraySizeException = loader_load (
+ unicode_new_char ("java/lang/NegativeArraySizeException") );
+ class_java_lang_OutOfMemoryError = loader_load (
+ unicode_new_char ("java/lang/OutOfMemoryError") );
+ class_java_lang_ArrayStoreException =
+ loader_load ( unicode_new_char ("java/lang/ArrayStoreException") );
+ class_java_lang_ArithmeticException =
+ loader_load ( unicode_new_char ("java/lang/ArithmeticException") );
+ class_java_lang_ThreadDeath = /* schani */
+ loader_load ( unicode_new_char ("java/lang/ThreadDeath") );
+
+ class_array = loader_createarrayclass ();
+
+
+ proto_java_lang_ClassCastException =
+ builtin_new(class_java_lang_ClassCastException);
+ heap_addreference ( (void**) &proto_java_lang_ClassCastException);
+
+ proto_java_lang_NullPointerException =
+ builtin_new(class_java_lang_NullPointerException);
+ heap_addreference ( (void**) &proto_java_lang_NullPointerException);
+
+ proto_java_lang_ArrayIndexOutOfBoundsException =
+ builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
+ heap_addreference ( (void**) &proto_java_lang_ArrayIndexOutOfBoundsException);
+
+ proto_java_lang_NegativeArraySizeException =
+ builtin_new(class_java_lang_NegativeArraySizeException);
+ heap_addreference ( (void**) &proto_java_lang_NegativeArraySizeException);
+
+ proto_java_lang_OutOfMemoryError =
+ builtin_new(class_java_lang_OutOfMemoryError);
+ heap_addreference ( (void**) &proto_java_lang_OutOfMemoryError);
+
+ proto_java_lang_ArithmeticException =
+ builtin_new(class_java_lang_ArithmeticException);
+ heap_addreference ( (void**) &proto_java_lang_ArithmeticException);
+
+ proto_java_lang_ArrayStoreException =
+ builtin_new(class_java_lang_ArrayStoreException);
+ heap_addreference ( (void**) &proto_java_lang_ArrayStoreException);
+
+ proto_java_lang_ThreadDeath = /* schani */
+ builtin_new(class_java_lang_ThreadDeath);
+ heap_addreference ( (void**) &proto_java_lang_ThreadDeath);
+}
+
+
+
+
+/********************* Funktion: loader_initclasses ****************************
+
+ initialisiert alle geladenen aber noch nicht initialisierten Klassen
+
+******************************************************************************/
+
+void loader_initclasses ()
+{
+ classinfo *c;
+
+ intsDisable(); /* schani */
+
+ if (makeinitializations) {
+ c = list_first (&linkedclasses);
+ while (c) {
+ class_init (c);
+ c = list_next (&linkedclasses, c);
+ }
+ }
+
+ intsRestore(); /* schani */
+}
+
+
+
+/******************** Funktion: loader_close **********************************
+
+ gibt alle Resourcen wieder frei
+
+******************************************************************************/
+
+void loader_close ()
+{
+ classinfo *c;
+
+ while ( (c=list_first(&unloadedclasses)) ) {
+ list_remove (&unloadedclasses,c);
+ class_free (c);
+ }
+ while ( (c=list_first(&unlinkedclasses)) ) {
+ list_remove (&unlinkedclasses,c);
+ class_free (c);
+ }
+ while ( (c=list_first(&linkedclasses)) ) {
+ list_remove (&linkedclasses,c);
+ class_free (c);
+ }
+}
+
--- /dev/null
+/******************************* loader.h **************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Contains the prototypes for the class loader.
+
+ Author: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1997/11/14
+
+*******************************************************************************/
+
+
+/************************* program switches ***********************************/
+
+extern bool loadverbose; /* Debug-Meldungen beim Laden ausgeben */
+extern bool linkverbose;
+extern bool initverbose; /* Meldungen ausgeben, wenn Klasse
+ initialisiert wird */
+extern bool makeinitializations; /* Klassen automatisch initialisieren */
+
+extern bool getloadingtime;
+extern long int loadingtime; /* CPU-Zeit f"urs Laden der Klassen */
+
+extern list linkedclasses; /* Liste aller fertig gelinkten Klassen */
+
+
+/************************ prototypes ******************************************/
+
+void loader_init ();
+void loader_close ();
+
+classinfo *loader_load (unicode *topname);
+void loader_initclasses ();
+
+classinfo *class_get (unicode *name);
+voidptr class_getconstant (classinfo *class, u4 pos, u4 ctype);
+u4 class_constanttype (classinfo *class, u4 pos);
+
+fieldinfo *class_findfield (classinfo *c, unicode *name, unicode *desc);
+methodinfo *class_findmethod (classinfo *c, unicode *name, unicode *desc);
+
+methodinfo *class_resolvemethod (classinfo *c, unicode *name, unicode *dest);
+
+bool class_issubclass (classinfo *sub, classinfo *super);
+
+void class_init (classinfo *c);
+
+void class_showmethods (classinfo *c);
+void class_showconstantpool (classinfo *c);
+
--- /dev/null
+/******************************* main.c ****************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Enthaelt die Funktion main() und die Variablen fuer die
+ globalen Optionen.
+ Dieser Modul erledigt folgende Aufgaben:
+ - Bearbeiten der command-line-options
+ - Aufrufen aller Initialisierungsroutinen
+ - Aufrufen des Classloaders
+ - Starten der main - Methode
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+ Changes: Andi Krall EMAIL: cacao@complang.tuwien.ac.at
+ Mark Probst EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1997/10/29
+
+*******************************************************************************/
+
+#include "global.h"
+
+#include "tables.h"
+#include "compiler.h"
+#include "ncomp/ncomp.h"
+#include "loader.h"
+
+#include "asmpart.h"
+#include "builtin.h"
+#include "native.h"
+
+#include "threads/thread.h" /* schani */
+
+bool compileall = false;
+int newcompiler = true;
+bool verbose = false;
+
+#ifndef USE_THREADS
+void **stackbottom = 0;
+#endif
+
+
+/********************* interne Funktion: get_opt *****************************
+
+ liest die n"achste Option aus der Kommandozeile
+
+******************************************************************************/
+
+#define OPT_DONE -1
+#define OPT_ERROR 0
+#define OPT_IGNORE 1
+
+#define OPT_CLASSPATH 2
+#define OPT_D 3
+#define OPT_MS 4
+#define OPT_MX 5
+#define OPT_VERBOSE1 6
+#define OPT_VERBOSE 7
+#define OPT_VERBOSEGC 8
+#define OPT_VERBOSECALL 9
+#define OPT_IEEE 10
+#define OPT_SOFTNULL 11
+#define OPT_TIME 12
+#define OPT_STAT 13
+#define OPT_LOG 14
+#define OPT_CHECK 15
+#define OPT_LOAD 16
+#define OPT_METHOD 17
+#define OPT_SIGNATURE 18
+#define OPT_SHOW 19
+#define OPT_ALL 20
+#define OPT_OLD 21
+
+struct { char *name; bool arg; int value; } opts[] = {
+ { "classpath", true, OPT_CLASSPATH },
+ { "D", true, OPT_D },
+ { "ms", true, OPT_MS },
+ { "mx", true, OPT_MX },
+ { "noasyncgc", false, OPT_IGNORE },
+ { "noverify", false, OPT_IGNORE },
+ { "oss", true, OPT_IGNORE },
+ { "ss", true, OPT_IGNORE },
+ { "v", false, OPT_VERBOSE1 },
+ { "verbose", false, OPT_VERBOSE },
+ { "verbosegc", false, OPT_VERBOSEGC },
+ { "verbosecall", false, OPT_VERBOSECALL },
+ { "ieee", false, OPT_IEEE },
+ { "softnull", false, OPT_SOFTNULL },
+ { "time", false, OPT_TIME },
+ { "stat", false, OPT_STAT },
+ { "log", true, OPT_LOG },
+ { "c", true, OPT_CHECK },
+ { "l", false, OPT_LOAD },
+ { "m", true, OPT_METHOD },
+ { "sig", true, OPT_SIGNATURE },
+ { "s", true, OPT_SHOW },
+ { "all", false, OPT_ALL },
+ { "old", false, OPT_OLD },
+ { NULL, false, 0 }
+};
+
+static int opt_ind = 1;
+static char *opt_arg;
+
+static int get_opt (int argc, char **argv)
+{
+ char *a;
+ int i;
+
+ if (opt_ind >= argc) return OPT_DONE;
+
+ a = argv[opt_ind];
+ if (a[0] != '-') return OPT_DONE;
+
+ for (i=0; opts[i].name; i++) {
+ if (! opts[i].arg) {
+ if (strcmp(a+1, opts[i].name) == 0) { /* boolean option found */
+ opt_ind++;
+ return opts[i].value;
+ }
+ }
+ else {
+ if (strcmp(a+1, opts[i].name) == 0) { /* parameter option found */
+ opt_ind++;
+ if (opt_ind < argc) {
+ opt_arg = argv[opt_ind];
+ opt_ind++;
+ return opts[i].value;
+ }
+ return OPT_ERROR;
+ }
+ else {
+ size_t l = strlen(opts[i].name);
+ if (strlen(a+1) > l) {
+ if (memcmp (a+1, opts[i].name, l)==0) {
+ opt_ind++;
+ opt_arg = a+1+l;
+ return opts[i].value;
+ }
+ }
+ }
+ }
+ } /* end for */
+
+ return OPT_ERROR;
+}
+
+
+
+
+/******************** interne Funktion: print_usage ************************
+
+Gibt die richtige Aufrufsyntax des JavaVM-Compilers auf stdout aus.
+
+***************************************************************************/
+
+static void print_usage()
+{
+ printf ("USAGE: cacao [options] classname [program arguments\n");
+ printf ("Options:\n");
+ printf (" -classpath path ...... specify a path to look for classes\n");
+ printf (" -Dpropertyname=value . add an entry to the property list\n");
+ printf (" -mx maxmem[k|m] ...... specify the size for the heap\n");
+ printf (" -ms initmem[k|m] ..... specify the initial size for the heap\n");
+ printf (" -v ................... write state-information\n");
+ printf (" -verbose ............. write more information\n");
+ printf (" -verbosegc ........... write message for each GC\n");
+ printf (" -verbosecall ......... write message for each call\n");
+ printf (" -ieee ................ use ieee compliant arithmetic\n");
+ printf (" -softnull ............ use software nullpointer check\n");
+ printf (" -time ................ measure the runtime\n");
+ printf (" -stat ................ detailed compiler statistics\n");
+ printf (" -log logfile ......... specify a name for the logfile\n");
+ printf (" -c(heck) b(ounds...... don't check array bounds\n");
+ printf (" s(ync) ...... don't check for synchronization\n");
+ printf (" -l ................... don't start the class after loading\n");
+ printf (" -all ................. compile all methods, no execution\n");
+ printf (" -old ................. use old JIT compiler\n");
+ printf (" -m ................... compile only a specific method\n");
+ printf (" -sig ................. specify signature for a specific method\n");
+ printf (" -s(how)m(ethods) ..... show all methods&fields of a class\n");
+ printf (" c(onstants) ... show the constant pool\n");
+ printf (" a(ssembler) ... show disassembled listing\n");
+ printf (" s(tack) ....... show stack for every javaVM-command\n");
+ printf (" i(ntermediate). show intermediate representation\n");
+ printf (" u(nicode) ..... show the unicode - hash\n");
+}
+
+
+
+/***************************** Funktion: print_times *********************
+
+ gibt eine Aufstellung der verwendeten CPU-Zeit aus
+
+**************************************************************************/
+
+static void print_times()
+{
+ long int totaltime = getcputime();
+ long int runtime = totaltime - loadingtime - compilingtime;
+
+ sprintf (logtext, "Time for loading classes: %ld secs, %ld millis",
+ loadingtime / 1000000, (loadingtime % 1000000) / 1000);
+ dolog();
+ sprintf (logtext, "Time for compiling code: %ld secs, %ld millis",
+ compilingtime / 1000000, (compilingtime % 1000000) / 1000);
+ dolog();
+ sprintf (logtext, "Time for running program: %ld secs, %ld millis",
+ runtime / 1000000, (runtime % 1000000) / 1000);
+ dolog();
+ sprintf (logtext, "Total time: %ld secs, %ld millis",
+ totaltime / 1000000, (totaltime % 1000000) / 1000);
+ dolog();
+}
+
+
+
+
+
+
+/***************************** Funktion: print_stats *********************
+
+ outputs detailed compiler statistics
+
+**************************************************************************/
+
+static void print_stats()
+{
+ sprintf (logtext, "Number of JitCompiler Calls: %d", count_jit_calls);
+ dolog();
+ sprintf (logtext, "Number of compiled Methods: %d", count_methods);
+ dolog();
+ sprintf (logtext, "Number of max basic blocks per method: %d", count_max_basic_blocks);
+ dolog();
+ sprintf (logtext, "Number of compiled basic blocks: %d", count_basic_blocks);
+ dolog();
+ sprintf (logtext, "Number of max JavaVM-Instructions per method: %d", count_max_javainstr);
+ dolog();
+ sprintf (logtext, "Number of compiled JavaVM-Instructions: %d", count_javainstr);
+ dolog();
+ sprintf (logtext, "Size of compiled JavaVM-Instructions: %d(%d)", count_javacodesize,
+ count_javacodesize - count_methods * 18);
+ dolog();
+ sprintf (logtext, "Size of compiled Exception Tables: %d", count_javaexcsize);
+ dolog();
+ sprintf (logtext, "Value of extended instruction set var: %d", has_ext_instr_set);
+ dolog();
+ sprintf (logtext, "Number of Alpha-Instructions: %d", count_code_len >> 2);
+ dolog();
+ sprintf (logtext, "Number of Spills: %d", count_spills);
+ dolog();
+ sprintf (logtext, "Number of Activ Pseudocommands: %5d", count_pcmd_activ);
+ dolog();
+ sprintf (logtext, "Number of Drop Pseudocommands: %5d", count_pcmd_drop);
+ dolog();
+ sprintf (logtext, "Number of Const Pseudocommands: %5d (zero:%5d)", count_pcmd_load, count_pcmd_zero);
+ dolog();
+ sprintf (logtext, "Number of ConstAlu Pseudocommands: %5d (cmp: %5d, store:%5d)", count_pcmd_const_alu, count_pcmd_const_bra, count_pcmd_const_store);
+ dolog();
+ sprintf (logtext, "Number of Move Pseudocommands: %5d", count_pcmd_move);
+ dolog();
+ sprintf (logtext, "Number of Load Pseudocommands: %5d", count_load_instruction);
+ dolog();
+ sprintf (logtext, "Number of Store Pseudocommands: %5d (combined: %5d)", count_pcmd_store, count_pcmd_store - count_pcmd_store_comb);
+ dolog();
+ sprintf (logtext, "Number of OP Pseudocommands: %5d", count_pcmd_op);
+ dolog();
+ sprintf (logtext, "Number of DUP Pseudocommands: %5d", count_dup_instruction);
+ dolog();
+ sprintf (logtext, "Number of Mem Pseudocommands: %5d", count_pcmd_mem);
+ dolog();
+ sprintf (logtext, "Number of Method Pseudocommands: %5d", count_pcmd_met);
+ dolog();
+ sprintf (logtext, "Number of Branch Pseudocommands: %5d (rets:%5d, Xrets: %5d)",
+ count_pcmd_bra, count_pcmd_return, count_pcmd_returnx);
+ dolog();
+ sprintf (logtext, "Number of Table Pseudocommands: %5d", count_pcmd_table);
+ dolog();
+ sprintf (logtext, "Number of Useful Pseudocommands: %5d", count_pcmd_table +
+ count_pcmd_bra + count_pcmd_load + count_pcmd_mem + count_pcmd_op);
+ dolog();
+ sprintf (logtext, "Number of Null Pointer Checks: %5d", count_check_null);
+ dolog();
+ sprintf (logtext, "Number of Array Bound Checks: %5d", count_check_bound);
+ dolog();
+ sprintf (logtext, "Number of Try-Blocks: %d", count_tryblocks);
+ dolog();
+ sprintf (logtext, "Maximal count of stack elements: %d", count_max_new_stack);
+ dolog();
+ sprintf (logtext, "Upper bound of max stack elements: %d", count_upper_bound_new_stack);
+ dolog();
+ sprintf (logtext, "Distribution of stack sizes at block boundary");
+ dolog();
+ sprintf (logtext, " 0 1 2 3 4 5 6 7 8 9 >=10");
+ dolog();
+ sprintf (logtext, "%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d", count_block_stack[0],
+ count_block_stack[1],count_block_stack[2],count_block_stack[3],count_block_stack[4],
+ count_block_stack[5],count_block_stack[6],count_block_stack[7],count_block_stack[8],
+ count_block_stack[9],count_block_stack[10]);
+ dolog();
+ sprintf (logtext, "Distribution of store stack depth");
+ dolog();
+ sprintf (logtext, " 0 1 2 3 4 5 6 7 8 9 >=10");
+ dolog();
+ sprintf (logtext, "%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d", count_store_depth[0],
+ count_store_depth[1],count_store_depth[2],count_store_depth[3],count_store_depth[4],
+ count_store_depth[5],count_store_depth[6],count_store_depth[7],count_store_depth[8],
+ count_store_depth[9],count_store_depth[10]);
+ dolog();
+ sprintf (logtext, "Distribution of store creator chains first part");
+ dolog();
+ sprintf (logtext, " 0 1 2 3 4 5 6 7 8 9 ");
+ dolog();
+ sprintf (logtext, "%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d", count_store_length[0],
+ count_store_length[1],count_store_length[2],count_store_length[3],count_store_length[4],
+ count_store_length[5],count_store_length[6],count_store_length[7],count_store_length[8],
+ count_store_length[9]);
+ dolog();
+ sprintf (logtext, "Distribution of store creator chains second part");
+ dolog();
+ sprintf (logtext, " 10 11 12 13 14 15 16 17 18 19 >=20");
+ dolog();
+ sprintf (logtext, "%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d", count_store_length[10],
+ count_store_length[11],count_store_length[12],count_store_length[13],count_store_length[14],
+ count_store_length[15],count_store_length[16],count_store_length[17],count_store_length[18],
+ count_store_length[19],count_store_length[20]);
+ dolog();
+ sprintf (logtext, "Distribution of analysis iterations");
+ dolog();
+ sprintf (logtext, " 1 2 3 4 >=5");
+ dolog();
+ sprintf (logtext, "%5d%5d%5d%5d%5d", count_analyse_iterations[0],count_analyse_iterations[1],
+ count_analyse_iterations[2],count_analyse_iterations[3],count_analyse_iterations[4]);
+ dolog();
+ sprintf (logtext, "Distribution of basic blocks per method");
+ dolog();
+ sprintf (logtext, " <= 5 <=10 <=15 <=20 <=30 <=40 <=50 <=75 >75");
+ dolog();
+ sprintf (logtext, "%5d%5d%5d%5d%5d%5d%5d%5d%5d", count_method_bb_distribution[0],
+ count_method_bb_distribution[1],count_method_bb_distribution[2],count_method_bb_distribution[3],
+ count_method_bb_distribution[4],count_method_bb_distribution[5],count_method_bb_distribution[6],
+ count_method_bb_distribution[7],count_method_bb_distribution[8]);
+ dolog();
+ sprintf (logtext, "Distribution of basic block sizes");
+ dolog();
+ sprintf (logtext,
+ " 1 2 3 4 5 6 7 8 9 10 <13 <15 <17 <19 <21 <26 <31 >30");
+ dolog();
+ sprintf (logtext, "%3d%5d%5d%5d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d",
+ count_block_size_distribution[0], count_block_size_distribution[1], count_block_size_distribution[2],
+ count_block_size_distribution[3], count_block_size_distribution[4], count_block_size_distribution[5],
+ count_block_size_distribution[6], count_block_size_distribution[7], count_block_size_distribution[8],
+ count_block_size_distribution[9], count_block_size_distribution[10],count_block_size_distribution[11],
+ count_block_size_distribution[12],count_block_size_distribution[13],count_block_size_distribution[14],
+ count_block_size_distribution[15],count_block_size_distribution[16],count_block_size_distribution[17]);
+ dolog();
+ sprintf (logtext, "Size of Code Area (Kb): %10.3f", (float) count_code_len / 1024);
+ dolog();
+ sprintf (logtext, "Size of data Area (Kb): %10.3f", (float) count_data_len / 1024);
+ dolog();
+ sprintf (logtext, "Size of Class Infos (Kb):%10.3f", (float) (count_class_infos) / 1024);
+ dolog();
+ sprintf (logtext, "Size of Const Pool (Kb): %10.3f", (float) (count_const_pool_len + count_unicode_len) / 1024);
+ dolog();
+ sprintf (logtext, "Size of Vftbl (Kb): %10.3f", (float) count_vftbl_len / 1024);
+ dolog();
+ sprintf (logtext, "Size of comp stub (Kb): %10.3f", (float) count_cstub_len / 1024);
+ dolog();
+ sprintf (logtext, "Size of native stub (Kb):%10.3f", (float) count_nstub_len / 1024);
+ dolog();
+ sprintf (logtext, "Size of Unicode (Kb): %10.3f", (float) count_unicode_len / 1024);
+ dolog();
+ sprintf (logtext, "Size of VMCode (Kb): %10.3f(%d)", (float) count_vmcode_len / 1024,
+ count_vmcode_len - 18 * count_all_methods);
+ dolog();
+ sprintf (logtext, "Size of ExTable (Kb): %10.3f", (float) count_extable_len / 1024);
+ dolog();
+ sprintf (logtext, "Number of loaded Methods: %d\n\n", count_all_methods);
+ dolog();
+}
+
+
+/********** Funktion: class_compile_methods (nur f"ur Debug-Zwecke) ********/
+
+void class_compile_methods ()
+{
+ int i;
+ classinfo *c;
+ methodinfo *m;
+
+ c = list_first (&linkedclasses);
+ while (c) {
+ for (i = 0; i < c -> methodscount; i++) {
+ m = &(c->methods[i]);
+ if (m->jcode) {
+ if (newcompiler)
+ (void) new_compile(m);
+ else
+ (void) compiler_compile(m);
+ }
+ }
+ c = list_next (&linkedclasses, c);
+ }
+}
+
+
+/************************** Funktion: main *******************************
+
+ Das Hauptprogramm.
+ Wird vom System zu Programstart aufgerufen (eh klar).
+
+**************************************************************************/
+
+
+int main(int argc, char **argv)
+{
+ s4 i,j;
+ char *cp;
+ classinfo *topclass;
+ java_objectheader *exceptionptr;
+ void *dummy;
+
+
+ /********** interne (nur fuer main relevante Optionen) **************/
+
+ char logfilename[200] = "";
+ u4 heapsize = 16000000;
+ u4 heapstartsize = 200000;
+ char classpath[500] = ".:/usr/local/lib/java/classes";
+ bool showmethods = false;
+ bool showconstantpool = false;
+ bool showunicode = false;
+ bool startit = true;
+ char *specificmethodname = NULL;
+ char *specificsignature = NULL;
+
+#ifndef USE_THREADS
+ stackbottom = &dummy;
+#endif
+
+
+ /************ Infos aus der Environment lesen ************************/
+
+ cp = getenv ("CLASSPATH");
+ if (cp) {
+ strcpy (classpath, cp);
+ }
+
+ /***************** Interpretieren der Kommandozeile *****************/
+
+ checknull = false;
+ checkfloats = false;
+
+ while ( (i = get_opt(argc,argv)) != OPT_DONE) {
+
+ switch (i) {
+ case OPT_IGNORE: break;
+
+ case OPT_CLASSPATH:
+ strcpy (classpath + strlen(classpath), ":");
+ strcpy (classpath + strlen(classpath), opt_arg);
+ break;
+
+ case OPT_D:
+ {
+ int n,l=strlen(opt_arg);
+ for (n=0; n<l; n++) {
+ if (opt_arg[n]=='=') {
+ opt_arg[n] = '\0';
+ attach_property (opt_arg, opt_arg+n+1);
+ goto didit;
+ }
+ }
+ print_usage();
+ exit(10);
+
+ didit: ;
+ }
+ break;
+
+ case OPT_MS:
+ case OPT_MX:
+ if (opt_arg[strlen(opt_arg)-1] == 'k') {
+ j = 1024 * atoi(opt_arg);
+ }
+ else if (opt_arg[strlen(opt_arg)-1] == 'm') {
+ j = 1024 * 1024 * atoi(opt_arg);
+ }
+ else j = atoi(opt_arg);
+
+ if (i==OPT_MX) heapsize = j;
+ else heapstartsize = j;
+ break;
+
+ case OPT_VERBOSE1:
+ verbose = true;
+ break;
+
+ case OPT_VERBOSE:
+ verbose = true;
+ loadverbose = true;
+ initverbose = true;
+ compileverbose = true;
+ break;
+
+ case OPT_VERBOSEGC:
+ collectverbose = true;
+ break;
+
+ case OPT_VERBOSECALL:
+ runverbose = true;
+ break;
+
+ case OPT_IEEE:
+ checkfloats = true;
+ break;
+
+ case OPT_SOFTNULL:
+ checknull = true;
+ break;
+
+ case OPT_TIME:
+ getcompilingtime = true;
+ getloadingtime = true;
+ break;
+
+ case OPT_STAT:
+ statistics = true;
+ break;
+
+ case OPT_LOG:
+ strcpy (logfilename, opt_arg);
+ break;
+
+
+ case OPT_CHECK:
+ for (j=0; j<strlen(opt_arg); j++) {
+ switch (opt_arg[j]) {
+ case 'b': checkbounds=false; break;
+ case 's': checksync=false; break;
+ default: print_usage();
+ exit(10);
+ }
+ }
+ break;
+
+ case OPT_LOAD:
+ startit = false;
+ makeinitializations = false;
+ break;
+
+ case OPT_METHOD:
+ startit = false;
+ specificmethodname = opt_arg;
+ makeinitializations = false;
+ break;
+
+ case OPT_SIGNATURE:
+ specificsignature = opt_arg;
+ break;
+
+ case OPT_ALL:
+ compileall = true;
+ startit = false;
+ makeinitializations = false;
+ break;
+
+ case OPT_OLD:
+ newcompiler = false;
+ checknull = true;
+ break;
+
+ case OPT_SHOW: /* Anzeigeoptionen */
+ for (j=0; j<strlen(opt_arg); j++) {
+ switch (opt_arg[j]) {
+ case 'm': showmethods=true; break;
+ case 'c': showconstantpool=true; break;
+ case 'a': showdisassemble=true; compileverbose=true; break;
+ case 's': showstack=true; compileverbose=true; break;
+ case 'i': showintermediate=true; compileverbose=true; break;
+ case 'u': showunicode=true; break;
+ default: print_usage();
+ exit(10);
+ }
+ }
+ break;
+
+ default:
+ print_usage();
+ exit(10);
+ }
+
+
+ }
+
+
+ if (opt_ind >= argc) {
+ print_usage ();
+ exit(10);
+ }
+
+
+ /**************************** Programmstart *****************************/
+
+ log_init (logfilename);
+ if (verbose) {
+ log_text (
+ "CACAO started -------------------------------------------------------");
+ }
+
+ suck_init (classpath);
+ native_setclasspath (classpath);
+
+ unicode_init();
+ heap_init(heapsize, heapstartsize, &dummy);
+ loader_init();
+ compiler_init();
+ ncomp_init();
+
+ native_loadclasses ();
+
+
+ /*********************** JAVA-Klassen laden ***************************/
+
+ cp = argv[opt_ind++];
+ for (i=strlen(cp)-1; i>=0; i--) { /* Punkte im Klassennamen */
+ if (cp[i]=='.') cp[i]='/'; /* auf slashes umbauen */
+ }
+
+ topclass = loader_load ( unicode_new_char (cp) );
+
+ gc_init();
+
+#ifdef USE_THREADS
+ initThreads((u1*)&dummy); /* schani */
+#endif
+
+ /************************* Arbeitsroutinen starten ********************/
+
+ if (startit) {
+ methodinfo *mainmethod;
+ java_objectarray *a;
+
+ mainmethod = class_findmethod (
+ topclass,
+ unicode_new_char ("main"),
+ unicode_new_char ("([Ljava/lang/String;)V")
+ );
+ if (!mainmethod) panic ("Can not find method 'void main(String[])'");
+ if ((mainmethod->flags & ACC_STATIC) != ACC_STATIC) panic ("main is not static!");
+
+ a = builtin_anewarray (argc - opt_ind, class_java_lang_String);
+ for (i=opt_ind; i<argc; i++) {
+ a->data[i-opt_ind] = javastring_new (unicode_new_char (argv[i]) );
+ }
+ exceptionptr = asm_calljavamethod (mainmethod, a, NULL,NULL,NULL );
+
+ if (exceptionptr) {
+ printf ("#### Program has thrown: ");
+ unicode_display (exceptionptr->vftbl->class->name);
+ printf ("\n");
+ }
+
+/* killThread(currentThread); */
+
+ }
+
+ /************* Auf Wunsch alle Methode "ubersetzen ********************/
+
+ if (compileall) {
+ class_compile_methods();
+ }
+
+
+ /******** Auf Wunsch eine spezielle Methode "ubersetzen ***************/
+
+ if (specificmethodname) {
+ methodinfo *m;
+ if (specificsignature)
+ m = class_findmethod(topclass,
+ unicode_new_char(specificmethodname),
+ unicode_new_char(specificsignature));
+ else
+ m = class_findmethod(topclass,
+ unicode_new_char(specificmethodname), NULL);
+ if (!m) panic ("Specific method not found");
+ if (newcompiler)
+ (void) new_compile(m);
+ else
+ (void) compiler_compile(m);
+ }
+
+ /********************* Debug-Tabellen ausgeben ************************/
+
+ if (showmethods) class_showmethods (topclass);
+ if (showconstantpool) class_showconstantpool (topclass);
+ if (showunicode) unicode_show ();
+
+
+
+ /************************ Freigeben aller Resourcen *******************/
+
+ compiler_close ();
+ loader_close ();
+ heap_close ();
+ unicode_close ( literalstring_free );
+
+
+ /* Endemeldung ausgeben und mit entsprechendem exit-Status terminieren */
+
+ if (verbose || getcompilingtime || statistics) {
+ log_text ("CACAO terminated");
+ if (statistics)
+ print_stats ();
+ if (getcompilingtime)
+ print_times ();
+ mem_usagelog(1);
+ }
+
+ exit(0);
+ return 1;
+}
+
+
+
+/************************************ SHUTDOWN-Funktion *********************************
+
+ Terminiert das System augenblicklich, ohne den Speicher
+ explizit freizugeben (eigentlich nur f"ur abnorme
+ Programmterminierung)
+
+*****************************************************************************************/
+
+void cacao_shutdown(s4 status)
+{
+ if (verbose || getcompilingtime || statistics) {
+ log_text ("CACAO terminated by shutdown");
+ if (statistics)
+ print_stats ();
+ if (getcompilingtime)
+ print_times ();
+ mem_usagelog(0);
+ sprintf (logtext, "Exit status: %d\n", (int) status);
+ dolog();
+ }
+
+ exit(status);
+}
--- /dev/null
+/****************************** nat/io.c ***************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Contains the native functions for class java.io.
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+ Mark Probst EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1997/10/22
+
+*******************************************************************************/
+
+#include <fcntl.h>
+#include <dirent.h>
+#include <sys/types.h>
+#ifdef _OSF_SOURCE
+#include <sys/mode.h>
+#endif
+#include <sys/stat.h>
+
+#include "../threads/threadio.h" /* schani */
+
+/*
+ * io is performed through the threaded... functions, since io operations may
+ * block and the corresponding thread must, in this case, be suspended.
+ *
+ * schani
+ */
+
+/********************* java.io.FileDescriptor ********************************/
+
+s4 java_io_FileDescriptor_valid (struct java_io_FileDescriptor* this)
+{
+ if (this->fd >= 0) return 1;
+ return 0;
+}
+
+struct java_io_FileDescriptor* java_io_FileDescriptor_initSystemFD
+ (struct java_io_FileDescriptor* fd, s4 handle)
+{
+ switch (handle) {
+ case 0: fd -> fd = fileno(stdin);
+ break;
+ case 1: fd -> fd = fileno(stdout);
+ break;
+ case 2: fd -> fd = fileno(stderr);
+ break;
+ default: panic ("Invalid file descriptor number");
+ }
+
+ threadedFileDescriptor(fd->fd);
+
+ return fd;
+}
+
+
+/************************* java.io.FileInputStream ***************************/
+
+
+void java_io_FileInputStream_open
+ (struct java_io_FileInputStream* this, struct java_lang_String* name)
+{
+ s4 fd;
+ char *fname = javastring_tochar ((java_objectheader*)name);
+
+ if (!fname) goto fail;
+
+ fd = open (fname, O_RDONLY, 0);
+ if (fd<0) goto fail;
+
+ threadedFileDescriptor(fd);
+
+ this->fd->fd = fd;
+ return;
+
+ fail:
+ exceptionptr = native_new_and_init (class_java_io_IOException);
+ return;
+}
+
+s4 java_io_FileInputStream_read (struct java_io_FileInputStream* this)
+{
+ s4 r;
+ u1 buffer[1];
+ r = threadedRead (this->fd->fd, (char *) buffer, 1);
+
+ if (r>0) return buffer[0];
+ if (r==0) return -1;
+
+ exceptionptr = native_new_and_init (class_java_io_IOException);
+ return 0;
+}
+
+
+s4 java_io_FileInputStream_readBytes (struct java_io_FileInputStream* this,
+ java_bytearray* buffer, s4 start, s4 len)
+{
+ s4 ret = threadedRead (this->fd->fd, (char *) buffer->data+start, len);
+ if (ret>0) return ret;
+ if (ret==0) return -1;
+
+ exceptionptr = native_new_and_init (class_java_io_IOException);
+ return 0;
+}
+
+
+s8 java_io_FileInputStream_skip
+ (struct java_io_FileInputStream* this, s8 numbytes)
+{
+ s4 ret = lseek (this->fd->fd, builtin_l2i(numbytes), SEEK_CUR);
+ if (ret>0) return builtin_i2l(ret);
+ if (ret==0) return builtin_i2l(-1);
+
+ exceptionptr = native_new_and_init (class_java_io_IOException);
+ return builtin_i2l(0);
+}
+
+s4 java_io_FileInputStream_available (struct java_io_FileInputStream* this)
+{
+ struct stat buffer;
+ s4 r1,r2;
+
+ r1 = fstat (this->fd->fd, &buffer);
+ r2 = lseek(this->fd->fd, 0, SEEK_CUR);
+
+ if ( (r1 >= 0) && (r2 >= 0) )
+ return buffer.st_size - r2;
+
+ exceptionptr = native_new_and_init (class_java_io_IOException);
+ return 0;
+}
+
+void java_io_FileInputStream_close (struct java_io_FileInputStream* this)
+{
+ if (this->fd->fd >= 0) {
+ s4 r = close (this->fd->fd);
+ this->fd->fd = -1;
+ if (r < 0)
+ exceptionptr = native_new_and_init (class_java_io_IOException);
+ }
+}
+
+
+
+
+
+/*************************** java.io.FileOutputStream ************************/
+
+
+void java_io_FileOutputStream_open (struct java_io_FileOutputStream* this,
+ struct java_lang_String* name)
+{
+ s4 fd;
+ char *fname = javastring_tochar ((java_objectheader*)name);
+ if (!fname) goto fail;
+
+ fd = creat (fname, 0666);
+ if (fd<0) goto fail;
+
+ threadedFileDescriptor(fd);
+
+ this->fd->fd = fd;
+ return;
+
+ fail:
+ exceptionptr = native_new_and_init (class_java_io_IOException);
+ return;
+}
+
+
+void java_io_FileOutputStream_write
+ (struct java_io_FileOutputStream* this, s4 byte)
+{
+ u1 buffer[1];
+ s4 l;
+
+ buffer[0] = byte;
+ l = threadedWrite (this->fd->fd, (char *) buffer, 1);
+
+ if (l<1) {
+ exceptionptr = native_new_and_init (class_java_io_IOException);
+ }
+}
+
+void java_io_FileOutputStream_writeBytes (struct java_io_FileOutputStream* this,
+ java_bytearray* buffer, s4 start, s4 len)
+{
+ s4 o;
+
+ if (len == 0)
+ return;
+ o = threadedWrite (this->fd->fd, (char *) buffer->data+start, len);
+ if (o!=len)
+ exceptionptr = native_new_and_init (class_java_io_IOException);
+}
+
+void java_io_FileOutputStream_close (struct java_io_FileOutputStream* this)
+{
+ if (this->fd->fd >= 0) {
+ s4 r = close (this->fd->fd);
+ this->fd->fd = -1;
+ if (r<0)
+ exceptionptr = native_new_and_init (class_java_io_IOException);
+ }
+}
+
+
+
+/************************** java.io.File **************************************/
+
+s4 java_io_File_exists0 (struct java_io_File* this)
+{
+ struct stat buffer;
+ char *path;
+ int err;
+
+ path = javastring_tochar( (java_objectheader*) (this->path));
+
+ err = stat (path, &buffer);
+ if (err==0) return 1;
+ return 0;
+}
+
+s4 java_io_File_canWrite0 (struct java_io_File* this)
+{
+ int err;
+ err = access (javastring_tochar( (java_objectheader*) (this->path)), W_OK);
+ if (err==0) return 1;
+ return 0;
+}
+
+s4 java_io_File_canRead0 (struct java_io_File* this)
+{
+ int err;
+ err = access (javastring_tochar( (java_objectheader*) (this->path)), R_OK);
+ if (err==0) return 1;
+ return 0;
+}
+
+s4 java_io_File_isFile0 (struct java_io_File* this)
+{
+ struct stat buffer;
+ char *path;
+ int err;
+
+ path = javastring_tochar( (java_objectheader*) (this->path));
+
+ err = stat (path, &buffer);
+ if (err!=0) return 0;
+ if (S_ISREG(buffer.st_mode)) return 1;
+ return 0;
+}
+
+s4 java_io_File_isDirectory0 (struct java_io_File* this)
+{
+ struct stat buffer;
+ char *path;
+ int err;
+
+ path = javastring_tochar( (java_objectheader*) (this->path));
+
+ err = stat (path, &buffer);
+ if (err!=0) return 0;
+ if (S_ISDIR(buffer.st_mode)) return 1;
+ return 0;
+}
+
+s8 java_io_File_lastModified0 (struct java_io_File* this)
+{
+ struct stat buffer;
+ int err;
+ err = stat (javastring_tochar( (java_objectheader*) (this->path)), &buffer);
+ if (err!=0) return builtin_i2l(0);
+ return builtin_lmul (builtin_i2l(buffer.st_mtime), builtin_i2l(1000) );
+}
+
+s8 java_io_File_length0 (struct java_io_File* this)
+{
+ struct stat buffer;
+ int err;
+ err = stat (javastring_tochar( (java_objectheader*) (this->path)), &buffer);
+ if (err!=0) return builtin_i2l(0);
+ return builtin_i2l(buffer.st_size);
+}
+
+s4 java_io_File_mkdir0 (struct java_io_File* this)
+{
+ char *name = javastring_tochar ( (java_objectheader*) (this->path) );
+ int err = mkdir (name, 0777);
+ if (err==0) return 1;
+ return 0;
+}
+
+s4 java_io_File_renameTo0 (struct java_io_File* this, struct java_io_File* new)
+{
+#define MAXPATHLEN 200
+ char newname[MAXPATHLEN];
+ char *n = javastring_tochar ( (java_objectheader*) (new->path) );
+ int err;
+
+ if (strlen(n)>=MAXPATHLEN) return 0;
+ strcpy (newname, n);
+ n = javastring_tochar ( (java_objectheader*) (this->path) );
+ err = rename (n, newname);
+ if (err==0) return 1;
+ return 0;
+}
+
+s4 java_io_File_delete0 (struct java_io_File* this)
+{
+ int err;
+ err = remove (javastring_tochar ( (java_objectheader*) (this->path) ) );
+ if (err==0) return 1;
+ return 0;
+}
+
+java_objectarray* java_io_File_list0 (struct java_io_File* this)
+{
+ char *name;
+ DIR *d;
+ int i,len, namlen;
+ java_objectarray *a;
+ struct dirent *ent;
+ struct java_lang_String *n;
+ char entbuffer[257];
+
+ name = javastring_tochar ( (java_objectheader*) (this->path) );
+ d = opendir(name);
+ if (!d) return NULL;
+
+ len=0;
+ while (readdir(d) != NULL) len++;
+ rewinddir (d);
+
+ a = builtin_anewarray (len, class_java_lang_String);
+ if (!a) {
+ closedir(d);
+ return NULL;
+ }
+
+ for (i=0; i<len; i++) {
+ if ( (ent = readdir(d)) != NULL) {
+ namlen = strlen(ent->d_name);
+ memcpy (entbuffer, ent->d_name, namlen);
+ entbuffer[namlen] = '\0';
+
+ n = (struct java_lang_String*)
+ javastring_new_char (entbuffer);
+
+ a -> data[i] = (java_objectheader*) n;
+ }
+ }
+
+
+ closedir(d);
+ return a;
+}
+
+s4 java_io_File_isAbsolute (struct java_io_File* this)
+{
+ char *name = javastring_tochar ( (java_objectheader*) (this->path) );
+ if (name[0] == '/') return 1;
+ return 0;
+}
+
+
+
+
+/********************** java.io.RandomAccessFile *****************************/
+
+void java_io_RandomAccessFile_open (struct java_io_RandomAccessFile* this,
+ struct java_lang_String* name, s4 writeable)
+{
+ s4 fd;
+ char *fname = javastring_tochar ((java_objectheader*)name);
+
+ if (writeable) fd = open (fname, O_RDWR, 0);
+ else fd = open (fname, O_RDONLY, 0);
+ if (fd==-1) goto fail;
+
+ threadedFileDescriptor(fd);
+
+ this->fd->fd = fd;
+ return;
+
+ fail:
+ exceptionptr = native_new_and_init (class_java_io_IOException);
+ return;
+}
+
+s4 java_io_RandomAccessFile_read (struct java_io_RandomAccessFile* this)
+{
+ s4 r;
+ u1 buffer[1];
+ r = threadedRead (this->fd->fd, (char *) buffer, 1);
+ if (r>0) return buffer[1];
+ if (r==0) return -1;
+ exceptionptr = native_new_and_init (class_java_io_IOException);
+ return 0;
+}
+
+s4 java_io_RandomAccessFile_readBytes (struct java_io_RandomAccessFile* this,
+ java_bytearray* buffer, s4 start, s4 len)
+{
+ s4 r = threadedRead (this->fd->fd, (char *) buffer->data+start, len);
+ if (r>0) return r;
+ if (r==0) return -1;
+ exceptionptr = native_new_and_init (class_java_io_IOException);
+ return 0;
+}
+
+void java_io_RandomAccessFile_write
+ (struct java_io_RandomAccessFile* this, s4 byte)
+{
+ u1 buffer[1];
+ int r;
+ buffer[1] = byte;
+ r = write (this->fd->fd, buffer, 1);
+ if (r<0) {
+ exceptionptr = native_new_and_init (class_java_io_IOException);
+ }
+}
+
+void java_io_RandomAccessFile_writeBytes (struct java_io_RandomAccessFile* this,
+ java_bytearray* buffer, s4 start, s4 len)
+{
+ s4 o;
+ if (len == 0)
+ return;
+ o = threadedWrite (this->fd->fd, (char *) buffer->data+start, len);
+ if (o!=len) exceptionptr = native_new_and_init (class_java_io_IOException);
+}
+
+s8 java_io_RandomAccessFile_getFilePointer
+ (struct java_io_RandomAccessFile* this)
+{
+ s4 p = lseek (this->fd->fd, 0, SEEK_CUR);
+ if (p>=0) return builtin_i2l(p);
+ exceptionptr = native_new_and_init (class_java_io_IOException);
+ return builtin_i2l(0);
+}
+
+void java_io_RandomAccessFile_seek
+ (struct java_io_RandomAccessFile* this, s8 offset)
+{
+ s4 p = lseek (this->fd->fd, builtin_l2i(offset), SEEK_SET);
+ if (p<0) {
+ exceptionptr = native_new_and_init (class_java_io_IOException);
+ }
+}
+
+s8 java_io_RandomAccessFile_length (struct java_io_RandomAccessFile* this)
+{
+ struct stat buffer;
+ s4 r = fstat(this->fd->fd, &buffer);
+ if (r>=0) return builtin_i2l(buffer.st_size);
+ exceptionptr = native_new_and_init (class_java_io_IOException);
+ return builtin_i2l(0);
+}
+
+void java_io_RandomAccessFile_close (struct java_io_RandomAccessFile* this)
+{
+ if (this->fd->fd >= 0) {
+ s4 r = close (this->fd->fd);
+ this->fd->fd = -1;
+ if (r<0)
+ exceptionptr = native_new_and_init (class_java_io_IOException);
+ }
+}
+
--- /dev/null
+/* -*- mode: c; tab-width: 4; c-basic-offset: 4 -*- */
+/****************************** nat/lang.c *************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Contains the native functions for class java.lang.
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+ Mark Probst EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1997/06/10
+
+*******************************************************************************/
+
+#include <math.h>
+#include <assert.h>
+#include <sys/time.h>
+
+#include "../threads/thread.h" /* schani */
+#include "../threads/locks.h"
+
+static void use_class_as_object (classinfo *c)
+{
+ c->header.vftbl = class_java_lang_Class -> vftbl;
+}
+
+
+/************************************** java.lang.Object ***********************************/
+
+struct java_lang_Class* java_lang_Object_getClass (struct java_lang_Object* this)
+{
+ classinfo *c = this->header.vftbl -> class;
+ use_class_as_object (c);
+ return (java_lang_Class*) c;
+}
+
+s4 java_lang_Object_hashCode (struct java_lang_Object* this)
+{
+ return ((char*) this) - ((char*) 0);
+}
+
+
+struct java_lang_Object* java_lang_Object_clone (struct java_lang_Object* this)
+{
+ classinfo *c;
+ java_lang_Object *new;
+
+ if (((java_objectheader*)this)->vftbl->class == class_array)
+ {
+ static u4 multiplicator[10];
+ static int is_initialized = 0;
+
+ java_arrayheader *array = (java_arrayheader*)this;
+ u4 size;
+
+ if (!is_initialized)
+ {
+ multiplicator[ARRAYTYPE_INT] = sizeof(s4);
+ multiplicator[ARRAYTYPE_LONG] = sizeof(s8);
+ multiplicator[ARRAYTYPE_FLOAT] = sizeof(float);
+ multiplicator[ARRAYTYPE_DOUBLE] = sizeof(double);
+ multiplicator[ARRAYTYPE_BYTE] = sizeof(s1);
+ multiplicator[ARRAYTYPE_CHAR] = sizeof(u2);
+ multiplicator[ARRAYTYPE_SHORT] = sizeof(s2);
+ multiplicator[ARRAYTYPE_BOOLEAN] = sizeof(u1);
+ multiplicator[ARRAYTYPE_OBJECT] = sizeof(void*);
+ multiplicator[ARRAYTYPE_ARRAY] = sizeof(void*);
+ is_initialized = 1;
+ }
+
+ size = sizeof(java_arrayheader)
+ + array->size * multiplicator[array->arraytype];
+
+ new = (java_lang_Object*)heap_allocate(size, false, NULL);
+ memcpy(new, this, size);
+
+ return new;
+ }
+ else
+ {
+ if (! builtin_instanceof ((java_objectheader*) this, class_java_lang_Cloneable) ) {
+ exceptionptr = native_new_and_init (class_java_lang_CloneNotSupportedException);
+ return NULL;
+ }
+
+ c = this -> header.vftbl -> class;
+ new = (java_lang_Object*) builtin_new (c);
+ if (!new) {
+ exceptionptr = proto_java_lang_OutOfMemoryError;
+ return NULL;
+ }
+
+ memcpy (new, this, c->instancesize);
+ return new;
+ }
+}
+
+void java_lang_Object_notify (struct java_lang_Object* this)
+{
+ if (runverbose)
+ log_text ("java_lang_Object_notify called");
+
+#ifdef USE_THREADS
+ signal_cond_for_object(&this->header);
+#endif
+}
+
+void java_lang_Object_notifyAll (struct java_lang_Object* this)
+{
+ if (runverbose)
+ log_text ("java_lang_Object_notifyAll called");
+
+#ifdef USE_THREADS
+ broadcast_cond_for_object(&this->header);
+#endif
+}
+
+void java_lang_Object_wait (struct java_lang_Object* this, s8 time)
+{
+ if (runverbose)
+ log_text ("java_lang_Object_wait called");
+
+#ifdef USE_THREADS
+ wait_cond_for_object(&this->header, time);
+#endif
+}
+
+
+/********************************** java.lang.Class **************************************/
+
+
+struct java_lang_Class* java_lang_Class_forName (struct java_lang_String* s)
+{
+ java_chararray *a,*b;
+ u4 i;
+ unicode *u;
+ classinfo *c;
+
+ if (!s) return NULL;
+ if (!(a = s->value) ) return NULL;
+ b = builtin_newarray_char (s->count);
+ if (!b) return NULL;
+ for (i=0; i<s->count; i++) {
+ if (a->data[s->offset+i]=='.') b->data[i] = '/';
+ else b->data[i] = a->data[s->offset+i];
+ }
+ u = unicode_new_u2 (b->data, b->header.size);
+ c = u->class;
+ if (!c) {
+ c = loader_load (u);
+ loader_initclasses ();
+
+ if (!c) {
+ exceptionptr =
+ native_new_and_init (class_java_lang_ClassNotFoundException);
+
+ return NULL;
+ }
+
+ }
+
+ use_class_as_object (c);
+ return (java_lang_Class*) c;
+}
+
+struct java_lang_Object* java_lang_Class_newInstance (struct java_lang_Class* this)
+{
+ java_objectheader *o = native_new_and_init ((classinfo*) this);
+ if (!o) {
+ exceptionptr =
+ native_new_and_init (class_java_lang_InstantiationException);
+ }
+ return (java_lang_Object*) o;
+}
+
+struct java_lang_String* java_lang_Class_getName (struct java_lang_Class* this)
+{
+ u4 i;
+ classinfo *c = (classinfo*) this;
+ java_lang_String *s = (java_lang_String*) javastring_new(c->name);
+
+ if (!s) return NULL;
+
+ for (i=0; i<s->value->header.size; i++) {
+ if (s->value->data[i] == '/') s->value->data[i] = '.';
+ }
+
+ return s;
+}
+
+struct java_lang_Class* java_lang_Class_getSuperclass (struct java_lang_Class* this)
+{
+ classinfo *c = ((classinfo*) this) -> super;
+ if (!c) return NULL;
+
+ use_class_as_object (c);
+ return (java_lang_Class*) c;
+}
+
+java_objectarray* java_lang_Class_getInterfaces (struct java_lang_Class* this)
+{
+ classinfo *c = (classinfo*) this;
+ u4 i;
+ java_objectarray *a = builtin_anewarray (c->interfacescount, class_java_lang_Class);
+ if (!a) return NULL;
+ for (i=0; i<c->interfacescount; i++) {
+ use_class_as_object (c->interfaces[i]);
+
+ a->data[i] = (java_objectheader*) c->interfaces[i];
+ }
+ return a;
+}
+
+struct java_lang_ClassLoader* java_lang_Class_getClassLoader (struct java_lang_Class* this)
+{
+ log_text ("java_lang_Class_getClassLoader called");
+ return NULL;
+}
+
+s4 java_lang_Class_isInterface (struct java_lang_Class* this)
+{
+ classinfo *c = (classinfo*) this;
+ if (c->flags & ACC_INTERFACE) return 1;
+ return 0;
+}
+
+/************************************ java.lang.ClassLoader *******************************/
+
+
+struct java_lang_Class* java_lang_ClassLoader_defineClass (struct java_lang_ClassLoader* this, java_bytearray* par1, s4 par2, s4 par3)
+{
+ log_text ("java_lang_ClassLoader_defineClass called");
+ return NULL;
+}
+void java_lang_ClassLoader_resolveClass (struct java_lang_ClassLoader* this, struct java_lang_Class* par1)
+{
+ log_text ("java_lang_ClassLoader_resolveClass called");
+}
+struct java_lang_Class* java_lang_ClassLoader_findSystemClass (struct java_lang_ClassLoader* this, struct java_lang_String* par1)
+{
+ log_text ("java_lang_ClassLoader_findSystemClass called");
+ return NULL;
+}
+void java_lang_ClassLoader_init (struct java_lang_ClassLoader* this)
+{
+ log_text ("java_lang_ClassLoader_init called");
+}
+struct java_lang_Class* java_lang_ClassLoader_findSystemClass0 (struct java_lang_ClassLoader* this, struct java_lang_String* par1)
+{
+ log_text ("java_lang_ClassLoader_findSystemClass0 called");
+ return NULL;
+}
+
+struct java_lang_Class* java_lang_ClassLoader_defineClass0 (struct java_lang_ClassLoader* this, java_bytearray* par1, s4 par2, s4 par3)
+{
+ log_text ("java_lang_ClassLoader_defineClass0 called");
+ return NULL;
+}
+void java_lang_ClassLoader_resolveClass0 (struct java_lang_ClassLoader* this, struct java_lang_Class* par1)
+{
+ log_text ("java_lang_ClassLoader_resolveClass0 called");
+ return;
+}
+
+/************************************** java.lang.Compiler *******************************/
+
+void java_lang_Compiler_initialize ()
+{
+ log_text ("java_lang_Compiler_initialize called");
+}
+s4 java_lang_Compiler_compileClass (struct java_lang_Class* par1)
+{
+ log_text ("java_lang_Compiler_compileClass called");
+ return 0;
+}
+s4 java_lang_Compiler_compileClasses (struct java_lang_String* par1)
+{
+ log_text ("java_lang_Compiler_compileClasses called");
+ return 0;
+}
+struct java_lang_Object* java_lang_Compiler_command (struct java_lang_Object* par1)
+{
+ log_text ("java_lang_Compiler_command called");
+ return NULL;
+}
+void java_lang_Compiler_enable ()
+{
+ log_text ("java_lang_Compiler_enable called");
+}
+void java_lang_Compiler_disable ()
+{
+ log_text ("java_lang_Compiler_disable called");
+}
+
+
+/******************************** java.lang.Double **************************************/
+
+struct java_lang_String* java_lang_Double_toString (double par1)
+{
+ char b[400];
+ sprintf (b, "%-.6g", par1);
+ return (java_lang_String*) javastring_new_char (b);
+}
+struct java_lang_Double* java_lang_Double_valueOf (struct java_lang_String* par1)
+{
+ float val;
+ java_lang_Double *d = (java_lang_Double*) builtin_new (class_java_lang_Double);
+ if (d) {
+ sscanf (javastring_tochar((java_objectheader*) par1), "%f", &val);
+ d->value = val;
+ return d;
+ }
+ return NULL;
+}
+s8 java_lang_Double_doubleToLongBits (double par1)
+{
+ s8 l;
+ double d = par1;
+ memcpy ((u1*) &l, (u1*) &d, 8);
+ return l;
+}
+double java_lang_Double_longBitsToDouble (s8 par1)
+{
+ s8 l = par1;
+ double d;
+ memcpy ((u1*) &d, (u1*) &l, 8);
+ return d;
+}
+
+/******************************** java.lang.Float ***************************************/
+
+struct java_lang_String* java_lang_Float_toString (float par1)
+{
+ char b[50];
+ sprintf (b, "%-.6g", (double) par1);
+ return (java_lang_String*) javastring_new_char (b);
+}
+struct java_lang_Float* java_lang_Float_valueOf (struct java_lang_String* par1)
+{
+ float val;
+ java_lang_Float *d = (java_lang_Float*) builtin_new (class_java_lang_Float);
+ if (d) {
+ sscanf (javastring_tochar((java_objectheader*) par1), "%f", &val);
+ d->value = val;
+ return d;
+ }
+ return NULL;
+}
+s4 java_lang_Float_floatToIntBits (float par1)
+{
+ s4 i;
+ float f = par1;
+ memcpy ((u1*) &i, (u1*) &f, 4);
+ return i;
+}
+float java_lang_Float_intBitsToFloat (s4 par1)
+{
+ s4 i = par1;
+ float f;
+ memcpy ((u1*) &f, (u1*) &i, 4);
+ return f;
+}
+
+
+/******************************** java.lang.Math ****************************************/
+
+double java_lang_Math_sin (double par1)
+{
+ return sin(par1);
+}
+
+double java_lang_Math_cos (double par1)
+{
+ return cos(par1);
+}
+
+double java_lang_Math_tan (double par1)
+{
+ return tan(par1);
+}
+
+double java_lang_Math_asin (double par1)
+{
+ return asin(par1);
+}
+
+double java_lang_Math_acos (double par1)
+{
+ return acos(par1);
+}
+
+double java_lang_Math_atan (double par1)
+{
+ return atan(par1);
+}
+
+double java_lang_Math_exp (double par1)
+{
+ return exp(par1);
+}
+
+double java_lang_Math_log (double par1)
+{
+ if (par1<0.0) {
+ exceptionptr = proto_java_lang_ArithmeticException;
+ return 0.0;
+ }
+ return log(par1);
+}
+
+double java_lang_Math_sqrt (double par1)
+{
+ if (par1<0.0) {
+ exceptionptr = proto_java_lang_ArithmeticException;
+ return 0.0;
+ }
+ return sqrt(par1);
+}
+
+static u8 dbl_nan = 0xffffffffffffffffL ;
+
+#define DBL_NAN (*((double*) (&dbl_nan)))
+
+double java_lang_Math_IEEEremainder (double a, double b)
+{
+ double d;
+ if (finite(a) && finite(b)) {
+ d = a / b;
+ if (finite(d))
+ return a - floor(d) * b;
+ return DBL_NAN;
+ }
+ if (isnan(b))
+ return DBL_NAN;
+ if (finite(a))
+ return a;
+ return DBL_NAN;
+}
+
+double java_lang_Math_ceil (double par1)
+{
+ return ceil(par1);
+}
+
+double java_lang_Math_floor (double par1)
+{
+ return floor(par1);
+}
+
+double java_lang_Math_rint (double par1)
+{
+ panic ("native Methode java_lang_rint not implemented yet");
+ return 0.0;
+}
+
+double java_lang_Math_atan2 (double par1, double par2)
+{
+ return atan2(par1,par2);
+}
+
+double java_lang_Math_pow (double par1, double par2)
+{
+ return pow(par1,par2);
+}
+
+
+/******************************* java.lang.Runtime **************************************/
+
+void java_lang_Runtime_exitInternal (struct java_lang_Runtime* this, s4 par1)
+{
+ cacao_shutdown (par1);
+}
+struct java_lang_Process* java_lang_Runtime_execInternal (struct java_lang_Runtime* this, java_objectarray* par1, java_objectarray* par2)
+{
+ log_text ("java_lang_Runtime_execInternal called");
+ return NULL;
+}
+s8 java_lang_Runtime_freeMemory (struct java_lang_Runtime* this)
+{
+ log_text ("java_lang_Runtime_freeMemory called");
+ return builtin_i2l (0);
+}
+s8 java_lang_Runtime_totalMemory (struct java_lang_Runtime* this)
+{
+ log_text ("java_lang_Runtime_totalMemory called");
+ return builtin_i2l (0);
+}
+void java_lang_Runtime_gc (struct java_lang_Runtime* this)
+{
+ gc_call();
+}
+void java_lang_Runtime_runFinalization (struct java_lang_Runtime* this)
+{
+ log_text ("java_lang_Runtime_runFinalization called");
+}
+void java_lang_Runtime_traceInstructions (struct java_lang_Runtime* this, s4 par1)
+{
+ log_text ("java_lang_Runtime_traceInstructions called");
+}
+void java_lang_Runtime_traceMethodCalls (struct java_lang_Runtime* this, s4 par1)
+{
+ log_text ("java_lang_Runtime_traceMethodCalls called");
+}
+struct java_lang_String* java_lang_Runtime_initializeLinkerInternal (struct java_lang_Runtime* this)
+{
+ log_text ("java_lang_Runtime_initializeLinkerInternal called");
+ return (java_lang_String*)javastring_new_char(".");
+}
+struct java_lang_String* java_lang_Runtime_buildLibName (struct java_lang_Runtime* this, struct java_lang_String* par1, struct java_lang_String* par2)
+{
+ log_text ("java_lang_Runtime_buildLibName called");
+ return NULL;
+}
+s4 java_lang_Runtime_loadFileInternal (struct java_lang_Runtime* this, struct java_lang_String* par1)
+{
+ log_text ("java_lang_Runtime_loadFileInternal called");
+ return 1;
+}
+
+
+/**************************************** java.lang.SecurityManager ***********************/
+
+java_objectarray* java_lang_SecurityManager_getClassContext (struct java_lang_SecurityManager* this)
+{
+ log_text ("called: java_lang_SecurityManager_getClassContext");
+ return NULL;
+}
+struct java_lang_ClassLoader* java_lang_SecurityManager_currentClassLoader (struct java_lang_SecurityManager* this)
+{
+ log_text ("called: java_lang_SecurityManager_currentClassLoader");
+ return NULL;
+}
+s4 java_lang_SecurityManager_classDepth (struct java_lang_SecurityManager* this, struct java_lang_String* par1)
+{
+ log_text ("called: java_lang_SecurityManager_classDepth");
+ return 0;
+}
+s4 java_lang_SecurityManager_classLoaderDepth (struct java_lang_SecurityManager* this)
+{
+ log_text ("called: java_lang_SecurityManager_classLoaderDepth");
+ return 0;
+}
+
+
+
+/*********************************** java.lang.System ************************************/
+
+s8 java_lang_System_currentTimeMillis ()
+{
+ struct timeval tv;
+
+ (void) gettimeofday(&tv, NULL);
+ return ((s8) tv.tv_sec) * 1000 + tv.tv_usec / 1000;
+}
+
+
+void java_lang_System_arraycopy (struct java_lang_Object* source, s4 sp,
+ struct java_lang_Object* dest, s4 dp, s4 len)
+{
+ s4 i;
+ java_arrayheader *s = (java_arrayheader*) source;
+ java_arrayheader *d = (java_arrayheader*) dest;
+
+ if ( (!s) || (!d) ) {
+ exceptionptr = proto_java_lang_NullPointerException;
+ return;
+ }
+ if ( (s->objheader.vftbl->class != class_array) || (d->objheader.vftbl->class != class_array) ) {
+ exceptionptr = proto_java_lang_ArrayStoreException;
+ return;
+ }
+
+ if (s->arraytype != d->arraytype) {
+ exceptionptr = proto_java_lang_ArrayStoreException;
+ return;
+ }
+
+ if ((sp<0) || (sp+len > s->size) || (dp<0) || (dp+len > d->size)) {
+ exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException;
+ return;
+ }
+
+ switch (s->arraytype) {
+ case ARRAYTYPE_BYTE:
+ {
+ java_bytearray *bas = (java_bytearray*) s;
+ java_bytearray *bad = (java_bytearray*) d;
+ if (dp<=sp)
+ for (i=0; i<len; i++) bad->data[dp+i] = bas->data[sp+i];
+ else
+ for (i=len-1; i>=0; i--) bad->data[dp+i] = bas->data[sp+i];
+ }
+ break;
+ case ARRAYTYPE_BOOLEAN:
+ {
+ java_booleanarray *bas = (java_booleanarray*) s;
+ java_booleanarray *bad = (java_booleanarray*) d;
+ if (dp<=sp)
+ for (i=0; i<len; i++) bad->data[dp+i] = bas->data[sp+i];
+ else
+ for (i=len-1; i>=0; i--) bad->data[dp+i] = bas->data[sp+i];
+ }
+ break;
+ case ARRAYTYPE_CHAR:
+ {
+ java_chararray *cas = (java_chararray*) s;
+ java_chararray *cad = (java_chararray*) d;
+ if (dp<=sp)
+ for (i=0; i<len; i++) cad->data[dp+i] = cas->data[sp+i];
+ else
+ for (i=len-1; i>=0; i--) cad->data[dp+i] = cas->data[sp+i];
+ }
+ break;
+ case ARRAYTYPE_SHORT:
+ {
+ java_shortarray *sas = (java_shortarray*) s;
+ java_shortarray *sad = (java_shortarray*) d;
+ if (dp<=sp)
+ for (i=0; i<len; i++) sad->data[dp+i] = sas->data[sp+i];
+ else
+ for (i=len-1; i>=0; i--) sad->data[dp+i] = sas->data[sp+i];
+ }
+ break;
+ case ARRAYTYPE_INT:
+ {
+ java_intarray *ias = (java_intarray*) s;
+ java_intarray *iad = (java_intarray*) d;
+ if (dp<=sp)
+ for (i=0; i<len; i++) iad->data[dp+i] = ias->data[sp+i];
+ else
+ for (i=len-1; i>=0; i--) iad->data[dp+i] = ias->data[sp+i];
+ }
+ break;
+ case ARRAYTYPE_LONG:
+ {
+ java_longarray *las = (java_longarray*) s;
+ java_longarray *lad = (java_longarray*) d;
+ if (dp<=sp)
+ for (i=0; i<len; i++) lad->data[dp+i] = las->data[sp+i];
+ else
+ for (i=len-1; i>=0; i--) lad->data[dp+i] = las->data[sp+i];
+ }
+ break;
+ case ARRAYTYPE_FLOAT:
+ {
+ java_floatarray *fas = (java_floatarray*) s;
+ java_floatarray *fad = (java_floatarray*) d;
+ if (dp<=sp)
+ for (i=0; i<len; i++) fad->data[dp+i] = fas->data[sp+i];
+ else
+ for (i=len-1; i>=0; i--) fad->data[dp+i] = fas->data[sp+i];
+ }
+ break;
+ case ARRAYTYPE_DOUBLE:
+ {
+ java_doublearray *das = (java_doublearray*) s;
+ java_doublearray *dad = (java_doublearray*) d;
+ if (dp<=sp)
+ for (i=0; i<len; i++) dad->data[dp+i] = das->data[sp+i];
+ else
+ for (i=len-1; i>=0; i--) dad->data[dp+i] = das->data[sp+i];
+ }
+ break;
+ case ARRAYTYPE_OBJECT:
+ {
+ java_objectarray *oas = (java_objectarray*) s;
+ java_objectarray *oad = (java_objectarray*) d;
+ if (dp<=sp)
+ for (i=0; i<len; i++) {
+ java_objectheader *o = oas->data[sp+i];
+ if (!builtin_canstore(oad, o)) {
+ exceptionptr = proto_java_lang_ArrayStoreException;
+ return;
+ }
+ oad->data[dp+i] = o;
+ }
+ else
+ for (i=len-1; i>=0; i--) {
+ java_objectheader *o = oas->data[sp+i];
+ if (!builtin_canstore(oad, o)) {
+ exceptionptr = proto_java_lang_ArrayStoreException;
+ return;
+ }
+ oad->data[dp+i] = o;
+ }
+
+ }
+ break;
+ case ARRAYTYPE_ARRAY:
+ {
+ java_arrayarray *aas = (java_arrayarray*) s;
+ java_arrayarray *aad = (java_arrayarray*) d;
+ if (dp<=sp)
+ for (i=0; i<len; i++) {
+ java_arrayheader *o = aas->data[sp+i];
+ if (!builtin_canstore( (java_objectarray*)aad,
+ (java_objectheader*)o )) {
+ exceptionptr = proto_java_lang_ArrayStoreException;
+ return;
+ }
+ aad->data[dp+i] = o;
+ }
+ else
+ for (i=len-1; i>=0; i--) {
+ java_arrayheader *o = aas->data[sp+i];
+ if (!builtin_canstore( (java_objectarray*)aad,
+ (java_objectheader*)o )) {
+ exceptionptr = proto_java_lang_ArrayStoreException;
+ return;
+ }
+ aad->data[dp+i] = o;
+ }
+
+ }
+ break;
+
+ default:
+ panic ("Unknown data type for arraycopy");
+ }
+
+}
+
+
+#define MAXPROPS 100
+static int activeprops = 15;
+
+static char *proplist[MAXPROPS][2] = {
+ { "java.class.path", NULL },
+ { "java.home", NULL },
+ { "user.home", NULL },
+ { "user.name", NULL },
+ { "user.dir", NULL },
+
+ { "java.class.version", "45.3" },
+ { "java.version", "cacao:0.2" },
+ { "java.vendor", "CACAO Team" },
+ { "java.vendor.url", "http://www.complang.tuwien.ac.at/java/cacao/" },
+ { "os.arch", "Alpha" },
+ { "os.name", "Linux/Digital Unix" },
+ { "os.version", "4.0/3.2C/V4.0" },
+ { "path.separator", ":" },
+ { "file.separator", "/" },
+ { "line.separator", "\n" }
+};
+
+void attach_property (char *name, char *value)
+{
+ if (activeprops >= MAXPROPS) panic ("Too many properties defined");
+ proplist[activeprops][0] = name;
+ proplist[activeprops][1] = value;
+ activeprops++;
+}
+
+
+struct java_util_Properties* java_lang_System_initProperties (struct java_util_Properties* p)
+{
+ u4 i;
+ methodinfo *m;
+#define BUFFERSIZE 200
+ char buffer[BUFFERSIZE];
+
+ proplist[0][1] = classpath;
+ proplist[1][1] = getenv("JAVAHOME");
+ proplist[2][1] = getenv("HOME");
+ proplist[3][1] = getenv("USER");
+ proplist[4][1] = getcwd(buffer,BUFFERSIZE);
+
+ if (!p) panic ("initProperties called with NULL-Argument");
+
+ m = class_resolvemethod (
+ p->header.vftbl->class,
+ unicode_new_char ("put"),
+ unicode_new_char ("(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;")
+ );
+ if (!m) panic ("Can not find method 'put' for class Properties");
+
+ for (i=0; i<activeprops; i++) {
+ if (proplist[i][1]==NULL) proplist[i][1]="";
+
+ asm_calljavamethod (m, p,
+ javastring_new_char(proplist[i][0]),
+ javastring_new_char(proplist[i][1]),
+ NULL
+ );
+ }
+
+ return p;
+}
+
+
+
+
+/*********************************** java.lang.Thread ***********************************/
+
+struct java_lang_Thread* java_lang_Thread_currentThread ()
+{
+ if (runverbose)
+ log_text ("java_lang_Thread_currentThread called");
+#ifdef USE_THREADS
+ return (struct java_lang_Thread*)currentThread;
+#else
+ return 0;
+#endif
+}
+
+void java_lang_Thread_yield ()
+{
+ if (runverbose)
+ log_text ("java_lang_Thread_yield called");
+#ifdef USE_THREADS
+ yieldThread();
+#endif
+}
+
+void java_lang_Thread_sleep (s8 par1)
+{
+ if (runverbose)
+ log_text ("java_lang_Thread_sleep called");
+#ifdef USE_THREADS
+ yieldThread();
+#endif
+ /* not yet implemented */
+}
+
+void java_lang_Thread_start (struct java_lang_Thread* this)
+{
+ if (runverbose)
+ log_text ("java_lang_Thread_start called");
+#ifdef USE_THREADS
+ startThread((thread*)this);
+#endif
+}
+
+s4 java_lang_Thread_isAlive (struct java_lang_Thread* this)
+{
+ if (runverbose)
+ log_text ("java_lang_Thread_isAlive called");
+#ifdef USE_THREADS
+ return aliveThread((thread*)this);
+#else
+ return 0;
+#endif
+}
+
+s4 java_lang_Thread_countStackFrames (struct java_lang_Thread* this)
+{
+ log_text ("java_lang_Thread_countStackFrames called");
+ return 0; /* not yet implemented */
+}
+
+void java_lang_Thread_setPriority0 (struct java_lang_Thread* this, s4 par1)
+{
+ if (runverbose)
+ log_text ("java_lang_Thread_setPriority0 called");
+#ifdef USE_THREADS
+ setPriorityThread((thread*)this, par1);
+#endif
+}
+
+void java_lang_Thread_stop0 (struct java_lang_Thread* this, struct java_lang_Object* par1)
+{
+ if (runverbose)
+ log_text ("java_lang_Thread_stop0 called");
+#ifdef USE_THREADS
+ if (currentThread == (thread*)this)
+ {
+ log_text("killing");
+ killThread(0);
+ /*
+ exceptionptr = proto_java_lang_ThreadDeath;
+ return;
+ */
+ }
+ else
+ {
+ CONTEXT((thread*)this).flags |= THREAD_FLAGS_KILLED;
+ resumeThread((thread*)this);
+ }
+#endif
+}
+
+void java_lang_Thread_suspend0 (struct java_lang_Thread* this)
+{
+ if (runverbose)
+ log_text ("java_lang_Thread_suspend0 called");
+#ifdef USE_THREADS
+ suspendThread((thread*)this);
+#endif
+}
+
+void java_lang_Thread_resume0 (struct java_lang_Thread* this)
+{
+ if (runverbose)
+ log_text ("java_lang_Thread_resume0 called");
+#ifdef USE_THREADS
+ resumeThread((thread*)this);
+#endif
+}
+
+
+
+/************************************ java.lang.Throwable *********************************/
+
+void java_lang_Throwable_printStackTrace0 (struct java_lang_Throwable* this, struct java_io_PrintStream* par1)
+{
+ log_text ("java_lang_Throwable_printStackTrace0 called");
+ return;
+}
+
+struct java_lang_Throwable* java_lang_Throwable_fillInStackTrace (struct java_lang_Throwable *this)
+{
+ this -> detailMessage =
+ (java_lang_String*) (javastring_new_char ("no backtrace info!") );
+ return this;
+}
+
--- /dev/null
+/***************************** nat/util.c **************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Contains the native functions for class java.util.
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1996/11/14
+
+*******************************************************************************/
+
+#include <time.h>
+
+/**************************** java.util.Date **********************************/
+
+
+struct java_lang_String* java_util_Date_toString
+ (struct java_util_Date* this)
+{
+ time_t tt;
+ char *buffer;
+ int l;
+
+ if (!this->valueValid) java_util_Date_computeValue(this);
+ tt = builtin_l2i ( builtin_ldiv(this->value, builtin_i2l(1000) ) );
+
+ buffer = ctime (&tt);
+ l = strlen(buffer);
+ while (l>1 && buffer[l-1]=='\n') l--;
+ buffer[l] = '\0';
+
+ return (java_lang_String*) javastring_new_char( buffer );
+}
+
+
+struct java_lang_String* java_util_Date_toLocaleString
+ (struct java_util_Date* this)
+{
+ time_t tt;
+ char *buffer;
+ int l;
+
+ if (!this->valueValid) java_util_Date_computeValue(this);
+ tt = builtin_l2i ( builtin_ldiv(this->value, builtin_i2l(1000) ) );
+
+ buffer = asctime (localtime(&tt));
+ l = strlen(buffer);
+ while (l>1 && buffer[l-1]=='\n') l--;
+ buffer[l] = '\0';
+
+ return (java_lang_String*) javastring_new_char ( buffer );
+}
+
+struct java_lang_String* java_util_Date_toGMTString
+ (struct java_util_Date* this)
+{
+ time_t tt;
+ char *buffer;
+ int l;
+
+ if (!this->valueValid) java_util_Date_computeValue(this);
+ tt = builtin_l2i ( builtin_ldiv(this->value, builtin_i2l(1000) ) );
+
+ buffer = asctime (gmtime(&tt));
+ l = strlen(buffer);
+ while (l>1 && buffer[l-1]=='\n') l--;
+ buffer[l] = '\0';
+
+
+ return (java_lang_String*) javastring_new_char ( buffer );
+}
+
+
+
+void java_util_Date_expand (struct java_util_Date* this)
+{
+ struct tm *t;
+ time_t tt;
+
+ if (this->expanded) return;
+
+ tt = builtin_l2i ( builtin_ldiv(this->value, builtin_i2l(1000) ) );
+ t = gmtime (&tt);
+ this->tm_millis =
+ builtin_l2i( builtin_lrem (this->value, builtin_i2l(1000) ) );
+ this->tm_sec = t->tm_sec;
+ this->tm_min = t->tm_min;
+ this->tm_hour = t->tm_hour;
+ this->tm_mday = t->tm_mday;
+ this->tm_mon = t->tm_mon;
+ this->tm_wday = t->tm_wday;
+ this->tm_yday = t->tm_yday;
+ this->tm_year = t->tm_year;
+ this->tm_isdst = t->tm_isdst;
+ this->expanded = 1;
+}
+
+void java_util_Date_computeValue (struct java_util_Date* this)
+{
+ struct tm t;
+
+ if (this->valueValid) return;
+ t.tm_sec = this->tm_sec;
+ t.tm_min = this->tm_min;
+ t.tm_hour = this->tm_hour;
+ t.tm_mday = this->tm_mday;
+ t.tm_mon = this->tm_mon;
+ t.tm_wday = this->tm_wday;
+ t.tm_yday = this->tm_yday;
+ t.tm_year = this->tm_year;
+ t.tm_isdst = this->tm_isdst;
+ this->value =
+ builtin_ladd(
+ builtin_lmul( builtin_i2l(mktime(&t)), builtin_i2l(1000)),
+ builtin_i2l(this->tm_millis)
+ );
+ this->valueValid = 1;
+}
--- /dev/null
+/****************************** native.c ***************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Enth"alt die Tabellen f"ur die native-methods.
+ Die vom Headerfile-Generator erzeugten -.hh - Dateien werden hier
+ eingebunden, und ebenso alle C-Funktionen, mit denen diese
+ Methoden implementiert werden.
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1996/11/14
+
+*******************************************************************************/
+
+#include <unistd.h>
+#include <time.h>
+
+
+#include "global.h"
+#include "native.h"
+
+#include "builtin.h"
+#include "nativetypes.hh"
+#include "asmpart.h"
+#include "tables.h"
+#include "loader.h"
+
+
+java_objectheader* exceptionptr = NULL;
+
+
+
+static char *classpath;
+
+
+/******************** die f"r die native-Methoden n"otigen Systemklassen *****/
+
+static classinfo *class_java_lang_Class;
+static classinfo *class_java_lang_Cloneable;
+static classinfo *class_java_lang_CloneNotSupportedException;
+static classinfo *class_java_lang_Double;
+static classinfo *class_java_lang_Float;
+static classinfo *class_java_io_IOException;
+static classinfo *class_java_lang_ClassNotFoundException;
+static classinfo *class_java_lang_InstantiationException;
+
+
+
+/************************** alle Funktionen einbinden ************************/
+
+#include "nat/lang.c"
+#include "nat/io.c"
+#include "nat/util.c"
+
+
+/********************** Tabellen f"ur die Methoden ***************************/
+
+static struct nativeref {
+ char *classname;
+ char *methodname;
+ char *descriptor;
+ bool isstatic;
+ functionptr func;
+} nativetable [] = {
+
+#include "nativetable.hh"
+
+};
+
+
+#define NATIVETABLESIZE (sizeof(nativetable)/sizeof(struct nativeref))
+
+static struct nativecompref {
+ unicode *classname;
+ unicode *methodname;
+ unicode *descriptor;
+ bool isstatic;
+ functionptr func;
+ } nativecomptable [NATIVETABLESIZE];
+
+static bool nativecompdone = false;
+
+
+/*********************** Funktion: native_loadclasses **************************
+
+ L"adt alle Klassen, die die native Methoden zus"atzlich ben"otigen
+
+*******************************************************************************/
+
+void native_loadclasses()
+{
+ class_java_lang_Cloneable =
+ loader_load ( unicode_new_char ("java/lang/Cloneable") );
+ class_java_lang_CloneNotSupportedException =
+ loader_load ( unicode_new_char ("java/lang/CloneNotSupportedException") );
+ class_java_lang_Class =
+ loader_load ( unicode_new_char ("java/lang/Class") );
+ class_java_lang_Double =
+ loader_load ( unicode_new_char ("java/lang/Double") );
+ class_java_lang_Float =
+ loader_load ( unicode_new_char ("java/lang/Float") );
+ class_java_io_IOException =
+ loader_load ( unicode_new_char ("java/io/IOException") );
+ class_java_lang_ClassNotFoundException =
+ loader_load ( unicode_new_char ("java/lang/ClassNotFoundException") );
+ class_java_lang_InstantiationException=
+ loader_load ( unicode_new_char ("java/lang/InstantiationException") );
+
+}
+
+/********************* Funktion: native_setclasspath ***************************/
+
+void native_setclasspath (char *path)
+{
+ classpath = path;
+}
+
+
+/*********************** Funktion: native_findfunction ************************
+
+ Sucht in der Tabelle die passende Methode (muss mit Klassennamen,
+ Methodennamen, Descriptor und 'static'-Status "ubereinstimmen),
+ und gibt den Funktionszeiger darauf zur"uck.
+ Return: Funktionszeiger oder NULL (wenn es keine solche Methode gibt)
+
+ Anmerkung: Zu Beschleunigung des Suchens werden die als C-Strings
+ vorliegenden Namen/Descriptors in entsprechende unicode-Symbole
+ umgewandelt (beim ersten Aufruf dieser Funktion).
+
+*******************************************************************************/
+
+functionptr native_findfunction (unicode *cname, unicode *mname,
+ unicode *desc, bool isstatic)
+{
+ u4 i;
+ struct nativecompref *n;
+
+ isstatic = isstatic ? true : false;
+
+ if (!nativecompdone) {
+ for (i=0; i<NATIVETABLESIZE; i++) {
+ nativecomptable[i].classname =
+ unicode_new_char(nativetable[i].classname);
+ nativecomptable[i].methodname =
+ unicode_new_char(nativetable[i].methodname);
+ nativecomptable[i].descriptor =
+ unicode_new_char(nativetable[i].descriptor);
+ nativecomptable[i].isstatic =
+ nativetable[i].isstatic;
+ nativecomptable[i].func =
+ nativetable[i].func;
+ }
+ nativecompdone = true;
+ }
+
+ for (i=0; i<NATIVETABLESIZE; i++) {
+ n = &(nativecomptable[i]);
+
+ if (cname==n->classname && mname==n->methodname &&
+ desc==n->descriptor && isstatic==n->isstatic) return n->func;
+ }
+
+ return NULL;
+}
+
+
+/********************** Funktion: javastring_new *****************************
+
+ Legt ein neues Objekt vom Typ java/lang/String an, und tr"agt als Text
+ das "ubergebene unicode-Symbol ein.
+ Return: Zeiger auf den String, oder NULL (wenn Speicher aus)
+
+*****************************************************************************/
+
+java_objectheader *javastring_new (unicode *text)
+{
+ u4 i;
+ java_lang_String *s;
+ java_chararray *a;
+
+ s = (java_lang_String*) builtin_new (class_java_lang_String);
+ a = builtin_newarray_char (text->length);
+
+ if ( (!a) || (!s) ) return NULL;
+
+ for (i=0; i<text->length; i++) a->data[i] = text->text[i];
+ s -> value = a;
+ s -> offset = 0;
+ s -> count = text->length;
+
+ return (java_objectheader*) s;
+}
+
+
+/********************** Funktion: javastring_new_char ************************
+
+ Legt ein neues Objekt vom Typ java/lang/String an, und tr"agt als Text
+ den "ubergebenen C-String ein.
+ Return: Zeiger auf den String, oder NULL (wenn Speicher aus)
+
+*****************************************************************************/
+
+java_objectheader *javastring_new_char (char *text)
+{
+ u4 i;
+ u4 len = strlen(text);
+ java_lang_String *s;
+ java_chararray *a;
+
+ s = (java_lang_String*) builtin_new (class_java_lang_String);
+ a = builtin_newarray_char (len);
+
+ if ( (!a) || (!s) ) return NULL;
+
+ for (i=0; i<len; i++) a->data[i] = text[i];
+ s -> value = a;
+ s -> offset = 0;
+ s -> count = len;
+
+ return (java_objectheader*) s;
+}
+
+
+/************************* Funktion: javastring_tochar *****************************
+
+ Macht aus einem java-string einen C-String, und liefert den Zeiger
+ darauf zur"uck.
+ Achtung: Beim n"achsten Aufruf der Funktion wird der vorige String
+ "uberschrieben
+
+***********************************************************************************/
+
+#define MAXSTRINGSIZE 1000
+char stringbuffer[MAXSTRINGSIZE];
+
+char *javastring_tochar (java_objectheader *so)
+{
+ java_lang_String *s = (java_lang_String*) so;
+ java_chararray *a;
+ u4 i;
+
+ if (!s) return "";
+ a = s->value;
+ if (!a) return "";
+ if (s->count > MAXSTRINGSIZE) return "";
+ for (i=0; i<s->count; i++) stringbuffer[i] = a->data[s->offset+i];
+ stringbuffer[i] = '\0';
+ return stringbuffer;
+}
+
+
+/******************** Funktion: native_new_and_init *************************
+
+ Legt ein neues Objekt einer Klasse am Heap an, und ruft automatisch
+ die Initialisierungsmethode auf.
+ Return: Der Zeiger auf das Objekt, oder NULL, wenn kein Speicher
+ mehr frei ist.
+
+*****************************************************************************/
+
+java_objectheader *native_new_and_init (classinfo *c)
+{
+ methodinfo *m;
+ java_objectheader *o = builtin_new (c);
+
+ if (!o) return NULL;
+
+ m = class_findmethod (c,
+ unicode_new_char ("<init>"),
+ unicode_new_char ("()V"));
+ if (!m) {
+ log_text ("warning: class has no instance-initializer:");
+ unicode_sprint (logtext, c->name);
+ dolog();
+ return o;
+ }
+
+ asm_calljavamethod (m, o,NULL,NULL,NULL);
+ return o;
+}
+
+
+/********************* Funktion: literalstring_new ****************************
+
+ erzeugt einen Java-String mit dem angegebenen Text, allerdings nicht
+ auf dem HEAP, sondern in einem anderen Speicherbereich (der String
+ muss dann sp"ater explizit wieder freigegeben werden).
+ Alle Strings, die auf diese Art erzeugt werden, werden in einer
+ gemeinsamen Struktur gespeichert (n"amlich auch "uber die
+ Unicode-Hashtabelle), sodass identische Strings auch wirklich den
+ gleichen Zeiger liefern.
+
+******************************************************************************/
+
+java_objectheader *literalstring_new (unicode *text)
+{
+ u4 i;
+ java_lang_String *s;
+ java_chararray *a;
+
+ if (text->string) return text->string;
+
+ a = lit_mem_alloc (sizeof(java_chararray) + sizeof(u2)*(text->length-1) );
+ a -> header.objheader.vftbl = class_array -> vftbl;
+ a -> header.size = text->length;
+ a -> header.arraytype = ARRAYTYPE_CHAR;
+ for (i=0; i<text->length; i++) a->data[i] = text->text[i];
+
+ s = LNEW (java_lang_String);
+ s -> header.vftbl = class_java_lang_String -> vftbl;
+ s -> value = a;
+ s -> offset = 0;
+ s -> count = text->length;
+
+ unicode_setstringlink (text, (java_objectheader*) s);
+ return (java_objectheader*) s;
+}
+
+
+/********************** Funktion: literalstring_free **************************
+
+ L"oscht einen Java-String wieder aus dem Speicher (wird zu Systemende
+ vom Hashtabellen-Verwalter aufgerufen)
+
+******************************************************************************/
+
+void literalstring_free (java_objectheader* sobj)
+{
+ java_lang_String *s = (java_lang_String*) sobj;
+ java_chararray *a = s->value;
+
+ LFREE (s, java_lang_String);
+ LFREE (a, sizeof(java_chararray) + sizeof(u2)*(a->header.size-1));
+}
+
+
+
--- /dev/null
+/****************************** native.h ***************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Contains the codegenerator for an Alpha processor.
+ This module generates Alpha machine code for a sequence of
+ pseudo commands (PCMDs).
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1997/03/12
+
+*******************************************************************************/
+
+
+extern java_objectheader* exceptionptr;
+
+void native_loadclasses ();
+void native_setclasspath (char *path);
+
+functionptr native_findfunction (unicode *cname, unicode *mname,
+ unicode *desc, bool isstatic);
+
+java_objectheader *javastring_new (unicode *text);
+java_objectheader *javastring_new_char (char *text);
+char *javastring_tochar (java_objectheader *s);
+
+java_objectheader *native_new_and_init (classinfo *c);
+
+java_objectheader *literalstring_new (unicode *text);
+void literalstring_free (java_objectheader*);
+
+void attach_property(char *name, char *value);
--- /dev/null
+/***************************** comp/mcode.c ************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ This file is an include file for "compiler.c" . It contains (mostly)
+ architecture independent functions for writing instructions into the
+ code area and constants into the data area.
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+ Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
+ Changes: Micheal Gschwind EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1998/08/10
+
+
+ All functions assume the following code area / data area layout:
+
+ +-----------+
+ | |
+ | code area | code area grows to higher addresses
+ | |
+ +-----------+ <-- start of procedure
+ | |
+ | data area | data area grows to lower addresses
+ | |
+ +-----------+
+
+ The functions first write into a temporary code/data area allocated by
+ "mcode_init". "mcode_finish" copies the code and data area into permanent
+ memory. All functions writing values into the data area return the offset
+ relative the begin of the code area (start of procedure).
+
+*******************************************************************************/
+
+#define MCODEINITSIZE (1<<15) /* 32 Kbyte code area initialization size */
+#define DSEGINITSIZE (1<<12) /* 4 Kbyte data area initialization size */
+
+static u1* mcodebase = NULL; /* base pointer of code area */
+static s4* mcodeend = NULL; /* pointer to end of code area */
+static int mcodesize; /* complete size of code area (bytes) */
+
+static u1* dsegtop = NULL; /* pointer to top (end) of data area */
+static int dsegsize; /* complete size of data area (bytes) */
+static int dseglen; /* used size of data area (bytes) */
+ /* data area grows from top to bottom */
+
+static jumpref *jumpreferences; /* list of jumptable target addresses */
+static branchref *xboundrefs; /* list of bound check branches */
+static branchref *xcheckarefs; /* list of array size check branches */
+static branchref *xnullrefs; /* list of null check branches */
+
+static void mcode_init(); /* allocates code and data area */
+static void mcode_close(); /* releases temporary storage */
+static void mcode_finish(); /* makes code and data area permanent and */
+ /* updates branch references to code/data */
+
+static s4 dseg_adds4(s4 value); /* adds an int to data area */
+static s4 dseg_adds8(s8 value); /* adds an long to data area */
+static s4 dseg_addfloat (float value); /* adds an float to data area */
+static s4 dseg_adddouble(double value); /* adds an double to data area */
+
+#if POINTERSIZE==8
+#define dseg_addaddress(value) dseg_adds8((s8)(value))
+#else
+#define dseg_addaddress(value) dseg_adds4((s4)(value))
+#endif
+
+static void dseg_addtarget(basicblock *target);
+static void mcode_addreference(basicblock *target, void *branchptr);
+static void mcode_addxboundrefs(void *branchptr);
+static void mcode_addxnullrefs(void *branchptr);
+
+static void dseg_display(s4 *s4ptr);
+
+/* mcode_init allocates and initialises code area, data area and references */
+
+static void mcode_init()
+{
+ if (!mcodebase) {
+ mcodebase = MNEW (u1, MCODEINITSIZE);
+ mcodesize = MCODEINITSIZE;
+ }
+
+ if (!dsegtop) {
+ dsegtop = MNEW (u1, DSEGINITSIZE);
+ dsegsize = DSEGINITSIZE;
+ dsegtop += dsegsize;
+ }
+
+ dseglen = 0;
+
+ jumpreferences = NULL;
+ xboundrefs = NULL;
+ xnullrefs = NULL;
+}
+
+
+/* mcode_close releases temporary code and data area */
+
+static void mcode_close()
+{
+ if (mcodebase) {
+ MFREE (mcodebase, u1, mcodesize);
+ mcodebase = NULL;
+ }
+ if (dsegtop) {
+ MFREE (dsegtop - dsegsize, u1, dsegsize);
+ dsegtop = NULL;
+ }
+}
+
+
+/* mcode_increase doubles code area */
+
+static s4 *mcode_increase(u1 *codeptr)
+{
+ long len;
+
+ len = codeptr - mcodebase;
+ mcodebase = MREALLOC(mcodebase, u1, mcodesize, mcodesize * 2);
+ mcodesize *= 2;
+ mcodeend = (s4*) (mcodebase + mcodesize);
+ return (s4*) (mcodebase + len);
+}
+
+
+/* desg_increase doubles data area */
+
+static void dseg_increase() {
+ u1 *newstorage = MNEW (u1, dsegsize * 2);
+ memcpy ( newstorage + dsegsize, dsegtop - dsegsize, dsegsize);
+ MFREE (dsegtop - dsegsize, u1, dsegsize);
+ dsegtop = newstorage;
+ dsegsize *= 2;
+ dsegtop += dsegsize;
+}
+
+
+static s4 dseg_adds4_increase(s4 value)
+{
+ dseg_increase();
+ *((s4 *) (dsegtop - dseglen)) = value;
+ return -dseglen;
+}
+
+
+static s4 dseg_adds4(s4 value)
+{
+ s4 *dataptr;
+
+ dseglen += 4;
+ dataptr = (s4 *) (dsegtop - dseglen);
+ if (dseglen > dsegsize)
+ return dseg_adds4_increase(value);
+ *dataptr = value;
+ return -dseglen;
+}
+
+
+static s4 dseg_adds8_increase(s8 value)
+{
+ dseg_increase();
+ *((s8 *) (dsegtop - dseglen)) = value;
+ return -dseglen;
+}
+
+
+static s4 dseg_adds8(s8 value)
+{
+ s8 *dataptr;
+
+ dseglen = ALIGN (dseglen + 8, 8);
+ dataptr = (s8 *) (dsegtop - dseglen);
+ if (dseglen > dsegsize)
+ return dseg_adds8_increase(value);
+ *dataptr = value;
+ return -dseglen;
+}
+
+
+static s4 dseg_addfloat_increase(float value)
+{
+ dseg_increase();
+ *((float *) (dsegtop - dseglen)) = value;
+ return -dseglen;
+}
+
+
+static s4 dseg_addfloat(float value)
+{
+ float *dataptr;
+
+ dseglen += 4;
+ dataptr = (float *) (dsegtop - dseglen);
+ if (dseglen > dsegsize)
+ return dseg_addfloat_increase(value);
+ *dataptr = value;
+ return -dseglen;
+}
+
+
+static s4 dseg_adddouble_increase(double value)
+{
+ dseg_increase();
+ *((double *) (dsegtop - dseglen)) = value;
+ return -dseglen;
+}
+
+
+static s4 dseg_adddouble(double value)
+{
+ double *dataptr;
+
+ dseglen = ALIGN (dseglen + 8, 8);
+ dataptr = (double *) (dsegtop - dseglen);
+ if (dseglen > dsegsize)
+ return dseg_adddouble_increase(value);
+ *dataptr = value;
+ return -dseglen;
+}
+
+
+static void dseg_addtarget(basicblock *target)
+{
+ jumpref *jr = DNEW(jumpref);
+
+ jr->tablepos = dseg_addaddress(NULL);
+ jr->target = target;
+ jr->next = jumpreferences;
+ jumpreferences = jr;
+}
+
+
+static void mcode_addreference(basicblock *target, void *branchptr)
+{
+ s4 branchpos = (u1*) branchptr - mcodebase;
+
+ if (target->mpc >= 0) {
+ gen_resolvebranch((u1*) mcodebase + branchpos, branchpos, target->mpc);
+ }
+ else {
+ branchref *br = DNEW(branchref);
+
+ br->branchpos = branchpos;
+ br->next = target->branchrefs;
+ target->branchrefs= br;
+ }
+}
+
+
+static void mcode_addxboundrefs(void *branchptr)
+{
+ s4 branchpos = (u1*) branchptr - mcodebase;
+
+ branchref *br = DNEW(branchref);
+
+ br->branchpos = branchpos;
+ br->next = xboundrefs;
+ xboundrefs = br;
+}
+
+
+static void mcode_addxcheckarefs(void *branchptr)
+{
+ s4 branchpos = (u1*) branchptr - mcodebase;
+
+ branchref *br = DNEW(branchref);
+
+ br->branchpos = branchpos;
+ br->next = xcheckarefs;
+ xcheckarefs = br;
+}
+
+
+static void mcode_addxnullrefs(void *branchptr)
+{
+ s4 branchpos = (u1*) branchptr - mcodebase;
+
+ branchref *br = DNEW(branchref);
+
+ br->branchpos = branchpos;
+ br->next = xnullrefs;
+ xnullrefs = br;
+}
+
+
+static void mcode_finish(int mcodelen)
+{
+ jumpref *jr;
+ u1 *epoint;
+
+ count_code_len += mcodelen;
+ count_data_len += dseglen;
+
+ dseglen = ALIGN(dseglen, MAX_ALIGN);
+
+ method -> mcodelength = mcodelen + dseglen;
+ method -> mcode = CNEW(u1, mcodelen + dseglen);
+
+ memcpy ( method->mcode, dsegtop - dseglen, dseglen);
+ memcpy ( method->mcode + dseglen, mcodebase, mcodelen);
+
+ method -> entrypoint = epoint = (u1*) (method->mcode + dseglen);
+
+ /* jump table resolving */
+
+ jr = jumpreferences;
+ while (jr != NULL) {
+ *((void**) (epoint + jr->tablepos)) = epoint + jr->target->mpc;
+ jr = jr->next;
+ }
+
+#ifdef CACHE_FLUSH_BLOCK
+ synchronize_caches(method->mcode, (mcodelen>>2));
+#endif
+
+}
+
+
+static void dseg_display(s4 *s4ptr)
+{
+ int i;
+
+ printf(" --- dump of datasegment\n");
+ for (i = dseglen; i > 0 ; i -= 4) {
+ printf("-%6x: %8x\n", i, (int)(*s4ptr++));
+ }
+ printf(" --- begin of data segment: %p\n", s4ptr);
+}
--- /dev/null
+/***************************** ncomp/nblock.c **********************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Basic block handling functions.
+
+ Authors: Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
+ Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1997/11/05
+
+*******************************************************************************/
+
+
+/******************** function determine_basic_blocks **************************
+
+ Scans the JavaVM code of a method and marks each instruction which is the
+ start of a basic block.
+
+*******************************************************************************/
+
+static void allocate_literals()
+{
+ int p, nextp;
+ int opcode, i;
+
+ p = 0;
+ while (p < jcodelength) {
+
+ opcode = jcode[p];
+ nextp = p + jcommandsize[opcode];
+
+ switch (opcode) {
+ case JAVA_WIDE:
+ switch (code_get_u1(p + 1)) {
+ case JAVA_RET: nextp = p + 4;
+ break;
+ case JAVA_IINC: nextp = p + 6;
+ break;
+ default: nextp = p + 4;
+ break;
+ }
+ break;
+
+ case JAVA_LOOKUPSWITCH:
+ {
+ s4 num;
+
+ nextp = ALIGN((p + 1), 4);
+ num = code_get_u4(nextp + 4);
+ nextp = nextp + 8 + 8 * num;
+ break;
+ }
+
+ case JAVA_TABLESWITCH:
+ {
+ s4 num;
+
+ nextp = ALIGN ((p + 1),4);
+ num = code_get_s4(nextp + 4);
+ num = code_get_s4(nextp + 8) - num;
+ nextp = nextp + 16 + 4 * num;
+ break;
+ }
+
+ case JAVA_LDC1:
+ i = code_get_u1(p+1);
+ goto pushconstantitem;
+ case JAVA_LDC2:
+ case JAVA_LDC2W:
+ i = code_get_u2(p + 1);
+ pushconstantitem:
+ if (class_constanttype(class, i) == CONSTANT_String) {
+ unicode *s;
+ s = class_getconstant(class, i, CONSTANT_String);
+ (void) literalstring_new(s);
+ }
+ break;
+ } /* end switch */
+
+ p = nextp;
+
+ } /* end while */
+
+}
--- /dev/null
+/****************************** ncomp.h ****************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ new compiler header file for inclusion in other moduls.
+
+ Authors: Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
+ Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1997/11/05
+
+*******************************************************************************/
+
+/************** compiler switches (are set by main function) ******************/
+
+extern bool runverbose; /* Das Programm soll w"arend des Laufs alle
+ Methodenaufrufe mitprotokollieren */
+extern bool compileverbose; /* Der Compiler soll sagen, was er macht */
+extern bool showstack; /* Alle Stackzust"ande ausgeben */
+extern bool showdisassemble; /* Disassemblerlisting ausgeben */
+extern bool showintermediate; /* Zwischencode ausgeben */
+extern int optimizelevel; /* Optimierungsstufe (0=keine) */
+
+extern bool checkbounds; /* Arraygrenzen "uberpr"ufen */
+extern bool checknull; /* auf Null-Pointer "uberpr"ufen */
+extern bool checkfloats; /* Fehler bei Fliesskommas abfangen */
+extern bool checksync; /* Thread-Synchronisation wirklich machen */
+
+extern bool getcompilingtime;
+extern long compilingtime; /* CPU-Zeit f"urs "Ubersetzen */
+
+extern int has_ext_instr_set; /* has instruction set extensions */
+
+
+extern int count_jit_calls;
+extern int count_methods;
+extern int count_spills;
+extern int count_pcmd_activ;
+extern int count_pcmd_drop;
+extern int count_pcmd_zero;
+extern int count_pcmd_const_store;
+extern int count_pcmd_const_alu;
+extern int count_pcmd_const_bra;
+extern int count_pcmd_load;
+extern int count_pcmd_move;
+extern int count_load_instruction;
+extern int count_pcmd_store;
+extern int count_pcmd_store_comb;
+extern int count_dup_instruction;
+extern int count_pcmd_op;
+extern int count_pcmd_mem;
+extern int count_pcmd_met;
+extern int count_pcmd_bra;
+extern int count_pcmd_table;
+extern int count_pcmd_return;
+extern int count_pcmd_returnx;
+extern int count_max_basic_blocks;
+extern int count_basic_blocks;
+extern int count_max_javainstr;
+extern int count_javainstr;
+extern int count_javacodesize;
+extern int count_javaexcsize;
+extern int count_calls;
+extern int count_tryblocks;
+extern int count_code_len;
+extern int count_data_len;
+extern int count_cstub_len;
+extern int count_nstub_len;
+extern int count_max_new_stack;
+extern int count_upper_bound_new_stack;
+extern int *count_block_stack;
+extern int *count_analyse_iterations;
+extern int *count_method_bb_distribution;
+extern int *count_block_size_distribution;
+extern int *count_store_length;
+extern int *count_store_depth;
+
+/******************************* prototypes ***********************************/
+
+methodptr new_compile (methodinfo *m); /* compile a method with new compiler */
+
+void ncomp_init(); /* compiler initialisation */
+void ncomp_close(); /* compiler finalisation */
+
+/*
+u1 *createcompilerstub (methodinfo *m);
+u1 *createnativestub (functionptr f, methodinfo *m);
+
+void removecompilerstub (u1 *stub);
+void removenativestub (u1 *stub);
+*/
--- /dev/null
+/******************************* ncomp/compdef.h *******************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ defines all the constants and data structures of the compiler
+
+ Authors: Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
+ Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+ Michael Gschwind EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1997/11/05
+
+*******************************************************************************/
+
+#include "../sysdep/types.h"
+
+/**************************** resolve typedef-cycles **************************/
+
+typedef struct stackelement stackelement;
+typedef stackelement *stackptr;
+typedef struct basicblock basicblock;
+typedef struct instruction instruction;
+typedef struct subroutineinfo subroutineinfo;
+typedef struct varinfo varinfo;
+typedef struct branchref branchref;
+typedef struct jumpref jumpref;
+typedef varinfo *varinfoptr;
+
+
+/************************** stack element structure ***************************/
+
+/* slot types */
+
+#define TYPE_INT 0 /* the stack slot types must numbered in the */
+#define TYPE_LNG 1 /* same order as the ICMD_Ixxx to ICMD_Axxx */
+#define TYPE_FLT 2 /* instructions (LOAD and STORE) */
+#define TYPE_DBL 3 /* integer, long, float, double, address */
+#define TYPE_ADR 4
+
+#define IS_INT_LNG_TYPE(a) (!((a)&TYPE_FLT))
+#define IS_FLT_DBL_TYPE(a) ((a)&TYPE_FLT)
+#define IS_2_WORD_TYPE(a) ((a)&TYPE_LNG)
+
+
+/* flags */
+
+#define SAVEDVAR 1 /* variable has to survive method invocations */
+#define INMEMORY 2 /* variable stored in memory */
+
+/* variable types */
+
+#define UNDEFVAR 0 /* stack slot will become temp during regalloc*/
+#define TEMPVAR 1 /* stack slot is temp register */
+#define STACKVAR 2 /* stack slot is numbered stack slot */
+#define LOCALVAR 3 /* stack slot is local variable */
+#define ARGVAR 4 /* stack slot is argument variable */
+
+struct stackelement {
+ stackptr prev; /* pointer to next element towards bottom */
+ int type; /* data type of stack element */
+ int flags; /* flags (SAVED, INMEMORY) */
+ int varkind; /* kind of variable or register */
+ int varnum; /* number of variable */
+ int regoff; /* register number or memory offset */
+ };
+
+
+/**************************** instruction structure ***************************/
+
+struct instruction {
+ stackptr dst; /* stack index of destination operand stack */
+ u2 opc; /* opcode of intermediate code command */
+ s4 op1; /* first operand, usually variable number */
+
+ union {
+ s4 i; /* integer operand */
+ s8 l; /* long operand */
+ float f; /* float operand */
+ double d; /* double operand */
+ void *a; /* address operand */
+ } val; /* immediate constant */
+ };
+
+
+/**************************** basic block structure ***************************/
+
+/* flags */
+
+#define BBUNDEF -1
+#define BBREACHED 0
+#define BBFINISHED 1
+
+#define BBTYPE_STD 0 /* standard basic block type */
+#define BBTYPE_EXH 1 /* exception handler basic block type */
+#define BBTYPE_SBR 2 /* subroutine basic block type */
+
+struct basicblock {
+ int flags; /* used during stack analysis, init with -1 */
+ int type; /* basic block type (std, xhandler, subroutine*/
+ int ipc; /* intermediate code pc at start of block */
+ int mpc; /* machine code pc at start of block */
+ stackptr instack; /* stack at begin of basic block */
+ stackptr outstack; /* stack at end of basic block */
+ int indepth; /* stack depth at begin of basic block */
+ int outdepth; /* stack depth end of basic block */
+ branchref *branchrefs; /* list of branches to be patched */
+ };
+
+
+/************************* pseudo variable structure **************************/
+
+struct varinfo {
+ int type; /* basic type of variable */
+ int flags; /* flags (SAVED, INMEMORY) */
+ int regoff; /* register number or memory offset */
+ };
+
+typedef varinfo varinfo5[5];
+
+
+/***************** forward references in branch instructions ******************/
+
+struct branchref {
+ s4 branchpos; /* patching position in code segment */
+ branchref *next; /* next element in branchref list */
+ };
+
+
+/******************** forward references in tables ***************************/
+
+struct jumpref {
+ s4 tablepos; /* patching position in data segment */
+ basicblock *target; /* target basic block */
+ jumpref *next; /* next element in jumpref list */
+ };
+
+
+/********** JavaVM operation codes (sorted) and instruction lengths ***********/
+
+static int stackreq[256];
+
+static int jcommandsize[256] = {
+
+#define JAVA_NOP 0
+#define ICMD_NOP 0
+ 1,
+#define JAVA_ACONST_NULL 1
+#define ICMD_ACONST 1 /* op1 = 0, val.a = constant */
+ 1,
+#define JAVA_ICONST_M1 2
+#define ICMD_NULLCHECKPOP 2
+ 1,
+#define JAVA_ICONST_0 3
+#define ICMD_ICONST 3 /* op1 = 0, val.i = constant */
+ 1,
+#define JAVA_ICONST_1 4
+ 1,
+#define JAVA_ICONST_2 5
+ 1,
+#define JAVA_ICONST_3 6
+ 1,
+#define JAVA_ICONST_4 7
+ 1,
+#define JAVA_ICONST_5 8
+ 1,
+#define JAVA_LCONST_0 9
+#define ICMD_LCONST 9 /* op1 = 0, val.l = constant */
+ 1,
+#define JAVA_LCONST_1 10
+#define ICMD_LCMPCONST 10 /* op1 = 0, val.l = constant */
+ 1,
+#define JAVA_FCONST_0 11
+#define ICMD_FCONST 11 /* op1 = 0, val.f = constant */
+ 1,
+#define JAVA_FCONST_1 12
+ 1,
+#define JAVA_FCONST_2 13
+ 1,
+#define JAVA_DCONST_0 14
+#define ICMD_DCONST 14 /* op1 = 0, val.a = constant */
+ 1,
+#define JAVA_DCONST_1 15
+ 1,
+#define JAVA_BIPUSH 16
+ 2,
+#define JAVA_SIPUSH 17
+ 3,
+#define JAVA_LDC1 18
+ 2,
+#define JAVA_LDC2 19
+ 3,
+#define JAVA_LDC2W 20
+ 3,
+ /* order of LOAD instructions must be */
+ /* equal to order of TYPE_XXX defines */
+#define JAVA_ILOAD 21
+#define ICMD_ILOAD 21 /* op1 = local variable */
+ 2,
+#define JAVA_LLOAD 22
+#define ICMD_LLOAD 22 /* op1 = local variable */
+ 2,
+#define JAVA_FLOAD 23
+#define ICMD_FLOAD 23 /* op1 = local variable */
+ 2,
+#define JAVA_DLOAD 24
+#define ICMD_DLOAD 24 /* op1 = local variable */
+ 2,
+#define JAVA_ALOAD 25
+#define ICMD_ALOAD 25 /* op1 = local variable */
+ 2,
+#define JAVA_ILOAD_0 26
+#define ICMD_IADDCONST 26
+ 1,
+#define JAVA_ILOAD_1 27
+#define ICMD_ISUBCONST 27
+ 1,
+#define JAVA_ILOAD_2 28
+#define ICMD_IMULCONST 28
+ 1,
+#define JAVA_ILOAD_3 29
+#define ICMD_IANDCONST 29
+ 1,
+#define JAVA_LLOAD_0 30
+#define ICMD_IORCONST 30
+ 1,
+#define JAVA_LLOAD_1 31
+#define ICMD_IXORCONST 31
+ 1,
+#define JAVA_LLOAD_2 32
+#define ICMD_ISHLCONST 32
+ 1,
+#define JAVA_LLOAD_3 33
+#define ICMD_ISHRCONST 33
+ 1,
+#define JAVA_FLOAD_0 34
+#define ICMD_IUSHRCONST 34
+ 1,
+#define JAVA_FLOAD_1 35
+ 1,
+#define JAVA_FLOAD_2 36
+#define ICMD_LADDCONST 36
+ 1,
+#define JAVA_FLOAD_3 37
+#define ICMD_LSUBCONST 37
+ 1,
+#define JAVA_DLOAD_0 38
+#define ICMD_LMULCONST 38
+ 1,
+#define JAVA_DLOAD_1 39
+#define ICMD_LANDCONST 39
+ 1,
+#define JAVA_DLOAD_2 40
+#define ICMD_LORCONST 40
+ 1,
+#define JAVA_DLOAD_3 41
+#define ICMD_LXORCONST 41
+ 1,
+#define JAVA_ALOAD_0 42
+#define ICMD_LSHLCONST 42
+ 1,
+#define JAVA_ALOAD_1 43
+#define ICMD_LSHRCONST 43
+ 1,
+#define JAVA_ALOAD_2 44
+#define ICMD_LUSHRCONST 44
+ 1,
+#define JAVA_ALOAD_3 45
+ 1,
+#define JAVA_IALOAD 46
+#define ICMD_IALOAD 46
+ 1,
+#define JAVA_LALOAD 47
+#define ICMD_LALOAD 47
+ 1,
+#define JAVA_FALOAD 48
+#define ICMD_FALOAD 48
+ 1,
+#define JAVA_DALOAD 49
+#define ICMD_DALOAD 49
+ 1,
+#define JAVA_AALOAD 50
+#define ICMD_AALOAD 50
+ 1,
+#define JAVA_BALOAD 51
+#define ICMD_BALOAD 51
+ 1,
+#define JAVA_CALOAD 52
+#define ICMD_CALOAD 52
+ 1,
+#define JAVA_SALOAD 53
+#define ICMD_SALOAD 53
+ 1,
+ /* order of STORE instructions must be*/
+ /* equal to order of TYPE_XXX defines */
+#define JAVA_ISTORE 54
+#define ICMD_ISTORE 54 /* op1 = local variable */
+ 2,
+#define JAVA_LSTORE 55
+#define ICMD_LSTORE 55 /* op1 = local variable */
+ 2,
+#define JAVA_FSTORE 56
+#define ICMD_FSTORE 56 /* op1 = local variable */
+ 2,
+#define JAVA_DSTORE 57
+#define ICMD_DSTORE 57 /* op1 = local variable */
+ 2,
+#define JAVA_ASTORE 58
+#define ICMD_ASTORE 58 /* op1 = local variable */
+ 2,
+#define JAVA_ISTORE_0 59
+#define ICMD_IF_LEQ 59 /* op1 = target JavaVM pc, val.l */
+ 1,
+#define JAVA_ISTORE_1 60
+#define ICMD_IF_LNE 60 /* op1 = target JavaVM pc, val.l */
+ 1,
+#define JAVA_ISTORE_2 61
+#define ICMD_IF_LLT 61 /* op1 = target JavaVM pc, val.l */
+ 1,
+#define JAVA_ISTORE_3 62
+#define ICMD_IF_LGE 62 /* op1 = target JavaVM pc, val.l */
+ 1,
+#define JAVA_LSTORE_0 63
+#define ICMD_IF_LGT 63 /* op1 = target JavaVM pc, val.l */
+ 1,
+#define JAVA_LSTORE_1 64
+#define ICMD_IF_LLE 64 /* op1 = target JavaVM pc, val.l */
+ 1,
+#define JAVA_LSTORE_2 65
+#define ICMD_IF_LCMPEQ 65 /* op1 = target JavaVM pc */
+ 1,
+#define JAVA_LSTORE_3 66
+#define ICMD_IF_LCMPNE 66 /* op1 = target JavaVM pc */
+ 1,
+#define JAVA_FSTORE_0 67
+#define ICMD_IF_LCMPLT 67 /* op1 = target JavaVM pc */
+ 1,
+#define JAVA_FSTORE_1 68
+#define ICMD_IF_LCMPGE 68 /* op1 = target JavaVM pc */
+ 1,
+#define JAVA_FSTORE_2 69
+#define ICMD_IF_LCMPGT 69 /* op1 = target JavaVM pc */
+ 1,
+#define JAVA_FSTORE_3 70
+#define ICMD_IF_LCMPLE 70 /* op1 = target JavaVM pc */
+ 1,
+#define JAVA_DSTORE_0 71
+ 1,
+#define JAVA_DSTORE_1 72
+ 1,
+#define JAVA_DSTORE_2 73
+ 1,
+#define JAVA_DSTORE_3 74
+ 1,
+#define JAVA_ASTORE_0 75
+ 1,
+#define JAVA_ASTORE_1 76
+ 1,
+#define JAVA_ASTORE_2 77
+ 1,
+#define JAVA_ASTORE_3 78
+ 1,
+#define JAVA_IASTORE 79
+#define ICMD_IASTORE 79
+ 1,
+#define JAVA_LASTORE 80
+#define ICMD_LASTORE 80
+ 1,
+#define JAVA_FASTORE 81
+#define ICMD_FASTORE 81
+ 1,
+#define JAVA_DASTORE 82
+#define ICMD_DASTORE 82
+ 1,
+#define JAVA_AASTORE 83
+#define ICMD_AASTORE 83
+ 1,
+#define JAVA_BASTORE 84
+#define ICMD_BASTORE 84
+ 1,
+#define JAVA_CASTORE 85
+#define ICMD_CASTORE 85
+ 1,
+#define JAVA_SASTORE 86
+#define ICMD_SASTORE 86
+ 1,
+#define JAVA_POP 87
+#define ICMD_POP 87
+ 1,
+#define JAVA_POP2 88
+#define ICMD_POP2 88
+ 1,
+#define JAVA_DUP 89
+#define ICMD_DUP 89
+ 1,
+#define JAVA_DUP_X1 90
+#define ICMD_DUP_X1 90
+ 1,
+#define JAVA_DUP_X2 91
+#define ICMD_DUP_X2 91
+ 1,
+#define JAVA_DUP2 92
+#define ICMD_DUP2 92
+ 1,
+#define JAVA_DUP2_X1 93
+#define ICMD_DUP2_X1 93
+ 1,
+#define JAVA_DUP2_X2 94
+#define ICMD_DUP2_X2 94
+ 1,
+#define JAVA_SWAP 95
+#define ICMD_SWAP 95
+ 1,
+#define JAVA_IADD 96
+#define ICMD_IADD 96
+ 1,
+#define JAVA_LADD 97
+#define ICMD_LADD 97
+ 1,
+#define JAVA_FADD 98
+#define ICMD_FADD 98
+ 1,
+#define JAVA_DADD 99
+#define ICMD_DADD 99
+ 1,
+#define JAVA_ISUB 100
+#define ICMD_ISUB 100
+ 1,
+#define JAVA_LSUB 101
+#define ICMD_LSUB 101
+ 1,
+#define JAVA_FSUB 102
+#define ICMD_FSUB 102
+ 1,
+#define JAVA_DSUB 103
+#define ICMD_DSUB 103
+ 1,
+#define JAVA_IMUL 104
+#define ICMD_IMUL 104
+ 1,
+#define JAVA_LMUL 105
+#define ICMD_LMUL 105
+ 1,
+#define JAVA_FMUL 106
+#define ICMD_FMUL 106
+ 1,
+#define JAVA_DMUL 107
+#define ICMD_DMUL 107
+ 1,
+#define JAVA_IDIV 108
+#define ICMD_IDIV 108
+ 1,
+#define JAVA_LDIV 109
+#define ICMD_LDIV 109
+ 1,
+#define JAVA_FDIV 110
+#define ICMD_FDIV 110
+ 1,
+#define JAVA_DDIV 111
+#define ICMD_DDIV 111
+ 1,
+#define JAVA_IREM 112
+#define ICMD_IREM 112
+ 1,
+#define JAVA_LREM 113
+#define ICMD_LREM 113
+ 1,
+#define JAVA_FREM 114
+#define ICMD_FREM 114
+ 1,
+#define JAVA_DREM 115
+#define ICMD_DREM 115
+ 1,
+#define JAVA_INEG 116
+#define ICMD_INEG 116
+ 1,
+#define JAVA_LNEG 117
+#define ICMD_LNEG 117
+ 1,
+#define JAVA_FNEG 118
+#define ICMD_FNEG 118
+ 1,
+#define JAVA_DNEG 119
+#define ICMD_DNEG 119
+ 1,
+#define JAVA_ISHL 120
+#define ICMD_ISHL 120
+ 1,
+#define JAVA_LSHL 121
+#define ICMD_LSHL 121
+ 1,
+#define JAVA_ISHR 122
+#define ICMD_ISHR 122
+ 1,
+#define JAVA_LSHR 123
+#define ICMD_LSHR 123
+ 1,
+#define JAVA_IUSHR 124
+#define ICMD_IUSHR 124
+ 1,
+#define JAVA_LUSHR 125
+#define ICMD_LUSHR 125
+ 1,
+#define JAVA_IAND 126
+#define ICMD_IAND 126
+ 1,
+#define JAVA_LAND 127
+#define ICMD_LAND 127
+ 1,
+#define JAVA_IOR 128
+#define ICMD_IOR 128
+ 1,
+#define JAVA_LOR 129
+#define ICMD_LOR 129
+ 1,
+#define JAVA_IXOR 130
+#define ICMD_IXOR 130
+ 1,
+#define JAVA_LXOR 131
+#define ICMD_LXOR 131
+ 1,
+#define JAVA_IINC 132
+#define ICMD_IINC 132 /* op1 = local variable, val.i = constant */
+ 3,
+#define JAVA_I2L 133
+#define ICMD_I2L 133
+ 1,
+#define JAVA_I2F 134
+#define ICMD_I2F 134
+ 1,
+#define JAVA_I2D 135
+#define ICMD_I2D 135
+ 1,
+#define JAVA_L2I 136
+#define ICMD_L2I 136
+ 1,
+#define JAVA_L2F 137
+#define ICMD_L2F 137
+ 1,
+#define JAVA_L2D 138
+#define ICMD_L2D 138
+ 1,
+#define JAVA_F2I 139
+#define ICMD_F2I 139
+ 1,
+#define JAVA_F2L 140
+#define ICMD_F2L 140
+ 1,
+#define JAVA_F2D 141
+#define ICMD_F2D 141
+ 1,
+#define JAVA_D2I 142
+#define ICMD_D2I 142
+ 1,
+#define JAVA_D2L 143
+#define ICMD_D2L 143
+ 1,
+#define JAVA_D2F 144
+#define ICMD_D2F 144
+ 1,
+#define JAVA_INT2BYTE 145
+#define ICMD_INT2BYTE 145
+ 1,
+#define JAVA_INT2CHAR 146
+#define ICMD_INT2CHAR 146
+ 1,
+#define JAVA_INT2SHORT 147
+#define ICMD_INT2SHORT 147
+ 1,
+#define JAVA_LCMP 148
+#define ICMD_LCMP 148
+ 1,
+#define JAVA_FCMPL 149
+#define ICMD_FCMPL 149
+ 1,
+#define JAVA_FCMPG 150
+#define ICMD_FCMPG 150
+ 1,
+#define JAVA_DCMPL 151
+#define ICMD_DCMPL 151
+ 1,
+#define JAVA_DCMPG 152
+#define ICMD_DCMPG 152
+ 1,
+#define JAVA_IFEQ 153
+#define ICMD_IFEQ 153 /* op1 = target JavaVM pc, val.i */
+ 3,
+#define JAVA_IFNE 154
+#define ICMD_IFNE 154 /* op1 = target JavaVM pc, val.i */
+ 3,
+#define JAVA_IFLT 155
+#define ICMD_IFLT 155 /* op1 = target JavaVM pc, val.i */
+ 3,
+#define JAVA_IFGE 156
+#define ICMD_IFGE 156 /* op1 = target JavaVM pc, val.i */
+ 3,
+#define JAVA_IFGT 157
+#define ICMD_IFGT 157 /* op1 = target JavaVM pc, val.i */
+ 3,
+#define JAVA_IFLE 158
+#define ICMD_IFLE 158 /* op1 = target JavaVM pc, val.i */
+ 3,
+#define JAVA_IF_ICMPEQ 159
+#define ICMD_IF_ICMPEQ 159 /* op1 = target JavaVM pc */
+ 3,
+#define JAVA_IF_ICMPNE 160
+#define ICMD_IF_ICMPNE 160 /* op1 = target JavaVM pc */
+ 3,
+#define JAVA_IF_ICMPLT 161
+#define ICMD_IF_ICMPLT 161 /* op1 = target JavaVM pc */
+ 3,
+#define JAVA_IF_ICMPGE 162
+#define ICMD_IF_ICMPGE 162 /* op1 = target JavaVM pc */
+ 3,
+#define JAVA_IF_ICMPGT 163
+#define ICMD_IF_ICMPGT 163 /* op1 = target JavaVM pc */
+ 3,
+#define JAVA_IF_ICMPLE 164
+#define ICMD_IF_ICMPLE 164 /* op1 = target JavaVM pc */
+ 3,
+#define JAVA_IF_ACMPEQ 165
+#define ICMD_IF_ACMPEQ 165 /* op1 = target JavaVM pc */
+ 3,
+#define JAVA_IF_ACMPNE 166
+#define ICMD_IF_ACMPNE 166 /* op1 = target JavaVM pc */
+ 3,
+#define JAVA_GOTO 167
+#define ICMD_GOTO 167 /* op1 = target JavaVM pc */
+ 3,
+#define JAVA_JSR 168
+#define ICMD_JSR 168 /* op1 = target JavaVM pc */
+ 3,
+#define JAVA_RET 169
+#define ICMD_RET 169 /* op1 = local variable */
+ 2,
+#define JAVA_TABLESWITCH 170
+#define ICMD_TABLESWITCH 170 /* val.a = pointer to s4 table */
+ 0, /* length must be computed */
+#define JAVA_LOOKUPSWITCH 171
+#define ICMD_LOOKUPSWITCH 171 /* val.a = pointer to s4 table */
+ 0, /* length must be computed */
+#define JAVA_IRETURN 172
+#define ICMD_IRETURN 172
+ 1,
+#define JAVA_LRETURN 173
+#define ICMD_LRETURN 173
+ 1,
+#define JAVA_FRETURN 174
+#define ICMD_FRETURN 174
+ 1,
+#define JAVA_DRETURN 175
+#define ICMD_DRETURN 175
+ 1,
+#define JAVA_ARETURN 176
+#define ICMD_ARETURN 176
+ 1,
+#define JAVA_RETURN 177
+#define ICMD_RETURN 177
+ 1,
+#define JAVA_GETSTATIC 178
+#define ICMD_GETSTATIC 178 /* op1 = type, val.a = field adress */
+ 3,
+#define JAVA_PUTSTATIC 179
+#define ICMD_PUTSTATIC 179 /* op1 = type, val.a = field adress */
+ 3,
+#define JAVA_GETFIELD 180
+#define ICMD_GETFIELD 180 /* op1 = type, val.i = field offset */
+ 3,
+#define JAVA_PUTFIELD 181
+#define ICMD_PUTFIELD 181 /* op1 = type, val.i = field offset */
+ 3,
+#define JAVA_INVOKEVIRTUAL 182
+#define ICMD_INVOKEVIRTUAL 182 /* val.a = method info pointer */
+ 3,
+#define JAVA_INVOKESPECIAL 183
+#define ICMD_INVOKESPECIAL 183 /* val.a = method info pointer */
+ 3,
+#define JAVA_INVOKESTATIC 184
+#define ICMD_INVOKESTATIC 184 /* val.a = method info pointer */
+ 3,
+#define JAVA_INVOKEINTERFACE 185
+#define ICMD_INVOKEINTERFACE 185 /* val.a = method info pointer */
+ 5,
+#define ICMD_CHECKASIZE 186 /* */
+ 1, /* unused */
+#define JAVA_NEW 187
+#define ICMD_NEW 187 /* op1 = 1, val.a = class pointer */
+ 3,
+#define JAVA_NEWARRAY 188
+#define ICMD_NEWARRAY 188 /* op1 = basic type */
+ 2,
+#define JAVA_ANEWARRAY 189
+#define ICMD_ANEWARRAY 189 /* op1 = 0, val.a = array pointer */
+ 3, /* op1 = 1, val.a = class pointer */
+#define JAVA_ARRAYLENGTH 190
+#define ICMD_ARRAYLENGTH 190
+ 1,
+#define JAVA_ATHROW 191
+#define ICMD_ATHROW 191
+ 1,
+#define JAVA_CHECKCAST 192
+#define ICMD_CHECKCAST 192 /* op1 = 0, val.a = array pointer */
+ 3, /* op1 = 1, val.a = class pointer */
+#define JAVA_INSTANCEOF 193
+#define ICMD_INSTANCEOF 193 /* op1 = 0, val.a = array pointer */
+ 3, /* op1 = 1, val.a = class pointer */
+#define JAVA_MONITORENTER 194
+#define ICMD_MONITORENTER 194
+ 1,
+#define JAVA_MONITOREXIT 195
+#define ICMD_MONITOREXIT 195
+ 1,
+#define JAVA_WIDE 196
+ 0, /* length must be computed */
+#define JAVA_MULTIANEWARRAY 197
+#define ICMD_MULTIANEWARRAY 197 /* op1 = dimension, val.a = array */
+ 4, /* pointer */
+#define JAVA_IFNULL 198
+#define ICMD_IFNULL 198 /* op1 = target JavaVM pc */
+ 3,
+#define JAVA_IFNONNULL 199
+#define ICMD_IFNONNULL 199 /* op1 = target JavaVM pc */
+ 3,
+#define JAVA_GOTO_W 200
+ 5,
+#define JAVA_JSR_W 201
+ 5,
+#define JAVA_BREAKPOINT 202
+ 1,
+
+ 1,1,1,1,1,1,1,1, /* unused */
+ 1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1
+ };
+
+#define ICMD_BUILTIN3 253 /* internal opcode */
+#define ICMD_BUILTIN2 254 /* internal opcode */
+#define ICMD_BUILTIN1 255 /* internal opcode */
+
+
+/******************* description of JavaVM instructions ***********************/
+
+typedef struct {
+ u1 opcode;
+ u1 type_s1;
+ u1 type_s2;
+ u1 type_d;
+ functionptr builtin;
+ bool supported;
+ bool isfloat;
+} stdopdescriptor;
+
+static stdopdescriptor *stdopdescriptors[256];
+
+static stdopdescriptor stdopdescriptortable[] = {
+ { JAVA_IADD, TYPE_INT, TYPE_INT, TYPE_INT, NULL, true, false },
+ { JAVA_ISUB, TYPE_INT, TYPE_INT, TYPE_INT, NULL, true, false },
+ { JAVA_IMUL, TYPE_INT, TYPE_INT, TYPE_INT, NULL, true, false },
+ { JAVA_ISHL, TYPE_INT, TYPE_INT, TYPE_INT, NULL, true, false },
+ { JAVA_ISHR, TYPE_INT, TYPE_INT, TYPE_INT, NULL, true, false },
+ { JAVA_IUSHR, TYPE_INT, TYPE_INT, TYPE_INT, NULL, true, false },
+ { JAVA_IAND, TYPE_INT, TYPE_INT, TYPE_INT, NULL, true, false },
+ { JAVA_IOR, TYPE_INT, TYPE_INT, TYPE_INT, NULL, true, false },
+ { JAVA_IXOR, TYPE_INT, TYPE_INT, TYPE_INT, NULL, true, false },
+ { JAVA_INEG, TYPE_INT, TYPE_VOID,TYPE_INT, NULL, true, false },
+
+ { JAVA_LADD, TYPE_LONG, TYPE_LONG, TYPE_LONG,
+ (functionptr) builtin_ladd , SUPPORT_LONG && SUPPORT_LONG_ADD, false },
+ { JAVA_LSUB, TYPE_LONG, TYPE_LONG, TYPE_LONG,
+ (functionptr) builtin_lsub , SUPPORT_LONG && SUPPORT_LONG_ADD, false },
+ { JAVA_LMUL, TYPE_LONG, TYPE_LONG, TYPE_LONG,
+ (functionptr) builtin_lmul , SUPPORT_LONG && SUPPORT_LONG_MULDIV, false },
+ { JAVA_LSHL, TYPE_LONG, TYPE_INT, TYPE_LONG,
+ (functionptr) builtin_lshl , SUPPORT_LONG && SUPPORT_LONG_SHIFT, false },
+ { JAVA_LSHR, TYPE_LONG, TYPE_INT, TYPE_LONG,
+ (functionptr) builtin_lshr, SUPPORT_LONG && SUPPORT_LONG_SHIFT, false },
+ { JAVA_LUSHR, TYPE_LONG, TYPE_INT, TYPE_LONG,
+ (functionptr) builtin_lushr, SUPPORT_LONG && SUPPORT_LONG_SHIFT, false },
+ { JAVA_LAND, TYPE_LONG, TYPE_LONG, TYPE_LONG,
+ (functionptr) builtin_land, SUPPORT_LONG && SUPPORT_LONG_LOG, false },
+ { JAVA_LOR, TYPE_LONG, TYPE_LONG, TYPE_LONG,
+ (functionptr) builtin_lor , SUPPORT_LONG && SUPPORT_LONG_LOG, false },
+ { JAVA_LXOR, TYPE_LONG, TYPE_LONG, TYPE_LONG,
+ (functionptr) builtin_lxor, SUPPORT_LONG && SUPPORT_LONG_LOG, false },
+ { JAVA_LNEG, TYPE_LONG, TYPE_VOID, TYPE_LONG,
+ (functionptr) builtin_lneg, SUPPORT_LONG && SUPPORT_LONG_ADD, false },
+ { JAVA_LCMP, TYPE_LONG, TYPE_LONG, TYPE_INT,
+ (functionptr) builtin_lcmp, SUPPORT_LONG && SUPPORT_LONG_CMP, false },
+
+ { JAVA_FADD, TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT,
+ (functionptr) builtin_fadd, SUPPORT_FLOAT, true },
+ { JAVA_FSUB, TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT,
+ (functionptr) builtin_fsub, SUPPORT_FLOAT, true },
+ { JAVA_FMUL, TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT,
+ (functionptr) builtin_fmul, SUPPORT_FLOAT, true },
+ { JAVA_FDIV, TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT,
+ (functionptr) builtin_fdiv, SUPPORT_FLOAT, true },
+ { JAVA_FREM, TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT,
+ (functionptr) builtin_frem, SUPPORT_FLOAT, true },
+ { JAVA_FNEG, TYPE_FLOAT, TYPE_VOID, TYPE_FLOAT,
+ (functionptr) builtin_fneg, SUPPORT_FLOAT, true },
+ { JAVA_FCMPL, TYPE_FLOAT, TYPE_FLOAT, TYPE_INT,
+ (functionptr) builtin_fcmpl, SUPPORT_FLOAT, true },
+ { JAVA_FCMPG, TYPE_FLOAT, TYPE_FLOAT, TYPE_INT,
+ (functionptr) builtin_fcmpg, SUPPORT_FLOAT, true },
+
+ { JAVA_DADD, TYPE_DOUBLE, TYPE_DOUBLE, TYPE_DOUBLE,
+ (functionptr) builtin_dadd, SUPPORT_DOUBLE, true },
+ { JAVA_DSUB, TYPE_DOUBLE, TYPE_DOUBLE, TYPE_DOUBLE,
+ (functionptr) builtin_dsub, SUPPORT_DOUBLE, true },
+ { JAVA_DMUL, TYPE_DOUBLE, TYPE_DOUBLE, TYPE_DOUBLE,
+ (functionptr) builtin_dmul, SUPPORT_DOUBLE, true },
+ { JAVA_DDIV, TYPE_DOUBLE, TYPE_DOUBLE, TYPE_DOUBLE,
+ (functionptr) builtin_ddiv, SUPPORT_DOUBLE, true },
+ { JAVA_DREM, TYPE_DOUBLE, TYPE_DOUBLE, TYPE_DOUBLE,
+ (functionptr) builtin_drem, SUPPORT_DOUBLE, true },
+ { JAVA_DNEG, TYPE_DOUBLE, TYPE_VOID, TYPE_DOUBLE,
+ (functionptr) builtin_dneg, SUPPORT_DOUBLE, true },
+ { JAVA_DCMPL, TYPE_DOUBLE, TYPE_DOUBLE, TYPE_INT,
+ (functionptr) builtin_dcmpl, SUPPORT_DOUBLE, true },
+ { JAVA_DCMPG, TYPE_DOUBLE, TYPE_DOUBLE, TYPE_INT,
+ (functionptr) builtin_dcmpg, SUPPORT_DOUBLE, true },
+
+ { JAVA_INT2BYTE, TYPE_INT, TYPE_VOID, TYPE_INT, NULL, true,false },
+ { JAVA_INT2CHAR, TYPE_INT, TYPE_VOID, TYPE_INT, NULL, true,false },
+ { JAVA_INT2SHORT, TYPE_INT, TYPE_VOID, TYPE_INT, NULL, true,false },
+ { JAVA_I2L, TYPE_INT, TYPE_VOID, TYPE_LONG,
+ (functionptr) builtin_i2l, SUPPORT_LONG && SUPPORT_LONG_ICVT, false },
+ { JAVA_I2F, TYPE_INT, TYPE_VOID, TYPE_FLOAT,
+ (functionptr) builtin_i2f, SUPPORT_FLOAT, true },
+ { JAVA_I2D, TYPE_INT, TYPE_VOID, TYPE_DOUBLE,
+ (functionptr) builtin_i2d, SUPPORT_DOUBLE, true },
+ { JAVA_L2I, TYPE_LONG, TYPE_VOID, TYPE_INT,
+ (functionptr) builtin_l2i, SUPPORT_LONG && SUPPORT_LONG_ICVT, false },
+ { JAVA_L2F, TYPE_LONG, TYPE_VOID, TYPE_FLOAT,
+ (functionptr) builtin_l2f, SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_LONG_FCVT, true },
+ { JAVA_L2D, TYPE_LONG, TYPE_VOID, TYPE_DOUBLE,
+ (functionptr) builtin_l2d, SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_LONG_FCVT, true },
+ { JAVA_F2I, TYPE_FLOAT, TYPE_VOID, TYPE_INT,
+ (functionptr) builtin_f2i, SUPPORT_FLOAT, true },
+ { JAVA_F2L, TYPE_FLOAT, TYPE_VOID, TYPE_LONG,
+ (functionptr) builtin_f2l, SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_LONG_FCVT, true },
+ { JAVA_F2D, TYPE_FLOAT, TYPE_VOID, TYPE_DOUBLE,
+ (functionptr) builtin_f2d, SUPPORT_FLOAT && SUPPORT_DOUBLE, true },
+ { JAVA_D2I, TYPE_DOUBLE, TYPE_VOID, TYPE_INT,
+ (functionptr) builtin_d2i, SUPPORT_DOUBLE, true },
+ { JAVA_D2L, TYPE_DOUBLE, TYPE_VOID, TYPE_LONG,
+ (functionptr) builtin_d2l, SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_LONG_FCVT, true },
+ { JAVA_D2F, TYPE_DOUBLE, TYPE_VOID, TYPE_FLOAT,
+ (functionptr) builtin_d2f, SUPPORT_DOUBLE && SUPPORT_FLOAT, true },
+
+};
+
+static char *icmd_names[256] = {
+ "NOP ", /* 0 */
+ "ACONST ", /* 1 */
+ "NULLCHECKPOP ", /* ICONST_M1 2 */
+ "ICONST ", /* 3 */
+ "UNDEF__4 ", /* ICONST_1 4 */
+ "UNDEF__5 ", /* ICONST_2 5 */
+ "UNDEF__6 ", /* ICONST_3 6 */
+ "UNDEF__7 ", /* ICONST_4 7 */
+ "UNDEF__8 ", /* ICONST_5 8 */
+ "LCONST ", /* 9 */
+ "LCMPCONST ", /* LCONST_1 10 */
+ "FCONST ", /* 11 */
+ "UNDEF_12 ", /* FCONST_1 12 */
+ "UNDEF_13 ", /* FCONST_2 13 */
+ "DCONST ", /* 14 */
+ "UNDEF_15 ", /* DCONST_1 15 */
+ "UNDEF_16 ", /* BIPUSH 16 */
+ "UNDEF_17 ", /* SIPUSH 17 */
+ "UNDEF_18 ", /* LDC1 18 */
+ "UNDEF_19 ", /* LDC2 19 */
+ "UNDEF_20 ", /* LDC2W 20 */
+ "ILOAD ", /* 21 */
+ "LLOAD ", /* 22 */
+ "FLOAD ", /* 23 */
+ "DLOAD ", /* 24 */
+ "ALOAD ", /* 25 */
+ "IADDCONST ", /* ILOAD_0 26 */
+ "ISUBCONST ", /* ILOAD_1 27 */
+ "IMULCONST ", /* ILOAD_2 28 */
+ "IANDCONST ", /* ILOAD_3 29 */
+ "IORCONST ", /* LLOAD_0 30 */
+ "IXORCONST ", /* LLOAD_1 31 */
+ "ISHLCONST ", /* LLOAD_2 32 */
+ "ISHRCONST ", /* LLOAD_3 33 */
+ "IUSHRCONST ", /* FLOAD_0 34 */
+ "UNDEF_35 ", /* FLOAD_1 35 */
+ "LADDCONST ", /* FLOAD_2 36 */
+ "LSUBCONST ", /* FLOAD_3 37 */
+ "LMULCONST ", /* DLOAD_0 38 */
+ "LANDCONST ", /* DLOAD_1 39 */
+ "LORCONST ", /* DLOAD_2 40 */
+ "LXORCONST ", /* DLOAD_3 41 */
+ "LSHLCONST ", /* ALOAD_0 42 */
+ "LSHRCONST ", /* ALOAD_1 43 */
+ "LUSHRCONST ", /* ALOAD_2 44 */
+ "UNDEF_45 ", /* ALOAD_3 45 */
+ "IALOAD ", /* 46 */
+ "LALOAD ", /* 47 */
+ "FALOAD ", /* 48 */
+ "DALOAD ", /* 49 */
+ "AALOAD ", /* 50 */
+ "BALOAD ", /* 51 */
+ "CALOAD ", /* 52 */
+ "SALOAD ", /* 53 */
+ "ISTORE ", /* 54 */
+ "LSTORE ", /* 55 */
+ "FSTORE ", /* 56 */
+ "DSTORE ", /* 57 */
+ "ASTORE ", /* 58 */
+ "IF_LEQ ", /* ISTORE_0 59 */
+ "IF_LNE ", /* ISTORE_1 60 */
+ "IF_LLT ", /* ISTORE_2 61 */
+ "IF_LGE ", /* ISTORE_3 62 */
+ "IF_LGT ", /* LSTORE_0 63 */
+ "IF_LLE ", /* LSTORE_1 64 */
+ "IF_LCMPEQ ", /* LSTORE_2 65 */
+ "IF_LCMPNE ", /* LSTORE_3 66 */
+ "IF_LCMPLT ", /* FSTORE_0 67 */
+ "IF_LCMPGE ", /* FSTORE_1 68 */
+ "IF_LCMPGT ", /* FSTORE_2 69 */
+ "IF_LCMPLE ", /* FSTORE_3 70 */
+ "UNDEF_71 ", /* DSTORE_0 71 */
+ "UNDEF_72 ", /* DSTORE_1 72 */
+ "UNDEF_73 ", /* DSTORE_2 73 */
+ "UNDEF_74 ", /* DSTORE_3 74 */
+ "UNDEF_75 ", /* ASTORE_0 75 */
+ "UNDEF_76 ", /* ASTORE_1 76 */
+ "UNDEF_77 ", /* ASTORE_2 77 */
+ "UNDEF_78 ", /* ASTORE_3 78 */
+ "IASTORE ", /* 79 */
+ "LASTORE ", /* 80 */
+ "FASTORE ", /* 81 */
+ "DASTORE ", /* 82 */
+ "AASTORE ", /* 83 */
+ "BASTORE ", /* 84 */
+ "CASTORE ", /* 85 */
+ "SASTORE ", /* 86 */
+ "POP ", /* 87 */
+ "POP2 ", /* 88 */
+ "DUP ", /* 89 */
+ "DUP_X1 ", /* 90 */
+ "DUP_X2 ", /* 91 */
+ "DUP2 ", /* 92 */
+ "DUP2_X1 ", /* 93 */
+ "DUP2_X2 ", /* 94 */
+ "SWAP ", /* 95 */
+ "IADD ", /* 96 */
+ "LADD ", /* 97 */
+ "FADD ", /* 98 */
+ "DADD ", /* 99 */
+ "ISUB ", /* 100 */
+ "LSUB ", /* 101 */
+ "FSUB ", /* 102 */
+ "DSUB ", /* 103 */
+ "IMUL ", /* 104 */
+ "LMUL ", /* 105 */
+ "FMUL ", /* 106 */
+ "DMUL ", /* 107 */
+ "IDIV ", /* 108 */
+ "LDIV ", /* 109 */
+ "FDIV ", /* 110 */
+ "DDIV ", /* 111 */
+ "IREM ", /* 112 */
+ "LREM ", /* 113 */
+ "FREM ", /* 114 */
+ "DREM ", /* 115 */
+ "INEG ", /* 116 */
+ "LNEG ", /* 117 */
+ "FNEG ", /* 118 */
+ "DNEG ", /* 119 */
+ "ISHL ", /* 120 */
+ "LSHL ", /* 121 */
+ "ISHR ", /* 122 */
+ "LSHR ", /* 123 */
+ "IUSHR ", /* 124 */
+ "LUSHR ", /* 125 */
+ "IAND ", /* 126 */
+ "LAND ", /* 127 */
+ "IOR ", /* 128 */
+ "LOR ", /* 129 */
+ "IXOR ", /* 130 */
+ "LXOR ", /* 131 */
+ "IINC ", /* 132 */
+ "I2L ", /* 133 */
+ "I2F ", /* 134 */
+ "I2D ", /* 135 */
+ "L2I ", /* 136 */
+ "L2F ", /* 137 */
+ "L2D ", /* 138 */
+ "F2I ", /* 139 */
+ "F2L ", /* 140 */
+ "F2D ", /* 141 */
+ "D2I ", /* 142 */
+ "D2L ", /* 143 */
+ "D2F ", /* 144 */
+ "INT2BYTE ", /* 145 */
+ "INT2CHAR ", /* 146 */
+ "INT2SHORT ", /* 147 */
+ "LCMP ", /* 148 */
+ "FCMPL ", /* 149 */
+ "FCMPG ", /* 150 */
+ "DCMPL ", /* 151 */
+ "DCMPG ", /* 152 */
+ "IFEQ ", /* 153 */
+ "IFNE ", /* 154 */
+ "IFLT ", /* 155 */
+ "IFGE ", /* 156 */
+ "IFGT ", /* 157 */
+ "IFLE ", /* 158 */
+ "IF_ICMPEQ ", /* 159 */
+ "IF_ICMPNE ", /* 160 */
+ "IF_ICMPLT ", /* 161 */
+ "IF_ICMPGE ", /* 162 */
+ "IF_ICMPGT ", /* 163 */
+ "IF_ICMPLE ", /* 164 */
+ "IF_ACMPEQ ", /* 165 */
+ "IF_ACMPNE ", /* 166 */
+ "GOTO ", /* 167 */
+ "JSR ", /* 168 */
+ "RET ", /* 169 */
+ "TABLESWITCH ", /* 170 */
+ "LOOKUPSWITCH ", /* 171 */
+ "IRETURN ", /* 172 */
+ "LRETURN ", /* 173 */
+ "FRETURN ", /* 174 */
+ "DRETURN ", /* 175 */
+ "ARETURN ", /* 176 */
+ "RETURN ", /* 177 */
+ "GETSTATIC ", /* 178 */
+ "PUTSTATIC ", /* 179 */
+ "GETFIELD ", /* 180 */
+ "PUTFIELD ", /* 181 */
+ "INVOKEVIRTUAL", /* 182 */
+ "INVOKESPECIAL", /* 183 */
+ "INVOKESTATIC ", /* 184 */
+ "INVOKEINTERFACE",/* 185 */
+ "CHECKASIZE ", /* UNDEF186 186 */
+ "NEW ", /* 187 */
+ "NEWARRAY ", /* 188 */
+ "ANEWARRAY ", /* 189 */
+ "ARRAYLENGTH ", /* 190 */
+ "ATHROW ", /* 191 */
+ "CHECKCAST ", /* 192 */
+ "INSTANCEOF ", /* 193 */
+ "MONITORENTER ", /* 194 */
+ "MONITOREXIT ", /* 195 */
+ "UNDEF196 ", /* WIDE 196 */
+ "MULTIANEWARRAY",/* 197 */
+ "IFNULL ", /* 198 */
+ "IFNONNULL ", /* 199 */
+ "UNDEF200 ", /* GOTO_W 200 */
+ "UNDEF201 ", /* JSR_W 201 */
+ "UNDEF202 ", /* BREAKPOINT 202 */
+
+ "UNDEF203","UNDEF204","UNDEF205",
+ "UNDEF206","UNDEF207","UNDEF208","UNDEF209","UNDEF210",
+ "UNDEF","UNDEF","UNDEF","UNDEF","UNDEF",
+ "UNDEF216","UNDEF217","UNDEF218","UNDEF219","UNDEF220",
+ "UNDEF","UNDEF","UNDEF","UNDEF","UNDEF",
+ "UNDEF226","UNDEF227","UNDEF228","UNDEF229","UNDEF230",
+ "UNDEF","UNDEF","UNDEF","UNDEF","UNDEF",
+ "UNDEF236","UNDEF237","UNDEF238","UNDEF239","UNDEF240",
+ "UNDEF","UNDEF","UNDEF","UNDEF","UNDEF",
+ "UNDEF246","UNDEF247","UNDEF248","UNDEF249","UNDEF250",
+ "UNDEF251","UNDEF252",
+ "BUILTIN3 ", /* 253 */
+ "BUILTIN2 ", /* 254 */
+ "BUILTIN1 " /* 255 */
+ };
+
+
+
+/***************************** register types *********************************/
+
+#define REG_RES 0 /* reserved register for OS or code generator */
+#define REG_RET 1 /* return value register */
+#define REG_EXC 2 /* exception value register */
+#define REG_SAV 3 /* (callee) saved register */
+#define REG_TMP 4 /* scratch temporary register (caller saved) */
+#define REG_ARG 5 /* argument register (caller saved) */
+
+#define REG_END -1 /* last entry in tables */
+
+#define PARAMMODE_NUMBERED 0
+#define PARAMMODE_STUFFED 1
+
+/***************************** register info block ****************************/
+
+extern int nregdescint[]; /* description of integer registers */
+extern int nregdescfloat[]; /* description of floating point registers */
+
+extern int nreg_parammode;
+
+void asm_handle_exception();
+void asm_handle_nat_exception();
--- /dev/null
+/****************************** ncomp/nparse.c *********************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Parser for JavaVM to intermediate code translation
+
+ Author: Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1998/05/07
+
+*******************************************************************************/
+
+#include "math.h"
+
+/*********************** function allocate_literals ****************************
+
+ Scans the JavaVM code of a method and allocates string literals. Needed
+ to generate the same addresses as the old JIT compiler.
+
+*******************************************************************************/
+
+static void allocate_literals()
+{
+ int p, nextp;
+ int opcode, i;
+ s4 num;
+ unicode *s;
+
+ for (p = 0; p < jcodelength; p = nextp) {
+
+ opcode = jcode[p];
+ nextp = p + jcommandsize[opcode];
+
+ switch (opcode) {
+ case JAVA_WIDE:
+ if (code_get_u1(p + 1) == JAVA_IINC)
+ nextp = p + 6;
+ else
+ nextp = p + 4;
+ break;
+
+ case JAVA_LOOKUPSWITCH:
+ nextp = ALIGN((p + 1), 4);
+ num = code_get_u4(nextp + 4);
+ nextp = nextp + 8 + 8 * num;
+ break;
+
+ case JAVA_TABLESWITCH:
+ nextp = ALIGN ((p + 1),4);
+ num = code_get_s4(nextp + 4);
+ num = code_get_s4(nextp + 8) - num;
+ nextp = nextp + 16 + 4 * num;
+ break;
+
+ case JAVA_LDC1:
+ i = code_get_u1(p+1);
+ goto pushconstantitem;
+ case JAVA_LDC2:
+ case JAVA_LDC2W:
+ i = code_get_u2(p + 1);
+ pushconstantitem:
+ if (class_constanttype(class, i) == CONSTANT_String) {
+ s = class_getconstant(class, i, CONSTANT_String);
+ (void) literalstring_new(s);
+ }
+ break;
+ } /* end switch */
+ } /* end while */
+}
+
+
+
+/*******************************************************************************
+
+ function 'parse' scans the JavaVM code and generates intermediate code
+
+ During parsing the block index table is used to store at bit pos 0
+ a flag which marks basic block starts and at position 1 to 31 the
+ intermediate instruction index. After parsing the block index table
+ is scanned, for marked positions a block is generated and the block
+ number is stored in the block index table.
+
+*******************************************************************************/
+
+/* intermediate code generating macros */
+
+#define PINC iptr++;ipc++
+#define LOADCONST_I(v) iptr->opc=ICMD_ICONST;iptr->op1=0;iptr->val.i=(v);PINC
+#define LOADCONST_L(v) iptr->opc=ICMD_LCONST;iptr->op1=0;iptr->val.l=(v);PINC
+#define LOADCONST_F(v) iptr->opc=ICMD_FCONST;iptr->op1=0;iptr->val.f=(v);PINC
+#define LOADCONST_D(v) iptr->opc=ICMD_DCONST;iptr->op1=0;iptr->val.d=(v);PINC
+#define LOADCONST_A(v) iptr->opc=ICMD_ACONST;iptr->op1=0;iptr->val.a=(v);PINC
+#define OP(o) iptr->opc=(o);iptr->op1=0;iptr->val.l=0;PINC
+#define OP1(o,o1) iptr->opc=(o);iptr->op1=(o1);iptr->val.l=(0);PINC
+#define OP2I(o,o1,v) iptr->opc=(o);iptr->op1=(o1);iptr->val.i=(v);PINC
+#define OP2A(o,o1,v) iptr->opc=(o);iptr->op1=(o1);iptr->val.a=(v);PINC
+#define BUILTIN1(v,t) isleafmethod=false;iptr->opc=ICMD_BUILTIN1;iptr->op1=t;\
+ iptr->val.a=(v);PINC
+#define BUILTIN2(v,t) isleafmethod=false;iptr->opc=ICMD_BUILTIN2;iptr->op1=t;\
+ iptr->val.a=(v);PINC
+#define BUILTIN3(v,t) isleafmethod=false;iptr->opc=ICMD_BUILTIN3;iptr->op1=t;\
+ iptr->val.a=(v);PINC
+
+
+/* block generating and checking macros */
+
+#define block_insert(i) {if(!(block_index[i]&1))\
+ {b_count++;block_index[i] |= 1;}}
+#define bound_check(i) {if((i< 0) || (i>=jcodelength)) \
+ panic("branch target out of code-boundary");}
+#define bound_check1(i) {if((i< 0) || (i>jcodelength)) \
+ panic("branch target out of code-boundary");}
+
+
+static void parse()
+{
+ int p; /* java instruction counter */
+ int nextp; /* start of next java instruction */
+ int opcode; /* java opcode */
+ int i; /* temporary for different uses (counters) */
+ int ipc = 0; /* intermediate instruction counter */
+ int b_count = 0; /* basic block counter */
+ int s_count = 0; /* stack element counter */
+ bool blockend = false; /* true if basic block end has reached */
+ bool iswide = false; /* true if last instruction was a wide */
+ instruction *iptr; /* current pointer into instruction array */
+
+
+ /* allocate instruction array and block index table */
+
+ /* 1 additional for end ipc and 3 for loop unrolling */
+
+ block_index = DMNEW(int, jcodelength + 3);
+
+ /* 1 additional for TRACEBUILTIN and 4 for MONITORENTER/EXIT */
+ /* additional MONITOREXITS are reached by branches which are 3 bytes */
+
+ iptr = instr = DMNEW(instruction, jcodelength + 5);
+
+ /* initialize block_index table (unrolled four times) */
+
+ {
+ int *ip;
+
+ for (i = 0, ip = block_index; i <= jcodelength; i += 4, ip += 4) {
+ ip[0] = 0;
+ ip[1] = 0;
+ ip[2] = 0;
+ ip[3] = 0;
+ }
+ }
+
+ /* compute branch targets of exception table */
+
+ for (i = 0; i < exceptiontablelength; i++) {
+ p = extable[i].startpc;
+ bound_check(p);
+ block_insert(p);
+ p = extable[i].endpc;
+ bound_check1(p);
+ if (p < jcodelength)
+ block_insert(p);
+ p = extable[i].handlerpc;
+ bound_check(p);
+ block_insert(p);
+ }
+
+ s_count = 1 + exceptiontablelength; /* initialize stack element counter */
+
+ if (runverbose) {
+/* isleafmethod=false; */
+ }
+
+#ifdef USE_THREADS
+ if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
+ isleafmethod=false;
+ }
+#endif
+
+ /* scan all java instructions */
+
+ for (p = 0; p < jcodelength; p = nextp) {
+
+ opcode = code_get_u1 (p); /* fetch op code */
+
+ block_index[p] |= (ipc << 1); /* store intermediate count */
+
+ if (blockend) {
+ block_insert(p); /* start new block */
+ blockend = false;
+ }
+
+ nextp = p + jcommandsize[opcode]; /* compute next instruction start */
+ s_count += stackreq[opcode]; /* compute stack element count */
+
+ switch (opcode) {
+
+ case JAVA_NOP:
+ break;
+
+ /* pushing constants onto the stack p */
+
+ case JAVA_BIPUSH:
+ LOADCONST_I(code_get_s1(p+1));
+ break;
+
+ case JAVA_SIPUSH:
+ LOADCONST_I(code_get_s2(p+1));
+ break;
+
+ case JAVA_LDC1:
+ i = code_get_u1(p+1);
+ goto pushconstantitem;
+ case JAVA_LDC2:
+ case JAVA_LDC2W:
+ i = code_get_u2(p + 1);
+
+ pushconstantitem:
+
+ if (i >= class->cpcount)
+ panic ("Attempt to access constant outside range");
+
+ switch (class->cptags[i]) {
+ case CONSTANT_Integer:
+ LOADCONST_I(((constant_integer*)
+ (class->cpinfos[i]))->value);
+ break;
+ case CONSTANT_Long:
+ LOADCONST_L(((constant_long*)
+ (class->cpinfos[i]))->value);
+ break;
+ case CONSTANT_Float:
+ LOADCONST_F(((constant_float*)
+ (class->cpinfos[i]))->value);
+ break;
+ case CONSTANT_Double:
+ LOADCONST_D(((constant_double*)
+ (class->cpinfos[i]))->value);
+ break;
+ case CONSTANT_String:
+ LOADCONST_A(literalstring_new((unicode*)
+ (class->cpinfos[i])));
+ break;
+ default: panic("Invalid constant type to push");
+ }
+ break;
+
+ case JAVA_ACONST_NULL:
+ LOADCONST_A(NULL);
+ break;
+
+ case JAVA_ICONST_M1:
+ case JAVA_ICONST_0:
+ case JAVA_ICONST_1:
+ case JAVA_ICONST_2:
+ case JAVA_ICONST_3:
+ case JAVA_ICONST_4:
+ case JAVA_ICONST_5:
+ LOADCONST_I(opcode - JAVA_ICONST_0);
+ break;
+
+ case JAVA_LCONST_0:
+ case JAVA_LCONST_1:
+ LOADCONST_L(opcode - JAVA_LCONST_0);
+ break;
+
+ case JAVA_FCONST_0:
+ case JAVA_FCONST_1:
+ case JAVA_FCONST_2:
+ LOADCONST_F(opcode - JAVA_FCONST_0);
+ break;
+
+ case JAVA_DCONST_0:
+ case JAVA_DCONST_1:
+ LOADCONST_D(opcode - JAVA_DCONST_0);
+ break;
+
+ /* loading variables onto the stack */
+
+ case JAVA_ILOAD:
+ case JAVA_LLOAD:
+ case JAVA_FLOAD:
+ case JAVA_DLOAD:
+ case JAVA_ALOAD:
+ if (!iswide)
+ i = code_get_u1(p+1);
+ else {
+ i = code_get_u2(p+1);
+ nextp = p+3;
+ iswide = false;
+ }
+ OP1(opcode, i);
+ break;
+
+ case JAVA_ILOAD_0:
+ case JAVA_ILOAD_1:
+ case JAVA_ILOAD_2:
+ case JAVA_ILOAD_3:
+ OP1(ICMD_ILOAD, opcode - JAVA_ILOAD_0);
+ break;
+
+ case JAVA_LLOAD_0:
+ case JAVA_LLOAD_1:
+ case JAVA_LLOAD_2:
+ case JAVA_LLOAD_3:
+ OP1(ICMD_LLOAD, opcode - JAVA_LLOAD_0);
+ break;
+
+ case JAVA_FLOAD_0:
+ case JAVA_FLOAD_1:
+ case JAVA_FLOAD_2:
+ case JAVA_FLOAD_3:
+ OP1(ICMD_FLOAD, opcode - JAVA_FLOAD_0);
+ break;
+
+ case JAVA_DLOAD_0:
+ case JAVA_DLOAD_1:
+ case JAVA_DLOAD_2:
+ case JAVA_DLOAD_3:
+ OP1(ICMD_DLOAD, opcode - JAVA_DLOAD_0);
+ break;
+
+ case JAVA_ALOAD_0:
+ case JAVA_ALOAD_1:
+ case JAVA_ALOAD_2:
+ case JAVA_ALOAD_3:
+ OP1(ICMD_ALOAD, opcode - JAVA_ALOAD_0);
+ break;
+
+ /* storing stack values into local variables */
+
+ case JAVA_ISTORE:
+ case JAVA_LSTORE:
+ case JAVA_FSTORE:
+ case JAVA_DSTORE:
+ case JAVA_ASTORE:
+ if (!iswide)
+ i = code_get_u1(p+1);
+ else {
+ i = code_get_u2(p+1);
+ iswide=false;
+ nextp = p+3;
+ }
+ OP1(opcode, i);
+ break;
+
+ case JAVA_ISTORE_0:
+ case JAVA_ISTORE_1:
+ case JAVA_ISTORE_2:
+ case JAVA_ISTORE_3:
+ OP1(ICMD_ISTORE, opcode - JAVA_ISTORE_0);
+ break;
+
+ case JAVA_LSTORE_0:
+ case JAVA_LSTORE_1:
+ case JAVA_LSTORE_2:
+ case JAVA_LSTORE_3:
+ OP1(ICMD_LSTORE, opcode - JAVA_LSTORE_0);
+ break;
+
+ case JAVA_FSTORE_0:
+ case JAVA_FSTORE_1:
+ case JAVA_FSTORE_2:
+ case JAVA_FSTORE_3:
+ OP1(ICMD_FSTORE, opcode - JAVA_FSTORE_0);
+ break;
+
+ case JAVA_DSTORE_0:
+ case JAVA_DSTORE_1:
+ case JAVA_DSTORE_2:
+ case JAVA_DSTORE_3:
+ OP1(ICMD_DSTORE, opcode - JAVA_DSTORE_0);
+ break;
+
+ case JAVA_ASTORE_0:
+ case JAVA_ASTORE_1:
+ case JAVA_ASTORE_2:
+ case JAVA_ASTORE_3:
+ OP1(ICMD_ASTORE, opcode - JAVA_ASTORE_0);
+ break;
+
+ case JAVA_IINC:
+ {
+ int v;
+
+ if (!iswide) {
+ i = code_get_u1(p + 1);
+ v = code_get_s1(p + 2);
+ }
+ else {
+ i = code_get_u2(p + 1);
+ v = code_get_s2(p + 3);
+ iswide = false;
+ nextp = p+5;
+ }
+ OP2I(opcode, i, v);
+ }
+ break;
+
+ /* wider index for loading, storing and incrementing */
+
+ case JAVA_WIDE:
+ iswide = true;
+ nextp = p + 1;
+ break;
+
+ /*********************** managing arrays **************************/
+
+ case JAVA_NEWARRAY:
+ OP2I(ICMD_CHECKASIZE, 0, 0);
+ switch (code_get_s1(p+1)) {
+ case 4:
+ BUILTIN1((functionptr)builtin_newarray_boolean, TYPE_ADR);
+ break;
+ case 5:
+ BUILTIN1((functionptr)builtin_newarray_char, TYPE_ADR);
+ break;
+ case 6:
+ BUILTIN1((functionptr)builtin_newarray_float, TYPE_ADR);
+ break;
+ case 7:
+ BUILTIN1((functionptr)builtin_newarray_double, TYPE_ADR);
+ break;
+ case 8:
+ BUILTIN1((functionptr)builtin_newarray_byte, TYPE_ADR);
+ break;
+ case 9:
+ BUILTIN1((functionptr)builtin_newarray_short, TYPE_ADR);
+ break;
+ case 10:
+ BUILTIN1((functionptr)builtin_newarray_int, TYPE_ADR);
+ break;
+ case 11:
+ BUILTIN1((functionptr)builtin_newarray_long, TYPE_ADR);
+ break;
+ default: panic("Invalid array-type to create");
+ }
+ break;
+
+ case JAVA_ANEWARRAY:
+ OP2I(ICMD_CHECKASIZE, 0, 0);
+ i = code_get_u2(p+1);
+ /* array or class type ? */
+ if (class_constanttype (class, i) == CONSTANT_Arraydescriptor) {
+ LOADCONST_A(class_getconstant(class, i,
+ CONSTANT_Arraydescriptor));
+ BUILTIN2((functionptr)builtin_newarray_array, TYPE_ADR);
+ }
+ else {
+ LOADCONST_A(class_getconstant(class, i, CONSTANT_Class));
+ BUILTIN2((functionptr)builtin_anewarray, TYPE_ADR);
+ }
+ break;
+
+ case JAVA_MULTIANEWARRAY:
+ isleafmethod=false;
+ i = code_get_u2(p+1);
+ {
+ int v = code_get_u1(p+3);
+ constant_arraydescriptor *desc =
+ class_getconstant (class, i, CONSTANT_Arraydescriptor);
+ OP2A(opcode, v, desc);
+ }
+ break;
+
+ case JAVA_IFEQ:
+ case JAVA_IFLT:
+ case JAVA_IFLE:
+ case JAVA_IFNE:
+ case JAVA_IFGT:
+ case JAVA_IFGE:
+ case JAVA_IFNULL:
+ case JAVA_IFNONNULL:
+ case JAVA_IF_ICMPEQ:
+ case JAVA_IF_ICMPNE:
+ case JAVA_IF_ICMPLT:
+ case JAVA_IF_ICMPGT:
+ case JAVA_IF_ICMPLE:
+ case JAVA_IF_ICMPGE:
+ case JAVA_IF_ACMPEQ:
+ case JAVA_IF_ACMPNE:
+ case JAVA_GOTO:
+ case JAVA_JSR:
+ i = p + code_get_s2(p+1);
+ bound_check(i);
+ block_insert(i);
+ blockend = true;
+ OP1(opcode, i);
+ break;
+ case JAVA_GOTO_W:
+ case JAVA_JSR_W:
+ i = p + code_get_s4(p+1);
+ bound_check(i);
+ block_insert(i);
+ blockend = true;
+ OP1(opcode, i);
+ break;
+
+ case JAVA_RET:
+ if (!iswide)
+ i = code_get_u1(p+1);
+ else {
+ i = code_get_u2(p+1);
+ nextp = p+3;
+ iswide = false;
+ }
+ blockend = true;
+ OP1(opcode, i);
+ break;
+
+ case JAVA_IRETURN:
+ case JAVA_LRETURN:
+ case JAVA_FRETURN:
+ case JAVA_DRETURN:
+ case JAVA_ARETURN:
+ case JAVA_RETURN:
+ blockend = true;
+ OP(opcode);
+ break;
+
+ case JAVA_ATHROW:
+ blockend = true;
+ OP(opcode);
+ break;
+
+
+ /**************** table jumps *****************/
+
+ case JAVA_LOOKUPSWITCH:
+ {
+ s4 num, j;
+
+ blockend = true;
+ nextp = ALIGN((p + 1), 4);
+ OP2A(opcode, 0, jcode + nextp);
+
+ /* default target */
+
+ j = p + code_get_s4(nextp);
+ *((s4*)(jcode + nextp)) = j; /* restore for little endian */
+ nextp += 4;
+ bound_check(j);
+ block_insert(j);
+
+ /* number of pairs */
+
+ num = code_get_u4(nextp);
+ *((s4*)(jcode + nextp)) = num;
+ nextp += 4;
+
+ for (i = 0; i < num; i++) {
+
+ /* value */
+
+ j = code_get_s4(nextp);
+ *((s4*)(jcode + nextp)) = j; /* restore for little endian */
+ nextp += 4;
+
+ /* target */
+
+ j = p + code_get_s4(nextp);
+ *((s4*)(jcode + nextp)) = j; /* restore for little endian */
+ nextp += 4;
+ bound_check(j);
+ block_insert(j);
+ }
+
+ break;
+ }
+
+
+ case JAVA_TABLESWITCH:
+ {
+ s4 num, j;
+
+ blockend = true;
+ nextp = ALIGN((p + 1), 4);
+ OP2A(opcode, 0, jcode + nextp);
+
+ /* default target */
+
+ j = p + code_get_s4(nextp);
+ *((s4*)(jcode + nextp)) = j; /* restore for little endian */
+ nextp += 4;
+ bound_check(j);
+ block_insert(j);
+
+ /* lower bound */
+
+ j = code_get_s4(nextp);
+ *((s4*)(jcode + nextp)) = j; /* restore for little endian */
+ nextp += 4;
+
+ /* upper bound */
+
+ num = code_get_s4(nextp);
+ *((s4*)(jcode + nextp)) = num; /* restore for little endian */
+ nextp += 4;
+
+ num -= j;
+
+ for (i = 0; i <= num; i++) {
+ j = p + code_get_s4(nextp);
+ *((s4*)(jcode + nextp)) = j; /* restore for little endian */
+ nextp += 4;
+ bound_check(j);
+ block_insert(j);
+ }
+
+ break;
+ }
+
+
+ /************ load and store of object fields ********/
+
+ case JAVA_AASTORE:
+ BUILTIN3((functionptr) new_builtin_aastore, TYPE_VOID);
+ break;
+
+ case JAVA_PUTSTATIC:
+ case JAVA_GETSTATIC:
+ i = code_get_u2(p + 1);
+ {
+ constant_FMIref *fr;
+ fieldinfo *fi;
+ fr = class_getconstant (class, i, CONSTANT_Fieldref);
+ fi = class_findfield (fr->class, fr->name, fr->descriptor);
+ compiler_addinitclass (fr->class);
+ OP2A(opcode, fi->type, &(fi->value));
+ }
+ break;
+ case JAVA_PUTFIELD:
+ case JAVA_GETFIELD:
+ i = code_get_u2(p + 1);
+ {
+ constant_FMIref *fr;
+ fieldinfo *fi;
+ fr = class_getconstant (class, i, CONSTANT_Fieldref);
+ fi = class_findfield (fr->class, fr->name, fr->descriptor);
+ OP2I(opcode, fi->type, fi->offset);
+ }
+ break;
+
+
+ /*** method invocation ***/
+
+ case JAVA_INVOKESTATIC:
+ i = code_get_u2(p + 1);
+ {
+ constant_FMIref *mr;
+ methodinfo *mi;
+
+ mr = class_getconstant (class, i, CONSTANT_Methodref);
+ mi = class_findmethod (mr->class, mr->name, mr->descriptor);
+ if (! (mi->flags & ACC_STATIC))
+ panic ("Static/Nonstatic mismatch calling static method");
+ descriptor2types(mi);
+ isleafmethod=false;
+ OP2A(opcode, mi->paramcount, mi);
+ }
+ break;
+ case JAVA_INVOKESPECIAL:
+ case JAVA_INVOKEVIRTUAL:
+ i = code_get_u2(p + 1);
+ {
+ constant_FMIref *mr;
+ methodinfo *mi;
+
+ mr = class_getconstant (class, i, CONSTANT_Methodref);
+ mi = class_findmethod (mr->class, mr->name, mr->descriptor);
+ if (mi->flags & ACC_STATIC)
+ panic ("Static/Nonstatic mismatch calling static method");
+ descriptor2types(mi);
+ isleafmethod=false;
+ OP2A(opcode, mi->paramcount, mi);
+ }
+ break;
+ case JAVA_INVOKEINTERFACE:
+ i = code_get_u2(p + 1);
+ {
+ constant_FMIref *mr;
+ methodinfo *mi;
+
+ mr = class_getconstant (class, i, CONSTANT_InterfaceMethodref);
+ mi = class_findmethod (mr->class, mr->name, mr->descriptor);
+ if (mi->flags & ACC_STATIC)
+ panic ("Static/Nonstatic mismatch calling static method");
+ descriptor2types(mi);
+ isleafmethod=false;
+ OP2A(opcode, mi->paramcount, mi);
+ }
+ break;
+
+ /***** miscellaneous object operations ****/
+
+ case JAVA_NEW:
+ i = code_get_u2 (p+1);
+ LOADCONST_A(class_getconstant(class, i, CONSTANT_Class));
+ BUILTIN1((functionptr) builtin_new, TYPE_ADR);
+ break;
+
+ case JAVA_CHECKCAST:
+ i = code_get_u2(p+1);
+
+ /* array type cast-check */
+ if (class_constanttype (class, i) == CONSTANT_Arraydescriptor) {
+ LOADCONST_A(class_getconstant(class, i, CONSTANT_Arraydescriptor));
+ BUILTIN2((functionptr) new_builtin_checkarraycast, TYPE_ADR);
+ }
+ else { /* object type cast-check */
+ LOADCONST_A(class_getconstant(class, i, CONSTANT_Class));
+ BUILTIN2((functionptr) new_builtin_checkcast, TYPE_ADR);
+ }
+ break;
+
+ case JAVA_INSTANCEOF:
+ i = code_get_u2(p+1);
+
+ /* array type cast-check */
+ if (class_constanttype (class, i) == CONSTANT_Arraydescriptor) {
+ LOADCONST_A(class_getconstant(class, i, CONSTANT_Arraydescriptor));
+ BUILTIN2((functionptr) builtin_arrayinstanceof, TYPE_INT);
+ }
+ else { /* object type cast-check */
+ LOADCONST_A(class_getconstant(class, i, CONSTANT_Class));
+ BUILTIN2((functionptr) builtin_instanceof, TYPE_INT);
+ }
+ break;
+
+ case JAVA_MONITORENTER:
+#ifdef USE_THREADS
+ if (checksync) {
+#ifdef SOFTNULLPTRCHECK
+ if (checknull) {
+ BUILTIN1((functionptr) new_builtin_monitorenter, TYPE_VOID);
+ }
+ else {
+/* BUILTIN1((functionptr) builtin_monitorenter, TYPE_VOID); */
+ BUILTIN1((functionptr) new_builtin_monitorenter, TYPE_VOID);
+ }
+#else
+ BUILTIN1((functionptr) builtin_monitorenter, TYPE_VOID);
+#endif
+ }
+ else
+#endif
+ {
+ OP(ICMD_NULLCHECKPOP);
+ }
+ break;
+
+ case JAVA_MONITOREXIT:
+#ifdef USE_THREADS
+ if (checksync) {
+ BUILTIN1((functionptr) builtin_monitorexit, TYPE_VOID);
+ }
+ else
+#endif
+ {
+ OP(ICMD_POP);
+ }
+ break;
+
+ /************** any other basic operation **********/
+
+ case JAVA_IDIV:
+ if (SUPPORT_DIVISION) {
+ OP(opcode);
+ }
+ else {
+ BUILTIN2((functionptr) new_builtin_idiv, TYPE_INT);
+ }
+ break;
+
+ case JAVA_IREM:
+ if (SUPPORT_DIVISION) {
+ OP(opcode);
+ }
+ else {
+ BUILTIN2((functionptr) new_builtin_irem, TYPE_INT);
+ }
+ break;
+
+ case JAVA_LDIV:
+ if (SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_MULDIV) {
+ OP(opcode);
+ }
+ else {
+ BUILTIN2((functionptr) new_builtin_ldiv, TYPE_LONG);
+ }
+ break;
+
+ case JAVA_LREM:
+ if (SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_MULDIV) {
+ OP(opcode);
+ }
+ else {
+ BUILTIN2((functionptr) new_builtin_lrem, TYPE_LONG);
+ }
+ break;
+
+ case JAVA_FREM:
+ BUILTIN2((functionptr) builtin_frem, TYPE_FLOAT);
+ break;
+
+ case JAVA_DREM:
+ BUILTIN2((functionptr) builtin_drem, TYPE_DOUBLE);
+ break;
+
+ case JAVA_F2I:
+ if (checkfloats) {
+ BUILTIN1((functionptr) builtin_f2i, TYPE_INT);
+ }
+ else {
+ OP(opcode);
+ }
+ break;
+
+ case JAVA_F2L:
+ if (checkfloats) {
+ BUILTIN1((functionptr) builtin_f2l, TYPE_LONG);
+ }
+ else {
+ OP(opcode);
+ }
+ break;
+
+ case JAVA_D2I:
+ if (checkfloats) {
+ BUILTIN1((functionptr) builtin_d2i, TYPE_INT);
+ }
+ else {
+ OP(opcode);
+ }
+ break;
+
+ case JAVA_D2L:
+ if (checkfloats) {
+ BUILTIN1((functionptr) builtin_d2l, TYPE_LONG);
+ }
+ else {
+ OP(opcode);
+ }
+ break;
+
+ case JAVA_BREAKPOINT:
+ panic("Illegal opcode Breakpoint encountered");
+ break;
+
+ case 203:
+ case 204:
+ case 205:
+ case 206:
+ case 207:
+ case 208:
+ case 209:
+ case 210:
+ case 211:
+ case 212:
+ case 213:
+ case 214:
+ case 215:
+ case 216:
+ case 217:
+ case 218:
+ case 219:
+ case 220:
+ case 221:
+ case 222:
+ case 223:
+ case 224:
+ case 225:
+ case 226:
+ case 227:
+ case 228:
+ case 229:
+ case 230:
+ case 231:
+ case 232:
+ case 233:
+ case 234:
+ case 235:
+ case 236:
+ case 237:
+ case 238:
+ case 239:
+ case 240:
+ case 241:
+ case 242:
+ case 243:
+ case 244:
+ case 245:
+ case 246:
+ case 247:
+ case 248:
+ case 249:
+ case 250:
+ case 251:
+ case 252:
+ case 253:
+ case 254:
+ case 255:
+ printf("Illegal opcode %d at instr %d", opcode, ipc);
+ panic("encountered");
+ break;
+
+ default:
+ OP(opcode);
+ break;
+
+ } /* end switch */
+
+ } /* end for */
+
+ if (p != jcodelength)
+ panic("Command-sequence crosses code-boundary");
+
+ if (!blockend)
+ panic("Code does not end with branch/return/athrow - stmt");
+
+ /* adjust block count if target 0 is not first intermediate instruction */
+
+ if (!block_index[0] || (block_index[0] > 1))
+ b_count++;
+
+ /* copy local to global variables */
+
+ instr_count = ipc;
+ block_count = b_count;
+ stack_count = s_count + block_count * maxstack;
+
+ /* allocate stack table */
+
+ stack = DMNEW(stackelement, stack_count);
+
+ {
+ basicblock *bptr;
+
+ bptr = block = DMNEW(basicblock, b_count + 1); /* one more for end ipc */
+
+ b_count = 0;
+
+ /* additional block if target 0 is not first intermediate instruction */
+
+ if (!block_index[0] || (block_index[0] > 1)) {
+ bptr->ipc = 0;
+ bptr->mpc = -1;
+ bptr->flags = -1;
+ bptr->type = BBTYPE_STD;
+ bptr->branchrefs = NULL;
+ bptr++;
+ b_count++;
+ }
+
+ /* allocate blocks */
+
+ for (p = 0; p < jcodelength; p++)
+ if (block_index[p] & 1) {
+ bptr->ipc = block_index[p] >> 1;
+ bptr->mpc = -1;
+ bptr->flags = -1;
+ bptr->type = BBTYPE_STD;
+ bptr->branchrefs = NULL;
+ block_index[p] = b_count;
+ bptr++;
+ b_count++;
+ }
+
+ /* allocate additional block at end */
+
+ bptr->ipc = instr_count;
+ bptr->mpc = -1;
+ bptr->flags = -1;
+ bptr->type = BBTYPE_STD;
+ bptr->branchrefs = NULL;
+ }
+}
--- /dev/null
+/******************************* comp/reg.c ************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ The register-manager.
+
+ Authors: Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
+ Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1997/10/23
+
+*******************************************************************************/
+
+static varinfo5 *locals;
+static varinfo5 *interfaces;
+
+static int intregsnum; /* absolute number of integer registers */
+static int floatregsnum; /* absolute number of float registers */
+
+static int intreg_ret; /* register to return integer values */
+static int intreg_argnum; /* number of integer argument registers */
+
+static int floatreg_ret; /* register for return float values */
+static int fltreg_argnum; /* number of float argument registers */
+
+
+static int *argintregs; /* scratch integer registers */
+static int *tmpintregs = NULL; /* scratch integer registers */
+static int *savintregs; /* saved integer registers */
+static int *argfltregs; /* scratch float registers */
+static int *tmpfltregs; /* scratch float registers */
+static int *savfltregs; /* saved float registers */
+static int *freetmpintregs; /* free scratch integer registers */
+static int *freesavintregs; /* free saved integer registers */
+static int *freetmpfltregs; /* free scratch float registers */
+static int *freesavfltregs; /* free saved float registers */
+
+static int *freemem; /* free scratch memory */
+static int memuse; /* used memory count */
+static int ifmemuse; /* interface used memory count */
+static int maxmemuse; /* maximal used memory count (spills) */
+static int freememtop; /* free memory count */
+
+static int tmpintregcnt; /* scratch integer register count */
+static int savintregcnt; /* saved integer register count */
+static int tmpfltregcnt; /* scratch float register count */
+static int savfltregcnt; /* saved float register count */
+
+static int iftmpintregcnt; /* iface scratch integer register count */
+static int ifsavintregcnt; /* iface saved integer register count */
+static int iftmpfltregcnt; /* iface scratch float register count */
+static int ifsavfltregcnt; /* iface saved float register count */
+
+static int tmpintreguse; /* used scratch integer register count */
+static int savintreguse; /* used saved integer register count */
+static int tmpfltreguse; /* used scratch float register count */
+static int savfltreguse; /* used saved float register count */
+
+static int maxtmpintreguse; /* max used scratch int register count */
+static int maxsavintreguse; /* max used saved int register count */
+static int maxtmpfltreguse; /* max used scratch float register count */
+static int maxsavfltreguse; /* max used saved float register count */
+
+static int freetmpinttop; /* free scratch integer register count */
+static int freesavinttop; /* free saved integer register count */
+static int freetmpflttop; /* free scratch float register count */
+static int freesavflttop; /* free saved float register count */
+
+static int savedregs_num; /* total number of registers to be saved */
+static int arguments_num; /* size of parameter field in the stackframe */
+
+
+
+/****************** function reg_init ******************************************
+
+ initialises the register-allocator
+
+*******************************************************************************/
+
+static void reg_init()
+{
+ int n;
+
+ if (!tmpintregs) {
+
+ if (TYPE_INT != 0 || TYPE_ADR != 4)
+ panic ("JAVA-Basictypes have been changed");
+
+ intreg_argnum = 0;
+ tmpintregcnt = 0;
+ savintregcnt = 0;
+
+ for (intregsnum = 0; nregdescint[intregsnum] != REG_END; intregsnum++) {
+ switch (nregdescint[intregsnum]) {
+ case REG_SAV: savintregcnt++;
+ break;
+ case REG_TMP: tmpintregcnt++;
+ break;
+ case REG_ARG: intreg_argnum++;
+ }
+ }
+
+ argintregs = MNEW (int, intreg_argnum);
+ tmpintregs = MNEW (int, tmpintregcnt);
+ savintregs = MNEW (int, savintregcnt);
+ freetmpintregs = MNEW (int, tmpintregcnt);
+ freesavintregs = MNEW (int, savintregcnt);
+
+ intreg_argnum = 0;
+ tmpintreguse = 0;
+ savintreguse = 0;
+
+ for (n = 0; n < intregsnum; n++) {
+ switch (nregdescint[n]) {
+ case REG_RET: intreg_ret = n;
+ break;
+ case REG_SAV: savintregs[savintreguse++] = n;
+ break;
+ case REG_TMP: tmpintregs[tmpintreguse++] = n;
+ break;
+ case REG_ARG: argintregs[intreg_argnum++] = n;
+ break;
+ }
+ }
+
+
+ fltreg_argnum = 0;
+ tmpfltregcnt = 0;
+ savfltregcnt = 0;
+
+ for (floatregsnum = 0; nregdescfloat[floatregsnum] != REG_END; floatregsnum++) {
+ switch (nregdescfloat[floatregsnum]) {
+ case REG_SAV: savfltregcnt++;
+ break;
+ case REG_TMP: tmpfltregcnt++;
+ break;
+ case REG_ARG: fltreg_argnum++;
+ break;
+ }
+ }
+
+ argfltregs = MNEW (int, fltreg_argnum);
+ tmpfltregs = MNEW (int, tmpfltregcnt);
+ savfltregs = MNEW (int, savfltregcnt);
+ freetmpfltregs = MNEW (int, tmpfltregcnt);
+ freesavfltregs = MNEW (int, savfltregcnt);
+
+ fltreg_argnum = 0;
+ tmpfltreguse = 0;
+ savfltreguse = 0;
+
+ for (n = 0; n < floatregsnum; n++) {
+ switch (nregdescfloat[n]) {
+ case REG_RET: floatreg_ret = n;
+ break;
+ case REG_SAV: savfltregs[savfltreguse++] = n;
+ break;
+ case REG_TMP: tmpfltregs[tmpfltreguse++] = n;
+ break;
+ case REG_ARG: argfltregs[fltreg_argnum++] = n;
+ break;
+ }
+ }
+
+ }
+
+}
+
+
+/********************** function reg_close *************************************
+
+ releases all allocated space for registers
+
+*******************************************************************************/
+
+static void reg_close ()
+{
+ if (argintregs) MFREE (argintregs, int, intreg_argnum);
+ if (argfltregs) MFREE (argfltregs, int, fltreg_argnum);
+ if (tmpintregs) MFREE (tmpintregs, int, tmpintregcnt);
+ if (savintregs) MFREE (savintregs, int, savintregcnt);
+ if (tmpfltregs) MFREE (tmpfltregs, int, tmpfltregcnt);
+ if (savfltregs) MFREE (savfltregs, int, savfltregcnt);
+
+ if (freetmpintregs) MFREE (freetmpintregs, int, tmpintregcnt);
+ if (freesavintregs) MFREE (freesavintregs, int, savintregcnt);
+ if (freetmpfltregs) MFREE (freetmpfltregs, int, tmpfltregcnt);
+ if (freesavfltregs) MFREE (freesavfltregs, int, savfltregcnt);
+}
+
+
+/****************** function local_init ****************************************
+
+ initialises the local variable and interfaces table
+
+*******************************************************************************/
+
+static void local_init()
+{
+ int i;
+ varinfo5 *v;
+
+ freemem = DMNEW(int, maxstack);
+ locals = DMNEW(varinfo5, maxlocals);
+ interfaces = DMNEW(varinfo5, maxstack);
+
+ for (v = locals, i = maxlocals; i > 0; v++, i--) {
+ v[0][TYPE_INT].type = -1;
+ v[0][TYPE_LNG].type = -1;
+ v[0][TYPE_FLT].type = -1;
+ v[0][TYPE_DBL].type = -1;
+ v[0][TYPE_ADR].type = -1;
+ }
+
+ for (v = interfaces, i = maxstack; i > 0; v++, i--) {
+ v[0][TYPE_INT].type = -1;
+ v[0][TYPE_INT].flags = 0;
+ v[0][TYPE_LNG].type = -1;
+ v[0][TYPE_LNG].flags = 0;
+ v[0][TYPE_FLT].type = -1;
+ v[0][TYPE_FLT].flags = 0;
+ v[0][TYPE_DBL].type = -1;
+ v[0][TYPE_DBL].flags = 0;
+ v[0][TYPE_ADR].type = -1;
+ v[0][TYPE_ADR].flags = 0;
+ }
+}
+
+
+/************************* function interface_regalloc *****************************
+
+ allocates registers for all interface variables
+
+*******************************************************************************/
+
+static void interface_regalloc ()
+{
+ int s, t, saved;
+ int intalloc, fltalloc;
+ varinfo *v;
+
+ /* allocate stack space for passing arguments to called methods */
+
+ if (arguments_num > intreg_argnum)
+ ifmemuse = arguments_num - intreg_argnum;
+ else
+ ifmemuse = 0;
+
+ iftmpintregcnt = tmpintregcnt;
+ ifsavintregcnt = savintregcnt;
+ iftmpfltregcnt = tmpfltregcnt;
+ ifsavfltregcnt = savfltregcnt;
+
+ for (s = 0; s < maxstack; s++) {
+ intalloc = -1; fltalloc = -1;
+ saved = (interfaces[s][TYPE_INT].flags | interfaces[s][TYPE_LNG].flags |
+ interfaces[s][TYPE_FLT].flags | interfaces[s][TYPE_DBL].flags |
+ interfaces[s][TYPE_ADR].flags) & SAVEDVAR;
+ for (t = TYPE_INT; t <= TYPE_ADR; t++) {
+ v = &interfaces[s][t];
+ if (v->type >= 0) {
+ if (!saved) {
+ if (IS_FLT_DBL_TYPE(t)) {
+ if (fltalloc >= 0) {
+ v->flags |= interfaces[s][fltalloc].flags & INMEMORY;
+ v->regoff = interfaces[s][fltalloc].regoff;
+ }
+ else if (iftmpfltregcnt > 0) {
+ iftmpfltregcnt--;
+ v->regoff = tmpfltregs[iftmpfltregcnt];
+ }
+ else if (ifsavfltregcnt > 0) {
+ ifsavfltregcnt--;
+ v->regoff = savfltregs[ifsavfltregcnt];
+ }
+ else {
+ v->flags |= INMEMORY;
+ v->regoff = ifmemuse++;
+ }
+ fltalloc = t;
+ }
+ else {
+ if (intalloc >= 0) {
+ v->flags |= interfaces[s][intalloc].flags & INMEMORY;
+ v->regoff = interfaces[s][intalloc].regoff;
+ }
+ else if (iftmpintregcnt > 0) {
+ iftmpintregcnt--;
+ v->regoff = tmpintregs[iftmpintregcnt];
+ }
+ else if (ifsavintregcnt > 0) {
+ ifsavintregcnt--;
+ v->regoff = savintregs[ifsavintregcnt];
+ }
+ else {
+ v->flags |= INMEMORY;
+ v->regoff = ifmemuse++;
+ }
+ intalloc = t;
+ }
+ }
+ else {
+ if (IS_FLT_DBL_TYPE(t)) {
+ if (fltalloc >= 0) {
+ v->flags |= interfaces[s][fltalloc].flags & INMEMORY;
+ v->regoff = interfaces[s][fltalloc].regoff;
+ }
+ else if (ifsavfltregcnt > 0) {
+ ifsavfltregcnt--;
+ v->regoff = savfltregs[ifsavfltregcnt];
+ }
+ else {
+ v->flags |= INMEMORY;
+ v->regoff = ifmemuse++;
+ }
+ fltalloc = t;
+ }
+ else {
+ if (intalloc >= 0) {
+ v->flags |= interfaces[s][intalloc].flags & INMEMORY;
+ v->regoff = interfaces[s][intalloc].regoff;
+ }
+ else if (ifsavintregcnt > 0) {
+ ifsavintregcnt--;
+ v->regoff = savintregs[ifsavintregcnt];
+ }
+ else {
+ v->flags |= INMEMORY;
+ v->regoff = ifmemuse++;
+ }
+ intalloc = t;
+ }
+ }
+ } /* if (type >= 0) */
+ } /* for t */
+ } /* for s */
+ maxmemuse = ifmemuse;
+ maxtmpintreguse = iftmpintregcnt;
+ maxsavintreguse = ifsavintregcnt;
+ maxtmpfltreguse = iftmpfltregcnt;
+ maxsavfltreguse = ifsavfltregcnt;
+}
+
+
+/************************* function local_regalloc *****************************
+
+ allocates registers for all local variables
+
+*******************************************************************************/
+
+static void local_regalloc ()
+{
+ int s, t;
+ int intalloc, fltalloc;
+ varinfo *v;
+
+ if (isleafmethod) {
+ for (s = 0; s < maxlocals; s++) {
+ intalloc = -1; fltalloc = -1;
+ for (t = TYPE_INT; t <= TYPE_ADR; t++) {
+ v = &locals[s][t];
+ if (v->type >= 0) {
+ if (IS_FLT_DBL_TYPE(t)) {
+ if (fltalloc >= 0) {
+ v->flags = locals[s][fltalloc].flags;
+ v->regoff = locals[s][fltalloc].regoff;
+ }
+ else if (s < fltreg_argnum) {
+ v->flags = 0;
+ v->regoff = argfltregs[s];
+ }
+ else if (maxtmpfltreguse > 0) {
+ maxtmpfltreguse--;
+ v->flags = 0;
+ v->regoff = tmpfltregs[maxtmpfltreguse];
+ }
+ else if (maxsavfltreguse > 0) {
+ maxsavfltreguse--;
+ v->flags = 0;
+ v->regoff = savfltregs[maxsavfltreguse];
+ }
+ else {
+ v->flags = INMEMORY;
+ v->regoff = maxmemuse++;
+ }
+ fltalloc = t;
+ }
+ else {
+ if (intalloc >= 0) {
+ v->flags = locals[s][intalloc].flags;
+ v->regoff = locals[s][intalloc].regoff;
+ }
+ else if (s < intreg_argnum) {
+ v->flags = 0;
+ v->regoff = argintregs[s];
+ }
+ else if (maxtmpintreguse > 0) {
+ maxtmpintreguse--;
+ v->flags = 0;
+ v->regoff = tmpintregs[maxtmpintreguse];
+ }
+ else if (maxsavintreguse > 0) {
+ maxsavintreguse--;
+ v->flags = 0;
+ v->regoff = savintregs[maxsavintreguse];
+ }
+ else {
+ v->flags = INMEMORY;
+ v->regoff = maxmemuse++;
+ }
+ intalloc = t;
+ }
+ }
+ }
+ }
+ return;
+ }
+ for (s = 0; s < maxlocals; s++) {
+ intalloc = -1; fltalloc = -1;
+ for (t=TYPE_INT; t<=TYPE_ADR; t++) {
+ v = &locals[s][t];
+ if (v->type >= 0) {
+ if (IS_FLT_DBL_TYPE(t)) {
+ if (fltalloc >= 0) {
+ v->flags = locals[s][fltalloc].flags;
+ v->regoff = locals[s][fltalloc].regoff;
+ }
+ else if (maxsavfltreguse > 0) {
+ maxsavfltreguse--;
+ v->flags = 0;
+ v->regoff = savfltregs[maxsavfltreguse];
+ }
+ else {
+ v->flags = INMEMORY;
+ v->regoff = maxmemuse++;
+ }
+ fltalloc = t;
+ }
+ else {
+ if (intalloc >= 0) {
+ v->flags = locals[s][intalloc].flags;
+ v->regoff = locals[s][intalloc].regoff;
+ }
+ else if (maxsavintreguse > 0) {
+ maxsavintreguse--;
+ v->flags = 0;
+ v->regoff = savintregs[maxsavintreguse];
+ }
+ else {
+ v->flags = INMEMORY;
+ v->regoff = maxmemuse++;
+ }
+ intalloc = t;
+ }
+ }
+ }
+ }
+}
+
+
+static void reg_init_temp()
+{
+ freememtop = 0;
+ memuse = ifmemuse;
+
+ freetmpinttop = 0;
+ freesavinttop = 0;
+ freetmpflttop = 0;
+ freesavflttop = 0;
+ tmpintreguse = iftmpintregcnt;
+ savintreguse = ifsavintregcnt;
+ tmpfltreguse = iftmpfltregcnt;
+ savfltreguse = ifsavfltregcnt;
+}
+
+
+#define reg_new_temp(s) if(s->varkind==TEMPVAR)reg_new_temp_func(s)
+
+static void reg_new_temp_func(stackptr s)
+{
+if (s->flags & SAVEDVAR) {
+ if (IS_FLT_DBL_TYPE(s->type)) {
+ if (freesavflttop > 0) {
+ freesavflttop--;
+ s->regoff = freesavfltregs[freesavflttop];
+ return;
+ }
+ else if (savfltreguse > 0) {
+ savfltreguse--;
+ if (savfltreguse < maxsavfltreguse)
+ maxsavfltreguse = savfltreguse;
+ s->regoff = savfltregs[savfltreguse];
+ return;
+ }
+ }
+ else {
+ if (freesavinttop > 0) {
+ freesavinttop--;
+ s->regoff = freesavintregs[freesavinttop];
+ return;
+ }
+ else if (savintreguse > 0) {
+ savintreguse--;
+ if (savintreguse < maxsavintreguse)
+ maxsavintreguse = savintreguse;
+ s->regoff = savintregs[savintreguse];
+ return;
+ }
+ }
+ }
+else {
+ if (IS_FLT_DBL_TYPE(s->type)) {
+ if (freetmpflttop > 0) {
+ freetmpflttop--;
+ s->regoff = freetmpfltregs[freetmpflttop];
+ return;
+ }
+ else if (tmpfltreguse > 0) {
+ tmpfltreguse--;
+ if (tmpfltreguse < maxtmpfltreguse)
+ maxtmpfltreguse = tmpfltreguse;
+ s->regoff = tmpfltregs[tmpfltreguse];
+ return;
+ }
+ }
+ else {
+ if (freetmpinttop > 0) {
+ freetmpinttop--;
+ s->regoff = freetmpintregs[freetmpinttop];
+ return;
+ }
+ else if (tmpintreguse > 0) {
+ tmpintreguse--;
+ if (tmpintreguse < maxtmpintreguse)
+ maxtmpintreguse = tmpintreguse;
+ s->regoff = tmpintregs[tmpintreguse];
+ return;
+ }
+ }
+ }
+if (freememtop > 0) {
+ freememtop--;
+ s->regoff = freemem[freememtop];
+ }
+else {
+ s->regoff = memuse++;
+ if (memuse > maxmemuse)
+ maxmemuse = memuse;
+ }
+s->flags |= INMEMORY;
+}
+
+
+#define reg_free_temp(s) if(s->varkind==TEMPVAR)reg_free_temp_func(s)
+
+static void reg_free_temp_func(stackptr s)
+{
+if (s->flags & INMEMORY)
+ freemem[freememtop++] = s->regoff;
+else if (IS_FLT_DBL_TYPE(s->type)) {
+ if (s->flags & SAVEDVAR)
+ freesavfltregs[freesavflttop++] = s->regoff;
+ else
+ freetmpfltregs[freetmpflttop++] = s->regoff;
+ }
+else
+ if (s->flags & SAVEDVAR)
+ freesavintregs[freesavinttop++] = s->regoff;
+ else
+ freetmpintregs[freetmpinttop++] = s->regoff;
+}
+
+
+static void allocate_scratch_registers()
+{
+ int b_count;
+ int opcode, i, len;
+ stackptr src, dst;
+ instruction *iptr = instr;
+ basicblock *bptr;
+
+ b_count = block_count;
+ bptr = block;
+ while (--b_count >= 0) {
+ if (bptr->flags >= BBREACHED) {
+ dst = bptr->instack;
+ reg_init_temp();
+ i = bptr[0].ipc;
+ len = bptr[1].ipc - i;
+ iptr = &instr[i];
+ while (--len >= 0) {
+ src = dst;
+ dst = iptr->dst;
+ opcode = iptr->opc;
+ switch (opcode) {
+
+ /* pop 0 push 0 */
+
+ case ICMD_NOP:
+ case ICMD_CHECKASIZE:
+ case ICMD_IINC:
+ case ICMD_JSR:
+ case ICMD_RET:
+ case ICMD_RETURN:
+ case ICMD_GOTO:
+ break;
+
+ /* pop 0 push 1 const */
+
+ case ICMD_ICONST:
+ case ICMD_LCONST:
+ case ICMD_FCONST:
+ case ICMD_DCONST:
+ case ICMD_ACONST:
+
+ /* pop 0 push 1 load */
+
+ case ICMD_ILOAD:
+ case ICMD_LLOAD:
+ case ICMD_FLOAD:
+ case ICMD_DLOAD:
+ case ICMD_ALOAD:
+ reg_new_temp(dst);
+ break;
+
+ /* pop 2 push 1 */
+
+ case ICMD_IALOAD:
+ case ICMD_LALOAD:
+ case ICMD_FALOAD:
+ case ICMD_DALOAD:
+ case ICMD_AALOAD:
+
+ case ICMD_BALOAD:
+ case ICMD_CALOAD:
+ case ICMD_SALOAD:
+ reg_free_temp(src);
+ reg_free_temp(src->prev);
+ reg_new_temp(dst);
+ break;
+
+ /* pop 3 push 0 */
+
+ case ICMD_IASTORE:
+ case ICMD_LASTORE:
+ case ICMD_FASTORE:
+ case ICMD_DASTORE:
+ case ICMD_AASTORE:
+
+ case ICMD_BASTORE:
+ case ICMD_CASTORE:
+ case ICMD_SASTORE:
+ reg_free_temp(src);
+ reg_free_temp(src->prev);
+ reg_free_temp(src->prev->prev);
+ break;
+
+ /* pop 1 push 0 store */
+
+ case ICMD_ISTORE:
+ case ICMD_LSTORE:
+ case ICMD_FSTORE:
+ case ICMD_DSTORE:
+ case ICMD_ASTORE:
+
+ /* pop 1 push 0 */
+
+ case ICMD_POP:
+
+ case ICMD_IRETURN:
+ case ICMD_LRETURN:
+ case ICMD_FRETURN:
+ case ICMD_DRETURN:
+ case ICMD_ARETURN:
+
+ case ICMD_ATHROW:
+
+ case ICMD_PUTSTATIC:
+
+ /* pop 1 push 0 branch */
+
+ case ICMD_IFNULL:
+ case ICMD_IFNONNULL:
+
+ case ICMD_IFEQ:
+ case ICMD_IFNE:
+ case ICMD_IFLT:
+ case ICMD_IFGE:
+ case ICMD_IFGT:
+ case ICMD_IFLE:
+
+ case ICMD_IF_LEQ:
+ case ICMD_IF_LNE:
+ case ICMD_IF_LLT:
+ case ICMD_IF_LGE:
+ case ICMD_IF_LGT:
+ case ICMD_IF_LLE:
+
+ /* pop 1 push 0 table branch */
+
+ case ICMD_TABLESWITCH:
+ case ICMD_LOOKUPSWITCH:
+
+ case ICMD_NULLCHECKPOP:
+ case ICMD_MONITORENTER:
+ case ICMD_MONITOREXIT:
+ reg_free_temp(src);
+ break;
+
+ /* pop 2 push 0 branch */
+
+ case ICMD_IF_ICMPEQ:
+ case ICMD_IF_ICMPNE:
+ case ICMD_IF_ICMPLT:
+ case ICMD_IF_ICMPGE:
+ case ICMD_IF_ICMPGT:
+ case ICMD_IF_ICMPLE:
+
+ case ICMD_IF_LCMPEQ:
+ case ICMD_IF_LCMPNE:
+ case ICMD_IF_LCMPLT:
+ case ICMD_IF_LCMPGE:
+ case ICMD_IF_LCMPGT:
+ case ICMD_IF_LCMPLE:
+
+ case ICMD_IF_ACMPEQ:
+ case ICMD_IF_ACMPNE:
+
+ /* pop 2 push 0 */
+
+ case ICMD_POP2:
+
+ case ICMD_PUTFIELD:
+ reg_free_temp(src);
+ reg_free_temp(src->prev);
+ break;
+
+ /* pop 0 push 1 dup */
+
+ case ICMD_DUP:
+ reg_new_temp(dst);
+ break;
+
+ /* pop 0 push 2 dup */
+
+ case ICMD_DUP2:
+ reg_new_temp(dst->prev);
+ reg_new_temp(dst);
+ break;
+
+ /* pop 2 push 3 dup */
+
+ case ICMD_DUP_X1:
+ reg_new_temp(dst->prev->prev);
+ reg_new_temp(dst->prev);
+ reg_new_temp(dst);
+ reg_free_temp(src);
+ reg_free_temp(src->prev);
+ break;
+
+ /* pop 3 push 4 dup */
+
+ case ICMD_DUP_X2:
+ reg_new_temp(dst->prev->prev->prev);
+ reg_new_temp(dst->prev->prev);
+ reg_new_temp(dst->prev);
+ reg_new_temp(dst);
+ reg_free_temp(src);
+ reg_free_temp(src->prev);
+ reg_free_temp(src->prev->prev);
+ break;
+
+ /* pop 3 push 5 dup */
+
+ case ICMD_DUP2_X1:
+ reg_new_temp(dst->prev->prev->prev->prev);
+ reg_new_temp(dst->prev->prev->prev);
+ reg_new_temp(dst->prev->prev);
+ reg_new_temp(dst->prev);
+ reg_new_temp(dst);
+ reg_free_temp(src);
+ reg_free_temp(src->prev);
+ reg_free_temp(src->prev->prev);
+ break;
+
+ /* pop 4 push 6 dup */
+
+ case ICMD_DUP2_X2:
+ reg_new_temp(dst->prev->prev->prev->prev->prev);
+ reg_new_temp(dst->prev->prev->prev->prev);
+ reg_new_temp(dst->prev->prev->prev);
+ reg_new_temp(dst->prev->prev);
+ reg_new_temp(dst->prev);
+ reg_new_temp(dst);
+ reg_free_temp(src);
+ reg_free_temp(src->prev);
+ reg_free_temp(src->prev->prev);
+ reg_free_temp(src->prev->prev->prev);
+ break;
+
+ /* pop 2 push 2 swap */
+
+ case ICMD_SWAP:
+ reg_new_temp(dst->prev);
+ reg_new_temp(dst);
+ reg_free_temp(src);
+ reg_free_temp(src->prev);
+ break;
+
+ /* pop 2 push 1 */
+
+ case ICMD_IADD:
+ case ICMD_ISUB:
+ case ICMD_IMUL:
+ case ICMD_IDIV:
+ case ICMD_IREM:
+
+ case ICMD_ISHL:
+ case ICMD_ISHR:
+ case ICMD_IUSHR:
+ case ICMD_IAND:
+ case ICMD_IOR:
+ case ICMD_IXOR:
+
+ case ICMD_LADD:
+ case ICMD_LSUB:
+ case ICMD_LMUL:
+ case ICMD_LDIV:
+ case ICMD_LREM:
+
+ case ICMD_LOR:
+ case ICMD_LAND:
+ case ICMD_LXOR:
+
+ case ICMD_LSHL:
+ case ICMD_LSHR:
+ case ICMD_LUSHR:
+
+ case ICMD_FADD:
+ case ICMD_FSUB:
+ case ICMD_FMUL:
+ case ICMD_FDIV:
+ case ICMD_FREM:
+
+ case ICMD_DADD:
+ case ICMD_DSUB:
+ case ICMD_DMUL:
+ case ICMD_DDIV:
+ case ICMD_DREM:
+
+ case ICMD_LCMP:
+ case ICMD_FCMPL:
+ case ICMD_FCMPG:
+ case ICMD_DCMPL:
+ case ICMD_DCMPG:
+ reg_free_temp(src);
+ reg_free_temp(src->prev);
+ reg_new_temp(dst);
+ break;
+
+ /* pop 1 push 1 */
+
+ case ICMD_IADDCONST:
+ case ICMD_ISUBCONST:
+ case ICMD_IMULCONST:
+ case ICMD_IANDCONST:
+ case ICMD_IORCONST:
+ case ICMD_IXORCONST:
+ case ICMD_ISHLCONST:
+ case ICMD_ISHRCONST:
+ case ICMD_IUSHRCONST:
+
+ case ICMD_LADDCONST:
+ case ICMD_LSUBCONST:
+ case ICMD_LMULCONST:
+ case ICMD_LANDCONST:
+ case ICMD_LORCONST:
+ case ICMD_LXORCONST:
+ case ICMD_LSHLCONST:
+ case ICMD_LSHRCONST:
+ case ICMD_LUSHRCONST:
+
+ case ICMD_INEG:
+ case ICMD_INT2BYTE:
+ case ICMD_INT2CHAR:
+ case ICMD_INT2SHORT:
+ case ICMD_LNEG:
+ case ICMD_FNEG:
+ case ICMD_DNEG:
+
+ case ICMD_I2L:
+ case ICMD_I2F:
+ case ICMD_I2D:
+ case ICMD_L2I:
+ case ICMD_L2F:
+ case ICMD_L2D:
+ case ICMD_F2I:
+ case ICMD_F2L:
+ case ICMD_F2D:
+ case ICMD_D2I:
+ case ICMD_D2L:
+ case ICMD_D2F:
+
+ case ICMD_CHECKCAST:
+
+ case ICMD_ARRAYLENGTH:
+ case ICMD_INSTANCEOF:
+
+ case ICMD_NEWARRAY:
+ case ICMD_ANEWARRAY:
+
+ case ICMD_GETFIELD:
+ reg_free_temp(src);
+ reg_new_temp(dst);
+ break;
+
+ /* pop 0 push 1 */
+
+ case ICMD_GETSTATIC:
+
+ case ICMD_NEW:
+
+ reg_new_temp(dst);
+ break;
+
+ /* pop many push any */
+
+ case ICMD_INVOKEVIRTUAL:
+ case ICMD_INVOKESPECIAL:
+ case ICMD_INVOKESTATIC:
+ case ICMD_INVOKEINTERFACE:
+ {
+ i = iptr->op1;
+ while (--i >= 0) {
+ reg_free_temp(src);
+ src = src->prev;
+ }
+ if (((methodinfo*)iptr->val.a)->returntype != TYPE_VOID)
+ reg_new_temp(dst);
+ break;
+ }
+
+ case ICMD_BUILTIN3:
+ reg_free_temp(src);
+ src = src->prev;
+ case ICMD_BUILTIN2:
+ reg_free_temp(src);
+ src = src->prev;
+ case ICMD_BUILTIN1:
+ reg_free_temp(src);
+ src = src->prev;
+ if (iptr->op1 != TYPE_VOID)
+ reg_new_temp(dst);
+ break;
+
+ case ICMD_MULTIANEWARRAY:
+ i = iptr->op1;
+ while (--i >= 0) {
+ reg_free_temp(src);
+ src = src->prev;
+ }
+ reg_new_temp(dst);
+ break;
+
+ default:
+ printf("ICMD %d at %d\n", iptr->opc, (int)(iptr-instr));
+ panic("Missing ICMD code during register allocation");
+ } /* switch */
+ iptr++;
+ } /* while instructions */
+ } /* if */
+ bptr++;
+ } /* while blocks */
+}
--- /dev/null
+/****************************** ncomp/nstack.c *********************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Parser for JavaVM to intermediate code translation
+
+ Authors: Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1997/11/18
+
+*******************************************************************************/
+
+
+#ifdef STATISTICS
+#define COUNT(cnt) cnt++
+#else
+#define COUNT(cnt)
+#endif
+
+#define STACKRESET {curstack=0;stackdepth=0;}
+
+#define TYPEPANIC {show_icmd_method();panic("Stack type mismatch");}
+#define CURKIND curstack->varkind
+#define CURTYPE curstack->type
+
+#define NEWSTACK(s,v,n) {new->prev=curstack;new->type=s;new->flags=0;\
+ new->varkind=v;new->varnum=n;curstack=new;new++;}
+#define NEWSTACKn(s,n) NEWSTACK(s,UNDEFVAR,n)
+#define NEWSTACK0(s) NEWSTACK(s,UNDEFVAR,0)
+#define NEWXSTACK {NEWSTACK(TYPE_ADR,STACKVAR,0);curstack=0;}
+
+#define SETDST {iptr->dst=curstack;}
+#define POP(s) {if(s!=curstack->type){TYPEPANIC;}\
+ if(curstack->varkind==UNDEFVAR)curstack->varkind=TEMPVAR;\
+ curstack=curstack->prev;}
+#define POPANY {if(curstack->varkind==UNDEFVAR)curstack->varkind=TEMPVAR;\
+ curstack=curstack->prev;}
+#define COPY(s,d) {(d)->flags=0;(d)->type=(s)->type;\
+ (d)->varkind=(s)->varkind;(d)->varnum=(s)->varnum;}
+
+#define CONST(s) {NEWSTACKn(s,stackdepth);SETDST;stackdepth++;}
+#define LOAD(s,v,n) {NEWSTACK(s,v,n);SETDST;stackdepth++;}
+#define STORE(s) {POP(s);SETDST;stackdepth--;}
+#define OP1_0(s) {POP(s);SETDST;stackdepth--;}
+#define OP1_0ANY {POPANY;SETDST;stackdepth--;}
+#define OP0_1(s) {NEWSTACKn(s,stackdepth);SETDST;stackdepth++;}
+#define OP1_1(s,d) {POP(s);NEWSTACKn(d,stackdepth-1);SETDST;}
+#define OP2_0(s) {POP(s);POP(s);SETDST;stackdepth-=2;}
+#define OPTT2_0(t,b){POP(t);POP(b);SETDST;stackdepth-=2;}
+#define OP2_1(s) {POP(s);POP(s);NEWSTACKn(s,stackdepth-2);SETDST;stackdepth--;}
+#define OP2IAT_1(s) {POP(TYPE_INT);POP(TYPE_ADR);NEWSTACKn(s,stackdepth-2);\
+ SETDST;stackdepth--;}
+#define OP2IT_1(s) {POP(TYPE_INT);POP(s);NEWSTACKn(s,stackdepth-2);\
+ SETDST;stackdepth--;}
+#define OPTT2_1(s,d){POP(s);POP(s);NEWSTACKn(d,stackdepth-2);SETDST;stackdepth--;}
+#define OP2_2(s) {POP(s);POP(s);NEWSTACKn(s,stackdepth-2);\
+ NEWSTACKn(s,stackdepth-1);SETDST;}
+#define OP3TIA_0(s) {POP(s);POP(TYPE_INT);POP(TYPE_ADR);SETDST;stackdepth-=3;}
+#define OP3_0(s) {POP(s);POP(s);POP(s);SETDST;stackdepth-=3;}
+#define POPMANY(i) {stackdepth-=i;while(--i>=0){POPANY;}SETDST;}
+#define DUP {NEWSTACK(CURTYPE,CURKIND,curstack->varnum);SETDST;\
+ stackdepth++;}
+#define SWAP {COPY(curstack,new);POPANY;COPY(curstack,new+1);POPANY;\
+ new[0].prev=curstack;new[1].prev=new;\
+ curstack=new+1;new+=2;SETDST;}
+#define DUP_X1 {COPY(curstack,new);COPY(curstack,new+2);POPANY;\
+ COPY(curstack,new+1);POPANY;new[0].prev=curstack;\
+ new[1].prev=new;new[2].prev=new+1;\
+ curstack=new+2;new+=3;SETDST;stackdepth++;}
+#define DUP2_X1 {COPY(curstack,new+1);COPY(curstack,new+4);POPANY;\
+ COPY(curstack,new);COPY(curstack,new+3);POPANY;\
+ COPY(curstack,new+2);POPANY;new[0].prev=curstack;\
+ new[1].prev=new;new[2].prev=new+1;\
+ new[3].prev=new+2;new[4].prev=new+3;\
+ curstack=new+4;new+=5;SETDST;stackdepth+=2;}
+#define DUP_X2 {COPY(curstack,new);COPY(curstack,new+3);POPANY;\
+ COPY(curstack,new+2);POPANY;COPY(curstack,new+1);POPANY;\
+ new[0].prev=curstack;new[1].prev=new;\
+ new[2].prev=new+1;new[3].prev=new+2;\
+ curstack=new+3;new+=4;SETDST;stackdepth++;}
+#define DUP2_X2 {COPY(curstack,new+1);COPY(curstack,new+5);POPANY;\
+ COPY(curstack,new);COPY(curstack,new+4);POPANY;\
+ COPY(curstack,new+3);POPANY;COPY(curstack,new+2);POPANY;\
+ new[0].prev=curstack;new[1].prev=new;\
+ new[2].prev=new+1;new[3].prev=new+2;\
+ new[4].prev=new+3;new[5].prev=new+4;\
+ curstack=new+5;new+=6;SETDST;stackdepth+=2;}
+
+#define COPYCURSTACK(copy) {\
+ int d;\
+ stackptr s;\
+ if(curstack){\
+ s=curstack;\
+ new+=stackdepth;\
+ d=stackdepth;\
+ copy=new;\
+ while(s){\
+ copy--;d--;\
+ copy->prev=copy-1;\
+ copy->type=s->type;\
+ copy->flags=0;\
+ copy->varkind=STACKVAR;\
+ copy->varnum=d;\
+ s=s->prev;\
+ }\
+ copy->prev=NULL;\
+ copy=new-1;\
+ }\
+ else\
+ copy=NULL;\
+}
+
+
+#define BBEND(s,i){\
+ i=stackdepth-1;\
+ copy=s;\
+ while(copy){\
+ if((copy->varkind==STACKVAR)&&(copy->varnum>i))\
+ copy->varkind=TEMPVAR;\
+ else {\
+ copy->varkind=STACKVAR;\
+ copy->varnum=i;\
+ }\
+ interfaces[i][copy->type].type = copy->type;\
+ interfaces[i][copy->type].flags |= copy->flags;\
+ i--;copy=copy->prev;\
+ }\
+ i=bptr->indepth-1;\
+ copy=bptr->instack;\
+ while(copy){\
+ interfaces[i][copy->type].type = copy->type;\
+ if(copy->varkind==STACKVAR){\
+ if (copy->flags & SAVEDVAR)\
+ interfaces[i][copy->type].flags |= SAVEDVAR;\
+ }\
+ i--;copy=copy->prev;\
+ }\
+}
+
+
+#define MARKREACHED(b,c) {\
+ if(b->flags<0)\
+ {COPYCURSTACK(c);b->flags=0;b->instack=c;b->indepth=stackdepth;}\
+ else {stackptr s=curstack;stackptr t=b->instack;\
+ if(b->indepth!=stackdepth)\
+ {show_icmd_method();panic("Stack depth mismatch");}\
+ while(s){if (s->type!=t->type)\
+ TYPEPANIC\
+ s=s->prev;t=t->prev;\
+ }\
+ }\
+}
+
+
+static void show_icmd_method();
+
+static void analyse_stack()
+{
+ int b_count;
+ int stackdepth;
+ stackptr curstack, new, copy;
+ int opcode, i, len, loops;
+ int superblockend, repeat, deadcode;
+ instruction *iptr = instr;
+ basicblock *bptr, *tbptr;
+ s4 *s4ptr;
+
+ arguments_num = 0;
+ new = stack;
+ loops = 0;
+ block[0].flags = BBREACHED;
+ block[0].instack = 0;
+ block[0].indepth = 0;
+
+ for (i = 0; i < exceptiontablelength; i++) {
+ bptr = &block[block_index[extable[i].handlerpc]];
+ bptr->flags = BBREACHED;
+ bptr->type = BBTYPE_EXH;
+ bptr->instack = new;
+ bptr->indepth = 1;
+ STACKRESET;
+ NEWXSTACK;
+ }
+
+ do {
+ loops++;
+ b_count = block_count;
+ bptr = block;
+ superblockend = true;
+ repeat = false;
+ STACKRESET;
+ deadcode = true;
+ while (--b_count >= 0) {
+ if (superblockend && (bptr->flags < BBREACHED))
+ repeat = true;
+ else if (bptr->flags <= BBREACHED) {
+ if (superblockend)
+ stackdepth = bptr->indepth;
+ else if (bptr->flags < BBREACHED) {
+ COPYCURSTACK(copy);
+ bptr->instack = copy;
+ bptr->indepth = stackdepth;
+ }
+ else if (bptr->indepth != stackdepth) {
+ show_icmd_method();
+ panic("Stack depth mismatch");
+
+ }
+ curstack = bptr->instack;
+ deadcode = false;
+ superblockend = false;
+ bptr->flags = BBFINISHED;
+ i = bptr[0].ipc;
+ len = bptr[1].ipc - i;
+ iptr = &instr[i];
+ while (--len >= 0) {
+ opcode = iptr->opc;
+ switch (opcode) {
+
+ /* pop 0 push 0 */
+
+ case ICMD_NOP:
+ case ICMD_CHECKASIZE:
+ SETDST;
+ break;
+ case ICMD_RET:
+ locals[iptr->op1][TYPE_ADR].type = TYPE_ADR;
+ case ICMD_RETURN:
+ COUNT(count_pcmd_return);
+ SETDST;
+ superblockend = true;
+ break;
+
+ /* pop 0 push 1 const */
+
+ case ICMD_ICONST:
+ COUNT(count_pcmd_load);
+ if (len > 0) {
+ switch (iptr[1].opc) {
+ case ICMD_IADD:
+ iptr[0].opc = ICMD_IADDCONST;
+icmd_iconst_tail:
+ iptr[1].opc = ICMD_NOP;
+ OP1_1(TYPE_INT,TYPE_INT);
+ COUNT(count_pcmd_op);
+ break;
+ case ICMD_ISUB:
+ iptr[0].opc = ICMD_ISUBCONST;
+ goto icmd_iconst_tail;
+ case ICMD_IMUL:
+ iptr[0].opc = ICMD_IMULCONST;
+ goto icmd_iconst_tail;
+ case ICMD_IAND:
+ iptr[0].opc = ICMD_IANDCONST;
+ goto icmd_iconst_tail;
+ case ICMD_IOR:
+ iptr[0].opc = ICMD_IORCONST;
+ goto icmd_iconst_tail;
+ case ICMD_IXOR:
+ iptr[0].opc = ICMD_IXORCONST;
+ goto icmd_iconst_tail;
+ case ICMD_ISHL:
+ iptr[0].opc = ICMD_ISHLCONST;
+ goto icmd_iconst_tail;
+ case ICMD_ISHR:
+ iptr[0].opc = ICMD_ISHRCONST;
+ goto icmd_iconst_tail;
+ case ICMD_IUSHR:
+ iptr[0].opc = ICMD_IUSHRCONST;
+ goto icmd_iconst_tail;
+ case ICMD_IF_ICMPEQ:
+ iptr[0].opc = ICMD_IFEQ;
+icmd_if_icmp_tail:
+ iptr[0].op1 = iptr[1].op1;
+ iptr[1].opc = ICMD_NOP;
+ OP1_0(TYPE_INT);
+ tbptr = block + block_index[iptr->op1];
+ MARKREACHED(tbptr, copy);
+ COUNT(count_pcmd_bra);
+ break;
+ case ICMD_IF_ICMPLT:
+ iptr[0].opc = ICMD_IFLT;
+ goto icmd_if_icmp_tail;
+ case ICMD_IF_ICMPLE:
+ iptr[0].opc = ICMD_IFLE;
+ goto icmd_if_icmp_tail;
+ case ICMD_IF_ICMPNE:
+ iptr[0].opc = ICMD_IFNE;
+ goto icmd_if_icmp_tail;
+ case ICMD_IF_ICMPGT:
+ iptr[0].opc = ICMD_IFGT;
+ goto icmd_if_icmp_tail;
+ case ICMD_IF_ICMPGE:
+ iptr[0].opc = ICMD_IFGE;
+ goto icmd_if_icmp_tail;
+ default:
+ CONST(TYPE_INT);
+ }
+ }
+ else
+ CONST(TYPE_INT);
+ break;
+ case ICMD_LCONST:
+ COUNT(count_pcmd_load);
+ if (len > 0) {
+ switch (iptr[1].opc) {
+ case ICMD_LADD:
+ iptr[0].opc = ICMD_LADDCONST;
+icmd_lconst_tail:
+ iptr[1].opc = ICMD_NOP;
+ OP1_1(TYPE_LNG,TYPE_LNG);
+ COUNT(count_pcmd_op);
+ break;
+ case ICMD_LSUB:
+ iptr[0].opc = ICMD_LSUBCONST;
+ goto icmd_lconst_tail;
+ case ICMD_LMUL:
+ iptr[0].opc = ICMD_LMULCONST;
+ goto icmd_lconst_tail;
+ case ICMD_LAND:
+ iptr[0].opc = ICMD_LANDCONST;
+ goto icmd_lconst_tail;
+ case ICMD_LOR:
+ iptr[0].opc = ICMD_LORCONST;
+ goto icmd_lconst_tail;
+ case ICMD_LXOR:
+ iptr[0].opc = ICMD_LXORCONST;
+ goto icmd_lconst_tail;
+ case ICMD_LSHL:
+ iptr[0].opc = ICMD_LSHLCONST;
+ goto icmd_lconst_tail;
+ case ICMD_LSHR:
+ iptr[0].opc = ICMD_LSHRCONST;
+ goto icmd_lconst_tail;
+ case ICMD_LUSHR:
+ iptr[0].opc = ICMD_LUSHRCONST;
+ goto icmd_lconst_tail;
+ case ICMD_LCMP:
+ if ((len > 1) && (iptr[2].val.i == 0)) {
+ switch (iptr[2].opc) {
+ case ICMD_IFEQ:
+ iptr[0].opc = ICMD_IF_LEQ;
+icmd_lconst_lcmp_tail:
+ iptr[0].op1 = iptr[2].op1;
+ iptr[1].opc = ICMD_NOP;
+ iptr[2].opc = ICMD_NOP;
+ OP1_0(TYPE_LNG);
+ tbptr = block + block_index[iptr->op1];
+ MARKREACHED(tbptr, copy);
+ COUNT(count_pcmd_bra);
+ COUNT(count_pcmd_op);
+ break;
+ case ICMD_IFNE:
+ iptr[0].opc = ICMD_IF_LNE;
+ goto icmd_lconst_lcmp_tail;
+ case ICMD_IFLT:
+ iptr[0].opc = ICMD_IF_LLT;
+ goto icmd_lconst_lcmp_tail;
+ case ICMD_IFGT:
+ iptr[0].opc = ICMD_IF_LGT;
+ goto icmd_lconst_lcmp_tail;
+ case ICMD_IFLE:
+ iptr[0].opc = ICMD_IF_LLE;
+ goto icmd_lconst_lcmp_tail;
+ case ICMD_IFGE:
+ iptr[0].opc = ICMD_IF_LGE;
+ goto icmd_lconst_lcmp_tail;
+ default:
+ CONST(TYPE_LNG);
+ } /* switch (iptr[2].opc) */
+ } /* if (iptr[2].val.i == 0) */
+ else
+ CONST(TYPE_LNG);
+ break;
+ default:
+ CONST(TYPE_LNG);
+ }
+ }
+ else
+ CONST(TYPE_LNG);
+ break;
+ case ICMD_FCONST:
+ COUNT(count_pcmd_load);
+ CONST(TYPE_FLT);
+ break;
+ case ICMD_DCONST:
+ COUNT(count_pcmd_load);
+ CONST(TYPE_DBL);
+ break;
+ case ICMD_ACONST:
+ COUNT(count_pcmd_load);
+ CONST(TYPE_ADR);
+ break;
+
+ /* pop 0 push 1 load */
+
+ case ICMD_ILOAD:
+ case ICMD_LLOAD:
+ case ICMD_FLOAD:
+ case ICMD_DLOAD:
+ case ICMD_ALOAD:
+ COUNT(count_load_instruction);
+ i = opcode-ICMD_ILOAD;
+ locals[iptr->op1][i].type = i;
+ LOAD(i, LOCALVAR, iptr->op1);
+ break;
+
+ /* pop 2 push 1 */
+
+ case ICMD_IALOAD:
+ case ICMD_LALOAD:
+ case ICMD_FALOAD:
+ case ICMD_DALOAD:
+ case ICMD_AALOAD:
+ COUNT(count_check_null);
+ COUNT(count_check_bound);
+ COUNT(count_pcmd_mem);
+ OP2IAT_1(opcode-ICMD_IALOAD);
+ break;
+
+ case ICMD_BALOAD:
+ case ICMD_CALOAD:
+ case ICMD_SALOAD:
+ COUNT(count_check_null);
+ COUNT(count_check_bound);
+ COUNT(count_pcmd_mem);
+ OP2IAT_1(TYPE_INT);
+ break;
+
+ /* pop 0 push 0 iinc */
+
+ case ICMD_IINC:
+#ifdef STATISTICS
+ i = stackdepth;
+ if (i >= 10)
+ count_store_depth[10]++;
+ else
+ count_store_depth[i]++;
+#endif
+ copy = curstack;
+ i = stackdepth - 1;
+ while (copy) {
+ if ((copy->varkind == LOCALVAR) &&
+ (copy->varnum == curstack->varnum)) {
+ copy->varkind = TEMPVAR;
+ copy->varnum = i;
+ }
+ i--;
+ copy = copy->prev;
+ }
+ SETDST;
+ break;
+
+ /* pop 1 push 0 store */
+
+ case ICMD_ISTORE:
+ case ICMD_LSTORE:
+ case ICMD_FSTORE:
+ case ICMD_DSTORE:
+ case ICMD_ASTORE:
+ i = opcode-ICMD_ISTORE;
+ locals[iptr->op1][i].type = i;
+#ifdef STATISTICS
+ count_pcmd_store++;
+ i = new - curstack;
+ if (i >= 20)
+ count_store_length[20]++;
+ else
+ count_store_length[i]++;
+ i = stackdepth - 1;
+ if (i >= 10)
+ count_store_depth[10]++;
+ else
+ count_store_depth[i]++;
+#endif
+ copy = curstack->prev;
+ i = stackdepth - 2;
+ while (copy) {
+ if ((copy->varkind == LOCALVAR) &&
+ (copy->varnum == curstack->varnum)) {
+ copy->varkind = TEMPVAR;
+ copy->varnum = i;
+ }
+ i--;
+ copy = copy->prev;
+ }
+ if ((new - curstack) == 1) {
+ curstack->varkind = LOCALVAR;
+ curstack->varnum = iptr->op1;
+ };
+ STORE(opcode-ICMD_ISTORE);
+ break;
+
+ /* pop 3 push 0 */
+
+ case ICMD_IASTORE:
+ case ICMD_LASTORE:
+ case ICMD_FASTORE:
+ case ICMD_DASTORE:
+ case ICMD_AASTORE:
+ COUNT(count_check_null);
+ COUNT(count_check_bound);
+ COUNT(count_pcmd_mem);
+ OP3TIA_0(opcode-ICMD_IASTORE);
+ break;
+ case ICMD_BASTORE:
+ case ICMD_CASTORE:
+ case ICMD_SASTORE:
+ COUNT(count_check_null);
+ COUNT(count_check_bound);
+ COUNT(count_pcmd_mem);
+ OP3TIA_0(TYPE_INT);
+ break;
+
+ /* pop 1 push 0 */
+
+ case ICMD_POP:
+ OP1_0ANY;
+ break;
+
+ case ICMD_IRETURN:
+ case ICMD_LRETURN:
+ case ICMD_FRETURN:
+ case ICMD_DRETURN:
+ case ICMD_ARETURN:
+ COUNT(count_pcmd_return);
+ OP1_0(opcode-ICMD_IRETURN);
+ superblockend = true;
+ break;
+
+ case ICMD_ATHROW:
+ COUNT(count_check_null);
+ OP1_0(TYPE_ADR);
+ STACKRESET;
+ SETDST;
+ superblockend = true;
+ break;
+
+ case ICMD_PUTSTATIC:
+ COUNT(count_pcmd_mem);
+ OP1_0(iptr->op1);
+ break;
+
+ /* pop 1 push 0 branch */
+
+ case ICMD_IFNULL:
+ case ICMD_IFNONNULL:
+ COUNT(count_pcmd_bra);
+ OP1_0(TYPE_ADR);
+ tbptr = block + block_index[iptr->op1];
+ MARKREACHED(tbptr, copy);
+ break;
+
+ case ICMD_IFEQ:
+ case ICMD_IFNE:
+ case ICMD_IFLT:
+ case ICMD_IFGE:
+ case ICMD_IFGT:
+ case ICMD_IFLE:
+ COUNT(count_pcmd_bra);
+ OP1_0(TYPE_INT);
+ tbptr = block + block_index[iptr->op1];
+ MARKREACHED(tbptr, copy);
+ break;
+
+ /* pop 0 push 0 branch */
+
+ case ICMD_GOTO:
+ COUNT(count_pcmd_bra);
+ tbptr = block + block_index[iptr->op1];
+ MARKREACHED(tbptr, copy);
+ SETDST;
+ superblockend = true;
+ break;
+
+ /* pop 1 push 0 table branch */
+
+ case ICMD_TABLESWITCH:
+ COUNT(count_pcmd_table);
+ OP1_0(TYPE_INT);
+ s4ptr = iptr->val.a;
+ tbptr = block + block_index[*s4ptr++]; /* default */
+ MARKREACHED(tbptr, copy);
+ i = *s4ptr++; /* low */
+ i = *s4ptr++ - i + 1; /* high */
+ while (--i >= 0) {
+ tbptr = block + block_index[*s4ptr++];
+ MARKREACHED(tbptr, copy);
+ }
+ SETDST;
+ superblockend = true;
+ break;
+
+ /* pop 1 push 0 table branch */
+
+ case ICMD_LOOKUPSWITCH:
+ COUNT(count_pcmd_table);
+ OP1_0(TYPE_INT);
+ s4ptr = iptr->val.a;
+ tbptr = block + block_index[*s4ptr++]; /* default */
+ MARKREACHED(tbptr, copy);
+ i = *s4ptr++; /* count */
+ while (--i >= 0) {
+ tbptr = block + block_index[s4ptr[1]];
+ MARKREACHED(tbptr, copy);
+ s4ptr += 2;
+ }
+ SETDST;
+ superblockend = true;
+ break;
+
+ case ICMD_NULLCHECKPOP:
+ case ICMD_MONITORENTER:
+ COUNT(count_check_null);
+ case ICMD_MONITOREXIT:
+ OP1_0(TYPE_ADR);
+ break;
+
+ /* pop 2 push 0 branch */
+
+ case ICMD_IF_ICMPEQ:
+ case ICMD_IF_ICMPNE:
+ case ICMD_IF_ICMPLT:
+ case ICMD_IF_ICMPGE:
+ case ICMD_IF_ICMPGT:
+ case ICMD_IF_ICMPLE:
+ COUNT(count_pcmd_bra);
+ OP2_0(TYPE_INT);
+ tbptr = block + block_index[iptr->op1];
+ MARKREACHED(tbptr, copy);
+ break;
+
+ case ICMD_IF_ACMPEQ:
+ case ICMD_IF_ACMPNE:
+ COUNT(count_pcmd_bra);
+ OP2_0(TYPE_ADR);
+ tbptr = block + block_index[iptr->op1];
+ MARKREACHED(tbptr, copy);
+ break;
+
+ /* pop 2 push 0 */
+
+ case ICMD_PUTFIELD:
+ COUNT(count_check_null);
+ COUNT(count_pcmd_mem);
+ OPTT2_0(iptr->op1,TYPE_ADR);
+ break;
+
+ case ICMD_POP2:
+ if (! IS_2_WORD_TYPE(curstack->type)) {
+ OP1_0ANY; /* second pop */
+ }
+ else
+ iptr->opc = ICMD_POP;
+ OP1_0ANY;
+ break;
+
+ /* pop 0 push 1 dup */
+
+ case ICMD_DUP:
+ COUNT(count_dup_instruction);
+ DUP;
+ break;
+
+ case ICMD_DUP2:
+ if (IS_2_WORD_TYPE(curstack->type)) {
+ iptr->opc = ICMD_DUP;
+ DUP;
+ }
+ else {
+ copy = curstack;
+ NEWSTACK(copy[-1].type, copy[-1].varkind,
+ copy[-1].varnum);
+ NEWSTACK(copy[ 0].type, copy[ 0].varkind,
+ copy[ 0].varnum);
+ SETDST;
+ stackdepth+=2;
+ }
+ break;
+
+ /* pop 2 push 3 dup */
+
+ case ICMD_DUP_X1:
+ DUP_X1;
+ break;
+
+ case ICMD_DUP2_X1:
+ if (IS_2_WORD_TYPE(curstack->type)) {
+ iptr->opc = ICMD_DUP_X1;
+ DUP_X1;
+ }
+ else {
+ DUP2_X1;
+ }
+ break;
+
+ /* pop 3 push 4 dup */
+
+ case ICMD_DUP_X2:
+ if (IS_2_WORD_TYPE(curstack[-1].type)) {
+ iptr->opc = ICMD_DUP_X1;
+ DUP_X1;
+ }
+ else {
+ DUP_X2;
+ }
+ break;
+
+ case ICMD_DUP2_X2:
+ if (IS_2_WORD_TYPE(curstack->type)) {
+ if (IS_2_WORD_TYPE(curstack[-1].type)) {
+ iptr->opc = ICMD_DUP_X1;
+ DUP_X1;
+ }
+ else {
+ iptr->opc = ICMD_DUP_X2;
+ DUP_X2;
+ }
+ }
+ else
+ if (IS_2_WORD_TYPE(curstack[-2].type)) {
+ iptr->opc = ICMD_DUP2_X1;
+ DUP2_X1;
+ }
+ else {
+ DUP2_X2;
+ }
+ break;
+
+ /* pop 2 push 2 swap */
+
+ case ICMD_SWAP:
+ SWAP;
+ break;
+
+ /* pop 2 push 1 */
+
+ case ICMD_IADD:
+ case ICMD_ISUB:
+ case ICMD_IMUL:
+ case ICMD_IDIV:
+ case ICMD_IREM:
+
+ case ICMD_ISHL:
+ case ICMD_ISHR:
+ case ICMD_IUSHR:
+ case ICMD_IAND:
+ case ICMD_IOR:
+ case ICMD_IXOR:
+ COUNT(count_pcmd_op);
+ OP2_1(TYPE_INT);
+ break;
+
+ case ICMD_LADD:
+ case ICMD_LSUB:
+ case ICMD_LMUL:
+ case ICMD_LDIV:
+ case ICMD_LREM:
+
+ case ICMD_LOR:
+ case ICMD_LAND:
+ case ICMD_LXOR:
+ COUNT(count_pcmd_op);
+ OP2_1(TYPE_LNG);
+ break;
+
+ case ICMD_LSHL:
+ case ICMD_LSHR:
+ case ICMD_LUSHR:
+ COUNT(count_pcmd_op);
+ OP2IT_1(TYPE_LNG);
+ break;
+
+ case ICMD_FADD:
+ case ICMD_FSUB:
+ case ICMD_FMUL:
+ case ICMD_FDIV:
+ case ICMD_FREM:
+ COUNT(count_pcmd_op);
+ OP2_1(TYPE_FLT);
+ break;
+
+ case ICMD_DADD:
+ case ICMD_DSUB:
+ case ICMD_DMUL:
+ case ICMD_DDIV:
+ case ICMD_DREM:
+ COUNT(count_pcmd_op);
+ OP2_1(TYPE_DBL);
+ break;
+
+ case ICMD_LCMP:
+ COUNT(count_pcmd_op);
+ if ((len > 0) && (iptr[1].val.i == 0)) {
+ switch (iptr[1].opc) {
+ case ICMD_IFEQ:
+ iptr[0].opc = ICMD_IF_LCMPEQ;
+icmd_lcmp_if_tail:
+ iptr[0].op1 = iptr[1].op1;
+ iptr[1].opc = ICMD_NOP;
+ OP2_0(TYPE_LNG);
+ tbptr = block + block_index[iptr->op1];
+ MARKREACHED(tbptr, copy);
+ COUNT(count_pcmd_bra);
+ break;
+ case ICMD_IFNE:
+ iptr[0].opc = ICMD_IF_LCMPNE;
+ goto icmd_lcmp_if_tail;
+ case ICMD_IFLT:
+ iptr[0].opc = ICMD_IF_LCMPLT;
+ goto icmd_lcmp_if_tail;
+ case ICMD_IFGT:
+ iptr[0].opc = ICMD_IF_LCMPGT;
+ goto icmd_lcmp_if_tail;
+ case ICMD_IFLE:
+ iptr[0].opc = ICMD_IF_LCMPLE;
+ goto icmd_lcmp_if_tail;
+ case ICMD_IFGE:
+ iptr[0].opc = ICMD_IF_LCMPGE;
+ goto icmd_lcmp_if_tail;
+ default:
+ OPTT2_1(TYPE_LNG, TYPE_INT);
+ }
+ }
+ else
+ OPTT2_1(TYPE_LNG, TYPE_INT);
+ break;
+ case ICMD_FCMPL:
+ case ICMD_FCMPG:
+ COUNT(count_pcmd_op);
+ OPTT2_1(TYPE_FLT, TYPE_INT);
+ break;
+ case ICMD_DCMPL:
+ case ICMD_DCMPG:
+ COUNT(count_pcmd_op);
+ OPTT2_1(TYPE_DBL, TYPE_INT);
+ break;
+
+ /* pop 1 push 1 */
+
+ case ICMD_INEG:
+ case ICMD_INT2BYTE:
+ case ICMD_INT2CHAR:
+ case ICMD_INT2SHORT:
+ COUNT(count_pcmd_op);
+ OP1_1(TYPE_INT, TYPE_INT);
+ break;
+ case ICMD_LNEG:
+ COUNT(count_pcmd_op);
+ OP1_1(TYPE_LNG, TYPE_LNG);
+ break;
+ case ICMD_FNEG:
+ COUNT(count_pcmd_op);
+ OP1_1(TYPE_FLT, TYPE_FLT);
+ break;
+ case ICMD_DNEG:
+ COUNT(count_pcmd_op);
+ OP1_1(TYPE_DBL, TYPE_DBL);
+ break;
+
+ case ICMD_I2L:
+ COUNT(count_pcmd_op);
+ OP1_1(TYPE_INT, TYPE_LNG);
+ break;
+ case ICMD_I2F:
+ COUNT(count_pcmd_op);
+ OP1_1(TYPE_INT, TYPE_FLT);
+ break;
+ case ICMD_I2D:
+ COUNT(count_pcmd_op);
+ OP1_1(TYPE_INT, TYPE_DBL);
+ break;
+ case ICMD_L2I:
+ COUNT(count_pcmd_op);
+ OP1_1(TYPE_LNG, TYPE_INT);
+ break;
+ case ICMD_L2F:
+ COUNT(count_pcmd_op);
+ OP1_1(TYPE_LNG, TYPE_FLT);
+ break;
+ case ICMD_L2D:
+ COUNT(count_pcmd_op);
+ OP1_1(TYPE_LNG, TYPE_DBL);
+ break;
+ case ICMD_F2I:
+ COUNT(count_pcmd_op);
+ OP1_1(TYPE_FLT, TYPE_INT);
+ break;
+ case ICMD_F2L:
+ COUNT(count_pcmd_op);
+ OP1_1(TYPE_FLT, TYPE_LNG);
+ break;
+ case ICMD_F2D:
+ COUNT(count_pcmd_op);
+ OP1_1(TYPE_FLT, TYPE_DBL);
+ break;
+ case ICMD_D2I:
+ COUNT(count_pcmd_op);
+ OP1_1(TYPE_DBL, TYPE_INT);
+ break;
+ case ICMD_D2L:
+ COUNT(count_pcmd_op);
+ OP1_1(TYPE_DBL, TYPE_LNG);
+ break;
+ case ICMD_D2F:
+ COUNT(count_pcmd_op);
+ OP1_1(TYPE_DBL, TYPE_FLT);
+ break;
+
+ case ICMD_CHECKCAST:
+ OP1_1(TYPE_ADR, TYPE_ADR);
+ break;
+
+ case ICMD_ARRAYLENGTH:
+ case ICMD_INSTANCEOF:
+ OP1_1(TYPE_ADR, TYPE_INT);
+ break;
+
+ case ICMD_NEWARRAY:
+ case ICMD_ANEWARRAY:
+ OP1_1(TYPE_INT, TYPE_ADR);
+ break;
+
+ case ICMD_GETFIELD:
+ COUNT(count_check_null);
+ COUNT(count_pcmd_mem);
+ OP1_1(TYPE_ADR, iptr->op1);
+ break;
+
+ /* pop 0 push 1 */
+
+ case ICMD_GETSTATIC:
+ COUNT(count_pcmd_mem);
+ OP0_1(iptr->op1);
+ break;
+
+ case ICMD_NEW:
+ OP0_1(TYPE_ADR);
+ break;
+
+ case ICMD_JSR:
+ OP0_1(TYPE_ADR);
+ tbptr = block + block_index[iptr->op1];
+ tbptr->type=BBTYPE_SBR;
+ MARKREACHED(tbptr, copy);
+ OP1_0ANY;
+ break;
+
+ /* pop many push any */
+
+ case ICMD_INVOKEVIRTUAL:
+ case ICMD_INVOKESPECIAL:
+ case ICMD_INVOKEINTERFACE:
+ case ICMD_INVOKESTATIC:
+ COUNT(count_pcmd_met);
+ {
+ methodinfo *m = iptr->val.a;
+ if (m->flags & ACC_STATIC)
+ {COUNT(count_check_null);}
+ i = iptr->op1;
+ if (i > arguments_num)
+ arguments_num = i;
+ copy = curstack;
+ while (--i >= 0) {
+ if (! (copy->flags & SAVEDVAR)) {
+ copy->varkind = ARGVAR;
+ copy->varnum = i;
+ }
+ copy = copy->prev;
+ }
+ while (copy) {
+ copy->flags |= SAVEDVAR;
+ copy = copy->prev;
+ }
+ i = iptr->op1;
+ POPMANY(i);
+ if (m->returntype != TYPE_VOID) {
+ OP0_1(m->returntype);
+ }
+ break;
+ }
+
+ case ICMD_BUILTIN3:
+ if (! (curstack->flags & SAVEDVAR)) {
+ curstack->varkind = ARGVAR;
+ curstack->varnum = 2;
+ }
+ OP1_0ANY;
+ case ICMD_BUILTIN2:
+ if (! (curstack->flags & SAVEDVAR)) {
+ curstack->varkind = ARGVAR;
+ curstack->varnum = 1;
+ }
+ OP1_0ANY;
+ case ICMD_BUILTIN1:
+ if (! (curstack->flags & SAVEDVAR)) {
+ curstack->varkind = ARGVAR;
+ curstack->varnum = 0;
+ }
+ OP1_0ANY;
+ copy = curstack;
+ while (copy) {
+ copy->flags |= SAVEDVAR;
+ copy = copy->prev;
+ }
+ if (iptr->op1 != TYPE_VOID)
+ OP0_1(iptr->op1);
+ break;
+
+ case ICMD_MULTIANEWARRAY:
+ i = iptr->op1;
+ if ((i + intreg_argnum) > arguments_num)
+ arguments_num = i + intreg_argnum;
+ copy = curstack;
+ while (--i >= 0) {
+ if (! (copy->flags & SAVEDVAR)) {
+ copy->varkind = ARGVAR;
+ copy->varnum = i + intreg_argnum;
+ }
+ copy = copy->prev;
+ }
+ while (copy) {
+ copy->flags |= SAVEDVAR;
+ copy = copy->prev;
+ }
+ i = iptr->op1;
+ POPMANY(i);
+ OP0_1(TYPE_ADR);
+ break;
+
+ default:
+ printf("ICMD %d at %d\n", iptr->opc, (int)(iptr-instr));
+ panic("Missing ICMD code during stack analysis");
+ } /* switch */
+ iptr++;
+ } /* while instructions */
+ bptr->outstack = curstack;
+ bptr->outdepth = stackdepth;
+ BBEND(curstack, i);
+ } /* if */
+ else
+ superblockend = true;
+ bptr++;
+ } /* while blocks */
+ } while (repeat && ! deadcode);
+
+#ifdef STATISTICS
+ if (block_count > count_max_basic_blocks)
+ count_max_basic_blocks = block_count;
+ count_basic_blocks += block_count;
+ if (block[block_count].ipc > count_max_javainstr)
+ count_max_javainstr = block[block_count].ipc;
+ count_javainstr += block[block_count].ipc;
+ if (stack_count > count_upper_bound_new_stack)
+ count_upper_bound_new_stack = stack_count;
+ if ((new - stack) > count_max_new_stack)
+ count_max_new_stack = (new - stack);
+
+ b_count = block_count;
+ bptr = block;
+ while (--b_count >= 0) {
+ if (bptr->flags > BBREACHED) {
+ if (bptr->indepth >= 10)
+ count_block_stack[10]++;
+ else
+ count_block_stack[bptr->indepth]++;
+ len = bptr[1].ipc - bptr[0].ipc;
+ if (len <= 10)
+ count_block_size_distribution[len - 1]++;
+ else if (len <= 12)
+ count_block_size_distribution[10]++;
+ else if (len <= 14)
+ count_block_size_distribution[11]++;
+ else if (len <= 16)
+ count_block_size_distribution[12]++;
+ else if (len <= 18)
+ count_block_size_distribution[13]++;
+ else if (len <= 20)
+ count_block_size_distribution[14]++;
+ else if (len <= 25)
+ count_block_size_distribution[15]++;
+ else if (len <= 30)
+ count_block_size_distribution[16]++;
+ else
+ count_block_size_distribution[17]++;
+ }
+ bptr++;
+ }
+
+ if (loops == 1)
+ count_analyse_iterations[0]++;
+ else if (loops == 2)
+ count_analyse_iterations[1]++;
+ else if (loops == 3)
+ count_analyse_iterations[2]++;
+ else if (loops == 4)
+ count_analyse_iterations[3]++;
+ else
+ count_analyse_iterations[4]++;
+
+ if (block_count <= 5)
+ count_method_bb_distribution[0]++;
+ else if (block_count <= 10)
+ count_method_bb_distribution[1]++;
+ else if (block_count <= 15)
+ count_method_bb_distribution[2]++;
+ else if (block_count <= 20)
+ count_method_bb_distribution[3]++;
+ else if (block_count <= 30)
+ count_method_bb_distribution[4]++;
+ else if (block_count <= 40)
+ count_method_bb_distribution[5]++;
+ else if (block_count <= 50)
+ count_method_bb_distribution[6]++;
+ else if (block_count <= 75)
+ count_method_bb_distribution[7]++;
+ else
+ count_method_bb_distribution[8]++;
+#endif
+}
+
+
+static void print_stack(stackptr s) {
+ int i, j;
+ stackptr t;
+
+ i = maxstack;
+ t = s;
+
+ while (t) {
+ i--;
+ t = t->prev;
+ }
+ j = maxstack - i;
+ while (--i >= 0)
+ printf(" ");
+ while (s) {
+ j--;
+ if (s->flags & SAVEDVAR)
+ switch (s->varkind) {
+ case TEMPVAR:
+ if (s->flags & INMEMORY)
+ printf(" m%02d", s->regoff);
+ else
+ printf(" r%02d", s->regoff);
+ break;
+ case STACKVAR:
+ printf(" s%02d", s->varnum);
+ break;
+ case LOCALVAR:
+ printf(" l%02d", s->varnum);
+ break;
+ case ARGVAR:
+ printf(" a%02d", s->varnum);
+ break;
+ default:
+ printf(" !%02d", j);
+ }
+ else
+ switch (s->varkind) {
+ case TEMPVAR:
+ if (s->flags & INMEMORY)
+ printf(" M%02d", s->regoff);
+ else
+ printf(" R%02d", s->regoff);
+ break;
+ case STACKVAR:
+ printf(" S%02d", s->varnum);
+ break;
+ case LOCALVAR:
+ printf(" L%02d", s->varnum);
+ break;
+ case ARGVAR:
+ printf(" A%02d", s->varnum);
+ break;
+ default:
+ printf(" ?%02d", j);
+ }
+ s = s->prev;
+ }
+}
+
+
+static void print_reg(stackptr s) {
+ if (s) {
+ if (s->flags & SAVEDVAR)
+ switch (s->varkind) {
+ case TEMPVAR:
+ if (s->flags & INMEMORY)
+ printf(" tm%02d", s->regoff);
+ else
+ printf(" tr%02d", s->regoff);
+ break;
+ case STACKVAR:
+ printf(" s %02d", s->varnum);
+ break;
+ case LOCALVAR:
+ printf(" l %02d", s->varnum);
+ break;
+ case ARGVAR:
+ printf(" a %02d", s->varnum);
+ break;
+ default:
+ printf(" ! %02d", s->varnum);
+ }
+ else
+ switch (s->varkind) {
+ case TEMPVAR:
+ if (s->flags & INMEMORY)
+ printf(" Tm%02d", s->regoff);
+ else
+ printf(" Tr%02d", s->regoff);
+ break;
+ case STACKVAR:
+ printf(" S %02d", s->varnum);
+ break;
+ case LOCALVAR:
+ printf(" L %02d", s->varnum);
+ break;
+ case ARGVAR:
+ printf(" A %02d", s->varnum);
+ break;
+ default:
+ printf(" ? %02d", s->varnum);
+ }
+ }
+ else
+ printf(" ");
+
+}
+
+
+static char *builtin_name(functionptr bptr)
+{
+ builtin_descriptor *bdesc = builtin_desc;
+ while ((bdesc->bptr != NULL) && (bdesc->bptr != bptr))
+ bdesc++;
+ return bdesc->name;
+}
+
+
+static void show_icmd_method()
+{
+ int b, i, j;
+ int deadcode;
+ s4 *s4ptr;
+
+ printf("\n");
+ unicode_fprint(stdout, class->name);
+ printf(".");
+ unicode_fprint(stdout, method->name);
+ printf(" ");
+ unicode_fprint(stdout, method->descriptor);
+ printf ("\n\nMax locals: %d\n", (int) maxlocals);
+ printf ("Max stack: %d\n", (int) maxstack);
+
+ printf ("Exceptions:\n");
+ for (i = 0; i < exceptiontablelength; i++) {
+ printf(" L%03d ... ", block_index[extable[i].startpc]);
+ printf("L%03d = ", block_index[extable[i].endpc]);
+ printf("L%03d\n", block_index[extable[i].handlerpc]);
+ }
+
+ printf ("Local Table:\n");
+ for (i = 0; i < maxlocals; i++) {
+ printf(" %3d: ", i);
+ for (j = TYPE_INT; j <= TYPE_ADR; j++)
+ if (locals[i][j].type >= 0) {
+ printf(" (%d) ", j);
+ if (locals[i][j].flags)
+ printf("m");
+ else
+ printf("r");
+ printf("%2d", locals[i][j].regoff);
+ }
+ printf("\n");
+ }
+ printf("\n");
+
+ printf ("Interface Table:\n");
+ for (i = 0; i < maxstack; i++) {
+ if ((interfaces[i][0].type >= 0) || (interfaces[i][1].type >= 0) ||
+ (interfaces[i][2].type >= 0) || (interfaces[i][3].type >= 0) ||
+ (interfaces[i][4].type >= 0)) {
+ printf(" %3d: ", i);
+ for (j = TYPE_INT; j <= TYPE_ADR; j++)
+ if (interfaces[i][j].type >= 0) {
+ printf(" (%d) ", j);
+ if (interfaces[i][j].flags & SAVEDVAR)
+ printf("s");
+ else
+ printf("t");
+ if (interfaces[i][j].flags & INMEMORY)
+ printf("m");
+ else
+ printf("r");
+ printf("%2d", interfaces[i][j].regoff);
+ }
+ printf("\n");
+ }
+ }
+ printf("\n");
+ for (b = 0; b < block_count; b++) {
+ deadcode = block[b].flags <= BBREACHED;
+ printf("[");
+ if (deadcode)
+ for (j = maxstack; j > 0; j--)
+ printf(" ? ");
+ else
+ print_stack(block[b].instack);
+ printf("] L%03d:\n", b);
+ for (i = block[b].ipc; i < block[b + 1].ipc; i++) {
+ printf("[");
+ if (deadcode) {
+ for (j = maxstack; j > 0; j--)
+ printf(" ? ");
+ }
+ else
+ print_stack(instr[i].dst);
+ printf("] %4d %s", i, icmd_names[instr[i].opc]);
+ switch ((int) instr[i].opc) {
+ case ICMD_IADDCONST:
+ case ICMD_ISUBCONST:
+ case ICMD_IMULCONST:
+ case ICMD_IANDCONST:
+ case ICMD_IORCONST:
+ case ICMD_IXORCONST:
+ case ICMD_ISHLCONST:
+ case ICMD_ISHRCONST:
+ case ICMD_IUSHRCONST:
+ case ICMD_ICONST:
+ case ICMD_GETFIELD:
+ case ICMD_PUTFIELD:
+ printf(" %d", instr[i].val.i);
+ break;
+ case ICMD_LADDCONST:
+ case ICMD_LSUBCONST:
+ case ICMD_LMULCONST:
+ case ICMD_LANDCONST:
+ case ICMD_LORCONST:
+ case ICMD_LXORCONST:
+ case ICMD_LSHLCONST:
+ case ICMD_LSHRCONST:
+ case ICMD_LUSHRCONST:
+ case ICMD_LCONST:
+ printf(" %ld", instr[i].val.l);
+ break;
+ case ICMD_FCONST:
+ printf(" %f", instr[i].val.f);
+ break;
+ case ICMD_DCONST:
+ printf(" %f", instr[i].val.d);
+ break;
+ case ICMD_ACONST:
+ case ICMD_PUTSTATIC:
+ case ICMD_GETSTATIC:
+ printf(" %p", instr[i].val.a);
+ break;
+ case ICMD_IINC:
+ printf(" %d + %d", instr[i].op1, instr[i].val.i);
+ break;
+ case ICMD_RET:
+ case ICMD_ILOAD:
+ case ICMD_LLOAD:
+ case ICMD_FLOAD:
+ case ICMD_DLOAD:
+ case ICMD_ALOAD:
+ case ICMD_ISTORE:
+ case ICMD_LSTORE:
+ case ICMD_FSTORE:
+ case ICMD_DSTORE:
+ case ICMD_ASTORE:
+ printf(" %d", instr[i].op1);
+ break;
+ case ICMD_NEW:
+ printf(" ");
+ unicode_fprint(stdout,
+ ((classinfo *) instr[i].val.a)->name);
+ break;
+ case ICMD_NEWARRAY:
+ switch (instr[i].op1) {
+ case 4:
+ printf(" boolean");
+ break;
+ case 5:
+ printf(" char");
+ break;
+ case 6:
+ printf(" float");
+ break;
+ case 7:
+ printf(" double");
+ break;
+ case 8:
+ printf(" byte");
+ break;
+ case 9:
+ printf(" short");
+ break;
+ case 10:
+ printf(" int");
+ break;
+ case 11:
+ printf(" long");
+ break;
+ }
+ break;
+ case ICMD_ANEWARRAY:
+ if (instr[i].op1) {
+ printf(" ");
+ unicode_fprint(stdout,
+ ((classinfo *) instr[i].val.a)->name);
+ }
+ break;
+ case ICMD_CHECKCAST:
+ case ICMD_INSTANCEOF:
+ if (instr[i].op1) {
+ printf(" ");
+ unicode_fprint(stdout,
+ ((classinfo *) instr[i].val.a)->name);
+ }
+ break;
+ case ICMD_BUILTIN3:
+ case ICMD_BUILTIN2:
+ case ICMD_BUILTIN1:
+ printf(" %s", builtin_name((functionptr) instr[i].val.a));
+ break;
+ case ICMD_INVOKEVIRTUAL:
+ case ICMD_INVOKESPECIAL:
+ case ICMD_INVOKESTATIC:
+ case ICMD_INVOKEINTERFACE:
+ printf(" ");
+ unicode_fprint(stdout,
+ ((methodinfo *) instr[i].val.a)->class->name);
+ printf(".");
+ unicode_fprint(stdout,
+ ((methodinfo *) instr[i].val.a)->name);
+ break;
+ case ICMD_IFEQ:
+ case ICMD_IFNE:
+ case ICMD_IFLT:
+ case ICMD_IFGE:
+ case ICMD_IFGT:
+ case ICMD_IFLE:
+ case ICMD_IF_LEQ:
+ case ICMD_IF_LNE:
+ case ICMD_IF_LLT:
+ case ICMD_IF_LGE:
+ case ICMD_IF_LGT:
+ case ICMD_IF_LLE:
+ printf("(%d) L%03d", instr[i].val.i, block_index[instr[i].op1]);
+ break;
+ case ICMD_JSR:
+ case ICMD_GOTO:
+ case ICMD_IFNULL:
+ case ICMD_IFNONNULL:
+ case ICMD_IF_ICMPEQ:
+ case ICMD_IF_ICMPNE:
+ case ICMD_IF_ICMPLT:
+ case ICMD_IF_ICMPGE:
+ case ICMD_IF_ICMPGT:
+ case ICMD_IF_ICMPLE:
+ case ICMD_IF_LCMPEQ:
+ case ICMD_IF_LCMPNE:
+ case ICMD_IF_LCMPLT:
+ case ICMD_IF_LCMPGE:
+ case ICMD_IF_LCMPGT:
+ case ICMD_IF_LCMPLE:
+ case ICMD_IF_ACMPEQ:
+ case ICMD_IF_ACMPNE:
+ printf(" L%03d", block_index[instr[i].op1]);
+ break;
+ case ICMD_TABLESWITCH:
+ s4ptr = instr[i].val.a;
+ printf(" L%03d;", block_index[*s4ptr++]); /* default */
+ j = *s4ptr++; /* low */
+ j = *s4ptr++ - j; /* high */
+ while (j >= 0) {
+ printf(" L%03d", block_index[*s4ptr++]);
+ j--;
+ }
+ break;
+ case ICMD_LOOKUPSWITCH:
+ s4ptr = instr[i].val.a;
+ printf(" L%d", block_index[*s4ptr++]); /* default */
+ j = *s4ptr++; /* count */
+ while (--j >= 0) {
+ printf(" L%03d", block_index[s4ptr[1]]);
+ s4ptr += 2;
+ }
+ break;
+ }
+ printf("\n");
+ }
+ }
+}
--- /dev/null
+/***************************** ncomp/ntools.c **********************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Ein paar zus"atzlich notwendige Funktionen, die sonst nirgends
+ hinpassen.
+
+ Authors: Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
+ Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1997/11/03
+
+*******************************************************************************/
+
+
+/***************** Funktion: compiler_addinitclass ****************************
+
+ zum Eintragen einer Klasse in die Liste der noch zu initialisierenden
+ Klassen
+
+******************************************************************************/
+
+static void compiler_addinitclass (classinfo *c)
+{
+ classinfo *cl;
+
+ if (c->initialized) return;
+
+ cl = chain_first(uninitializedclasses);
+ if (cl == c)
+ return;
+
+ if (cl == class)
+ cl = chain_next(uninitializedclasses);
+ for (;;) {
+ if (cl == c)
+ return;
+ if (cl == NULL) {
+ if (runverbose) {
+ sprintf(logtext, "compiler_addinitclass: ");
+ unicode_sprint(logtext+strlen(logtext), c->name);
+ dolog();
+ }
+ chain_addlast(uninitializedclasses, c);
+ return;
+ }
+ if (c < cl) {
+ if (runverbose) {
+ sprintf(logtext, "compiler_addinitclass: ");
+ unicode_sprint(logtext+strlen(logtext), c->name);
+ dolog();
+ }
+ chain_addbefore(uninitializedclasses, c);
+ return;
+ }
+ cl = chain_next(uninitializedclasses);
+ }
+}
+
+
+
+/***************** Hilfsfunktionen zum Decodieren des Bytecodes ***************
+
+ lesen ein Datum des gew"unschten Typs aus dem Bytecode an der
+ angegebenen Stelle
+
+******************************************************************************/
+
+#define code_get_u1(pos) jcode[pos]
+#define code_get_s1(pos) ((s1)jcode[pos])
+#define code_get_u2(pos) ((((u2)jcode[pos])<<8)+jcode[pos+1])
+#define code_get_s2(pos) ((s2)((((u2)jcode[pos])<<8)+jcode[pos+1]))
+#define code_get_u4(pos) ((((u4)jcode[pos])<<24)+(((u4)jcode[pos+1])<<16)+\
+ (((u4)jcode[pos+2])<<8)+jcode[pos+3])
+#define code_get_s4(pos) ((s4)((((u4)jcode[pos])<<24)+(((u4)jcode[pos+1])<<16)+\
+ (((u4)jcode[pos+2])<<8)+jcode[pos+3]))
+
+
+/******************** Funktion: descriptor2types *****************************
+
+ Decodiert einen Methoddescriptor.
+ Beim Aufruf dieser Funktion MUSS (!!!) der Descriptor ein
+ gueltiges Format haben (wird eh vorher vom loader ueberprueft).
+
+ Die Funktion erzeugt ein Array von integers (u2), in das die
+ Parametertypen eingetragen werden, und liefert einen Zeiger auf
+ das Array in einem Referenzparameter ('paramtypes') zur"uck.
+ Die L"ange dieses Arrays und der Methodenr"uckgabewert werden ebenfalls
+ in Referenzparametern zur"uckgeliefert.
+
+ Der Parameter 'isstatic' gibt an (wenn true), dass kein zus"atzlicher
+ erster Eintrag f"ur den this-Zeiger in das Array eingetragen
+ werden soll (sonst wird er n"amlich automatisch erzeugt, mit dem
+ Typ TYPE_ADR).
+
+******************************************************************************/
+
+static void descriptor2types (methodinfo *m)
+{
+ u1 *types, *tptr;
+ int pcount, c;
+ u2 *cptr;
+
+ pcount = 0;
+ types = DMNEW (u1, m->descriptor->length);
+
+ tptr = types;
+ if (!(m->flags & ACC_STATIC)) {
+ *tptr++ = TYPE_ADR;
+ pcount++;
+ }
+
+ cptr = m->descriptor->text;
+ cptr++;
+ while ((c = *cptr++) != ')') {
+ pcount++;
+ switch (c) {
+ case 'B':
+ case 'C':
+ case 'I':
+ case 'S':
+ case 'Z': *tptr++ = TYPE_INT;
+ break;
+ case 'J': *tptr++ = TYPE_LNG;
+ break;
+ case 'F': *tptr++ = TYPE_FLT;
+ break;
+ case 'D': *tptr++ = TYPE_DBL;
+ break;
+ case 'L': *tptr++ = TYPE_ADR;
+ while (*cptr++ != ';');
+ break;
+ case '[': *tptr++ = TYPE_ADR;
+ while (c == '[')
+ c = *cptr++;
+ if (c == 'L')
+ while (*cptr++ != ';') /* skip */;
+ break;
+ default: panic ("Ill formed methodtype-descriptor");
+ }
+ }
+
+ switch (*cptr) {
+ case 'B':
+ case 'C':
+ case 'I':
+ case 'S':
+ case 'Z': m->returntype = TYPE_INT;
+ break;
+ case 'J': m->returntype = TYPE_LNG;
+ break;
+ case 'F': m->returntype = TYPE_FLT;
+ break;
+ case 'D': m->returntype = TYPE_DBL;
+ break;
+ case '[':
+ case 'L': m->returntype = TYPE_ADR;
+ break;
+ case 'V': m->returntype = TYPE_VOID;
+ break;
+
+ default: panic ("Ill formed methodtype-descriptor");
+ }
+
+ m->paramcount = pcount;
+ m->paramtypes = types;
+}
+
--- /dev/null
+/***************************** ncomp/ncomp.c ***********************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties.
+
+ Contains the functions which translates a JavaVM method into native code.
+ This is the new version of the compiler which is a lot faster and has new
+ exception handling schemes. The main function is new_comp.
+
+ Authors: Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
+ Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1997/11/05
+
+*******************************************************************************/
+
+#include "signal.h"
+#include "global.h"
+#include "ncomp/ncomp.h"
+
+#include "loader.h"
+#include "tables.h"
+#include "builtin.h"
+#include "native.h"
+#include "asmpart.h"
+
+#include "threads/thread.h"
+
+
+/*************************** global switches **********************************/
+
+bool compileverbose = false;
+bool showstack = false;
+bool showdisassemble = false;
+bool showintermediate = false;
+int optimizelevel = 0;
+
+bool checkbounds = true;
+bool checknull = true;
+bool checkfloats = true;
+bool checksync = true;
+
+bool getcompilingtime = false;
+long compilingtime = 0;
+
+int has_ext_instr_set = 0;
+
+bool statistics = false;
+
+int count_jit_calls = 0;
+int count_methods = 0;
+int count_spills = 0;
+int count_pcmd_activ = 0;
+int count_pcmd_drop = 0;
+int count_pcmd_zero = 0;
+int count_pcmd_const_store = 0;
+int count_pcmd_const_alu = 0;
+int count_pcmd_const_bra = 0;
+int count_pcmd_load = 0;
+int count_pcmd_move = 0;
+int count_load_instruction = 0;
+int count_pcmd_store = 0;
+int count_pcmd_store_comb = 0;
+int count_dup_instruction = 0;
+int count_pcmd_op = 0;
+int count_pcmd_mem = 0;
+int count_pcmd_met = 0;
+int count_pcmd_bra = 0;
+int count_pcmd_table = 0;
+int count_pcmd_return = 0;
+int count_pcmd_returnx = 0;
+int count_check_null = 0;
+int count_check_bound = 0;
+int count_max_basic_blocks = 0;
+int count_basic_blocks = 0;
+int count_javainstr = 0;
+int count_max_javainstr = 0;
+int count_javacodesize = 0;
+int count_javaexcsize = 0;
+int count_calls = 0;
+int count_tryblocks = 0;
+int count_code_len = 0;
+int count_data_len = 0;
+int count_cstub_len = 0;
+int count_nstub_len = 0;
+int count_max_new_stack = 0;
+int count_upper_bound_new_stack = 0;
+static int count_block_stack_init[11] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+int *count_block_stack = count_block_stack_init;
+static int count_analyse_iterations_init[5] = {0, 0, 0, 0, 0};
+int *count_analyse_iterations = count_analyse_iterations_init;
+static int count_method_bb_distribution_init[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+int *count_method_bb_distribution = count_method_bb_distribution_init;
+static int count_block_size_distribution_init[18] = {0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+int *count_block_size_distribution = count_block_size_distribution_init;
+static int count_store_length_init[21] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+int *count_store_length = count_store_length_init;
+static int count_store_depth_init[11] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+int *count_store_depth = count_store_depth_init;
+
+
+/*********************** include compiler data types **************************/
+
+#include "ncomp/ncompdef.h"
+
+
+/*********************** global compiler variables ****************************/
+
+ /* data about the currently compiled method */
+
+static classinfo *class; /* class the compiled method belongs to */
+static methodinfo *method; /* pointer to method info of compiled method */
+static unicode *descriptor; /* type descriptor of compiled method */
+static u2 mparamcount; /* number of parameters (incl. this) */
+static u1 *mparamtypes; /* types of all parameters (TYPE_INT, ...) */
+static u2 mreturntype; /* return type of method */
+
+static int maxstack; /* maximal JavaVM stack size */
+static int maxlocals; /* maximal number of local JavaVM variables */
+static int jcodelength; /* length of JavaVM-codes */
+static u1 *jcode; /* pointer to start of JavaVM-code */
+static int exceptiontablelength;/* length of exception table */
+static exceptiontable *extable; /* pointer to start of exception table */
+
+static int block_count; /* number of basic blocks */
+static basicblock *block; /* points to basic block array */
+static int *block_index; /* a table which contains for every byte of */
+ /* JavaVM code a basic block index if at this */
+ /* byte there is the start of a basic block */
+
+static int instr_count; /* number of JavaVM instructions */
+static instruction *instr; /* points to intermediate code instructions */
+
+static int stack_count; /* number of stack elements */
+static stackelement *stack; /* points to intermediate code instructions */
+
+static bool isleafmethod; /* true if a method doesn't call subroutines */
+
+/* list of all classes used by the compiled method which have to be */
+/* initialised (if not already done) before execution of this method */
+
+static chain *uninitializedclasses;
+
+
+/******************** include compiler subsystems *****************************/
+
+#include "sysdep/ngen.h" /* code generator header file */
+#include "ncomp/ntools.c" /* compiler tool functions */
+#include "ncomp/mcode.c" /* code generation tool functions */
+#include "ncomp/nparse.c" /* parsing of JavaVM code */
+#include "ncomp/nreg.c" /* register allocation and support routines */
+#include "ncomp/nstack.c" /* analysing the stack operations */
+#include "sysdep/ngen.c" /* code generator */
+#include "sysdep/disass.c" /* disassembler (for debug purposes only) */
+
+
+
+
+/* dummy function, used when there is no JavaVM code available */
+
+static void* do_nothing_function()
+{
+ return NULL;
+}
+
+
+/*******************************************************************************
+
+ new_compile, new version of compiler, translates one method to machine code
+
+*******************************************************************************/
+
+methodptr new_compile(methodinfo *m)
+{
+ int dumpsize;
+ long starttime = 0;
+ long stoptime = 0;
+
+ /* if method has been already compiled return immediately */
+
+ count_jit_calls++;
+
+ if (m->entrypoint)
+ return m->entrypoint;
+
+ count_methods++;
+
+ intsDisable(); /* disable interrupts */
+
+
+ /* mark start of dump memory area */
+
+ dumpsize = dump_size ();
+
+ /* measure time */
+
+ if (getcompilingtime)
+ starttime = getcputime();
+
+ /* if there is no javacode print error message and return empty method */
+
+ if (! m->jcode) {
+ sprintf(logtext, "No code given for: ");
+ unicode_sprint(logtext+strlen(logtext), m->class->name);
+ strcpy(logtext+strlen(logtext), ".");
+ unicode_sprint(logtext+strlen(logtext), m->name);
+ unicode_sprint(logtext+strlen(logtext), m->descriptor);
+ dolog();
+ intsRestore(); /* enable interrupts again */
+ return (methodptr) do_nothing_function; /* return empty method */
+ }
+
+ /* print log message for compiled method */
+
+ if (compileverbose) {
+ sprintf(logtext, "Compiling: ");
+ unicode_sprint(logtext+strlen(logtext), m->class->name);
+ strcpy(logtext+strlen(logtext), ".");
+ unicode_sprint(logtext+strlen(logtext), m->name);
+ unicode_sprint(logtext+strlen(logtext), m->descriptor);
+ dolog ();
+ }
+
+
+ /* initialisation of variables and subsystems */
+
+ isleafmethod = true;
+
+ method = m;
+ class = m->class;
+ descriptor = m->descriptor;
+ maxstack = m->maxstack;
+ maxlocals = m->maxlocals;
+ jcodelength = m->jcodelength;
+ jcode = m->jcode;
+ exceptiontablelength = m->exceptiontablelength;
+ extable = m->exceptiontable;
+
+#ifdef STATISTICS
+ count_tryblocks += exceptiontablelength;
+ count_javacodesize += jcodelength + 18;
+ count_javaexcsize += exceptiontablelength * 8;
+#endif
+
+ /* initialise parameter type descriptor */
+
+ descriptor2types (m);
+ mreturntype = m->returntype;
+ mparamcount = m->paramcount;
+ mparamtypes = m->paramtypes;
+
+ /* initialize class list with class the compiled method belongs to */
+
+ uninitializedclasses = chain_new();
+ compiler_addinitclass (m->class);
+
+
+ /********************** call the compiler passes **************************/
+
+ reg_init();
+ local_init();
+ mcode_init();
+
+ if (runverbose)
+ allocate_literals();
+
+ parse();
+
+ analyse_stack();
+
+ interface_regalloc();
+
+ allocate_scratch_registers();
+
+ local_regalloc();
+
+ gen_mcode();
+
+
+ /*********** Zwischendarstellungen auf Wunsch ausgeben **********/
+
+ if (showintermediate)
+ show_icmd_method();
+
+ if (showdisassemble) {
+ dseg_display((void*) (m->mcode));
+ disassemble((void*) (m->mcode + dseglen), m->mcodelength - dseglen);
+ fflush(stdout);
+ }
+
+
+ /* release dump area */
+
+ dump_release (dumpsize);
+
+ /* measure time */
+
+ if (getcompilingtime) {
+ stoptime = getcputime();
+ compilingtime += (stoptime-starttime);
+ }
+
+ /* initialize all used classes */
+ /* because of reentrant code global variables are not allowed here */
+
+ {
+ chain *ul = uninitializedclasses; /* list of uninitialized classes */
+ classinfo *c; /* single class */
+
+ while ((c = chain_first(ul)) != NULL) {
+ chain_remove (ul);
+ class_init (c); /* may again call the compiler */
+ }
+ chain_free (ul);
+ }
+
+ intsRestore(); /* enable interrupts again */
+
+ /* return pointer to the methods entry point */
+
+ return m -> entrypoint;
+}
+
+
+/************ functions for compiler initialisation and finalisation **********/
+
+void ncomp_init ()
+{
+ int i;
+
+ has_ext_instr_set = ! has_no_x_instr_set();
+
+ for (i = 0; i < 256; i++)
+ stackreq[i] = 1;
+
+ stackreq[JAVA_NOP] = 0;
+ stackreq[JAVA_ISTORE] = 0;
+ stackreq[JAVA_LSTORE] = 0;
+ stackreq[JAVA_FSTORE] = 0;
+ stackreq[JAVA_DSTORE] = 0;
+ stackreq[JAVA_ASTORE] = 0;
+ stackreq[JAVA_ISTORE_0] = 0;
+ stackreq[JAVA_ISTORE_1] = 0;
+ stackreq[JAVA_ISTORE_2] = 0;
+ stackreq[JAVA_ISTORE_3] = 0;
+ stackreq[JAVA_LSTORE_0] = 0;
+ stackreq[JAVA_LSTORE_1] = 0;
+ stackreq[JAVA_LSTORE_2] = 0;
+ stackreq[JAVA_LSTORE_3] = 0;
+ stackreq[JAVA_FSTORE_0] = 0;
+ stackreq[JAVA_FSTORE_1] = 0;
+ stackreq[JAVA_FSTORE_2] = 0;
+ stackreq[JAVA_FSTORE_3] = 0;
+ stackreq[JAVA_DSTORE_0] = 0;
+ stackreq[JAVA_DSTORE_1] = 0;
+ stackreq[JAVA_DSTORE_2] = 0;
+ stackreq[JAVA_DSTORE_3] = 0;
+ stackreq[JAVA_ASTORE_0] = 0;
+ stackreq[JAVA_ASTORE_1] = 0;
+ stackreq[JAVA_ASTORE_2] = 0;
+ stackreq[JAVA_ASTORE_3] = 0;
+ stackreq[JAVA_IASTORE] = 0;
+ stackreq[JAVA_LASTORE] = 0;
+ stackreq[JAVA_FASTORE] = 0;
+ stackreq[JAVA_DASTORE] = 0;
+ stackreq[JAVA_AASTORE] = 0;
+ stackreq[JAVA_BASTORE] = 0;
+ stackreq[JAVA_CASTORE] = 0;
+ stackreq[JAVA_SASTORE] = 0;
+ stackreq[JAVA_POP] = 0;
+ stackreq[JAVA_POP2] = 0;
+ stackreq[JAVA_IINC] = 0;
+ stackreq[JAVA_IFEQ] = 0;
+ stackreq[JAVA_IFNE] = 0;
+ stackreq[JAVA_IFLT] = 0;
+ stackreq[JAVA_IFGE] = 0;
+ stackreq[JAVA_IFGT] = 0;
+ stackreq[JAVA_IFLE] = 0;
+ stackreq[JAVA_IF_ICMPEQ] = 0;
+ stackreq[JAVA_IF_ICMPNE] = 0;
+ stackreq[JAVA_IF_ICMPLT] = 0;
+ stackreq[JAVA_IF_ICMPGE] = 0;
+ stackreq[JAVA_IF_ICMPGT] = 0;
+ stackreq[JAVA_IF_ICMPLE] = 0;
+ stackreq[JAVA_IF_ACMPEQ] = 0;
+ stackreq[JAVA_IF_ACMPNE] = 0;
+ stackreq[JAVA_GOTO] = 0;
+ stackreq[JAVA_RET] = 0;
+ stackreq[JAVA_TABLESWITCH] = 0;
+ stackreq[ICMD_LOOKUPSWITCH] = 0;
+ stackreq[JAVA_IRETURN] = 0;
+ stackreq[JAVA_LRETURN] = 0;
+ stackreq[JAVA_FRETURN] = 0;
+ stackreq[JAVA_DRETURN] = 0;
+ stackreq[JAVA_ARETURN] = 0;
+ stackreq[JAVA_RETURN] = 0;
+ stackreq[JAVA_PUTSTATIC] = 0;
+ stackreq[JAVA_PUTFIELD] = 0;
+ stackreq[JAVA_MONITORENTER] = 0;
+ stackreq[ICMD_MONITOREXIT] = 0;
+ stackreq[JAVA_WIDE] = 0;
+ stackreq[JAVA_IFNULL] = 0;
+ stackreq[JAVA_IFNONNULL] = 0;
+ stackreq[JAVA_GOTO_W] = 0;
+ stackreq[JAVA_BREAKPOINT] = 0;
+
+ stackreq[JAVA_SWAP] = 2;
+ stackreq[JAVA_DUP2] = 2;
+ stackreq[JAVA_DUP_X1] = 3;
+ stackreq[JAVA_DUP_X2] = 4;
+ stackreq[JAVA_DUP2_X1] = 3;
+ stackreq[JAVA_DUP2_X2] = 4;
+
+ for (i = 0; i < 256; i++) stdopdescriptors[i] = NULL;
+
+ for (i = 0; i < sizeof(stdopdescriptortable)/sizeof(stdopdescriptor); i++) {
+
+ if (stdopdescriptortable[i].isfloat && checkfloats) {
+ stdopdescriptortable[i].supported = false;
+ }
+
+ stdopdescriptors[stdopdescriptortable[i].opcode] =
+ &(stdopdescriptortable[i]);
+ }
+
+ init_exceptions();
+}
+
+
+void ncomp_close()
+{
+/* mcode_close(); */
+}
+
--- /dev/null
+/******************************* main.c ****************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Enthaelt die Funktion main() und die Variablen fuer die
+ globalen Optionen.
+ Dieser Modul erledigt folgende Aufgaben:
+ - Bearbeiten der command-line-options
+ - Aufrufen aller Initialisierungsroutinen
+ - Aufrufen des Classloaders
+ - Starten der main - Methode
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+ Changes: Andi Krall EMAIL: cacao@complang.tuwien.ac.at
+ Mark Probst EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1997/10/29
+
+*******************************************************************************/
+
+#include "global.h"
+
+#include "tables.h"
+#include "compiler.h"
+#include "ncomp/ncomp.h"
+#include "loader.h"
+
+#include "asmpart.h"
+#include "builtin.h"
+#include "native.h"
+
+#include "threads/thread.h" /* schani */
+
+bool compileall = false;
+int newcompiler = true;
+bool verbose = false;
+
+#ifndef USE_THREADS
+void **stackbottom = 0;
+#endif
+
+
+/********************* interne Funktion: get_opt *****************************
+
+ liest die n"achste Option aus der Kommandozeile
+
+******************************************************************************/
+
+#define OPT_DONE -1
+#define OPT_ERROR 0
+#define OPT_IGNORE 1
+
+#define OPT_CLASSPATH 2
+#define OPT_D 3
+#define OPT_MS 4
+#define OPT_MX 5
+#define OPT_VERBOSE1 6
+#define OPT_VERBOSE 7
+#define OPT_VERBOSEGC 8
+#define OPT_VERBOSECALL 9
+#define OPT_IEEE 10
+#define OPT_SOFTNULL 11
+#define OPT_TIME 12
+#define OPT_STAT 13
+#define OPT_LOG 14
+#define OPT_CHECK 15
+#define OPT_LOAD 16
+#define OPT_METHOD 17
+#define OPT_SIGNATURE 18
+#define OPT_SHOW 19
+#define OPT_ALL 20
+#define OPT_OLD 21
+
+struct { char *name; bool arg; int value; } opts[] = {
+ { "classpath", true, OPT_CLASSPATH },
+ { "D", true, OPT_D },
+ { "ms", true, OPT_MS },
+ { "mx", true, OPT_MX },
+ { "noasyncgc", false, OPT_IGNORE },
+ { "noverify", false, OPT_IGNORE },
+ { "oss", true, OPT_IGNORE },
+ { "ss", true, OPT_IGNORE },
+ { "v", false, OPT_VERBOSE1 },
+ { "verbose", false, OPT_VERBOSE },
+ { "verbosegc", false, OPT_VERBOSEGC },
+ { "verbosecall", false, OPT_VERBOSECALL },
+ { "ieee", false, OPT_IEEE },
+ { "softnull", false, OPT_SOFTNULL },
+ { "time", false, OPT_TIME },
+ { "stat", false, OPT_STAT },
+ { "log", true, OPT_LOG },
+ { "c", true, OPT_CHECK },
+ { "l", false, OPT_LOAD },
+ { "m", true, OPT_METHOD },
+ { "sig", true, OPT_SIGNATURE },
+ { "s", true, OPT_SHOW },
+ { "all", false, OPT_ALL },
+ { "old", false, OPT_OLD },
+ { NULL, false, 0 }
+};
+
+static int opt_ind = 1;
+static char *opt_arg;
+
+static int get_opt (int argc, char **argv)
+{
+ char *a;
+ int i;
+
+ if (opt_ind >= argc) return OPT_DONE;
+
+ a = argv[opt_ind];
+ if (a[0] != '-') return OPT_DONE;
+
+ for (i=0; opts[i].name; i++) {
+ if (! opts[i].arg) {
+ if (strcmp(a+1, opts[i].name) == 0) { /* boolean option found */
+ opt_ind++;
+ return opts[i].value;
+ }
+ }
+ else {
+ if (strcmp(a+1, opts[i].name) == 0) { /* parameter option found */
+ opt_ind++;
+ if (opt_ind < argc) {
+ opt_arg = argv[opt_ind];
+ opt_ind++;
+ return opts[i].value;
+ }
+ return OPT_ERROR;
+ }
+ else {
+ size_t l = strlen(opts[i].name);
+ if (strlen(a+1) > l) {
+ if (memcmp (a+1, opts[i].name, l)==0) {
+ opt_ind++;
+ opt_arg = a+1+l;
+ return opts[i].value;
+ }
+ }
+ }
+ }
+ } /* end for */
+
+ return OPT_ERROR;
+}
+
+
+
+
+/******************** interne Funktion: print_usage ************************
+
+Gibt die richtige Aufrufsyntax des JavaVM-Compilers auf stdout aus.
+
+***************************************************************************/
+
+static void print_usage()
+{
+ printf ("USAGE: cacao [options] classname [program arguments\n");
+ printf ("Options:\n");
+ printf (" -classpath path ...... specify a path to look for classes\n");
+ printf (" -Dpropertyname=value . add an entry to the property list\n");
+ printf (" -mx maxmem[k|m] ...... specify the size for the heap\n");
+ printf (" -ms initmem[k|m] ..... specify the initial size for the heap\n");
+ printf (" -v ................... write state-information\n");
+ printf (" -verbose ............. write more information\n");
+ printf (" -verbosegc ........... write message for each GC\n");
+ printf (" -verbosecall ......... write message for each call\n");
+ printf (" -ieee ................ use ieee compliant arithmetic\n");
+ printf (" -softnull ............ use software nullpointer check\n");
+ printf (" -time ................ measure the runtime\n");
+ printf (" -stat ................ detailed compiler statistics\n");
+ printf (" -log logfile ......... specify a name for the logfile\n");
+ printf (" -c(heck) b(ounds...... don't check array bounds\n");
+ printf (" s(ync) ...... don't check for synchronization\n");
+ printf (" -l ................... don't start the class after loading\n");
+ printf (" -all ................. compile all methods, no execution\n");
+ printf (" -old ................. use old JIT compiler\n");
+ printf (" -m ................... compile only a specific method\n");
+ printf (" -sig ................. specify signature for a specific method\n");
+ printf (" -s(how)m(ethods) ..... show all methods&fields of a class\n");
+ printf (" c(onstants) ... show the constant pool\n");
+ printf (" a(ssembler) ... show disassembled listing\n");
+ printf (" s(tack) ....... show stack for every javaVM-command\n");
+ printf (" i(ntermediate). show intermediate representation\n");
+ printf (" u(nicode) ..... show the unicode - hash\n");
+}
+
+
+
+/***************************** Funktion: print_times *********************
+
+ gibt eine Aufstellung der verwendeten CPU-Zeit aus
+
+**************************************************************************/
+
+static void print_times()
+{
+ long int totaltime = getcputime();
+ long int runtime = totaltime - loadingtime - compilingtime;
+
+ sprintf (logtext, "Time for loading classes: %ld secs, %ld millis",
+ loadingtime / 1000000, (loadingtime % 1000000) / 1000);
+ dolog();
+ sprintf (logtext, "Time for compiling code: %ld secs, %ld millis",
+ compilingtime / 1000000, (compilingtime % 1000000) / 1000);
+ dolog();
+ sprintf (logtext, "Time for running program: %ld secs, %ld millis",
+ runtime / 1000000, (runtime % 1000000) / 1000);
+ dolog();
+ sprintf (logtext, "Total time: %ld secs, %ld millis",
+ totaltime / 1000000, (totaltime % 1000000) / 1000);
+ dolog();
+}
+
+
+
+
+
+
+/***************************** Funktion: print_stats *********************
+
+ outputs detailed compiler statistics
+
+**************************************************************************/
+
+static void print_stats()
+{
+ sprintf (logtext, "Number of JitCompiler Calls: %d", count_jit_calls);
+ dolog();
+ sprintf (logtext, "Number of compiled Methods: %d", count_methods);
+ dolog();
+ sprintf (logtext, "Number of max basic blocks per method: %d", count_max_basic_blocks);
+ dolog();
+ sprintf (logtext, "Number of compiled basic blocks: %d", count_basic_blocks);
+ dolog();
+ sprintf (logtext, "Number of max JavaVM-Instructions per method: %d", count_max_javainstr);
+ dolog();
+ sprintf (logtext, "Number of compiled JavaVM-Instructions: %d", count_javainstr);
+ dolog();
+ sprintf (logtext, "Size of compiled JavaVM-Instructions: %d(%d)", count_javacodesize,
+ count_javacodesize - count_methods * 18);
+ dolog();
+ sprintf (logtext, "Size of compiled Exception Tables: %d", count_javaexcsize);
+ dolog();
+ sprintf (logtext, "Value of extended instruction set var: %d", has_ext_instr_set);
+ dolog();
+ sprintf (logtext, "Number of Alpha-Instructions: %d", count_code_len >> 2);
+ dolog();
+ sprintf (logtext, "Number of Spills: %d", count_spills);
+ dolog();
+ sprintf (logtext, "Number of Activ Pseudocommands: %5d", count_pcmd_activ);
+ dolog();
+ sprintf (logtext, "Number of Drop Pseudocommands: %5d", count_pcmd_drop);
+ dolog();
+ sprintf (logtext, "Number of Const Pseudocommands: %5d (zero:%5d)", count_pcmd_load, count_pcmd_zero);
+ dolog();
+ sprintf (logtext, "Number of ConstAlu Pseudocommands: %5d (cmp: %5d, store:%5d)", count_pcmd_const_alu, count_pcmd_const_bra, count_pcmd_const_store);
+ dolog();
+ sprintf (logtext, "Number of Move Pseudocommands: %5d", count_pcmd_move);
+ dolog();
+ sprintf (logtext, "Number of Load Pseudocommands: %5d", count_load_instruction);
+ dolog();
+ sprintf (logtext, "Number of Store Pseudocommands: %5d (combined: %5d)", count_pcmd_store, count_pcmd_store - count_pcmd_store_comb);
+ dolog();
+ sprintf (logtext, "Number of OP Pseudocommands: %5d", count_pcmd_op);
+ dolog();
+ sprintf (logtext, "Number of DUP Pseudocommands: %5d", count_dup_instruction);
+ dolog();
+ sprintf (logtext, "Number of Mem Pseudocommands: %5d", count_pcmd_mem);
+ dolog();
+ sprintf (logtext, "Number of Method Pseudocommands: %5d", count_pcmd_met);
+ dolog();
+ sprintf (logtext, "Number of Branch Pseudocommands: %5d (rets:%5d, Xrets: %5d)",
+ count_pcmd_bra, count_pcmd_return, count_pcmd_returnx);
+ dolog();
+ sprintf (logtext, "Number of Table Pseudocommands: %5d", count_pcmd_table);
+ dolog();
+ sprintf (logtext, "Number of Useful Pseudocommands: %5d", count_pcmd_table +
+ count_pcmd_bra + count_pcmd_load + count_pcmd_mem + count_pcmd_op);
+ dolog();
+ sprintf (logtext, "Number of Null Pointer Checks: %5d", count_check_null);
+ dolog();
+ sprintf (logtext, "Number of Array Bound Checks: %5d", count_check_bound);
+ dolog();
+ sprintf (logtext, "Number of Try-Blocks: %d", count_tryblocks);
+ dolog();
+ sprintf (logtext, "Maximal count of stack elements: %d", count_max_new_stack);
+ dolog();
+ sprintf (logtext, "Upper bound of max stack elements: %d", count_upper_bound_new_stack);
+ dolog();
+ sprintf (logtext, "Distribution of stack sizes at block boundary");
+ dolog();
+ sprintf (logtext, " 0 1 2 3 4 5 6 7 8 9 >=10");
+ dolog();
+ sprintf (logtext, "%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d", count_block_stack[0],
+ count_block_stack[1],count_block_stack[2],count_block_stack[3],count_block_stack[4],
+ count_block_stack[5],count_block_stack[6],count_block_stack[7],count_block_stack[8],
+ count_block_stack[9],count_block_stack[10]);
+ dolog();
+ sprintf (logtext, "Distribution of store stack depth");
+ dolog();
+ sprintf (logtext, " 0 1 2 3 4 5 6 7 8 9 >=10");
+ dolog();
+ sprintf (logtext, "%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d", count_store_depth[0],
+ count_store_depth[1],count_store_depth[2],count_store_depth[3],count_store_depth[4],
+ count_store_depth[5],count_store_depth[6],count_store_depth[7],count_store_depth[8],
+ count_store_depth[9],count_store_depth[10]);
+ dolog();
+ sprintf (logtext, "Distribution of store creator chains first part");
+ dolog();
+ sprintf (logtext, " 0 1 2 3 4 5 6 7 8 9 ");
+ dolog();
+ sprintf (logtext, "%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d", count_store_length[0],
+ count_store_length[1],count_store_length[2],count_store_length[3],count_store_length[4],
+ count_store_length[5],count_store_length[6],count_store_length[7],count_store_length[8],
+ count_store_length[9]);
+ dolog();
+ sprintf (logtext, "Distribution of store creator chains second part");
+ dolog();
+ sprintf (logtext, " 10 11 12 13 14 15 16 17 18 19 >=20");
+ dolog();
+ sprintf (logtext, "%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d", count_store_length[10],
+ count_store_length[11],count_store_length[12],count_store_length[13],count_store_length[14],
+ count_store_length[15],count_store_length[16],count_store_length[17],count_store_length[18],
+ count_store_length[19],count_store_length[20]);
+ dolog();
+ sprintf (logtext, "Distribution of analysis iterations");
+ dolog();
+ sprintf (logtext, " 1 2 3 4 >=5");
+ dolog();
+ sprintf (logtext, "%5d%5d%5d%5d%5d", count_analyse_iterations[0],count_analyse_iterations[1],
+ count_analyse_iterations[2],count_analyse_iterations[3],count_analyse_iterations[4]);
+ dolog();
+ sprintf (logtext, "Distribution of basic blocks per method");
+ dolog();
+ sprintf (logtext, " <= 5 <=10 <=15 <=20 <=30 <=40 <=50 <=75 >75");
+ dolog();
+ sprintf (logtext, "%5d%5d%5d%5d%5d%5d%5d%5d%5d", count_method_bb_distribution[0],
+ count_method_bb_distribution[1],count_method_bb_distribution[2],count_method_bb_distribution[3],
+ count_method_bb_distribution[4],count_method_bb_distribution[5],count_method_bb_distribution[6],
+ count_method_bb_distribution[7],count_method_bb_distribution[8]);
+ dolog();
+ sprintf (logtext, "Distribution of basic block sizes");
+ dolog();
+ sprintf (logtext,
+ " 1 2 3 4 5 6 7 8 9 10 <13 <15 <17 <19 <21 <26 <31 >30");
+ dolog();
+ sprintf (logtext, "%3d%5d%5d%5d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d",
+ count_block_size_distribution[0], count_block_size_distribution[1], count_block_size_distribution[2],
+ count_block_size_distribution[3], count_block_size_distribution[4], count_block_size_distribution[5],
+ count_block_size_distribution[6], count_block_size_distribution[7], count_block_size_distribution[8],
+ count_block_size_distribution[9], count_block_size_distribution[10],count_block_size_distribution[11],
+ count_block_size_distribution[12],count_block_size_distribution[13],count_block_size_distribution[14],
+ count_block_size_distribution[15],count_block_size_distribution[16],count_block_size_distribution[17]);
+ dolog();
+ sprintf (logtext, "Size of Code Area (Kb): %10.3f", (float) count_code_len / 1024);
+ dolog();
+ sprintf (logtext, "Size of data Area (Kb): %10.3f", (float) count_data_len / 1024);
+ dolog();
+ sprintf (logtext, "Size of Class Infos (Kb):%10.3f", (float) (count_class_infos) / 1024);
+ dolog();
+ sprintf (logtext, "Size of Const Pool (Kb): %10.3f", (float) (count_const_pool_len + count_unicode_len) / 1024);
+ dolog();
+ sprintf (logtext, "Size of Vftbl (Kb): %10.3f", (float) count_vftbl_len / 1024);
+ dolog();
+ sprintf (logtext, "Size of comp stub (Kb): %10.3f", (float) count_cstub_len / 1024);
+ dolog();
+ sprintf (logtext, "Size of native stub (Kb):%10.3f", (float) count_nstub_len / 1024);
+ dolog();
+ sprintf (logtext, "Size of Unicode (Kb): %10.3f", (float) count_unicode_len / 1024);
+ dolog();
+ sprintf (logtext, "Size of VMCode (Kb): %10.3f(%d)", (float) count_vmcode_len / 1024,
+ count_vmcode_len - 18 * count_all_methods);
+ dolog();
+ sprintf (logtext, "Size of ExTable (Kb): %10.3f", (float) count_extable_len / 1024);
+ dolog();
+ sprintf (logtext, "Number of loaded Methods: %d\n\n", count_all_methods);
+ dolog();
+}
+
+
+/********** Funktion: class_compile_methods (nur f"ur Debug-Zwecke) ********/
+
+void class_compile_methods ()
+{
+ int i;
+ classinfo *c;
+ methodinfo *m;
+
+ c = list_first (&linkedclasses);
+ while (c) {
+ for (i = 0; i < c -> methodscount; i++) {
+ m = &(c->methods[i]);
+ if (m->jcode) {
+ if (newcompiler)
+ (void) new_compile(m);
+ else
+ (void) compiler_compile(m);
+ }
+ }
+ c = list_next (&linkedclasses, c);
+ }
+}
+
+
+/************************** Funktion: main *******************************
+
+ Das Hauptprogramm.
+ Wird vom System zu Programstart aufgerufen (eh klar).
+
+**************************************************************************/
+
+
+int main(int argc, char **argv)
+{
+ s4 i,j;
+ char *cp;
+ classinfo *topclass;
+ java_objectheader *exceptionptr;
+ void *dummy;
+
+
+ /********** interne (nur fuer main relevante Optionen) **************/
+
+ char logfilename[200] = "";
+ u4 heapsize = 16000000;
+ u4 heapstartsize = 200000;
+ char classpath[500] = ".:/usr/local/lib/java/classes";
+ bool showmethods = false;
+ bool showconstantpool = false;
+ bool showunicode = false;
+ bool startit = true;
+ char *specificmethodname = NULL;
+ char *specificsignature = NULL;
+
+#ifndef USE_THREADS
+ stackbottom = &dummy;
+#endif
+
+
+ /************ Infos aus der Environment lesen ************************/
+
+ cp = getenv ("CLASSPATH");
+ if (cp) {
+ strcpy (classpath, cp);
+ }
+
+ /***************** Interpretieren der Kommandozeile *****************/
+
+ checknull = false;
+ checkfloats = false;
+
+ while ( (i = get_opt(argc,argv)) != OPT_DONE) {
+
+ switch (i) {
+ case OPT_IGNORE: break;
+
+ case OPT_CLASSPATH:
+ strcpy (classpath + strlen(classpath), ":");
+ strcpy (classpath + strlen(classpath), opt_arg);
+ break;
+
+ case OPT_D:
+ {
+ int n,l=strlen(opt_arg);
+ for (n=0; n<l; n++) {
+ if (opt_arg[n]=='=') {
+ opt_arg[n] = '\0';
+ attach_property (opt_arg, opt_arg+n+1);
+ goto didit;
+ }
+ }
+ print_usage();
+ exit(10);
+
+ didit: ;
+ }
+ break;
+
+ case OPT_MS:
+ case OPT_MX:
+ if (opt_arg[strlen(opt_arg)-1] == 'k') {
+ j = 1024 * atoi(opt_arg);
+ }
+ else if (opt_arg[strlen(opt_arg)-1] == 'm') {
+ j = 1024 * 1024 * atoi(opt_arg);
+ }
+ else j = atoi(opt_arg);
+
+ if (i==OPT_MX) heapsize = j;
+ else heapstartsize = j;
+ break;
+
+ case OPT_VERBOSE1:
+ verbose = true;
+ break;
+
+ case OPT_VERBOSE:
+ verbose = true;
+ loadverbose = true;
+ initverbose = true;
+ compileverbose = true;
+ break;
+
+ case OPT_VERBOSEGC:
+ collectverbose = true;
+ break;
+
+ case OPT_VERBOSECALL:
+ runverbose = true;
+ break;
+
+ case OPT_IEEE:
+ checkfloats = true;
+ break;
+
+ case OPT_SOFTNULL:
+ checknull = true;
+ break;
+
+ case OPT_TIME:
+ getcompilingtime = true;
+ getloadingtime = true;
+ break;
+
+ case OPT_STAT:
+ statistics = true;
+ break;
+
+ case OPT_LOG:
+ strcpy (logfilename, opt_arg);
+ break;
+
+
+ case OPT_CHECK:
+ for (j=0; j<strlen(opt_arg); j++) {
+ switch (opt_arg[j]) {
+ case 'b': checkbounds=false; break;
+ case 's': checksync=false; break;
+ default: print_usage();
+ exit(10);
+ }
+ }
+ break;
+
+ case OPT_LOAD:
+ startit = false;
+ makeinitializations = false;
+ break;
+
+ case OPT_METHOD:
+ startit = false;
+ specificmethodname = opt_arg;
+ makeinitializations = false;
+ break;
+
+ case OPT_SIGNATURE:
+ specificsignature = opt_arg;
+ break;
+
+ case OPT_ALL:
+ compileall = true;
+ startit = false;
+ makeinitializations = false;
+ break;
+
+ case OPT_OLD:
+ newcompiler = false;
+ checknull = true;
+ break;
+
+ case OPT_SHOW: /* Anzeigeoptionen */
+ for (j=0; j<strlen(opt_arg); j++) {
+ switch (opt_arg[j]) {
+ case 'm': showmethods=true; break;
+ case 'c': showconstantpool=true; break;
+ case 'a': showdisassemble=true; compileverbose=true; break;
+ case 's': showstack=true; compileverbose=true; break;
+ case 'i': showintermediate=true; compileverbose=true; break;
+ case 'u': showunicode=true; break;
+ default: print_usage();
+ exit(10);
+ }
+ }
+ break;
+
+ default:
+ print_usage();
+ exit(10);
+ }
+
+
+ }
+
+
+ if (opt_ind >= argc) {
+ print_usage ();
+ exit(10);
+ }
+
+
+ /**************************** Programmstart *****************************/
+
+ log_init (logfilename);
+ if (verbose) {
+ log_text (
+ "CACAO started -------------------------------------------------------");
+ }
+
+ suck_init (classpath);
+ native_setclasspath (classpath);
+
+ unicode_init();
+ heap_init(heapsize, heapstartsize, &dummy);
+ loader_init();
+ compiler_init();
+ ncomp_init();
+
+ native_loadclasses ();
+
+
+ /*********************** JAVA-Klassen laden ***************************/
+
+ cp = argv[opt_ind++];
+ for (i=strlen(cp)-1; i>=0; i--) { /* Punkte im Klassennamen */
+ if (cp[i]=='.') cp[i]='/'; /* auf slashes umbauen */
+ }
+
+ topclass = loader_load ( unicode_new_char (cp) );
+
+ gc_init();
+
+#ifdef USE_THREADS
+ initThreads((u1*)&dummy); /* schani */
+#endif
+
+ /************************* Arbeitsroutinen starten ********************/
+
+ if (startit) {
+ methodinfo *mainmethod;
+ java_objectarray *a;
+
+ mainmethod = class_findmethod (
+ topclass,
+ unicode_new_char ("main"),
+ unicode_new_char ("([Ljava/lang/String;)V")
+ );
+ if (!mainmethod) panic ("Can not find method 'void main(String[])'");
+ if ((mainmethod->flags & ACC_STATIC) != ACC_STATIC) panic ("main is not static!");
+
+ a = builtin_anewarray (argc - opt_ind, class_java_lang_String);
+ for (i=opt_ind; i<argc; i++) {
+ a->data[i-opt_ind] = javastring_new (unicode_new_char (argv[i]) );
+ }
+ exceptionptr = asm_calljavamethod (mainmethod, a, NULL,NULL,NULL );
+
+ if (exceptionptr) {
+ printf ("#### Program has thrown: ");
+ unicode_display (exceptionptr->vftbl->class->name);
+ printf ("\n");
+ }
+
+/* killThread(currentThread); */
+
+ }
+
+ /************* Auf Wunsch alle Methode "ubersetzen ********************/
+
+ if (compileall) {
+ class_compile_methods();
+ }
+
+
+ /******** Auf Wunsch eine spezielle Methode "ubersetzen ***************/
+
+ if (specificmethodname) {
+ methodinfo *m;
+ if (specificsignature)
+ m = class_findmethod(topclass,
+ unicode_new_char(specificmethodname),
+ unicode_new_char(specificsignature));
+ else
+ m = class_findmethod(topclass,
+ unicode_new_char(specificmethodname), NULL);
+ if (!m) panic ("Specific method not found");
+ if (newcompiler)
+ (void) new_compile(m);
+ else
+ (void) compiler_compile(m);
+ }
+
+ /********************* Debug-Tabellen ausgeben ************************/
+
+ if (showmethods) class_showmethods (topclass);
+ if (showconstantpool) class_showconstantpool (topclass);
+ if (showunicode) unicode_show ();
+
+
+
+ /************************ Freigeben aller Resourcen *******************/
+
+ compiler_close ();
+ loader_close ();
+ heap_close ();
+ unicode_close ( literalstring_free );
+
+
+ /* Endemeldung ausgeben und mit entsprechendem exit-Status terminieren */
+
+ if (verbose || getcompilingtime || statistics) {
+ log_text ("CACAO terminated");
+ if (statistics)
+ print_stats ();
+ if (getcompilingtime)
+ print_times ();
+ mem_usagelog(1);
+ }
+
+ exit(0);
+ return 1;
+}
+
+
+
+/************************************ SHUTDOWN-Funktion *********************************
+
+ Terminiert das System augenblicklich, ohne den Speicher
+ explizit freizugeben (eigentlich nur f"ur abnorme
+ Programmterminierung)
+
+*****************************************************************************************/
+
+void cacao_shutdown(s4 status)
+{
+ if (verbose || getcompilingtime || statistics) {
+ log_text ("CACAO terminated by shutdown");
+ if (statistics)
+ print_stats ();
+ if (getcompilingtime)
+ print_times ();
+ mem_usagelog(0);
+ sprintf (logtext, "Exit status: %d\n", (int) status);
+ dolog();
+ }
+
+ exit(status);
+}
--- /dev/null
+/* -*- mode: c; tab-width: 4; c-basic-offset: 4 -*- */
+/****************************** headers.c **************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Dieser Modul ersetzt f"ur den Headerfile-Betrieb den Modul 'main',
+ und 'f"alscht' einige Verweise auf externe Module (damit nicht schon
+ alle Module des eigentlichen Programmes fertig sein m"ussen, was ja
+ unm"oglich w"are, da die Headerfile-Tabellen ja erst hier und jetzt
+ generiert werden).
+
+ Dieser Modul ist ein ziemlich schneller Hack und dementsprechend
+ schlecht (nicht) kommentiert.
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+ Changes: Mark Probst EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1997/05/23
+
+*******************************************************************************/
+
+#include "global.h"
+
+#include "tables.h"
+#include "loader.h"
+
+
+/******* verschiedene externe Funktionen "faelschen" (=durch Dummys ersetzen),
+ damit der Linker zufrieden ist *********/
+
+functionptr native_findfunction
+ (unicode *cname, unicode *mname, unicode *desc, bool isstatic)
+{ return NULL; }
+
+java_objectheader *literalstring_new (unicode *text)
+{ return NULL; }
+
+java_objectheader *javastring_new (unicode *text) /* schani */
+{ return NULL; }
+
+void synchronize_caches() { }
+void asm_call_jit_compiler () { }
+void asm_calljavamethod () { }
+void asm_dumpregistersandcall () { }
+
+s4 new_builtin_idiv (s4 a, s4 b) {return 0;}
+s4 new_builtin_irem (s4 a, s4 b) {return 0;}
+s8 new_builtin_ldiv (s8 a, s8 b) {return 0;}
+s8 new_builtin_lrem (s8 a, s8 b) {return 0;}
+
+
+void new_builtin_monitorenter (java_objectheader *o) {}
+void new_builtin_monitorexit (java_objectheader *o) {}
+
+s4 new_builtin_checkcast(java_objectheader *o, classinfo *c)
+ {return 0;}
+s4 new_builtin_checkarraycast
+ (java_objectheader *o, constant_arraydescriptor *d)
+ {return 0;}
+
+void new_builtin_aastore (java_objectarray *a, s4 index, java_objectheader *o) {}
+
+u1 *createcompilerstub (methodinfo *m) {return NULL;}
+u1 *createnativestub (functionptr f, methodinfo *m) {return NULL;}
+u1 *ncreatenativestub (functionptr f, methodinfo *m) {return NULL;}
+
+void removecompilerstub (u1 *stub) {}
+void removenativestub (u1 *stub) {}
+
+void perform_alpha_threadswitch (u1 **from, u1 **to) {}
+u1* initialize_thread_stack (void *func, u1 *stack) { return NULL; }
+u1* used_stack_top (void) { return NULL; }
+
+java_objectheader *native_new_and_init (void *p) { return NULL; }
+
+/************************ globale Variablen **********************/
+
+java_objectheader *exceptionptr; /* schani */
+int newcompiler = true;
+bool verbose = false;
+
+static chain *nativechain;
+static FILE *file = NULL;
+
+static void printIDpart (int c)
+{
+ if ( (c>='a' && c<='z')
+ || (c>='A' && c<='Z')
+ || (c>='0' && c<='9')
+ || (c=='_') )
+ putc (c,file);
+ else putc ('_',file);
+
+}
+
+static void printID (unicode *name)
+{
+ int i;
+ for (i=0; i<name->length; i++) {
+ printIDpart (name->text[i]);
+ }
+}
+
+
+u4 outputsize;
+bool dopadding;
+
+static void addoutputsize (int len)
+{
+ u4 newsize,i;
+ if (!dopadding) return;
+
+ newsize = ALIGN (outputsize, len);
+
+ for (i=outputsize; i<newsize; i++) fprintf (file, " u1 pad%d\n",(int) i);
+ outputsize = newsize;
+}
+
+
+static u2 *printtype (u2 *desc)
+{
+ u2 c;
+
+ switch (*(desc++)) {
+ case 'V': fprintf (file, "void");
+ break;
+ case 'I':
+ case 'S':
+ case 'B':
+ case 'C':
+ case 'Z': addoutputsize (4);
+ fprintf (file, "s4");
+ break;
+ case 'J': addoutputsize (8);
+ fprintf (file, "s8");
+ break;
+ case 'F': addoutputsize (4);
+ fprintf (file, "float");
+ break;
+ case 'D': addoutputsize (8);
+ fprintf (file, "double");
+ break;
+ case '[':
+ addoutputsize ( sizeof(java_arrayheader*) );
+ switch (*(desc++)) {
+ case 'I': fprintf (file, "java_intarray*"); break;
+ case 'J': fprintf (file, "java_longarray*"); break;
+ case 'Z': fprintf (file, "java_booleanarray*"); break;
+ case 'B': fprintf (file, "java_bytearray*"); break;
+ case 'S': fprintf (file, "java_shortarray*"); break;
+ case 'C': fprintf (file, "java_chararray*"); break;
+ case 'F': fprintf (file, "java_floatarray*"); break;
+ case 'D': fprintf (file, "java_doublearray*"); break;
+
+ case '[': fprintf (file, "java_arrayarray*");
+ while ((*desc) == '[') desc++;
+ if ((*desc)!='L') desc++;
+ else while (*(desc++) != ';');
+ break;
+
+ case 'L': fprintf (file, "java_objectarray*");
+ while ( *(desc++) != ';');
+ break;
+ default: panic ("invalid type descriptor");
+ }
+ break;
+
+ case 'L':
+ addoutputsize ( sizeof(java_objectheader*));
+ fprintf (file, "struct ");
+ while ( (c = *(desc++)) != ';' ) printIDpart (c);
+ fprintf (file, "*");
+ break;
+
+ default: panic ("Unknown type in field descriptor");
+ }
+
+ return (desc);
+}
+
+
+
+static void printfields (classinfo *c)
+{
+ u4 i;
+ fieldinfo *f;
+
+ if (!c) {
+ addoutputsize ( sizeof(java_objectheader) );
+ fprintf (file, " java_objectheader header;\n");
+ return;
+ }
+
+ printfields (c->super);
+
+ for (i=0; i<c->fieldscount; i++) {
+ f = &(c->fields[i]);
+
+ if (! (f->flags & ACC_STATIC) ) {
+ fprintf (file," ");
+ printtype (f->descriptor->text);
+ fprintf (file, " ");
+ unicode_fprint (file, f->name);
+ fprintf (file, ";\n");
+ }
+ }
+}
+
+
+
+
+static void remembermethods (classinfo *c)
+{
+ u2 i;
+ methodinfo *m;
+
+ for (i=0; i<c->methodscount; i++) {
+ m = &(c->methods[i]);
+
+ if (m->flags & ACC_NATIVE) {
+ chain_addlast (nativechain, m);
+ }
+
+ }
+}
+
+
+
+
+static void printmethod (methodinfo *m)
+{
+ u2 *d;
+ u2 paramnum=1;
+
+ d = m->descriptor->text;
+ while (*(d++) != ')');
+
+ printtype (d);
+ fprintf (file," ");
+ printID (m->class->name);
+ fprintf (file,"_");
+ printID (m->name);
+ fprintf (file," (");
+
+ d = m->descriptor->text+1;
+
+ if (! (m->flags & ACC_STATIC) ) {
+ fprintf (file, "struct ");
+ printID (m->class->name);
+ fprintf (file, "* this");
+ if ((*d)!=')') fprintf (file, ", ");
+ }
+
+ while ((*d)!=')') {
+ d = printtype (d);
+ fprintf (file, " par%d", paramnum++);
+ if ((*d)!=')') fprintf (file, ", ");
+ }
+
+ fprintf (file, ");\n");
+}
+
+
+static void headers_generate (classinfo *c)
+{
+ fprintf (file, "/* Structure information for class: ");
+ unicode_fprint (file, c->name);
+ fprintf (file, " */\n\n");
+
+ fprintf (file, "typedef struct ");
+ printID (c->name);
+ fprintf (file, " {\n");
+
+ outputsize=0;
+ dopadding=true;
+ printfields (c);
+
+ fprintf (file, "} ");
+ printID (c->name);
+ fprintf (file, ";\n\n");
+
+ remembermethods (c);
+
+
+ fprintf (file, "\n\n");
+}
+
+
+
+static void printnativetableentry (methodinfo *m)
+{
+ fprintf (file, " { \"");
+ unicode_fprint (file, m->class->name);
+ fprintf (file, "\",\n \"");
+ unicode_fprint (file, m->name);
+ fprintf (file, "\",\n \"");
+ unicode_fprint (file, m->descriptor);
+ fprintf (file, "\",\n ");
+ if ( (m->flags & ACC_STATIC) !=0) fprintf (file, "true");
+ else fprintf (file, "false");
+ fprintf (file, ",\n ");
+ fprintf (file, "(functionptr) ");
+ printID (m->class->name);
+ fprintf (file,"_");
+ printID (m->name);
+ fprintf (file,"\n },\n");
+}
+
+
+
+
+
+static void headers_start ()
+{
+ file = fopen ("nativetypes.hh", "w");
+ if (!file) panic ("Can not open file 'native.h' to store header information");
+
+ fprintf (file, "/* Headerfile for native methods: nativetypes.hh */\n");
+ fprintf (file, "/* This file is machine generated, don't edit it !*/\n\n");
+
+ nativechain = chain_new ();
+}
+
+
+static void headers_finish ()
+{
+ methodinfo *m;
+
+ fprintf (file, "\n/* Prototypes for native methods */\n\n");
+
+ m = chain_first (nativechain);
+ while (m) {
+ dopadding=false;
+ printmethod (m);
+
+ m = chain_next (nativechain);
+ }
+
+
+ file = fopen ("nativetable.hh", "w");
+ if (!file) panic ("Can not open file 'nativetable' to store native-link-table");
+
+ fprintf (file, "/* Table of native methods: nativetables.hh */\n");
+ fprintf (file, "/* This file is machine generated, don't edit it !*/\n\n");
+
+ while ( (m = chain_first (nativechain)) != NULL) {
+ chain_remove (nativechain);
+
+ printnativetableentry (m);
+
+ }
+
+ chain_free (nativechain);
+ fclose (file);
+}
+
+
+
+
+
+/******************** interne Funktion: print_usage ************************
+
+Gibt die richtige Aufrufsyntax des JAVA-Header-Generators auf stdout aus.
+
+***************************************************************************/
+
+static void print_usage()
+{
+ printf ("USAGE: jch class [class..]\n");
+}
+
+
+
+
+/************************** Funktion: main *******************************
+
+ Das Hauptprogramm.
+ Wird vom System zu Programstart aufgerufen (eh klar).
+
+**************************************************************************/
+
+int main(int argc, char **argv)
+{
+ s4 i,a;
+ char *cp;
+ classinfo *topclass;
+ void *dummy;
+
+
+ /********** interne (nur fuer main relevante Optionen) **************/
+
+ char classpath[500] = "";
+ u4 heapsize = 100000;
+
+ /*********** Optionen, damit wirklich nur headers generiert werden ***/
+
+ makeinitializations=false;
+
+
+ /************ Infos aus der Environment lesen ************************/
+
+ cp = getenv ("CLASSPATH");
+ if (cp) {
+ strcpy (classpath + strlen(classpath), ":");
+ strcpy (classpath + strlen(classpath), cp);
+ }
+
+ if (argc < 2) {
+ print_usage ();
+ exit(10);
+ }
+
+
+ /**************************** Programmstart *****************************/
+
+ log_init (NULL);
+ log_text ("Java - header-generator started");
+
+
+ suck_init (classpath);
+
+ unicode_init ();
+ heap_init (heapsize, heapsize, &dummy);
+ loader_init ();
+
+
+ /*********************** JAVA-Klassen laden ***************************/
+
+ headers_start ();
+
+
+ for (a=1; a<argc; a++) {
+ cp = argv[a];
+ for (i=strlen(cp)-1; i>=0; i--) { /* Punkte im Klassennamen */
+ if (cp[i]=='.') cp[i]='/'; /* auf slashes umbauen */
+ }
+
+ topclass = loader_load ( unicode_new_char (cp) );
+
+ headers_generate (topclass);
+ }
+
+
+ headers_finish ();
+
+
+ /************************ Freigeben aller Resourcen *******************/
+
+ loader_close ();
+ heap_close ();
+ unicode_close (NULL);
+
+
+ /* Endemeldung ausgeben und mit entsprechendem exit-Status terminieren */
+
+ log_text ("Java - header-generator stopped");
+ log_cputime ();
+ mem_usagelog(1);
+
+ return 0;
+}
+
+
--- /dev/null
+/************************* toolbox/memory.c ************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Not documented, see memory.h.
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1996/10/03
+
+*******************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+#include "../callargs.h"
+#include "loging.h"
+#include "memory.h"
+
+
+ /********* allgemeine Typen, Variablen und Hilfsfunktionen *********/
+
+#define DUMPBLOCKSIZE (2<<18)
+#define ALIGNSIZE 8
+
+typedef struct dumplist {
+ struct dumplist *prev;
+ char *dumpmem;
+} dumplist;
+
+
+
+long int memoryusage = 0;
+
+long int dumpsize = 0;
+long int dumpspace = 0;
+dumplist *topdumpblock = NULL;
+
+long int maxmemusage = 0;
+long int maxdumpsize = 0;
+
+/* #define TRACECALLARGS */
+
+#ifdef TRACECALLARGS
+static char nomallocmem[16777216];
+static char *nomalloctop = nomallocmem + 16777216;
+static char *nomallocptr = nomallocmem;
+
+static void *lit_checked_alloc (int length)
+{
+ void *m;
+
+ nomallocptr = (void*) ALIGN ((long) nomallocptr, ALIGNSIZE);
+
+ m = nomallocptr;
+ nomallocptr += length;
+ if (nomallocptr > nomalloctop) panic ("Out of memory");
+ return m;
+}
+
+#else
+
+static void *lit_checked_alloc (int length)
+{
+ void *m = malloc(length);
+ if (!m) panic ("Out of memory");
+ return m;
+}
+
+#endif
+
+
+static void *checked_alloc (int length)
+{
+ void *m = malloc(length);
+ if (!m) panic ("Out of memory");
+ return m;
+}
+
+static int mmapcodesize = 0;
+static void *mmapcodeptr = NULL;
+
+void *mem_mmap(int length)
+{
+ void *retptr;
+
+ length = (ALIGN(length,ALIGNSIZE));
+ if (length > mmapcodesize) {
+ mmapcodesize = 0x10000;
+ if (length > mmapcodesize)
+ mmapcodesize = length;
+ mmapcodesize = (ALIGN(mmapcodesize, getpagesize()));
+ mmapcodeptr = mmap (NULL, (size_t) mmapcodesize,
+ PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, (off_t) 0);
+ if (mmapcodeptr == (void*) -1)
+ panic ("Out of memory");
+ }
+ retptr = mmapcodeptr;
+ mmapcodeptr = (void*) ((char*) mmapcodeptr + length);
+ mmapcodesize -= length;
+ return retptr;
+}
+
+
+#ifdef DEBUG
+
+ /************ Sichere Version des Speichermanages **************/
+
+
+typedef struct memblock {
+ struct memblock *prev,*next;
+ int length;
+} memblock;
+
+#define BLOCKOFFSET (ALIGN(sizeof(memblock),ALIGNSIZE))
+
+struct memblock *firstmemblock;
+
+
+
+void *mem_alloc(int length)
+{
+ memblock *mb;
+
+ if (length==0) return NULL;
+ mb = checked_alloc (length + BLOCKOFFSET);
+
+ mb -> prev = NULL;
+ mb -> next = firstmemblock;
+ mb -> length = length;
+
+ if (firstmemblock) firstmemblock -> prev = mb;
+ firstmemblock = mb;
+
+ memoryusage += length;
+ if (memoryusage > maxmemusage) maxmemusage = memoryusage;
+
+ return ((char*) mb) + BLOCKOFFSET;
+}
+
+
+void *lit_mem_alloc(int length)
+{
+ memblock *mb;
+
+ if (length==0) return NULL;
+ mb = lit_checked_alloc (length + BLOCKOFFSET);
+
+ mb -> prev = NULL;
+ mb -> next = firstmemblock;
+ mb -> length = length;
+
+ if (firstmemblock) firstmemblock -> prev = mb;
+ firstmemblock = mb;
+
+ memoryusage += length;
+ if (memoryusage > maxmemusage) maxmemusage = memoryusage;
+
+ return ((char*) mb) + BLOCKOFFSET;
+}
+
+
+void mem_free(void *m, int length)
+{
+ memblock *mb;
+ if (!m) {
+ if (length==0) return;
+ panic ("returned memoryblock with address NULL, length != 0");
+ }
+
+ mb = (memblock*) (((char*) m) - BLOCKOFFSET);
+
+ if (mb->length != length) {
+ sprintf (logtext,
+ "Memory block of size %d has been return as size %d",
+ mb->length, length);
+ error();
+ }
+
+ if (mb->prev) mb->prev->next = mb->next;
+ else firstmemblock = mb->next;
+ if (mb->next) mb->next->prev = mb->prev;
+
+ free (mb);
+
+ memoryusage -= length;
+}
+
+
+void lit_mem_free(void *m, int length)
+{
+ memblock *mb;
+ if (!m) {
+ if (length==0) return;
+ panic ("returned memoryblock with address NULL, length != 0");
+ }
+
+ mb = (memblock*) (((char*) m) - BLOCKOFFSET);
+
+ if (mb->length != length) {
+ sprintf (logtext,
+ "Memory block of size %d has been return as size %d",
+ mb->length, length);
+ error();
+ }
+
+ if (mb->prev) mb->prev->next = mb->next;
+ else firstmemblock = mb->next;
+ if (mb->next) mb->next->prev = mb->prev;
+
+#ifdef TRACECALLARGS
+#else
+ free (mb);
+#endif
+
+ memoryusage -= length;
+}
+
+
+void *mem_realloc (void *m1, int len1, int len2)
+{
+ void *m2;
+
+ m2 = mem_alloc (len2);
+ memcpy (m2, m1, len1);
+ mem_free (m1, len1);
+
+ return m2;
+}
+
+
+
+
+static void mem_characterlog (unsigned char *m, int len)
+{
+# define LINESIZE 16
+ int z,i;
+
+ for (z=0; z<len; z+=LINESIZE) {
+ sprintf (logtext, " ");
+
+ for (i=z; i<(z+LINESIZE) && i<len; i++) {
+ sprintf (logtext+strlen(logtext), "%2x ", m[i]);
+ }
+ for (; i<(z+LINESIZE); i++) {
+ sprintf (logtext+strlen(logtext), " ");
+ }
+
+ sprintf (logtext+strlen(logtext)," ");
+ for (i=z; i<(z+LINESIZE) && i<len; i++) {
+ sprintf (logtext+strlen(logtext),
+ "%c", (m[i]>=' ' && m[i]<=127) ? m[i] : '.');
+ }
+
+ dolog();
+ }
+}
+
+#else
+ /******* Schnelle Version des Speichermanagers ******/
+
+
+void *mem_alloc(int length)
+{
+ if (length==0) return NULL;
+
+ memoryusage += length;
+ if (memoryusage > maxmemusage) maxmemusage = memoryusage;
+
+ return checked_alloc (length);
+}
+
+
+void *lit_mem_alloc(int length)
+{
+ if (length==0) return NULL;
+
+ memoryusage += length;
+ if (memoryusage > maxmemusage) maxmemusage = memoryusage;
+
+ return lit_checked_alloc (length);
+}
+
+
+void mem_free(void *m, int length)
+{
+ if (!m) {
+ if (length==0) return;
+ panic ("returned memoryblock with address NULL, length != 0");
+ }
+
+ memoryusage -= length;
+
+ free (m);
+}
+
+
+void lit_mem_free(void *m, int length)
+{
+ if (!m) {
+ if (length==0) return;
+ panic ("returned memoryblock with address NULL, length != 0");
+ }
+
+ memoryusage -= length;
+
+#ifdef TRACECALLARGS
+#else
+ free (m);
+#endif
+}
+
+
+void *mem_realloc (void *m1, int len1, int len2)
+{
+ void *m2;
+
+ if (!m1) {
+ if (len1!=0)
+ panic ("reallocating memoryblock with address NULL, length != 0");
+ }
+
+ memoryusage = (memoryusage - len1) + len2;
+
+ m2 = realloc (m1, len2);
+ if (!m2) panic ("Out of memory");
+ return m2;
+}
+
+
+#endif
+
+ /******* allgemeine Teile des Speichermanagers ******/
+
+
+
+long int mem_usage()
+{
+ return memoryusage;
+}
+
+
+
+
+
+void *dump_alloc(int length)
+{
+ void *m;
+
+ if (length==0) return NULL;
+
+ length = ALIGN (length, ALIGNSIZE);
+
+ assert (length <= DUMPBLOCKSIZE);
+ assert (length > 0);
+
+ if (dumpsize + length > dumpspace) {
+ dumplist *newdumpblock = checked_alloc (sizeof(dumplist));
+
+ newdumpblock -> prev = topdumpblock;
+ topdumpblock = newdumpblock;
+
+ newdumpblock -> dumpmem = checked_alloc (DUMPBLOCKSIZE);
+
+ dumpsize = dumpspace;
+ dumpspace += DUMPBLOCKSIZE;
+ }
+
+ m = topdumpblock -> dumpmem + DUMPBLOCKSIZE - (dumpspace - dumpsize);
+ dumpsize += length;
+
+ if (dumpsize > maxdumpsize) {
+ maxdumpsize = dumpsize;
+ }
+
+ return m;
+}
+
+
+void *dump_realloc(void *ptr, int len1, int len2)
+{
+ void *p2 = dump_alloc (len2);
+ memcpy (p2, ptr, len1);
+ return p2;
+}
+
+
+long int dump_size()
+{
+ return dumpsize;
+}
+
+
+void dump_release(long int size)
+{
+ assert (size >= 0 && size <= dumpsize);
+
+ dumpsize = size;
+
+ while (dumpspace > dumpsize + DUMPBLOCKSIZE) {
+ dumplist *oldtop = topdumpblock;
+
+ topdumpblock = oldtop -> prev;
+ dumpspace -= DUMPBLOCKSIZE;
+
+#ifdef TRACECALLARGS
+#else
+ free (oldtop -> dumpmem);
+ free (oldtop);
+#endif
+ }
+}
+
+
+
+
+void mem_usagelog (int givewarnings)
+{
+ if ((memoryusage!=0) && givewarnings) {
+ sprintf (logtext, "Allocated memory not returned: %d",
+ (int)memoryusage);
+ dolog();
+
+#ifdef DEBUG
+ {
+ memblock *mb = firstmemblock;
+ while (mb) {
+ sprintf (logtext, " Memory block size: %d",
+ (int)(mb->length) );
+ dolog();
+ mem_characterlog ( ((unsigned char*)mb) + BLOCKOFFSET, mb->length);
+ mb = mb->next;
+ }
+ }
+#endif
+
+ }
+
+ if ((dumpsize!=0) && givewarnings) {
+ sprintf (logtext, "Dump memory not returned: %d",(int)dumpsize);
+ dolog();
+ }
+
+
+ sprintf (logtext, "Random/Dump - memory usage: %dK/%dK",
+ (int)((maxmemusage+1023)/1024),
+ (int)((maxdumpsize+1023)/1024) );
+ dolog();
+
+}
+
--- /dev/null
+/************************* toolbox/memory.h ************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Headerfiles und Makros f"ur die Speicherverwaltung.
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1996/10/03
+
+*******************************************************************************/
+
+#define CODEMMAP
+
+#define ALIGN(pos,size) ( ( ((pos)+(size)-1) / (size))*(size) )
+#define PADDING(pos,size) ( ALIGN((pos),(size)) - (pos) )
+#define OFFSET(s,el) ( (int) &( ((s*)0) -> el ) )
+
+
+#define NEW(type) ((type*) mem_alloc ( sizeof(type) ))
+#define FREE(ptr,type) mem_free (ptr, sizeof(type) )
+
+#define LNEW(type) ((type*) lit_mem_alloc ( sizeof(type) ))
+#define LFREE(ptr,type) lit_mem_free (ptr, sizeof(type) )
+
+#define MNEW(type,num) ((type*) mem_alloc ( sizeof(type) * (num) ))
+#define MFREE(ptr,type,num) mem_free (ptr, sizeof(type) * (num) )
+#define MREALLOC(ptr,type,num1,num2) mem_realloc (ptr, sizeof(type) * (num1), \
+ sizeof(type) * (num2) )
+
+#define DNEW(type) ((type*) dump_alloc ( sizeof(type) ))
+#define DMNEW(type,num) ((type*) dump_alloc ( sizeof(type) * (num) ))
+#define DMREALLOC(ptr,type,num1,num2) dump_realloc (ptr, sizeof(type)*(num1),\
+ sizeof(type) * (num2) )
+
+#define MCOPY(dest,src,type,num) memcpy (dest,src, sizeof(type)* (num) )
+
+#ifdef CODEMMAP
+#define CNEW(type,num) ((type*) mem_mmap ( sizeof(type) * (num) ))
+#define CFREE(ptr,num)
+#else
+#define CNEW(type,num) ((type*) mem_alloc ( sizeof(type) * (num) ))
+#define CFREE(ptr,num) mem_free (ptr, num)
+#endif
+
+void *mem_alloc(int length);
+void *mem_mmap(int length);
+void *lit_mem_alloc(int length);
+void mem_free(void *m, int length);
+void lit_mem_free(void *m, int length);
+void *mem_realloc(void *m, int len1, int len2);
+long int mem_usage();
+
+void *dump_alloc(int length);
+void *dump_realloc(void *m, int len1, int len2);
+long int dump_size();
+void dump_release(long int size);
+
+void mem_usagelog(int givewarnings);
+
+
+
+/*
+---------------------------- Schnittstellenbeschreibung -----------------------
+
+Der Speicherverwalter hat zwei m"ogliche Arten Speicher zu reservieren
+und freizugeben:
+
+ 1. explizites Anfordern / Freigeben
+
+ mem_alloc ..... Anfordern eines Speicherblocks
+ mem_free ...... Freigeben eines Speicherblocks
+ mem_realloc ... Vergr"o"sern eines Speicherblocks (wobei
+ der Inhalt eventuell an eine neue Position kommt)
+ mem_usage ..... Menge des bereits belegten Speichers
+
+
+ 2. explizites Anfordern und automatisches Freigeben
+
+ dump_alloc .... Anfordern eines Speicherblocks vom
+ (wie ich es nenne) DUMP-Speicher
+ dump_realloc .. Vergr"o"sern eines Speicherblocks
+ dump_size ..... Merkt sich eine Freigabemarke am Dump
+ dump_release .. Gibt allen Speicher, der nach der Marke angelegt
+ worden ist, wieder frei.
+
+
+Es gibt f"ur diese Funktionen ein paar praktische Makros:
+
+ NEW (type) ....... legt Speicher f"ur ein Element des Typs `type` an.
+ FREE (ptr,type) .. gibt Speicher zur"uck
+
+ MNEW (type,num) .. legt Speicher f"ur ein ganzes Array an
+ MFREE (ptr,type,num) .. gibt den Speicher wieder her
+
+ MREALLOC (ptr,type,num1,num2) .. vergr"o"sert den Speicher f"ur das Array
+ auf die Gr"o"se num2
+
+Die meisten der Makros gibt es auch f"ur den DUMP-Speicher, na"mlich mit
+gleichem Namen, nur mit vorangestelltem 'D', also:
+
+ DNEW, DMNEW, DMREALLOC (DFREE gibt es nat"urlich keines)
+
+
+-------------------------------------------------------------------------------
+
+Die restlichen Makros:
+
+ ALIGN (pos, size) ... Rundet den Wert von 'pos' auf die n"achste durch
+ 'size' teilbare Zahl auf.
+
+
+ OFFSET (s,el) ....... Berechnet den Offset (in Bytes) des Elementes 'el'
+ in der Struktur 's'.
+
+ MCOPY (dest,src,type,num) ... Kopiert 'num' Elemente vom Typ 'type'.
+
+
+*/
--- /dev/null
+/****************************** native.c ***************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Enth"alt die Tabellen f"ur die native-methods.
+ Die vom Headerfile-Generator erzeugten -.hh - Dateien werden hier
+ eingebunden, und ebenso alle C-Funktionen, mit denen diese
+ Methoden implementiert werden.
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1996/11/14
+
+*******************************************************************************/
+
+#include <unistd.h>
+#include <time.h>
+
+
+#include "global.h"
+#include "native.h"
+
+#include "builtin.h"
+#include "nativetypes.hh"
+#include "asmpart.h"
+#include "tables.h"
+#include "loader.h"
+
+
+java_objectheader* exceptionptr = NULL;
+
+
+
+static char *classpath;
+
+
+/******************** die f"r die native-Methoden n"otigen Systemklassen *****/
+
+static classinfo *class_java_lang_Class;
+static classinfo *class_java_lang_Cloneable;
+static classinfo *class_java_lang_CloneNotSupportedException;
+static classinfo *class_java_lang_Double;
+static classinfo *class_java_lang_Float;
+static classinfo *class_java_io_IOException;
+static classinfo *class_java_lang_ClassNotFoundException;
+static classinfo *class_java_lang_InstantiationException;
+
+
+
+/************************** alle Funktionen einbinden ************************/
+
+#include "nat/lang.c"
+#include "nat/io.c"
+#include "nat/util.c"
+
+
+/********************** Tabellen f"ur die Methoden ***************************/
+
+static struct nativeref {
+ char *classname;
+ char *methodname;
+ char *descriptor;
+ bool isstatic;
+ functionptr func;
+} nativetable [] = {
+
+#include "nativetable.hh"
+
+};
+
+
+#define NATIVETABLESIZE (sizeof(nativetable)/sizeof(struct nativeref))
+
+static struct nativecompref {
+ unicode *classname;
+ unicode *methodname;
+ unicode *descriptor;
+ bool isstatic;
+ functionptr func;
+ } nativecomptable [NATIVETABLESIZE];
+
+static bool nativecompdone = false;
+
+
+/*********************** Funktion: native_loadclasses **************************
+
+ L"adt alle Klassen, die die native Methoden zus"atzlich ben"otigen
+
+*******************************************************************************/
+
+void native_loadclasses()
+{
+ class_java_lang_Cloneable =
+ loader_load ( unicode_new_char ("java/lang/Cloneable") );
+ class_java_lang_CloneNotSupportedException =
+ loader_load ( unicode_new_char ("java/lang/CloneNotSupportedException") );
+ class_java_lang_Class =
+ loader_load ( unicode_new_char ("java/lang/Class") );
+ class_java_lang_Double =
+ loader_load ( unicode_new_char ("java/lang/Double") );
+ class_java_lang_Float =
+ loader_load ( unicode_new_char ("java/lang/Float") );
+ class_java_io_IOException =
+ loader_load ( unicode_new_char ("java/io/IOException") );
+ class_java_lang_ClassNotFoundException =
+ loader_load ( unicode_new_char ("java/lang/ClassNotFoundException") );
+ class_java_lang_InstantiationException=
+ loader_load ( unicode_new_char ("java/lang/InstantiationException") );
+
+}
+
+/********************* Funktion: native_setclasspath ***************************/
+
+void native_setclasspath (char *path)
+{
+ classpath = path;
+}
+
+
+/*********************** Funktion: native_findfunction ************************
+
+ Sucht in der Tabelle die passende Methode (muss mit Klassennamen,
+ Methodennamen, Descriptor und 'static'-Status "ubereinstimmen),
+ und gibt den Funktionszeiger darauf zur"uck.
+ Return: Funktionszeiger oder NULL (wenn es keine solche Methode gibt)
+
+ Anmerkung: Zu Beschleunigung des Suchens werden die als C-Strings
+ vorliegenden Namen/Descriptors in entsprechende unicode-Symbole
+ umgewandelt (beim ersten Aufruf dieser Funktion).
+
+*******************************************************************************/
+
+functionptr native_findfunction (unicode *cname, unicode *mname,
+ unicode *desc, bool isstatic)
+{
+ u4 i;
+ struct nativecompref *n;
+
+ isstatic = isstatic ? true : false;
+
+ if (!nativecompdone) {
+ for (i=0; i<NATIVETABLESIZE; i++) {
+ nativecomptable[i].classname =
+ unicode_new_char(nativetable[i].classname);
+ nativecomptable[i].methodname =
+ unicode_new_char(nativetable[i].methodname);
+ nativecomptable[i].descriptor =
+ unicode_new_char(nativetable[i].descriptor);
+ nativecomptable[i].isstatic =
+ nativetable[i].isstatic;
+ nativecomptable[i].func =
+ nativetable[i].func;
+ }
+ nativecompdone = true;
+ }
+
+ for (i=0; i<NATIVETABLESIZE; i++) {
+ n = &(nativecomptable[i]);
+
+ if (cname==n->classname && mname==n->methodname &&
+ desc==n->descriptor && isstatic==n->isstatic) return n->func;
+ }
+
+ return NULL;
+}
+
+
+/********************** Funktion: javastring_new *****************************
+
+ Legt ein neues Objekt vom Typ java/lang/String an, und tr"agt als Text
+ das "ubergebene unicode-Symbol ein.
+ Return: Zeiger auf den String, oder NULL (wenn Speicher aus)
+
+*****************************************************************************/
+
+java_objectheader *javastring_new (unicode *text)
+{
+ u4 i;
+ java_lang_String *s;
+ java_chararray *a;
+
+ s = (java_lang_String*) builtin_new (class_java_lang_String);
+ a = builtin_newarray_char (text->length);
+
+ if ( (!a) || (!s) ) return NULL;
+
+ for (i=0; i<text->length; i++) a->data[i] = text->text[i];
+ s -> value = a;
+ s -> offset = 0;
+ s -> count = text->length;
+
+ return (java_objectheader*) s;
+}
+
+
+/********************** Funktion: javastring_new_char ************************
+
+ Legt ein neues Objekt vom Typ java/lang/String an, und tr"agt als Text
+ den "ubergebenen C-String ein.
+ Return: Zeiger auf den String, oder NULL (wenn Speicher aus)
+
+*****************************************************************************/
+
+java_objectheader *javastring_new_char (char *text)
+{
+ u4 i;
+ u4 len = strlen(text);
+ java_lang_String *s;
+ java_chararray *a;
+
+ s = (java_lang_String*) builtin_new (class_java_lang_String);
+ a = builtin_newarray_char (len);
+
+ if ( (!a) || (!s) ) return NULL;
+
+ for (i=0; i<len; i++) a->data[i] = text[i];
+ s -> value = a;
+ s -> offset = 0;
+ s -> count = len;
+
+ return (java_objectheader*) s;
+}
+
+
+/************************* Funktion: javastring_tochar *****************************
+
+ Macht aus einem java-string einen C-String, und liefert den Zeiger
+ darauf zur"uck.
+ Achtung: Beim n"achsten Aufruf der Funktion wird der vorige String
+ "uberschrieben
+
+***********************************************************************************/
+
+#define MAXSTRINGSIZE 1000
+char stringbuffer[MAXSTRINGSIZE];
+
+char *javastring_tochar (java_objectheader *so)
+{
+ java_lang_String *s = (java_lang_String*) so;
+ java_chararray *a;
+ u4 i;
+
+ if (!s) return "";
+ a = s->value;
+ if (!a) return "";
+ if (s->count > MAXSTRINGSIZE) return "";
+ for (i=0; i<s->count; i++) stringbuffer[i] = a->data[s->offset+i];
+ stringbuffer[i] = '\0';
+ return stringbuffer;
+}
+
+
+/******************** Funktion: native_new_and_init *************************
+
+ Legt ein neues Objekt einer Klasse am Heap an, und ruft automatisch
+ die Initialisierungsmethode auf.
+ Return: Der Zeiger auf das Objekt, oder NULL, wenn kein Speicher
+ mehr frei ist.
+
+*****************************************************************************/
+
+java_objectheader *native_new_and_init (classinfo *c)
+{
+ methodinfo *m;
+ java_objectheader *o = builtin_new (c);
+
+ if (!o) return NULL;
+
+ m = class_findmethod (c,
+ unicode_new_char ("<init>"),
+ unicode_new_char ("()V"));
+ if (!m) {
+ log_text ("warning: class has no instance-initializer:");
+ unicode_sprint (logtext, c->name);
+ dolog();
+ return o;
+ }
+
+ asm_calljavamethod (m, o,NULL,NULL,NULL);
+ return o;
+}
+
+
+/********************* Funktion: literalstring_new ****************************
+
+ erzeugt einen Java-String mit dem angegebenen Text, allerdings nicht
+ auf dem HEAP, sondern in einem anderen Speicherbereich (der String
+ muss dann sp"ater explizit wieder freigegeben werden).
+ Alle Strings, die auf diese Art erzeugt werden, werden in einer
+ gemeinsamen Struktur gespeichert (n"amlich auch "uber die
+ Unicode-Hashtabelle), sodass identische Strings auch wirklich den
+ gleichen Zeiger liefern.
+
+******************************************************************************/
+
+java_objectheader *literalstring_new (unicode *text)
+{
+ u4 i;
+ java_lang_String *s;
+ java_chararray *a;
+
+ if (text->string) return text->string;
+
+ a = lit_mem_alloc (sizeof(java_chararray) + sizeof(u2)*(text->length-1) );
+ a -> header.objheader.vftbl = class_array -> vftbl;
+ a -> header.size = text->length;
+ a -> header.arraytype = ARRAYTYPE_CHAR;
+ for (i=0; i<text->length; i++) a->data[i] = text->text[i];
+
+ s = LNEW (java_lang_String);
+ s -> header.vftbl = class_java_lang_String -> vftbl;
+ s -> value = a;
+ s -> offset = 0;
+ s -> count = text->length;
+
+ unicode_setstringlink (text, (java_objectheader*) s);
+ return (java_objectheader*) s;
+}
+
+
+/********************** Funktion: literalstring_free **************************
+
+ L"oscht einen Java-String wieder aus dem Speicher (wird zu Systemende
+ vom Hashtabellen-Verwalter aufgerufen)
+
+******************************************************************************/
+
+void literalstring_free (java_objectheader* sobj)
+{
+ java_lang_String *s = (java_lang_String*) sobj;
+ java_chararray *a = s->value;
+
+ LFREE (s, java_lang_String);
+ LFREE (a, sizeof(java_chararray) + sizeof(u2)*(a->header.size-1));
+}
+
+
+
--- /dev/null
+/****************************** native.h ***************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Contains the codegenerator for an Alpha processor.
+ This module generates Alpha machine code for a sequence of
+ pseudo commands (PCMDs).
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1997/03/12
+
+*******************************************************************************/
+
+
+extern java_objectheader* exceptionptr;
+
+void native_loadclasses ();
+void native_setclasspath (char *path);
+
+functionptr native_findfunction (unicode *cname, unicode *mname,
+ unicode *desc, bool isstatic);
+
+java_objectheader *javastring_new (unicode *text);
+java_objectheader *javastring_new_char (char *text);
+char *javastring_tochar (java_objectheader *s);
+
+java_objectheader *native_new_and_init (classinfo *c);
+
+java_objectheader *literalstring_new (unicode *text);
+void literalstring_free (java_objectheader*);
+
+void attach_property(char *name, char *value);
--- /dev/null
+/* -*- mode: c; tab-width: 4; c-basic-offset: 4 -*- */
+/*
+ * locks.c
+ * Manage locking system
+ * This include the mutex's and cv's.
+ *
+ * Copyright (c) 1996 T. J. Wilkinson & Associates, London, UK.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * Written by Tim Wilkinson <tim@tjwassoc.demon.co.uk>, 1996.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+
+#include "thread.h"
+#include "locks.h"
+
+#include "../tables.h"
+#include "../native.h"
+#include "../loader.h"
+
+static classinfo *class_java_lang_IllegalMonitorStateException;
+
+#if 1
+#define DBG(s)
+#else
+#define DBG(s) s
+#endif
+
+extern thread* currentThread;
+
+#if defined(USE_INTERNAL_THREADS)
+
+mutexHashEntry *mutexHashTable;
+int mutexHashTableSize;
+long mutexHashMask;
+
+mutexHashEntry *mutexOverflowTable;
+int mutexOverflowTableSize;
+mutexHashEntry *firstFreeOverflowEntry = 0;
+
+conditionHashEntry *conditionHashTable;
+int conditionHashTableSize;
+long conditionHashMask;
+
+/*
+ * Init the tables.
+ */
+void
+initLocks (void)
+{
+ int i;
+
+ mutexHashTableSize = MUTEX_HASH_TABLE_SIZE;
+ mutexHashTable = (mutexHashEntry*)malloc(sizeof(mutexHashEntry) * mutexHashTableSize);
+ mutexHashMask = (mutexHashTableSize - 1) << 3;
+
+ for (i = 0; i < mutexHashTableSize; ++i)
+ {
+ mutexHashTable[i].object = 0;
+ mutexHashTable[i].mutex.holder = 0;
+ mutexHashTable[i].mutex.count = 0;
+ mutexHashTable[i].mutex.muxWaiters = 0;
+ mutexHashTable[i].conditionCount = 0;
+ mutexHashTable[i].next = 0;
+ }
+
+ mutexOverflowTableSize = MUTEX_OVERFLOW_TABLE_SIZE;
+ mutexOverflowTable = (mutexHashEntry*)malloc(sizeof(mutexHashEntry)
+ * mutexOverflowTableSize);
+
+ firstFreeOverflowEntry = &mutexOverflowTable[0];
+
+ for (i = 0; i < mutexOverflowTableSize; ++i)
+ {
+ mutexOverflowTable[i].object = 0;
+ mutexOverflowTable[i].mutex.holder = 0;
+ mutexOverflowTable[i].mutex.count = 0;
+ mutexOverflowTable[i].mutex.muxWaiters = 0;
+ mutexOverflowTable[i].conditionCount = 0;
+ mutexOverflowTable[i].next = &mutexOverflowTable[i + 1];
+ }
+ mutexOverflowTable[i - 1].next = 0;
+
+ conditionHashTableSize = CONDITION_HASH_TABLE_SIZE;
+ conditionHashTable = (conditionHashEntry*)malloc(sizeof(conditionHashEntry)
+ * conditionHashTableSize);
+ conditionHashMask = (conditionHashTableSize - 1) << 3;
+
+ for (i = 0; i < conditionHashTableSize; ++i)
+ {
+ conditionHashTable[i].object = 0;
+ conditionHashTable[i].condition.cvWaiters = 0;
+ conditionHashTable[i].condition.mux = 0;
+ }
+
+ /* Load exception classes */
+ class_java_lang_IllegalMonitorStateException =
+ loader_load(unicode_new_char("java/lang/IllegalMonitorStateException"));
+}
+
+/*
+ * Reorders part of the condition hash table. Must be called after an entry has been deleted.
+ */
+void
+reorderConditionHashTable (int begin)
+{
+ while (conditionHashTable[begin].object != 0)
+ {
+ int hashValue = CONDITION_HASH_VALUE(conditionHashTable[begin].object);
+
+ if (hashValue != begin)
+ {
+ while (conditionHashTable[hashValue].object != 0)
+ {
+ hashValue = CONDITION_HASH_SUCCESSOR(hashValue);
+ if (hashValue == begin)
+ break;
+ }
+ if (hashValue != begin)
+ {
+ conditionHashTable[hashValue] = conditionHashTable[begin];
+ conditionHashTable[begin].object = 0;
+ conditionHashTable[begin].condition.cvWaiters = 0;
+ conditionHashTable[begin].condition.mux = 0;
+ }
+ }
+
+ begin = CONDITION_HASH_SUCCESSOR(begin);
+ }
+}
+
+/*
+ * Looks up an entry in the condition hash table.
+ */
+iCv*
+conditionForObject (java_objectheader *object)
+{
+ int hashValue;
+
+ intsDisable();
+
+ hashValue = CONDITION_HASH_VALUE(object);
+ while (conditionHashTable[hashValue].object != object
+ && conditionHashTable[hashValue].object != 0)
+ hashValue = CONDITION_HASH_SUCCESSOR(hashValue);
+
+ if (conditionHashTable[hashValue].object == 0)
+ {
+ intsRestore();
+ return 0;
+ }
+
+ intsRestore();
+ return &conditionHashTable[hashValue].condition;
+}
+
+/*
+ * Adds a new entry in the condition hash table and returns a pointer to the condition
+ */
+iCv*
+addConditionForObject (java_objectheader *object)
+{
+ int hashValue;
+
+ intsDisable();
+
+ hashValue = CONDITION_HASH_VALUE(object);
+ while (conditionHashTable[hashValue].object != 0)
+ hashValue = CONDITION_HASH_SUCCESSOR(hashValue);
+
+ conditionHashTable[hashValue].object = object;
+
+ intsRestore();
+
+ return &conditionHashTable[hashValue].condition;
+}
+
+/*
+ * Removes an entry from the condition hash table.
+ */
+void
+removeConditionForObject (java_objectheader *object)
+{
+ int hashValue;
+
+ intsDisable();
+
+ hashValue = CONDITION_HASH_VALUE(object);
+ while (conditionHashTable[hashValue].object != object)
+ hashValue = CONDITION_HASH_SUCCESSOR(hashValue);
+
+ conditionHashTable[hashValue].object = 0;
+ conditionHashTable[hashValue].condition.cvWaiters = 0;
+ conditionHashTable[hashValue].condition.mux = 0;
+
+ reorderConditionHashTable(CONDITION_HASH_SUCCESSOR(hashValue));
+
+ intsRestore();
+}
+
+/*
+ * Returns the mutex entry for the specified object and increments its conditionCount.
+ */
+mutexHashEntry*
+conditionLockedMutexForObject (java_objectheader *object)
+{
+ int hashValue;
+ mutexHashEntry *entry;
+
+ assert(object != 0);
+
+ intsDisable();
+
+ hashValue = MUTEX_HASH_VALUE(object);
+ entry = &mutexHashTable[hashValue];
+
+ if (entry->object != 0)
+ {
+ if (entry->mutex.count == 0 && entry->conditionCount == 0)
+ {
+ entry->object = 0;
+ entry->mutex.holder = 0;
+ entry->mutex.count = 0;
+ entry->mutex.muxWaiters = 0;
+ }
+ else
+ {
+ while (entry->next != 0 && entry->object != object)
+ entry = entry->next;
+
+ if (entry->object != object)
+ {
+ entry->next = firstFreeOverflowEntry;
+ firstFreeOverflowEntry = firstFreeOverflowEntry->next;
+
+ entry = entry->next;
+ entry->object = 0;
+ entry->next = 0;
+ assert(entry->conditionCount == 0);
+ }
+ }
+ }
+
+ if (entry->object == 0)
+ entry->object = object;
+
+ ++entry->conditionCount;
+
+ intsRestore();
+
+ return entry;
+}
+
+/*
+ * Wait for the condition of an object to be signalled
+ */
+void
+wait_cond_for_object (java_objectheader *obj, s8 time)
+{
+ iCv *condition;
+ mutexHashEntry *mutexEntry;
+
+ intsDisable();
+
+ mutexEntry = conditionLockedMutexForObject(obj);
+
+ condition = conditionForObject(obj);
+ if (condition == 0)
+ condition = addConditionForObject(obj);
+
+ DBG( fprintf(stderr, "condition of %p is %p\n", obj, condition); );
+
+ internal_wait_cond(&mutexEntry->mutex, condition, time);
+
+ if (condition->cvWaiters == 0 && condition->mux == 0)
+ removeConditionForObject(obj);
+ --mutexEntry->conditionCount;
+
+ intsRestore();
+}
+
+/*
+ * Signal the condition of an object
+ */
+void
+signal_cond_for_object (java_objectheader *obj)
+{
+ iCv *condition;
+
+ intsDisable();
+
+ condition = conditionForObject(obj);
+ if (condition == 0)
+ condition = addConditionForObject(obj);
+
+ DBG( fprintf(stderr, "condition of %p is %p\n", obj, condition); );
+
+ internal_signal_cond(condition);
+
+ if (condition->cvWaiters == 0 && condition->mux == 0)
+ removeConditionForObject(obj);
+
+ intsRestore();
+}
+
+/*
+ * Broadcast the condition of an object.
+ */
+void
+broadcast_cond_for_object (java_objectheader *obj)
+{
+ intsDisable();
+ internal_broadcast_cond_for_object(obj);
+ intsRestore();
+}
+
+/*
+ * Internal: Broadcast the condition of an object.
+ */
+void
+internal_broadcast_cond_for_object (java_objectheader *obj)
+{
+ iCv *condition;
+
+ condition = conditionForObject(obj);
+ if (condition == 0)
+ condition = addConditionForObject(obj);
+
+ internal_broadcast_cond(condition);
+
+ if (condition->cvWaiters == 0 && condition->mux == 0)
+ removeConditionForObject(obj);
+}
+
+/*
+ * Lock a mutex.
+ */
+void
+lock_mutex (iMux *mux)
+{
+ intsDisable();
+ internal_lock_mutex(mux);
+ intsRestore();
+}
+
+/*
+ * Lock the mutex for an object.
+ */
+void
+lock_mutex_for_object (java_objectheader *obj)
+{
+ intsDisable();
+ internal_lock_mutex_for_object(obj);
+ intsRestore();
+}
+
+/*
+ * Unlock a mutex.
+ */
+void
+unlock_mutex (iMux *mux)
+{
+ intsDisable();
+ internal_unlock_mutex(mux);
+ intsRestore();
+}
+
+/*
+ * Unlock the mutex for an object.
+ */
+void
+unlock_mutex_for_object (java_objectheader *obj)
+{
+ intsDisable();
+ internal_unlock_mutex_for_object(obj);
+ intsRestore();
+}
+
+/*
+ * Wait on a condition variable.
+ */
+void
+wait_cond (iMux *mux, iCv *cond, s8 timeout)
+{
+ intsDisable();
+ internal_wait_cond(mux, cond, timeout);
+ intsRestore();
+}
+
+/*
+ * Signal a condition variable.
+ */
+void
+signal_cond (iCv *cond)
+{
+ intsDisable();
+ internal_signal_cond(cond);
+ intsRestore();
+}
+
+/*
+ * Broadcast a condition variable.
+ */
+void
+broadcast_cond (iCv *cond)
+{
+ intsDisable();
+ internal_broadcast_cond(cond);
+ intsRestore();
+}
+
+/*
+ * Internal: Lock a mutex.
+ */
+void
+internal_lock_mutex(iMux* mux)
+{
+ assert(blockInts == 1);
+
+ if (mux->holder == 0)
+ {
+ mux->holder = currentThread;
+ mux->count = 1;
+ DBG( fprintf(stderr, "set holder of %p to %p\n", mux, mux->holder); )
+ }
+ else if (mux->holder == currentThread)
+ {
+ mux->count++;
+ }
+ else
+ {
+ while (mux->holder != 0)
+ {
+ suspendOnQThread(currentThread, &mux->muxWaiters);
+ }
+ mux->holder = currentThread;
+ mux->count = 1;
+ }
+}
+
+/*
+ * Internal: Release a mutex.
+ */
+void
+internal_unlock_mutex(iMux* mux)
+{
+ thread* tid;
+
+ assert(blockInts == 1);
+
+ assert(mux->holder == currentThread);
+
+ mux->count--;
+ if (mux->count == 0)
+ {
+ mux->holder = 0;
+ if (mux->muxWaiters != 0)
+ {
+ tid = mux->muxWaiters;
+ mux->muxWaiters = tid->next;
+ iresumeThread(tid);
+ }
+ }
+}
+
+/*
+ * Internal: Wait on a conditional variable.
+ * (timeout currently ignored)
+ */
+void
+internal_wait_cond(iMux* mux, iCv* cv, s8 timeout)
+{
+ int count;
+ thread* tid;
+
+ DBG( fprintf(stderr, "waiting on %p\n", cv); );
+
+ if (mux->holder != currentThread) {
+ exceptionptr = native_new_and_init(class_java_lang_IllegalMonitorStateException);
+ }
+
+ assert(blockInts == 1);
+
+ count = mux->count;
+ mux->holder = 0;
+ mux->count = 0;
+ cv->mux = mux;
+
+ /* If there's anyone waiting here, wake them up */
+ if (mux->muxWaiters != 0) {
+ tid = mux->muxWaiters;
+ mux->muxWaiters = tid->next;
+ iresumeThread(tid);
+ }
+
+ /* Suspend, and keep suspended until I re-get the lock */
+ suspendOnQThread(currentThread, &cv->cvWaiters);
+ while (mux->holder != 0) {
+ DBG( fprintf(stderr, "woke up\n"); );
+ suspendOnQThread(currentThread, &mux->muxWaiters);
+ }
+
+ mux->holder = currentThread;
+ mux->count = count;
+}
+
+/*
+ * Internal: Wake one thread on a conditional variable.
+ */
+void
+internal_signal_cond (iCv* cv)
+{
+ thread* tid;
+
+ DBG( fprintf(stderr, "signalling on %p\n", cv); );
+
+ /* If 'mux' isn't set then we've never waited on this object. */
+ if (cv->mux == 0) {
+ return;
+ }
+
+ if (cv->mux->holder != currentThread) {
+ exceptionptr = native_new_and_init(class_java_lang_IllegalMonitorStateException);
+ }
+
+ assert(blockInts == 1);
+
+ /* Remove one thread from cv list */
+ if (cv->cvWaiters != 0) {
+ DBG( fprintf(stderr, "releasing a waiter\n"); );
+
+ tid = cv->cvWaiters;
+ cv->cvWaiters = tid->next;
+
+ /* Place it on mux list */
+ tid->next = cv->mux->muxWaiters;
+ cv->mux->muxWaiters = tid;
+ }
+}
+
+/*
+ * Internal: Wake all threads on a conditional variable.
+ */
+void
+internal_broadcast_cond (iCv* cv)
+{
+ thread** tidp;
+
+ /* If 'mux' isn't set then we've never waited on this object. */
+ if (cv->mux == 0) {
+ return;
+ }
+
+ if (cv->mux->holder != currentThread) {
+ exceptionptr = native_new_and_init(class_java_lang_IllegalMonitorStateException);
+ }
+
+ assert(blockInts == 1);
+
+ /* Find the end of the cv list */
+ if (cv->cvWaiters) {
+ for (tidp = &cv->cvWaiters; *tidp != 0; tidp = &(*tidp)->next)
+ ;
+
+ /* Place entire cv list on mux list */
+ (*tidp) = cv->mux->muxWaiters;
+ cv->mux->muxWaiters = cv->cvWaiters;
+ cv->cvWaiters = 0;
+ }
+}
+
+#endif
--- /dev/null
+/*
+ * locks.h
+ * Manage locking system
+ * This include the mutex's and cv's.
+ *
+ * Copyright (c) 1996 T. J. Wilkinson & Associates, London, UK.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * Written by Tim Wilkinson <tim@tjwassoc.demon.co.uk>, 1996.
+ */
+
+#ifndef __locks_h
+#define __locks_h
+
+#ifdef USE_THREADS
+
+#include "../global.h"
+#include "sysdep/defines.h"
+
+#define WAITFOREVER -1
+
+#if defined(USE_INTERNAL_THREADS)
+
+struct _thread;
+
+typedef struct _iMux {
+ struct _thread *holder;
+ int count;
+ struct _thread *muxWaiters;
+} iMux;
+
+typedef struct _iCv {
+ struct _thread* cvWaiters;
+ struct _iMux* mux;
+} iCv;
+
+#define MAX_MUTEXES 256
+
+typedef struct _mutexHashEntry
+{
+ java_objectheader *object;
+ iMux mutex;
+ struct _mutexHashEntry *next;
+ int conditionCount;
+} mutexHashEntry;
+
+#define MUTEX_HASH_TRASH_BITS 3
+#define MUTEX_HASH_SIGN_BITS 10
+
+#define MUTEX_HASH_TABLE_SIZE 1024
+#define MUTEX_OVERFLOW_TABLE_SIZE 1024
+/*
+#define MAX_MUTEX_HASH_TABLE_SIZE 65536
+*/
+
+/*
+#define MUTEX_USE_THRESHOLD 1024
+*/
+
+extern long mutexHashMask;
+extern int mutexHashTableSize;
+extern mutexHashEntry *mutexHashTable;
+
+extern mutexHashEntry *mutexOverflowTable;
+extern int mutexOverflowTableSize;
+extern mutexHashEntry *firstFreeOverflowEntry;
+
+#define MUTEX_HASH_MASK ((MUTEX_HASH_TABLE_SIZE - 1) << 3)
+
+#if 0
+#define MUTEX_HASH_VALUE(a) ((((long)(a)) & MUTEX_HASH_MASK) >> MUTEX_HASH_TRASH_BITS)
+#else
+#define MUTEX_HASH_VALUE(a) (( (((long)(a)) ^ ((long)(a) >> MUTEX_HASH_SIGN_BITS)) & mutexHashMask) >> MUTEX_HASH_TRASH_BITS)
+#endif
+#define MUTEX_HASH_SUCCESSOR(h) (((h) + 7) & (mutexHashTableSize - 1))
+
+typedef struct _conditionHashEntry
+{
+ java_objectheader *object;
+ iCv condition;
+} conditionHashEntry;
+
+#define CONDITION_HASH_TABLE_SIZE 1024
+
+#define CONDITION_HASH_VALUE(a) ((((long)(a)) & conditionHashMask) >> 3)
+#define CONDITION_HASH_SUCCESSOR(h) (((h) + 7) & (conditionHashTableSize - 1))
+
+typedef struct
+{
+ bool free;
+ java_objectheader *object;
+ iMux mutex;
+ iCv condition;
+} object_mutex;
+
+extern void initLocks (void);
+
+mutexHashEntry* conditionLockedMutexForObject (java_objectheader *object);
+
+void reorderConditionHashTable (int begin);
+iCv* conditionForObject (java_objectheader *object);
+iCv* addConditionForObject (java_objectheader *object);
+void removeConditionForObject (java_objectheader *object);
+
+/*
+ * use these functions only outside critical sections (intsEnable/intsRestore).
+ */
+
+void signal_cond_for_object (java_objectheader *obj);
+void broadcast_cond_for_object (java_objectheader *obj);
+void wait_cond_for_object (java_objectheader *obj, s8 time);
+void lock_mutex_for_object (java_objectheader *obj);
+void unlock_mutex_for_object (java_objectheader *obj);
+
+void lock_mutex (iMux*);
+void unlock_mutex (iMux*);
+void wait_cond (iMux*, iCv*, s8);
+void signal_cond (iCv*);
+void broadcast_cond (iCv*);
+
+/*
+ * use these internal functions only in critical sections. blockInts must be exactly
+ * 1.
+ */
+void internal_lock_mutex (iMux*);
+void internal_unlock_mutex (iMux*);
+void internal_wait_cond (iMux*, iCv*, s8);
+void internal_signal_cond (iCv*);
+void internal_broadcast_cond (iCv*);
+
+void internal_lock_mutex_for_object (java_objectheader *obj);
+void internal_unlock_mutex_for_object (java_objectheader *obj);
+void internal_broadcast_cond_for_object (java_objectheader *obj);
+
+#endif
+
+#endif /* USE_THREADS */
+
+#endif /* __locks_h */
--- /dev/null
+/*
+ * threadCalls.c
+ * Support for threaded ops which may block (read, write, connect, etc.).
+ *
+ * Copyright (c) 1996 T. J. Wilkinson & Associates, London, UK.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * Written by Tim Wilkinson <tim@tjwassoc.demon.co.uk>, 1996.
+ */
+
+#define DBG(s)
+
+#include "sysdep/defines.h"
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <assert.h>
+#include <unistd.h>
+
+#include "thread.h"
+
+/*
+ * We only need this stuff is we are using the internal thread system.
+ */
+#if defined(USE_INTERNAL_THREADS)
+
+#define TH_READ 0
+#define TH_WRITE 1
+#define TH_ACCEPT TH_READ
+#define TH_CONNECT TH_WRITE
+
+static int maxFd;
+static fd_set readsPending;
+static fd_set writesPending;
+static thread* readQ[FD_SETSIZE];
+static thread* writeQ[FD_SETSIZE];
+static struct timeval tm = { 0, 0 };
+
+void blockOnFile(int, int);
+void waitOnEvents(void);
+
+extern thread* currentThread;
+
+/* These are undefined because we do not yet support async I/O */
+#undef F_SETOWN
+#undef FIOSETOWN
+#undef O_ASYNC
+#undef FIOASYNC
+
+/*
+ * Create a threaded file descriptor.
+ */
+int
+threadedFileDescriptor(int fd)
+{
+#if !defined(BLOCKING_CALLS)
+ int r;
+ int on = 1;
+ int pid;
+
+ /* Make non-blocking */
+#if defined(HAVE_FCNTL) && defined(O_NONBLOCK)
+ r = fcntl(fd, F_GETFL, 0);
+ r = fcntl(fd, F_SETFL, r|O_NONBLOCK);
+#elif defined(HAVE_IOCTL) && defined(FIONBIO)
+ r = ioctl(fd, FIONBIO, &on);
+#else
+ r = 0;
+#endif
+ if (r < 0)
+ {
+ return (r);
+ }
+
+ /* Allow socket to signal this process when new data is available */
+ pid = getpid();
+#if defined(HAVE_FCNTL) && defined(F_SETOWN)
+ r = fcntl(fd, F_SETOWN, pid);
+#elif defined(HAVE_IOCTL) && defined(FIOSETOWN)
+ r = ioctl(fd, FIOSETOWN, &pid);
+#else
+ r = 0;
+#endif
+ if (r < 0)
+ {
+ return (r);
+ }
+
+#if defined(HAVE_FCNTL) && defined(O_ASYNC)
+ r = fcntl(fd, F_GETFL, 0);
+ r = fcntl(fd, F_SETFL, r|O_ASYNC);
+#elif defined(HAVE_IOCTL) && defined(FIOASYNC)
+ r = ioctl(fd, FIOASYNC, &on);
+#else
+ r = 0;
+#endif
+ if (r < 0)
+ {
+ return (r);
+ }
+#endif
+ return (fd);
+}
+
+/*
+ * Threaded create socket.
+ */
+int
+threadedSocket(int af, int type, int proto)
+{
+ int fd;
+ int r;
+ int on = 1;
+ int pid;
+
+ fd = socket(af, type, proto);
+ return (threadedFileDescriptor(fd));
+}
+
+/*
+ * Threaded file open.
+ */
+int
+threadedOpen(char* path, int flags, int mode)
+{
+ int fd;
+ int r;
+ int on = 1;
+ int pid;
+
+ fd = open(path, flags, mode);
+ return (threadedFileDescriptor(fd));
+}
+
+/*
+ * Threaded socket connect.
+ */
+int
+threadedConnect(int fd, struct sockaddr* addr, int len)
+{
+ int r;
+
+ r = connect(fd, addr, len);
+#if !defined(BLOCKING_CALLS)
+ if ((r < 0)
+ && (errno == EINPROGRESS || errno == EALREADY
+ || errno == EWOULDBLOCK)) {
+ blockOnFile(fd, TH_CONNECT);
+ r = 0; /* Assume it's okay when we get released */
+ }
+#endif
+
+ return (r);
+}
+
+/*
+ * Threaded socket accept.
+ */
+int
+threadedAccept(int fd, struct sockaddr* addr, int* len)
+{
+ int r;
+ int on = 1;
+
+ for (;;)
+ {
+#if defined(BLOCKING_CALLS)
+ blockOnFile(fd, TH_ACCEPT);
+#endif
+ r = accept(fd, addr, len);
+ if (r >= 0
+ || !(errno == EINPROGRESS || errno == EALREADY
+ || errno == EWOULDBLOCK))
+ {
+ break;
+ }
+#if !defined(BLOCKING_CALLS)
+ blockOnFile(fd, TH_ACCEPT);
+#endif
+ }
+ return (threadedFileDescriptor(r));
+}
+
+/*
+ * Read but only if we can.
+ */
+int
+threadedRead(int fd, char* buf, int len)
+{
+ int r;
+
+ DBG( printf("threadedRead\n"); )
+
+#if defined(BLOCKING_CALLS)
+ blockOnFile(fd, TH_READ);
+#endif
+ for (;;)
+ {
+ r = read(fd, buf, len);
+ if (r < 0
+ && (errno == EAGAIN || errno == EWOULDBLOCK
+ || errno == EINTR))
+ {
+ blockOnFile(fd, TH_READ);
+ continue;
+ }
+ return (r);
+ }
+}
+
+/*
+ * Write but only if we can.
+ */
+int
+threadedWrite(int fd, char* buf, int len)
+{
+ int r;
+ char* ptr;
+
+ ptr = buf;
+ r = 1;
+
+ DBG( printf("threadedWrite %dbytes\n",len); )
+
+ while (len > 0 && r > 0)
+ {
+#if defined(BLOCKING_CALLS)
+ blockOnFile(fd, TH_WRITE);
+#endif
+ r = write(fd, ptr, len);
+ if (r < 0
+ && (errno == EAGAIN || errno == EWOULDBLOCK
+ || errno == EINTR))
+ {
+#if !defined(BLOCKING_CALLS)
+ blockOnFile(fd, TH_WRITE);
+#endif
+ r = 1;
+ }
+ else
+ {
+ ptr += r;
+ len -= r;
+ }
+ }
+ return (ptr - buf);
+}
+
+/*
+ * An attempt to access a file would block, so suspend the thread until
+ * it will happen.
+ */
+void
+blockOnFile(int fd, int op)
+{
+DBG( printf("blockOnFile()\n"); )
+
+ intsDisable();
+
+ if (fd > maxFd)
+ {
+ maxFd = fd;
+ }
+ if (op == TH_READ)
+ {
+ FD_SET(fd, &readsPending);
+ suspendOnQThread(currentThread, &readQ[fd]);
+ FD_CLR(fd, &readsPending);
+ }
+ else
+ {
+ FD_SET(fd, &writesPending);
+ suspendOnQThread(currentThread, &writeQ[fd]);
+ FD_CLR(fd, &writesPending);
+ }
+
+ intsRestore();
+}
+
+/*
+ * Check if some file descriptor or other event to become ready.
+ * Block if required (but make sure we can still take timer interrupts).
+ */
+void
+checkEvents(bool block)
+{
+ int r;
+ fd_set rd;
+ fd_set wr;
+ thread* tid;
+ thread* ntid;
+ int i;
+ int b;
+
+DBG( printf("checkEvents block:%d\n", block); )
+
+#if defined(FD_COPY)
+ FD_COPY(&readsPending, &rd);
+ FD_COPY(&writesPending, &wr);
+#else
+ memcpy(&rd, &readsPending, sizeof(rd));
+ memcpy(&wr, &writesPending, sizeof(wr));
+#endif
+
+ /*
+ * If select() is called with indefinite wait, we have to make sure
+ * we can get interrupted by timer events.
+ */
+ if (block == true)
+ {
+ b = blockInts;
+ blockInts = 0;
+ r = select(maxFd+1, &rd, &wr, 0, 0);
+ blockInts = b;
+ }
+ else
+ {
+ r = select(maxFd+1, &rd, &wr, 0, &tm);
+ }
+
+ /* We must be holding off interrupts before we start playing with
+ * the read and write queues. This should be already done but a
+ * quick check never hurt anyone.
+ */
+ assert(blockInts > 0);
+
+DBG( printf("Select returns %d\n", r); )
+
+ for (i = 0; r > 0 && i <= maxFd; i++)
+ {
+ if (readQ[i] != 0 && FD_ISSET(i, &rd))
+ {
+ for (tid = readQ[i]; tid != 0; tid = ntid)
+ {
+ ntid = tid->next;
+ iresumeThread(tid);
+ }
+ readQ[i] = 0;
+ r--;
+ }
+ if (writeQ[i] != 0 && FD_ISSET(i, &wr))
+ {
+ for (tid = writeQ[i]; tid != 0; tid = ntid)
+ {
+ ntid = tid->next;
+ iresumeThread(tid);
+ }
+ writeQ[i] = 0;
+ r--;
+ }
+ }
+}
+#endif
--- /dev/null
+/* -*- c -*- */
+
+#ifndef __threadio_h_
+#define __threadio_h_
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include "../global.h"
+
+#ifdef USE_THREADS
+int threadedFileDescriptor(int fd);
+int threadedSocket(int af, int type, int proto);
+int threadedOpen(char* path, int flags, int mode);
+int threadedConnect(int fd, struct sockaddr* addr, int len);
+int threadedAccept(int fd, struct sockaddr* addr, int* len);
+int threadedRead(int fd, char* buf, int len);
+int threadedWrite(int fd, char* buf, int len);
+#else
+#define threadedFileDescriptor(fd)
+#define threadedRead(fd,buf,len) read(fd,buf,len)
+#define threadedWrite(fd,buf,len) write(fd,buf,len)
+#endif
+
+
+#endif
--- /dev/null
+/* -*- mode: c; tab-width: 4; c-basic-offset: 4 -*- */
+/*
+ * thread.c
+ * Thread support.
+ *
+ * Copyright (c) 1996 T. J. Wilkinson & Associates, London, UK.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * Written by Tim Wilkinson <tim@tjwassoc.demon.co.uk>, 1996.
+ */
+
+#include <assert.h>
+
+#include <sys/types.h>
+#include <sys/mman.h> /* for mprotect */
+#include <unistd.h>
+
+#include "thread.h"
+#include "locks.h"
+#include "sysdep/defines.h"
+#include "sysdep/threads.h"
+
+#include "../tables.h"
+#include "../native.h"
+#include "../loader.h"
+#include "../builtin.h"
+#include "../asmpart.h"
+
+static classinfo *class_java_lang_ThreadDeath;
+
+#if 1
+#define DBG(s)
+#define SDBG(s)
+#else
+#define DBG(s) s
+#define SDBG(s) s
+#endif
+
+#if defined(USE_INTERNAL_THREADS)
+
+thread* currentThread;
+thread* threadQhead[MAX_THREAD_PRIO + 1];
+thread* threadQtail[MAX_THREAD_PRIO + 1];
+
+thread* liveThreads;
+thread* alarmList;
+
+thread* gcDaemonThread;
+
+int blockInts;
+bool needReschedule;
+
+ctx contexts[MAXTHREADS];
+
+/* Number of threads alive, also counting daemons */
+static int talive;
+
+/* Number of daemon threads alive */
+static int tdaemon;
+
+static void firstStartThread(void);
+
+void reschedule(void);
+
+/* Setup default thread stack size - this can be overwritten if required */
+int threadStackSize = THREADSTACKSIZE;
+
+static thread* startDaemon(void* func, char* nm, int stackSize);
+
+/*
+ * Allocate the stack for a thread
+ */
+void
+allocThreadStack (thread *tid, int size)
+{
+ int pageSize = getpagesize(),
+ result;
+ unsigned long pageBegin;
+
+ CONTEXT(tid).stackMem = malloc(size + 2 * pageSize);
+ assert(CONTEXT(tid).stackMem != 0);
+ CONTEXT(tid).stackEnd = CONTEXT(tid).stackMem + size + 2 * pageSize;
+
+ pageBegin = (unsigned long)(CONTEXT(tid).stackMem) + pageSize - 1;
+ pageBegin = pageBegin - pageBegin % pageSize;
+
+ result = mprotect((void*)pageBegin, pageSize, PROT_NONE);
+ assert(result == 0);
+
+ CONTEXT(tid).stackBase = (u1*)pageBegin + pageSize;
+}
+
+/*
+ * Free the stack for a thread
+ */
+void
+freeThreadStack (thread *tid)
+{
+ if (!(CONTEXT(tid).flags & THREAD_FLAGS_NOSTACKALLOC))
+ {
+ int pageSize = getpagesize(),
+ result;
+ unsigned long pageBegin;
+
+ pageBegin = (unsigned long)(CONTEXT(tid).stackMem) + pageSize - 1;
+ pageBegin = pageBegin - pageBegin % pageSize;
+
+ result = mprotect((void*)pageBegin, pageSize,
+ PROT_READ | PROT_WRITE | PROT_EXEC);
+ assert(result == 0);
+
+ free(CONTEXT(tid).stackMem);
+ }
+ CONTEXT(tid).stackMem = 0;
+ CONTEXT(tid).stackBase = 0;
+ CONTEXT(tid).stackEnd = 0;
+}
+
+/*
+ * Initialize threads.
+ */
+void
+initThreads(u1 *stackbottom)
+{
+ int i;
+
+ initLocks();
+
+ for (i = 0; i < MAXTHREADS; ++i)
+ contexts[i].free = true;
+
+ /* Allocate a thread to be the main thread */
+ currentThread = (thread*)builtin_new(loader_load(unicode_new_char("java/lang/Thread")));
+ assert(currentThread != 0);
+
+ currentThread->PrivateInfo = 1;
+ CONTEXT(currentThread).free = false;
+
+ liveThreads = currentThread;
+
+ currentThread->name = javastring_new(unicode_new_char("main"));
+ currentThread->priority = NORM_THREAD_PRIO;
+ CONTEXT(currentThread).priority = (u1)currentThread->priority;
+ CONTEXT(currentThread).exceptionptr = 0;
+ currentThread->next = 0;
+ CONTEXT(currentThread).status = THREAD_SUSPENDED;
+ CONTEXT(currentThread).stackBase = CONTEXT(currentThread).stackEnd = stackbottom;
+ THREADINFO(&CONTEXT(currentThread));
+
+ DBG( printf("main thread %p base %p end %p\n",
+ currentThread,
+ CONTEXT(currentThread).stackBase,
+ CONTEXT(currentThread).stackEnd); );
+
+ CONTEXT(currentThread).flags = THREAD_FLAGS_NOSTACKALLOC;
+ CONTEXT(currentThread).nextlive = 0;
+ currentThread->single_step = 0;
+ currentThread->daemon = 0;
+ currentThread->stillborn = 0;
+ currentThread->target = 0;
+ currentThread->interruptRequested = 0;
+ currentThread->group =
+ (threadGroup*)builtin_new(loader_load(unicode_new_char("java/lang/ThreadGroup")));
+ /* we should call the constructor */
+ assert(currentThread->group != 0);
+
+ talive++;
+
+ /* Add thread into runQ */
+ iresumeThread(currentThread);
+
+ /* Start garbage collection thread */
+ gcDaemonThread = startDaemon(gc_thread, "gc", 1024*512);
+ iresumeThread(gcDaemonThread);
+
+ heap_addreference((void**)&gcDaemonThread);
+
+ /* Load exception classes */
+ class_java_lang_ThreadDeath = loader_load(unicode_new_char("java/lang/ThreadDeath"));
+
+ DBG( fprintf(stderr, "finishing initThreads\n"); );
+
+ assert(blockInts == 0);
+}
+
+/*
+ * Start a new thread running.
+ */
+void
+startThread (thread* tid)
+{
+ int i;
+
+ /* Allocate a stack context */
+ for (i = 0; i < MAXTHREADS; ++i)
+ if (contexts[i].free)
+ break;
+
+ if (i == MAXTHREADS)
+ panic("Too many threads");
+
+ tid->PrivateInfo = i + 1;
+ CONTEXT(tid).free = false;
+ CONTEXT(tid).nextlive = liveThreads;
+ liveThreads = tid;
+ allocThreadStack(tid, threadStackSize);
+ CONTEXT(tid).usedStackTop = CONTEXT(tid).stackBase;
+ CONTEXT(tid).flags = THREAD_FLAGS_GENERAL;
+ CONTEXT(tid).status = THREAD_SUSPENDED;
+ CONTEXT(tid).priority = (u1)tid->priority;
+ CONTEXT(tid).exceptionptr = 0;
+
+ /* Construct the initial restore point. */
+ THREADINIT((&CONTEXT(tid)), firstStartThread);
+
+ DBG( printf("new thread %p base %p end %p\n",
+ tid, CONTEXT(tid).stackBase,
+ CONTEXT(tid).stackEnd); );
+
+ talive++;
+ if (tid->daemon)
+ tdaemon++;
+
+ /* Add thread into runQ */
+ iresumeThread(tid);
+}
+
+/*
+ * Start a daemon thread.
+ */
+static thread*
+startDaemon(void* func, char* nm, int stackSize)
+{
+ thread* tid;
+ int i;
+
+ DBG( printf("startDaemon %s\n", nm); );
+
+ tid = (thread*)builtin_new(loader_load(unicode_new_char("java/lang/Thread")));
+ assert(tid != 0);
+
+ for (i = 0; i < MAXTHREADS; ++i)
+ if (contexts[i].free)
+ break;
+ if (i == MAXTHREADS)
+ panic("Too many threads");
+
+ tid->PrivateInfo = i + 1;
+ CONTEXT(tid).free = false;
+ tid->name = 0; /* for the moment */
+ tid->priority = MAX_THREAD_PRIO;
+ CONTEXT(tid).priority = (u1)tid->priority;
+ tid->next = 0;
+ CONTEXT(tid).status = THREAD_SUSPENDED;
+
+ allocThreadStack(tid, stackSize);
+ tid->single_step = 0;
+ tid->daemon = 1;
+ tid->stillborn = 0;
+ tid->target = 0;
+ tid->interruptRequested = 0;
+ tid->group = 0;
+
+ /* Construct the initial restore point. */
+ THREADINIT((&CONTEXT(tid)), func);
+
+ talive++;
+ tdaemon++;
+
+ return tid;
+}
+
+/*
+ * All threads start here.
+ */
+static void
+firstStartThread(void)
+{
+ methodinfo *method;
+
+ DBG( printf("firstStartThread %p\n", currentThread); );
+
+ /* Every thread starts with the interrupts off */
+ intsRestore();
+ assert(blockInts == 0);
+
+ /* Find the run()V method and call it */
+ method = class_findmethod(currentThread->header.vftbl->class,
+ unicode_new_char("run"), unicode_new_char("()V"));
+ if (method == 0)
+ panic("Cannot find method \'void run ()\'");
+ asm_calljavamethod(method, currentThread, NULL, NULL, NULL);
+
+ killThread(0);
+ assert("Thread returned from killThread" == 0);
+}
+
+/*
+ * Resume a thread running.
+ * This routine has to be called only from locations which ensure
+ * run / block queue consistency. There is no check for illegal resume
+ * conditions (like explicitly resuming an IO blocked thread). There also
+ * is no update of any blocking queue. Both has to be done by the caller
+ */
+void
+iresumeThread(thread* tid)
+{
+ DBG( printf("resumeThread %p\n", tid); );
+
+ intsDisable();
+
+ if (CONTEXT(tid).status != THREAD_RUNNING)
+ {
+ CONTEXT(tid).status = THREAD_RUNNING;
+
+ DBG( fprintf(stderr, "prio is %d\n", CONTEXT(tid).priority); );
+
+ /* Place thread on the end of its queue */
+ if (threadQhead[CONTEXT(tid).priority] == 0) {
+ threadQhead[CONTEXT(tid).priority] = tid;
+ threadQtail[CONTEXT(tid).priority] = tid;
+ if (CONTEXT(tid).priority
+ > CONTEXT(currentThread).priority)
+ needReschedule = true;
+ }
+ else
+ {
+ threadQtail[CONTEXT(tid).priority]->next = tid;
+ threadQtail[CONTEXT(tid).priority] = tid;
+ }
+ tid->next = 0;
+ }
+ SDBG( else { printf("Re-resuming %p\n", tid); } );
+
+ intsRestore();
+}
+
+/*
+ * Yield process to another thread of equal priority.
+ */
+void
+yieldThread()
+{
+ intsDisable();
+
+ if (threadQhead[CONTEXT(currentThread).priority]
+ != threadQtail[CONTEXT(currentThread).priority])
+ {
+ /* Get the next thread and move me to the end */
+ threadQhead[CONTEXT(currentThread).priority] = currentThread->next;
+ threadQtail[CONTEXT(currentThread).priority]->next = currentThread;
+ threadQtail[CONTEXT(currentThread).priority] = currentThread;
+ currentThread->next = 0;
+ needReschedule = true;
+ }
+
+ intsRestore();
+}
+
+/*
+ * Explicit request by user to resume a thread
+ * The definition says that it is just legal to call this after a preceeding
+ * suspend (which got through). If the thread was blocked for some other
+ * reason (either sleep or IO or a muxSem), we simply can't do it
+ * We use a new thread flag THREAD_FLAGS_USER_SUSPEND for this purpose
+ * (which is set by suspendThread(.))
+ */
+void
+resumeThread(thread* tid)
+{
+ if ((CONTEXT(tid).flags & THREAD_FLAGS_USER_SUSPEND) != 0)
+ {
+ intsDisable();
+ CONTEXT(tid).flags &= ~THREAD_FLAGS_USER_SUSPEND;
+ iresumeThread(tid);
+ intsRestore();
+ }
+}
+
+/*
+ * Suspend a thread.
+ * This is an explicit user request to suspend the thread - the counterpart
+ * for resumeThreadRequest(.). It is JUST called by the java method
+ * Thread.suspend()
+ * What makes it distinct is the fact that the suspended thread is not contained
+ * in any block queue. Without a special flag (indicating the user suspend), we
+ * can't check s suspended thread for this condition afterwards (which is
+ * required by resumeThreadRequest()). The new thread flag
+ * THREAD_FLAGS_USER_SUSPEND is used for this purpose.
+ */
+void
+suspendThread(thread* tid)
+{
+ thread** ntid;
+
+ intsDisable();
+
+ if (CONTEXT(tid).status != THREAD_SUSPENDED)
+ {
+ CONTEXT(tid).status = THREAD_SUSPENDED;
+
+ /*
+ * This is used to indicate the explicit suspend condition
+ * required by resumeThreadRequest()
+ */
+ CONTEXT(tid).flags |= THREAD_FLAGS_USER_SUSPEND;
+
+ for (ntid = &threadQhead[CONTEXT(tid).priority];
+ *ntid != 0;
+ ntid = &(*ntid)->next)
+ {
+ if (*ntid == tid)
+ {
+ *ntid = tid->next;
+ tid->next = 0;
+ if (tid == currentThread)
+ {
+ reschedule();
+ }
+ break;
+ }
+ }
+ }
+ SDBG( else { printf("Re-suspending %p\n", tid); } );
+
+ intsRestore();
+}
+
+/*
+ * Suspend a thread on a queue.
+ */
+void
+suspendOnQThread(thread* tid, thread** queue)
+{
+ thread** ntid;
+
+ DBG( printf("suspendOnQThread %p %p\n", tid, queue); );
+
+ assert(blockInts == 1);
+
+ if (CONTEXT(tid).status != THREAD_SUSPENDED)
+ {
+ CONTEXT(tid).status = THREAD_SUSPENDED;
+
+ for (ntid = &threadQhead[CONTEXT(tid).priority];
+ *ntid != 0;
+ ntid = &(*ntid)->next)
+ {
+ if (*ntid == tid)
+ {
+ *ntid = tid->next;
+ /* Insert onto head of lock wait Q */
+ tid->next = *queue;
+ *queue = tid;
+ if (tid == currentThread)
+ {
+ DBG( fprintf(stderr, "suspending %p (cur=%p) with prio %d\n",
+ tid, currentThread, CONTEXT(tid).priority); );
+ reschedule();
+ }
+ break;
+ }
+ }
+ }
+ SDBG( else { printf("Re-suspending %p on %p\n", tid, *queue); } );
+}
+
+/*
+ * Kill thread.
+ */
+void
+killThread(thread* tid)
+{
+ thread** ntid;
+
+ intsDisable();
+
+ /* A null tid means the current thread */
+ if (tid == 0)
+ {
+ tid = currentThread;
+ }
+
+ DBG( printf("killThread %p\n", tid); );
+
+ if (CONTEXT(tid).status != THREAD_DEAD)
+ {
+ /* Get thread off runq (if it needs it) */
+ if (CONTEXT(tid).status == THREAD_RUNNING)
+ {
+ for (ntid = &threadQhead[CONTEXT(tid).priority];
+ *ntid != 0;
+ ntid = &(*ntid)->next)
+ {
+ if (*ntid == tid)
+ {
+ *ntid = tid->next;
+ break;
+ }
+ }
+ }
+
+ CONTEXT(tid).status = THREAD_DEAD;
+ talive--;
+ if (tid->daemon) {
+ tdaemon--;
+ }
+
+ /* If we only have daemons left, then everyone is dead. */
+ if (talive == tdaemon) {
+ /* Am I suppose to close things down nicely ?? */
+ exit(0);
+ }
+
+ /* Notify on the object just in case anyone is waiting */
+ internal_lock_mutex_for_object(&tid->header);
+ internal_broadcast_cond_for_object(&tid->header);
+ internal_unlock_mutex_for_object(&tid->header);
+
+ /* Remove thread from live list to it can be garbaged */
+ for (ntid = &liveThreads;
+ *ntid != 0;
+ ntid = &(CONTEXT((*ntid)).nextlive))
+ {
+ if (tid == (*ntid))
+ {
+ (*ntid) = CONTEXT(tid).nextlive;
+ break;
+ }
+ }
+
+ /* Free stack */
+ freeThreadStack(tid);
+
+ /* free context */
+ CONTEXT(tid).free = true;
+
+ /* Run something else */
+ needReschedule = true;
+ }
+ intsRestore();
+}
+
+/*
+ * Change thread priority.
+ */
+void
+setPriorityThread(thread* tid, int prio)
+{
+ thread** ntid;
+
+ if (tid->PrivateInfo == 0) {
+ tid->priority = prio;
+ return;
+ }
+
+ if (CONTEXT(tid).status == THREAD_SUSPENDED) {
+ CONTEXT(tid).priority = (u8)prio;
+ return;
+ }
+
+ intsDisable();
+
+ /* Remove from current thread list */
+ for (ntid = &threadQhead[CONTEXT(tid).priority]; *ntid != 0; ntid = &(*ntid)->next) {
+ if (*ntid == tid) {
+ *ntid = tid->next;
+ break;
+ }
+ }
+
+ /* Insert onto a new one */
+ tid->priority = prio;
+ CONTEXT(tid).priority = (u8)tid->priority;
+ if (threadQhead[prio] == 0) {
+ threadQhead[prio] = tid;
+ threadQtail[prio] = tid;
+ if (prio > CONTEXT(currentThread).priority) {
+ needReschedule = true;
+ }
+ }
+ else {
+ threadQtail[prio]->next = tid;
+ threadQtail[prio] = tid;
+ }
+ tid->next = 0;
+
+ intsRestore();
+}
+
+/*
+ * Is this thread alive?
+ */
+bool
+aliveThread(thread* tid)
+{
+ if (tid->PrivateInfo != 0 && CONTEXT(tid).status != THREAD_DEAD)
+ return (true);
+ else
+ return (false);
+}
+
+/*
+ * Reschedule the thread.
+ * Called whenever a change in the running thread is required.
+ */
+void
+reschedule(void)
+{
+ int i;
+ thread* lastThread;
+ int b;
+ /* sigset_t nsig; */
+
+ /* A reschedule in a non-blocked context is half way to hell */
+ assert(blockInts > 0);
+ b = blockInts;
+
+ /* Check events - we may release a high priority thread */
+ /* Just check IO, no need for a reschedule call by checkEvents() */
+ needReschedule = false;
+ checkEvents(false);
+
+ for (;;)
+ {
+ for (i = MAX_THREAD_PRIO; i >= MIN_THREAD_PRIO; i--)
+ {
+ if (threadQhead[i] != 0)
+ {
+ DBG( fprintf(stderr, "found thread %p in head %d\n", threadQhead[i], i); );
+
+ if (threadQhead[i] != currentThread)
+ {
+ USEDSTACKTOP((CONTEXT(currentThread).usedStackTop));
+
+ lastThread = currentThread;
+ currentThread = threadQhead[i];
+
+ CONTEXT(currentThread).exceptionptr = exceptionptr;
+
+ THREADSWITCH((&CONTEXT(currentThread)),
+ (&CONTEXT(lastThread)));
+ blockInts = b;
+
+ exceptionptr = CONTEXT(currentThread).exceptionptr;
+
+ /* Alarm signal may be blocked - if so
+ * unblock it.
+ */
+ /*
+ if (alarmBlocked == true) {
+ alarmBlocked = false;
+ sigemptyset(&nsig);
+ sigaddset(&nsig, SIGALRM);
+ sigprocmask(SIG_UNBLOCK, &nsig, 0);
+ }
+ */
+
+ /* I might be dying */
+ if ((CONTEXT(lastThread).flags & THREAD_FLAGS_KILLED)
+ != 0)
+ {
+ CONTEXT(lastThread).flags &= ~THREAD_FLAGS_KILLED;
+ exceptionptr = native_new_and_init(class_java_lang_ThreadDeath);
+ }
+ }
+ /* Now we kill the schedule and turn ints
+ back on */
+ needReschedule = false;
+ return;
+ }
+ }
+ /* Nothing to run - wait for external event */
+ DBG( fprintf(stderr, "nothing more to do\n"); );
+ checkEvents(true);
+ }
+}
+
+#endif
--- /dev/null
+/*
+ * thread.h
+ * Thread support.
+ *
+ * Copyright (c) 1996 T. J. Wilkinson & Associates, London, UK.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * Written by Tim Wilkinson <tim@tjwassoc.demon.co.uk>, 1996.
+ */
+
+#ifndef __thread_h
+#define __thread_h
+
+#ifdef USE_THREADS
+
+#include "../global.h"
+
+#define MAXTHREADS 256 /* schani */
+
+#define THREADCLASS "java/lang/Thread"
+#define THREADGROUPCLASS "java/lang/ThreadGroup"
+#define THREADDEATHCLASS "java/lang/ThreadDeath"
+
+#define MIN_THREAD_PRIO 1
+#define NORM_THREAD_PRIO 5
+#define MAX_THREAD_PRIO 10
+
+#define THREAD_SUSPENDED 0
+#define THREAD_RUNNING 1
+#define THREAD_DEAD 2
+#define THREAD_KILL 3
+
+#define THREAD_FLAGS_GENERAL 0
+#define THREAD_FLAGS_NOSTACKALLOC 1
+#define THREAD_FLAGS_USER_SUSPEND 2 /* Flag explicit suspend() call */
+#define THREAD_FLAGS_KILLED 4
+
+struct _thread;
+
+typedef struct _ctx
+{
+ bool free; /* schani */
+ u1 status;
+ u1 priority;
+ u1* restorePoint;
+ u1* stackMem; /* includes guard page */
+ u1* stackBase;
+ u1* stackEnd;
+ u1* usedStackTop;
+ s8 time;
+ java_objectheader *exceptionptr;
+ struct _thread *nextlive;
+ u1 flags;
+} ctx;
+
+/*
+struct _stringClass;
+struct _object;
+*/
+
+/* This structure mirrors java.lang.ThreadGroup.h */
+
+typedef struct _threadGroup
+{
+ java_objectheader header;
+ struct _threadGroup* parent;
+ java_objectheader* name;
+ s4 maxPrio;
+ s4 destroyed;
+ s4 daemon;
+ s4 nthreads;
+ java_objectheader* threads;
+ s4 ngroups;
+ java_objectheader* groups;
+} threadGroup;
+
+/* This structure mirrors java.lang.Thread.h */
+typedef struct _thread
+{
+ java_objectheader header;
+ java_objectheader* name;
+ s4 priority;
+ struct _thread* next;
+ s8 PrivateInfo;
+ struct java_lang_Object* eetop; /* ??? */
+ s4 single_step;
+ s4 daemon;
+ s4 stillborn;
+ java_objectheader* target;
+ s4 interruptRequested;
+ threadGroup* group;
+} thread;
+
+void initThreads(u1 *stackbottom);
+void startThread(thread*);
+void resumeThread(thread*);
+void iresumeThread(thread*);
+void suspendThread(thread*);
+void suspendOnQThread(thread*, thread**);
+void yieldThread(void);
+void killThread(thread*);
+void setPriorityThread(thread*, int);
+
+void sleepThread(s8);
+bool aliveThread(thread*);
+long framesThread(thread*);
+
+void reschedule(void);
+
+void checkEvents(bool block);
+
+extern int blockInts;
+extern bool needReschedule;
+extern thread *currentThread;
+extern ctx contexts[];
+extern int threadStackSize;
+
+extern thread *liveThreads;
+
+extern thread *threadQhead[MAX_THREAD_PRIO + 1];
+
+#define CONTEXT(_t) \
+ (contexts[(_t)->PrivateInfo - 1])
+
+#if 1
+#define intsDisable() blockInts++
+#define intsRestore() if (blockInts == 1 && needReschedule) { \
+ reschedule(); \
+ } \
+ blockInts--
+#else
+#define intsDisable() do { blockInts++; fprintf(stderr, "++: %d (%s:%d)\n", blockInts, __FILE__, __LINE__); } while (0)
+#define intsRestore() do { \
+ if (blockInts == 1 && needReschedule) { \
+ reschedule(); \
+ } \
+ blockInts--; \
+ fprintf(stderr, "--: %d (%s:%d)\n", blockInts, __FILE__, __LINE__); \
+ } while (0)
+#endif
+
+#else
+
+#define intsDisable()
+#define intsRestore()
+
+#endif
+
+#endif
--- /dev/null
+/************************* toolbox/chain.c *************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Not documented, see chain.h.
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1996/10/03
+
+*******************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "memory.h"
+#include "chain.h"
+
+
+
+chain *chain_new ()
+{
+ chain *c;
+
+ c = NEW (chain);
+ c -> usedump = 0;
+ c -> first = NULL;
+ c -> last = NULL;
+ c -> active = NULL;
+
+ return c;
+}
+
+chain *chain_dnew ()
+{
+ chain *c;
+
+ c = DNEW (chain);
+ c -> usedump = 1;
+ c -> first = NULL;
+ c -> last = NULL;
+ c -> active = NULL;
+
+ return c;
+}
+
+
+void chain_free (chain *c)
+{
+ chainlink *l;
+
+ assert (! c->usedump);
+
+ l = c->first;
+ while (l) {
+ chainlink *nextl = l->next;
+
+ FREE (l, chainlink);
+ l = nextl;
+ }
+
+ FREE (c, chain);
+}
+
+
+void chain_addafter(chain *c, void *element)
+{
+ chainlink *active,*newlink;
+
+ active = c->active;
+
+ if (c -> usedump) newlink = DNEW (chainlink);
+ else newlink = NEW (chainlink);
+
+ newlink -> element = element;
+
+ if (active) {
+ newlink -> next = active -> next;
+ newlink -> prev = active;
+
+ active -> next = newlink;
+ if (newlink -> next) newlink -> next -> prev = newlink;
+ else c -> last = newlink;
+ }
+ else {
+ newlink -> next = NULL;
+ newlink -> prev = NULL;
+
+ c -> active = newlink;
+ c -> first = newlink;
+ c -> last = newlink;
+ }
+}
+
+
+void chain_addbefore(chain *c, void *element)
+{
+ chainlink *active,*newlink;
+
+ active = c->active;
+
+ if (c -> usedump) newlink = DNEW (chainlink);
+ else newlink = NEW (chainlink);
+
+ newlink -> element = element;
+
+ if (active) {
+ newlink -> next = active;
+ newlink -> prev = active -> prev;
+
+ active -> prev = newlink;
+ if (newlink -> prev) newlink -> prev -> next = newlink;
+ else c -> first = newlink;
+ }
+ else {
+ newlink -> next = NULL;
+ newlink -> prev = NULL;
+
+ c -> active = newlink;
+ c -> first = newlink;
+ c -> last = newlink;
+ }
+}
+
+void chain_addlast (chain *c, void *e)
+{
+ chain_last (c);
+ chain_addafter (c, e);
+}
+
+void chain_addfirst (chain *c, void *e)
+{
+ chain_first (c);
+ chain_addbefore (c, e);
+}
+
+
+void chain_remove (chain *c)
+{
+ chainlink *active;
+
+ active = c -> active;
+ assert (active);
+
+ if (active -> next) {
+ active -> next -> prev = active -> prev;
+ }
+ else {
+ c -> last = active -> prev;
+ }
+
+ if (active -> prev) {
+ active -> prev -> next = active -> next;
+ }
+ else {
+ c -> first = active -> next;
+ }
+
+
+ if (active->prev)
+ c -> active = active->prev;
+ else
+ c -> active = active->next;
+
+ if (! c -> usedump) FREE (active, chainlink);
+}
+
+
+void *chain_remove_go_prev (chain *c)
+{
+ chain_remove (c);
+ return chain_this (c);
+}
+
+
+
+void chain_removespecific(chain *c, void *e)
+{
+ void *ce;
+
+ ce = chain_first (c);
+ while (ce) {
+ if (e == ce) { chain_remove (c); return; }
+ ce = chain_next (c);
+ }
+
+}
+
+void *chain_next(chain *c)
+{
+ chainlink *active;
+
+ active = c -> active;
+ if (!active) return NULL;
+
+ if (active -> next) {
+ c -> active = active -> next;
+ return c -> active -> element;
+ }
+
+ return NULL;
+}
+
+void *chain_prev(chain *c)
+{
+ chainlink *active;
+
+ active = c -> active;
+ if (!active) return NULL;
+
+ if (active -> prev) {
+ c -> active = active -> prev;
+ return c -> active -> element;
+ }
+
+ return NULL;
+}
+
+
+void *chain_this(chain *c)
+{
+ if (c -> active) return c -> active -> element;
+ return NULL;
+}
+
+
+void *chain_first(chain *c)
+{
+ c -> active = c -> first;
+ if (c -> active) return c -> active -> element;
+ return NULL;
+}
+
+void *chain_last(chain *c)
+{
+ c -> active = c -> last;
+ if (c -> active) return c -> active -> element;;
+ return NULL;
+}
+
--- /dev/null
+/************************* toolbox/chain.h *************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ dient zur Verwaltung doppelt verketteter Listen mit externer Verkettung
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1996/10/03
+
+*******************************************************************************/
+
+typedef struct chainlink { /* Struktur f"ur ein Listenelement */
+ struct chainlink *next,*prev;
+ void *element;
+ } chainlink;
+
+typedef struct chain { /* Struktur f"ur eine Liste */
+ int usedump;
+
+ chainlink *first,*last;
+ chainlink *active;
+ } chain;
+
+
+chain *chain_new ();
+chain *chain_dnew ();
+void chain_free(chain *c);
+
+void chain_addafter(chain *c, void *element);
+void chain_addbefore(chain *c, void *element);
+void chain_addlast (chain *c, void *element);
+void chain_addfirst (chain *c, void *element);
+
+void chain_remove(chain *c);
+void *chain_remove_go_prev(chain *c);
+void chain_removespecific(chain *c, void *element);
+
+void *chain_next(chain *c);
+void *chain_prev(chain *c);
+void *chain_this(chain *c);
+
+void *chain_first(chain *c);
+void *chain_last(chain *c);
+
+
+/*
+--------------------------- Schnittstellenbeschreibung ------------------------
+
+Bei Verwendung dieser Funktionen f"ur die Listenverwaltung mu"s, im
+Gegenstatz zum Modul 'list', keine zus"atzliche Vorbereitung in den
+Element-Strukturen gemacht werden.
+
+Diese Funktionen sind daher auch ein wenig langsamer und brauchen
+mehr Speicher.
+
+Eine neue Liste wird mit
+ chain_new
+ oder chain_dnew
+angelegt. Der Unterschied ist, da"s bei der zweiten Variante alle
+zus"atzlichen Datenstrukturen am DUMP-Speicher angelegt werden (was
+schneller geht, und ein explizites Freigeben am Ende der Verarbeitung
+unn"otig macht). Dabei mu"s man aber achtgeben, da"s man nicht
+versehentlich Teile dieser Strukturen durch ein verfr"uhtes 'dump_release'
+freigibt.
+
+Eine nicht mehr verwendete Liste kann mit
+ chain_free
+freigegeben werden (nur verwenden, wenn mit 'chain_new' angefordert)
+
+
+Das Eintragen neuer Elemente geht sehr einfach mit:
+ chain_addafter, chain_addlast, chain_addbefore, chain_addfirst
+
+Durchsuchen der Liste mit:
+ chain_first, chain_last, chain_prev, chain_next, chain_this
+
+L"oschen von Elementen aus der Liste:
+ chain_remove, chain_remove_go_prev, chain_removespecific
+
+
+ACHTUNG: In den zu verkettenden Elementen gibt es ja (wie oben gesagt) keine
+ Referenzen auf die Liste oder irgendwelche Listenknoten, deshalb k"onnen
+ die Elemente nicht als Ortsangabe innerhalb der Liste fungieren.
+ Es gibt vielmehr ein Art 'Cursor', der ein Element als das gerade
+ aktuelle festh"alt, und alle Ein-/und Ausf"ugeoperationen geschehen
+ relativ zu diesem Cursor.
+
+*/
+
--- /dev/null
+/************************** toolbox/list.c *************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Not documented, see chain.h.
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1996/10/03
+
+*******************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "list.h"
+
+
+void list_init (list *l, int nodeoffset)
+{
+ l->first = NULL;
+ l->last = NULL;
+ l->nodeoffset = nodeoffset;
+}
+
+void list_addlast (list *l, void *element)
+{
+ listnode *n = (listnode*) ( ((char*) element) + l->nodeoffset );
+
+ if (l->last) {
+ n->prev = l->last;
+ n->next = NULL;
+ l->last->next = n;
+ l->last = n;
+ }
+ else {
+ n->prev = NULL;
+ n->next = NULL;
+ l->last = n;
+ l->first = n;
+ }
+}
+
+void list_addfirst (list *l, void *element)
+{
+ listnode *n = (listnode*) ( ((char*) element) + l->nodeoffset );
+
+ if (l->first) {
+ n->prev = NULL;
+ n->next = l->first;
+ l->first->prev = n;
+ l->first = n;
+ }
+ else {
+ n->prev = NULL;
+ n->next = NULL;
+ l->last = n;
+ l->first = n;
+ }
+}
+
+
+void list_remove (list *l, void *element)
+{
+ listnode *n = (listnode*) ( ((char*) element) + l->nodeoffset );
+
+ if (n->next) n->next->prev = n->prev;
+ else l->last = n->prev;
+ if (n->prev) n->prev->next = n->next;
+ else l->first = n->next;
+}
+
+
+void *list_first (list *l)
+{
+ if (!l->first) return NULL;
+ return ((char*) l->first) - l->nodeoffset;
+}
+
+
+void *list_last (list *l)
+{
+ if (!l->last) return NULL;
+ return ((char*) l->last) - l->nodeoffset;
+}
+
+
+void *list_next (list *l, void *element)
+{
+ listnode *n;
+ n = (listnode*) ( ((char*) element) + l->nodeoffset );
+ if (!n->next) return NULL;
+ return ((char*) n->next) - l->nodeoffset;
+}
+
+
+void *list_prev (list *l, void *element)
+{
+ listnode *n;
+ n = (listnode*) ( ((char*) element) + l->nodeoffset );
+ if (!n->prev) return NULL;
+ return ((char*) n->prev) - l->nodeoffset;
+}
+
--- /dev/null
+/************************** toolbox/list.h *************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Verwaltung von doppelt verketteten Listen.
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1996/10/03
+
+*******************************************************************************/
+
+typedef struct listnode { /* Struktur f"ur ein Listenelement */
+ struct listnode *next,*prev;
+ } listnode;
+
+typedef struct list { /* Struktur f"ur den Listenkopf */
+ listnode *first,*last;
+ int nodeoffset;
+ } list;
+
+
+void list_init (list *l, int nodeoffset);
+
+void list_addlast (list *l, void *element);
+void list_addfirst (list *l, void *element);
+
+void list_remove (list *l, void *element);
+
+void *list_first (list *l);
+void *list_last (list *l);
+
+void *list_next (list *l, void *element);
+void *list_prev (list *l, void *element);
+
+
+/*
+---------------------- Schnittstellenbeschreibung -----------------------------
+
+Die Listenverwaltung mit diesem Modul geht so vor sich:
+
+ - jede Struktur, die in die Liste eingeh"angt werden soll, mu"s
+ eine Komponente vom Typ 'listnode' haben.
+
+ - es mu"s ein Struktur vom Typ 'list' bereitgestellt werden.
+
+ - die Funktion list_init (l, nodeoffset) initialisiert diese Struktur,
+ dabei gibt der nodeoffset den Offset der 'listnode'-Komponente in
+ den Knotenstrukturen an.
+
+ - Einf"ugen, Aush"angen und Suchen von Elementen der Liste geht mit
+ den "ubrigen Funktionen.
+
+Zum besseren Verst"andnis ein kleines Beispiel:
+
+
+ void bsp() {
+ struct node {
+ listnode linkage;
+ int value;
+ } a,b,c, *el;
+
+ list l;
+
+ a.value = 7;
+ b.value = 9;
+ c.value = 11;
+
+ list_init (&l, OFFSET(struct node,linkage) );
+ list_addlast (&l, a);
+ list_addlast (&l, b);
+ list_addlast (&l, c);
+
+ e = list_first (&l);
+ while (e) {
+ printf ("Element: %d\n", e->value);
+ e = list_next (&l,e);
+ }
+ }
+
+
+ Dieses Programm w"urde also folgendes ausgeben:
+ 7
+ 9
+ 11
+
+
+
+Der Grund, warum beim Initialisieren der Liste der Offset mitangegeben
+werden mu"s, ist der da"s ein und das selbe Datenelement gleichzeitig
+in verschiedenen Listen eingeh"angt werden kann (f"ur jede Liste mu"s
+also eine Komponente vom Typ 'listnode' im Element enthalten sein).
+
+*/
+
--- /dev/null
+/************************** toolbox/tree.c *************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Not documented, see tree.h.
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1996/10/03
+
+*******************************************************************************/
+
+#include <stdio.h>
+#include <assert.h>
+
+#include "memory.h"
+#include "tree.h"
+
+
+tree *tree_new (treeelementcomperator comperator)
+{
+ tree *t = NEW (tree);
+
+ t -> usedump = 0;
+ t -> comperator = comperator;
+ t -> top = NULL;
+ t -> active = NULL;
+
+ return t;
+}
+
+tree *tree_dnew (treeelementcomperator comperator)
+{
+ tree *t = DNEW (tree);
+
+ t -> usedump = 1;
+ t -> comperator = comperator;
+ t -> top = NULL;
+ t -> active = NULL;
+
+ return t;
+}
+
+
+static void tree_nodefree (treenode *tn)
+{
+ if (!tn) return;
+ tree_nodefree (tn -> left);
+ tree_nodefree (tn -> right);
+ FREE (tn, treenode);
+}
+
+void tree_free (tree *t)
+{
+ assert (! t -> usedump);
+
+ tree_nodefree ( t -> top );
+ FREE (t, tree);
+}
+
+
+static treenode *tree_nodeadd
+ (tree *t, treenode *par, treenode *n, void *element, void *key)
+{
+ if (!n) {
+ if ( t-> usedump ) n = DNEW (treenode);
+ else n = NEW (treenode);
+
+ n -> left = NULL;
+ n -> right = NULL;
+ n -> parent = par;
+ n -> element = element;
+ }
+ else {
+ if ( t->comperator (key, n -> element) < 0 ) {
+ n -> left = tree_nodeadd (t, n, n -> left, element, key);
+ }
+ else {
+ n -> right = tree_nodeadd (t, n, n -> right, element, key);
+ }
+ }
+
+ return n;
+}
+
+void tree_add (tree *t, void *element, void *key)
+{
+ t -> top = tree_nodeadd (t, NULL, t -> top, element, key);
+ t -> active = t -> top;
+}
+
+
+static treenode *tree_nodefind (tree *t, treenode *n, void *key)
+{
+ int way;
+
+ if (!n) return NULL;
+
+ way = t -> comperator (key, n->element);
+ if (way==0) return n;
+ if (way<0) return tree_nodefind (t, n -> left, key);
+ else return tree_nodefind (t, n -> right, key);
+}
+
+
+void *tree_find (tree *t, void *key)
+{
+ treenode *tn = tree_nodefind (t, t -> top, key);
+ if (!tn) return NULL;
+
+ t -> active = tn;
+ return tn -> element;
+}
+
+
+
+void *tree_this (tree *t)
+{
+ if (! t->active) return NULL;
+ return t->active->element;
+}
+
+
+static treenode *leftmostnode(treenode *t)
+{
+ while (t->left) t=t->left;
+ return t;
+}
+
+void *tree_first (tree *t)
+{
+ treenode *a = t->top;
+ if (!a) return NULL;
+
+ a = leftmostnode (a);
+ t->active = a;
+ return a->element;
+}
+
+void *tree_next (tree *t)
+{
+ treenode *a = t->active;
+ treenode *comefrom = NULL;
+
+ while (a) {
+ if (!a) return NULL;
+
+ if (a->left && (a->left == comefrom)) {
+ t -> active = a;
+ return a->element;
+ }
+
+ if (a->right && (a->right != comefrom) ) {
+ a = leftmostnode(a->right);
+ t -> active = a;
+ return a->element;
+ }
+
+ comefrom=a;
+ a=a->parent;
+ }
+ t->active = NULL;
+ return NULL;
+}
--- /dev/null
+/************************* toolbox/tree.h **************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Verwaltung bin"arer B"aume
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1996/10/03
+
+*******************************************************************************/
+
+typedef int (*treeelementcomperator) (void *key, void * element);
+
+
+typedef struct treenode {
+ struct treenode *left,*right;
+ struct treenode *parent;
+
+ void *element;
+ } treenode;
+
+typedef struct {
+ int usedump;
+ treeelementcomperator comperator;
+
+ treenode *top;
+ treenode *active;
+ } tree;
+
+
+
+tree *tree_new (treeelementcomperator comperator);
+tree *tree_dnew (treeelementcomperator comperator);
+void tree_free (tree *t);
+
+void tree_add (tree *t, void *element, void *key);
+void *tree_find (tree *t, void *key);
+
+void *tree_this (tree *t);
+void *tree_first (tree *t);
+void *tree_next (tree *t);
+
--- /dev/null
+/* -*- mode: c; tab-width: 4; c-basic-offset: 4 -*- */
+/****************************** builtin.c **************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Enthaelt die C-Funktionen fuer alle JavaVM-Befehle, die sich nicht direkt
+ auf Maschinencode "ubersetzen lassen. Im Code f"ur die Methoden steht
+ dann ein Funktionsaufruf (nat"urlich mit den Aufrufskonventionen von C).
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+ Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
+ Mark Probst EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1996/12/03
+
+*******************************************************************************/
+
+#include <assert.h>
+#include <values.h>
+
+#include "global.h"
+#include "builtin.h"
+
+#include "loader.h"
+#include "tables.h"
+
+#include "threads/thread.h"
+#include "threads/locks.h" /* schani */
+
+#include "sysdep/native-math.h"
+
+builtin_descriptor builtin_desc[] = {
+ {(functionptr) builtin_instanceof, "instanceof"},
+ {(functionptr) builtin_checkcast, "checkcast"},
+ {(functionptr) new_builtin_checkcast, "checkcast"},
+ {(functionptr) builtin_arrayinstanceof, "arrayinstanceof"},
+ {(functionptr) builtin_checkarraycast, "checkarraycast"},
+ {(functionptr) new_builtin_checkarraycast, "checkarraycast"},
+ {(functionptr) new_builtin_aastore, "aastore"},
+ {(functionptr) builtin_new, "new"},
+ {(functionptr) builtin_anewarray, "anewarray"},
+ {(functionptr) builtin_newarray_array, "newarray_array"},
+ {(functionptr) builtin_newarray_boolean, "newarray_boolean"},
+ {(functionptr) builtin_newarray_char, "newarray_char"},
+ {(functionptr) builtin_newarray_float, "newarray_float"},
+ {(functionptr) builtin_newarray_double, "newarray_double"},
+ {(functionptr) builtin_newarray_byte, "newarray_byte"},
+ {(functionptr) builtin_newarray_short, "newarray_short"},
+ {(functionptr) builtin_newarray_int, "newarray_int"},
+ {(functionptr) builtin_newarray_long, "newarray_long"},
+ {(functionptr) builtin_displaymethodstart, "displaymethodstart"},
+ {(functionptr) builtin_displaymethodstop, "displaymethodstop"},
+ {(functionptr) builtin_monitorenter, "monitorenter"},
+ {(functionptr) new_builtin_monitorenter, "monitorenter"},
+ {(functionptr) builtin_monitorexit, "monitorexit"},
+ {(functionptr) new_builtin_monitorexit, "monitorexit"},
+ {(functionptr) builtin_idiv, "idiv"},
+ {(functionptr) new_builtin_idiv, "idiv"},
+ {(functionptr) builtin_irem, "irem"},
+ {(functionptr) new_builtin_irem, "irem"},
+ {(functionptr) builtin_ladd, "ladd"},
+ {(functionptr) builtin_lsub, "lsub"},
+ {(functionptr) builtin_lmul, "lmul"},
+ {(functionptr) builtin_ldiv, "ldiv"},
+ {(functionptr) new_builtin_ldiv, "ldiv"},
+ {(functionptr) builtin_lrem, "lrem"},
+ {(functionptr) new_builtin_lrem, "lrem"},
+ {(functionptr) builtin_lshl, "lshl"},
+ {(functionptr) builtin_lshr, "lshr"},
+ {(functionptr) builtin_lushr, "lushr"},
+ {(functionptr) builtin_land, "land"},
+ {(functionptr) builtin_lor, "lor"},
+ {(functionptr) builtin_lxor, "lxor"},
+ {(functionptr) builtin_lneg, "lneg"},
+ {(functionptr) builtin_lcmp, "lcmp"},
+ {(functionptr) builtin_fadd, "fadd"},
+ {(functionptr) builtin_fsub, "fsub"},
+ {(functionptr) builtin_fmul, "fmul"},
+ {(functionptr) builtin_fdiv, "fdiv"},
+ {(functionptr) builtin_frem, "frem"},
+ {(functionptr) builtin_fneg, "fneg"},
+ {(functionptr) builtin_fcmpl, "fcmpl"},
+ {(functionptr) builtin_fcmpg, "fcmpg"},
+ {(functionptr) builtin_dadd, "dadd"},
+ {(functionptr) builtin_dsub, "dsub"},
+ {(functionptr) builtin_dmul, "dmul"},
+ {(functionptr) builtin_ddiv, "ddiv"},
+ {(functionptr) builtin_drem, "drem"},
+ {(functionptr) builtin_dneg, "dneg"},
+ {(functionptr) builtin_dcmpl, "dcmpl"},
+ {(functionptr) builtin_dcmpg, "dcmpg"},
+ {(functionptr) builtin_i2l, "i2l"},
+ {(functionptr) builtin_i2f, "i2f"},
+ {(functionptr) builtin_i2d, "i2d"},
+ {(functionptr) builtin_l2i, "l2i"},
+ {(functionptr) builtin_l2f, "l2f"},
+ {(functionptr) builtin_l2d, "l2d"},
+ {(functionptr) builtin_f2i, "f2i"},
+ {(functionptr) builtin_f2l, "f2l"},
+ {(functionptr) builtin_f2d, "f2d"},
+ {(functionptr) builtin_d2i, "d2i"},
+ {(functionptr) builtin_d2l, "d2l"},
+ {(functionptr) builtin_d2f, "d2f"},
+ {(functionptr) NULL, "unknown"}
+ };
+
+
+/*****************************************************************************
+ TYPCHECKS
+*****************************************************************************/
+
+
+
+/*************** interne Funktion: builtin_isanysubclass *********************
+
+ "uberpr"uft, ob eine Klasse eine Unterklasse einer anderen Klasse ist.
+ Dabei gelten auch Interfaces, die eine Klasse implementiert, als
+ deren Oberklassen.
+ R"uckgabewert: 1 ... es trifft zu
+ 0 ... es trifft nicht zu
+
+*****************************************************************************/
+
+static s4 builtin_isanysubclass (classinfo *sub, classinfo *super)
+{
+ if (super->flags & ACC_INTERFACE) {
+ u4 index = super->index;
+/* if (sub->vftbl == NULL) return 0; */
+ if (index >= sub->vftbl->interfacetablelength) return 0;
+ return ( sub->vftbl->interfacevftbl[index] ) ? 1 : 0;
+ }
+ else {
+ while (sub) {
+ if (sub==super) return 1;
+ sub = sub->super;
+ }
+ return 0;
+ }
+}
+
+
+/****************** Funktion: builtin_instanceof *****************************
+
+ "Uberpr"uft, ob ein Objekt eine Instanz einer Klasse (oder einer davon
+ abgeleiteten Klasse) ist, oder ob die Klasse des Objekts ein Interface
+ implementiert.
+ Return: 1, wenn ja
+ 0, wenn nicht, oder wenn Objekt ein NULL-Zeiger
+
+*****************************************************************************/
+
+s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
+{
+#ifdef DEBUG
+ log_text ("builtin_instanceof called");
+#endif
+
+ if (!obj) return 0;
+ return builtin_isanysubclass (obj->vftbl->class, class);
+}
+
+
+
+/**************** Funktion: builtin_checkcast *******************************
+
+ "Uberpr"uft, ob ein Objekt eine Instanz einer Klasse (oder einer davon
+ abgeleiteten Klasse ist).
+ Unterschied zu builtin_instanceof: Ein NULL-Zeiger ist immer richtig
+ Return: 1, wenn ja, oder wenn Objekt ein NULL-Zeiger
+ 0, wenn nicht
+
+****************************************************************************/
+
+s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
+{
+#ifdef DEBUG
+ log_text ("builtin_checkcast called");
+#endif
+
+ if (!obj) return 1;
+ if ( builtin_isanysubclass (obj->vftbl->class, class) ) {
+ return 1;
+ }
+#if DEBUG
+ printf ("#### checkcast failed ");
+ unicode_display (obj->vftbl->class->name);
+ printf (" -> ");
+ unicode_display (class->name);
+ printf ("\n");
+#endif
+
+ return 0;
+}
+
+
+
+/*********** interne Funktion: builtin_descriptorscompatible ******************
+
+ "uberpr"uft, ob zwei Array-Typdescriptoren compartible sind, d.h.,
+ ob ein Array vom Typ 'desc' gefahrlos einer Variblen vom Typ 'target'
+ zugewiesen werden kann.
+ Return: 1, wenn ja
+ 0, wenn nicht
+
+******************************************************************************/
+
+static s4 builtin_descriptorscompatible
+ (constant_arraydescriptor *desc, constant_arraydescriptor *target)
+{
+ if (desc==target) return 1;
+ if (desc->arraytype != target->arraytype) return 0;
+ switch (target->arraytype) {
+ case ARRAYTYPE_OBJECT:
+ return builtin_isanysubclass (desc->objectclass, target->objectclass);
+ case ARRAYTYPE_ARRAY:
+ return builtin_descriptorscompatible
+ (desc->elementdescriptor, target->elementdescriptor);
+ default: return 1;
+ }
+}
+
+
+
+/******************** Funktion: builtin_checkarraycast ***********************
+
+ "uberpr"uft, ob ein gegebenes Objekt tats"achlich von einem
+ Untertyp des geforderten Arraytyps ist.
+ Dazu muss das Objekt auf jeden Fall ein Array sein.
+ Bei einfachen Arrays (int,short,double,etc.) muss der Typ genau
+ "ubereinstimmen.
+ Bei Arrays von Objekten muss der Elementtyp des tats"achlichen Arrays
+ ein Untertyp (oder der selbe Typ) vom geforderten Elementtyp sein.
+ Bei Arrays vom Arrays (die eventuell wieder Arrays von Arrays
+ sein k"onnen) m"ussen die untersten Elementtypen in der entsprechenden
+ Unterklassenrelation stehen.
+
+ Return: 1, wenn Cast in Ordung ist
+ 0, wenn es nicht geht
+
+ Achtung: ein Cast mit einem NULL-Zeiger geht immer gut.
+
+*****************************************************************************/
+
+s4 builtin_checkarraycast(java_objectheader *o, constant_arraydescriptor *desc)
+{
+ java_arrayheader *a = (java_arrayheader*) o;
+
+ if (!o) return 1;
+ if (o->vftbl->class != class_array) {
+ return 0;
+ }
+
+ if (a->arraytype != desc->arraytype) {
+ return 0;
+ }
+
+ switch (a->arraytype) {
+ case ARRAYTYPE_OBJECT: {
+ java_objectarray *oa = (java_objectarray*) o;
+ return builtin_isanysubclass (oa->elementtype, desc->objectclass);
+ }
+ case ARRAYTYPE_ARRAY: {
+ java_arrayarray *aa = (java_arrayarray*) o;
+ return builtin_descriptorscompatible
+ (aa->elementdescriptor, desc->elementdescriptor);
+ }
+ default:
+ return 1;
+ }
+}
+
+
+s4 builtin_arrayinstanceof
+ (java_objectheader *obj, constant_arraydescriptor *desc)
+{
+ if (!obj) return 1;
+ return builtin_checkarraycast (obj, desc);
+}
+
+
+/************************** exception functions *******************************
+
+******************************************************************************/
+
+java_objectheader *builtin_throw_exception (java_objectheader *exceptionptr) {
+ unicode_display (exceptionptr->vftbl->class->name);
+ printf ("\n");
+ fflush (stdout);
+ return exceptionptr;
+}
+
+
+/******************* Funktion: builtin_canstore *******************************
+
+ "uberpr"uft, ob ein Objekt in einem Array gespeichert werden
+ darf.
+ Return: 1, wenn es geht
+ 0, wenn nicht
+
+******************************************************************************/
+
+
+s4 builtin_canstore (java_objectarray *a, java_objectheader *o)
+{
+ if (!o) return 1;
+
+ switch (a->header.arraytype) {
+ case ARRAYTYPE_OBJECT:
+ if ( ! builtin_checkcast (o, a->elementtype) ) {
+ return 0;
+ }
+ return 1;
+ break;
+
+ case ARRAYTYPE_ARRAY:
+ if ( ! builtin_checkarraycast
+ (o, ((java_arrayarray*)a)->elementdescriptor) ) {
+ return 0;
+ }
+ return 1;
+ break;
+
+ default:
+ panic ("builtin_canstore called with invalid arraytype");
+ return 0;
+ }
+}
+
+
+
+/*****************************************************************************
+ ARRAYOPERATIONEN
+*****************************************************************************/
+
+
+
+/******************** Funktion: builtin_new **********************************
+
+ Legt ein neues Objekt einer Klasse am Heap an.
+ Return: Der Zeiger auf das Objekt, oder NULL, wenn kein Speicher
+ mehr frei ist.
+
+*****************************************************************************/
+
+java_objectheader *builtin_new (classinfo *c)
+{
+ java_objectheader *o;
+
+ o = heap_allocate ( c->instancesize, true, c->finalizer );
+ if (!o) return NULL;
+
+ memset (o, 0, c->instancesize);
+
+ o -> vftbl = c -> vftbl;
+ return o;
+}
+
+
+
+/******************** Funktion: builtin_anewarray ****************************
+
+ Legt ein Array von Zeigern auf Objekte am Heap an.
+ Parameter:
+ size ......... Anzahl der Elemente
+ elementtype .. ein Zeiger auf die classinfo-Struktur des Typs
+ der Elemente
+
+ Return: Zeiger auf das Array, oder NULL (wenn kein Speicher frei)
+
+*****************************************************************************/
+
+java_objectarray *builtin_anewarray (s4 size, classinfo *elementtype)
+{
+ s4 i;
+ java_objectarray *a;
+
+ a = heap_allocate ( sizeof(java_objectarray) + (size-1) * sizeof(void*),
+ true, 0 /* FALSE */ );
+ if (!a) return NULL;
+
+ a -> header.objheader.vftbl = class_array -> vftbl;
+ a -> header.size = size;
+ a -> header.arraytype = ARRAYTYPE_OBJECT;
+ a -> elementtype = elementtype;
+ for (i=0; i<size; i++) a->data[i] = NULL;
+ return a;
+}
+
+
+
+/******************** Funktion: builtin_newarray_array ***********************
+
+ Legt ein Array von Zeigern auf Arrays am Heap an.
+ Paramter: size ......... Anzahl der Elemente
+ elementdesc .. Zeiger auf die Arraybeschreibungs-Struktur f"ur
+ die Element-Arrays.
+
+ Return: Zeiger auf das Array, oder NULL
+
+*****************************************************************************/
+
+java_arrayarray *builtin_newarray_array
+ (s4 size, constant_arraydescriptor *elementdesc)
+{
+ s4 i;
+ java_arrayarray *a;
+
+ a = heap_allocate ( sizeof(java_arrayarray) + (size-1) * sizeof(void*),
+ true, NULL );
+ if (!a) return NULL;
+
+ a -> header.objheader.vftbl = class_array -> vftbl;
+ a -> header.size = size;
+ a -> header.arraytype = ARRAYTYPE_ARRAY;
+ a -> elementdescriptor = elementdesc;
+ for (i=0; i<size; i++) a->data[i] = NULL;
+ return a;
+}
+
+
+/******************** Funktion: builtin_newarray_boolean ************************
+
+ Legt ein Array von Bytes am Heap an, das allerdings als Boolean-Array
+ gekennzeichnet wird (wichtig bei Casts!)
+
+ Return: Zeiger auf das Array, oder NULL
+
+*****************************************************************************/
+
+java_booleanarray *builtin_newarray_boolean (s4 size)
+{
+ java_booleanarray *a;
+
+ a = heap_allocate ( sizeof(java_booleanarray) + (size-1) * sizeof(u1),
+ false, NULL );
+ if (!a) return NULL;
+
+ a -> header.objheader.vftbl = class_array -> vftbl;
+ a -> header.size = size;
+ a -> header.arraytype = ARRAYTYPE_BOOLEAN;
+ memset (a->data, 0, sizeof(u1) * size);
+
+ return a;
+}
+
+/******************** Funktion: builtin_newarray_char ************************
+
+ Legt ein Array von 16-bit-Integers am Heap an.
+ Return: Zeiger auf das Array, oder NULL
+
+*****************************************************************************/
+
+java_chararray *builtin_newarray_char (s4 size)
+{
+ java_chararray *a;
+
+ a = heap_allocate ( sizeof(java_chararray) + (size-1) * sizeof(u2),
+ false, NULL );
+ if (!a) return NULL;
+
+ a -> header.objheader.vftbl = class_array -> vftbl;
+ a -> header.size = size;
+ a -> header.arraytype = ARRAYTYPE_CHAR;
+ memset (a->data, 0, sizeof(u2) * size);
+
+ return a;
+}
+
+
+/******************** Funktion: builtin_newarray_float ***********************
+
+ Legt ein Array von 32-bit-IEEE-float am Heap an.
+ Return: Zeiger auf das Array, oder NULL
+
+*****************************************************************************/
+
+java_floatarray *builtin_newarray_float (s4 size)
+{
+ s4 i;
+ java_floatarray *a;
+
+ a = heap_allocate ( sizeof(java_floatarray) + (size-1) * sizeof(float),
+ false, NULL );
+ if (!a) return NULL;
+
+ a -> header.objheader.vftbl = class_array -> vftbl;
+ a -> header.size = size;
+ a -> header.arraytype = ARRAYTYPE_FLOAT;
+ for (i=0; i<size; i++) a->data[i] = 0.0;
+ return a;
+}
+
+
+/******************** Funktion: builtin_newarray_double ***********************
+
+ Legt ein Array von 64-bit-IEEE-float am Heap an.
+ Return: Zeiger auf das Array, oder NULL
+
+*****************************************************************************/
+
+java_doublearray *builtin_newarray_double (s4 size)
+{
+ s4 i;
+ java_doublearray *a;
+
+ a = heap_allocate ( sizeof(java_doublearray) + (size-1) * sizeof(double),
+ false, NULL );
+ if (!a) return NULL;
+
+ a -> header.objheader.vftbl = class_array -> vftbl;
+ a -> header.size = size;
+ a -> header.arraytype = ARRAYTYPE_DOUBLE;
+ for (i=0; i<size; i++) a->data[i] = 0.0;
+ return a;
+}
+
+
+
+
+/******************** Funktion: builtin_newarray_byte ***********************
+
+ Legt ein Array von 8-bit-Integers am Heap an.
+ Return: Zeiger auf das Array, oder NULL
+
+*****************************************************************************/
+
+java_bytearray *builtin_newarray_byte (s4 size)
+{
+ java_bytearray *a;
+
+ a = heap_allocate ( sizeof(java_bytearray) + (size-1) * sizeof(s1),
+ false, NULL );
+ if (!a) return NULL;
+
+ a -> header.objheader.vftbl = class_array->vftbl;
+ a -> header.size = size;
+ a -> header.arraytype = ARRAYTYPE_BYTE;
+ memset (a->data, 0, sizeof(u1) * size);
+ return a;
+}
+
+
+/******************** Funktion: builtin_newarray_short ***********************
+
+ Legt ein Array von 16-bit-Integers am Heap an.
+ Return: Zeiger auf das Array, oder NULL
+
+*****************************************************************************/
+
+java_shortarray *builtin_newarray_short (s4 size)
+{
+ java_shortarray *a;
+
+ a = heap_allocate ( sizeof(java_shortarray) + (size-1) * sizeof(s2),
+ false, NULL );
+ if (!a) return NULL;
+
+ a -> header.objheader.vftbl = class_array -> vftbl;
+ a -> header.size = size;
+ a -> header.arraytype = ARRAYTYPE_SHORT;
+ memset (a->data, 0, sizeof(s2) * size);
+ return a;
+}
+
+
+/******************** Funktion: builtin_newarray_int ***********************
+
+ Legt ein Array von 32-bit-Integers am Heap an.
+ Return: Zeiger auf das Array, oder NULL
+
+*****************************************************************************/
+
+java_intarray *builtin_newarray_int (s4 size)
+{
+ java_intarray *a;
+
+ a = heap_allocate ( sizeof(java_intarray) + (size-1) * sizeof(s4),
+ false, NULL );
+ if (!a) return NULL;
+
+ a -> header.objheader.vftbl = class_array -> vftbl;
+ a -> header.size = size;
+ a -> header.arraytype = ARRAYTYPE_INT;
+ memset (a->data, 0, sizeof(s4) * size);
+ return a;
+}
+
+
+/******************** Funktion: builtin_newarray_long ***********************
+
+ Legt ein Array von 64-bit-Integers am Heap an.
+ Return: Zeiger auf das Array, oder NULL
+
+*****************************************************************************/
+
+java_longarray *builtin_newarray_long (s4 size)
+{
+ java_longarray *a;
+
+ a = heap_allocate ( sizeof(java_longarray) + (size-1) * sizeof(s8),
+ false, NULL );
+ if (!a) return NULL;
+
+ a -> header.objheader.vftbl = class_array -> vftbl;
+ a -> header.size = size;
+ a -> header.arraytype = ARRAYTYPE_LONG;
+ memset (a->data, 0, sizeof(s8) * size);
+ return a;
+}
+
+
+
+/***************** Funktion: builtin_multianewarray ***************************
+
+ Legt ein mehrdimensionales Array am Heap an.
+ Die Gr"ossen der einzelnen Dimensionen werden in einem Integerarray
+ "ubergeben. Der Typ es zu erzeugenden Arrays wird als
+ Referenz auf eine constant_arraydescriptor - Struktur "ubergeben.
+
+ Return: Ein Zeiger auf das Array, oder NULL, wenn kein Speicher mehr
+ vorhanden ist.
+
+******************************************************************************/
+
+ /* Hilfsfunktion */
+
+static java_arrayheader *multianewarray_part (java_intarray *dims, int thisdim,
+ constant_arraydescriptor *desc)
+{
+ u4 size,i;
+ java_arrayarray *a;
+
+ size = dims -> data[thisdim];
+
+ if (thisdim == (dims->header.size-1)) {
+ /* letzte Dimension schon erreicht */
+
+ switch (desc -> arraytype) {
+ case ARRAYTYPE_BOOLEAN:
+ return (java_arrayheader*) builtin_newarray_boolean (size);
+ case ARRAYTYPE_CHAR:
+ return (java_arrayheader*) builtin_newarray_char (size);
+ case ARRAYTYPE_FLOAT:
+ return (java_arrayheader*) builtin_newarray_float (size);
+ case ARRAYTYPE_DOUBLE:
+ return (java_arrayheader*) builtin_newarray_double (size);
+ case ARRAYTYPE_BYTE:
+ return (java_arrayheader*) builtin_newarray_byte (size);
+ case ARRAYTYPE_SHORT:
+ return (java_arrayheader*) builtin_newarray_short (size);
+ case ARRAYTYPE_INT:
+ return (java_arrayheader*) builtin_newarray_int (size);
+ case ARRAYTYPE_LONG:
+ return (java_arrayheader*) builtin_newarray_long (size);
+ case ARRAYTYPE_OBJECT:
+ return (java_arrayheader*) builtin_anewarray (size, desc->objectclass);
+
+ case ARRAYTYPE_ARRAY:
+ return (java_arrayheader*) builtin_newarray_array (size, desc->elementdescriptor);
+
+ default: panic ("Invalid arraytype in multianewarray");
+ }
+ }
+
+ /* wenn letzte Dimension noch nicht erreicht wurde */
+
+ if (desc->arraytype != ARRAYTYPE_ARRAY)
+ panic ("multianewarray with too many dimensions");
+
+ a = builtin_newarray_array (size, desc->elementdescriptor);
+ if (!a) return NULL;
+
+ for (i=0; i<size; i++) {
+ java_arrayheader *ea =
+ multianewarray_part (dims, thisdim+1, desc->elementdescriptor);
+ if (!ea) return NULL;
+
+ a -> data[i] = ea;
+ }
+
+ return (java_arrayheader*) a;
+}
+
+
+java_arrayheader *builtin_multianewarray (java_intarray *dims,
+ constant_arraydescriptor *desc)
+{
+ return multianewarray_part (dims, 0, desc);
+}
+
+
+static java_arrayheader *nmultianewarray_part (int n, long *dims, int thisdim,
+ constant_arraydescriptor *desc)
+{
+ int size, i;
+ java_arrayarray *a;
+
+ size = (int) dims[thisdim];
+
+ if (thisdim == (n - 1)) {
+ /* letzte Dimension schon erreicht */
+
+ switch (desc -> arraytype) {
+ case ARRAYTYPE_BOOLEAN:
+ return (java_arrayheader*) builtin_newarray_boolean(size);
+ case ARRAYTYPE_CHAR:
+ return (java_arrayheader*) builtin_newarray_char(size);
+ case ARRAYTYPE_FLOAT:
+ return (java_arrayheader*) builtin_newarray_float(size);
+ case ARRAYTYPE_DOUBLE:
+ return (java_arrayheader*) builtin_newarray_double(size);
+ case ARRAYTYPE_BYTE:
+ return (java_arrayheader*) builtin_newarray_byte(size);
+ case ARRAYTYPE_SHORT:
+ return (java_arrayheader*) builtin_newarray_short(size);
+ case ARRAYTYPE_INT:
+ return (java_arrayheader*) builtin_newarray_int(size);
+ case ARRAYTYPE_LONG:
+ return (java_arrayheader*) builtin_newarray_long(size);
+ case ARRAYTYPE_OBJECT:
+ return (java_arrayheader*) builtin_anewarray(size,
+ desc->objectclass);
+ case ARRAYTYPE_ARRAY:
+ return (java_arrayheader*) builtin_newarray_array(size,
+ desc->elementdescriptor);
+
+ default: panic ("Invalid arraytype in multianewarray");
+ }
+ }
+
+ /* wenn letzte Dimension noch nicht erreicht wurde */
+
+ if (desc->arraytype != ARRAYTYPE_ARRAY)
+ panic ("multianewarray with too many dimensions");
+
+ a = builtin_newarray_array(size, desc->elementdescriptor);
+ if (!a) return NULL;
+
+ for (i = 0; i < size; i++) {
+ java_arrayheader *ea =
+ nmultianewarray_part(n, dims, thisdim + 1, desc->elementdescriptor);
+ if (!ea) return NULL;
+
+ a -> data[i] = ea;
+ }
+
+ return (java_arrayheader*) a;
+}
+
+
+java_arrayheader *builtin_nmultianewarray (int size,
+ constant_arraydescriptor *desc, long *dims)
+{
+ (void) builtin_newarray_int(size); /* for compatibility with -old */
+ return nmultianewarray_part (size, dims, 0, desc);
+}
+
+
+
+
+/************************* Funktion: builtin_aastore *************************
+
+ speichert eine Referenz auf ein Objekt in einem Object-Array oder
+ in einem Array-Array.
+ Dabei wird allerdings vorher "uberpr"uft, ob diese Operation
+ zul"assig ist.
+
+ Return: 1, wenn alles OK ist
+ 0, wenn dieses Objekt nicht in dieses Array gespeichert werden
+ darf
+
+*****************************************************************************/
+
+s4 builtin_aastore (java_objectarray *a, s4 index, java_objectheader *o)
+{
+ if (builtin_canstore(a,o)) {
+ a->data[index] = o;
+ return 1;
+ }
+ return 0;
+}
+
+
+
+
+
+
+/*****************************************************************************
+ METHODEN-PROTOKOLLIERUNG
+
+ Verschiedene Funktionen, mit denen eine Meldung ausgegeben werden
+ kann, wann immer Methoden aufgerufen oder beendet werden.
+ (f"ur Debug-Zwecke)
+
+*****************************************************************************/
+
+
+u4 methodindent=0;
+
+java_objectheader *builtin_trace_exception (java_objectheader *exceptionptr,
+ methodinfo *method, int *pos, int noindent) {
+
+ if (!noindent)
+ methodindent--;
+ if (verbose || runverbose) {
+ printf("Exception ");
+ unicode_display (exceptionptr->vftbl->class->name);
+ printf(" thrown in ");
+ if (method) {
+ unicode_display (method->class->name);
+ printf(".");
+ unicode_display (method->name);
+ if (method->flags & ACC_SYNCHRONIZED)
+ printf("(SYNC)");
+ else
+ printf("(NOSYNC)");
+ printf("(%p) at position %p\n", method->entrypoint, pos);
+ }
+ else
+ printf("call_java_method\n");
+ fflush (stdout);
+ }
+ return exceptionptr;
+}
+
+
+void builtin_trace_args(long a0, long a1, long a2, long a3, long a4, long a5,
+ methodinfo *method)
+{
+ sprintf (logtext, " ");
+ sprintf (logtext+methodindent, "called: ");
+ unicode_sprint (logtext+strlen(logtext), method->class->name);
+ sprintf (logtext+strlen(logtext), ".");
+ unicode_sprint (logtext+strlen(logtext), method->name);
+ unicode_sprint (logtext+strlen(logtext), method->descriptor);
+ sprintf (logtext+strlen(logtext), "(");
+ switch (method->paramcount) {
+ case 6:
+ sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
+ a0, a1, a2, a3, a4, a5);
+ break;
+ case 5:
+ sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
+ a0, a1, a2, a3, a4);
+ break;
+ case 4:
+ sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
+ a0, a1, a2, a3);
+ break;
+ case 3:
+ sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0, a1, a2);
+ break;
+ case 2:
+ sprintf(logtext+strlen(logtext), "%lx, %lx", a0, a1);
+ break;
+ case 1:
+ sprintf(logtext+strlen(logtext), "%lx", a0);
+ break;
+ }
+ sprintf (logtext+strlen(logtext), ")");
+
+ dolog ();
+ methodindent++;
+}
+
+void builtin_displaymethodstart(methodinfo *method)
+{
+ sprintf (logtext, " ");
+ sprintf (logtext+methodindent, "called: ");
+ unicode_sprint (logtext+strlen(logtext), method->class->name);
+ sprintf (logtext+strlen(logtext), ".");
+ unicode_sprint (logtext+strlen(logtext), method->name);
+ unicode_sprint (logtext+strlen(logtext), method->descriptor);
+ dolog ();
+ methodindent++;
+}
+
+void builtin_displaymethodstop(methodinfo *method, long l, double d)
+{
+ methodindent--;
+ sprintf (logtext, " ");
+ sprintf (logtext+methodindent, "finished: ");
+ unicode_sprint (logtext+strlen(logtext), method->class->name);
+ sprintf (logtext+strlen(logtext), ".");
+ unicode_sprint (logtext+strlen(logtext), method->name);
+ unicode_sprint (logtext+strlen(logtext), method->descriptor);
+ switch (method->returntype) {
+ case TYPE_INT:
+ case TYPE_LONG:
+ sprintf (logtext+strlen(logtext), "->%ld", l);
+ break;
+ case TYPE_FLOAT:
+ case TYPE_DOUBLE:
+ sprintf (logtext+strlen(logtext), "->%g", d);
+ break;
+ case TYPE_ADDRESS:
+ sprintf (logtext+strlen(logtext), "->%p", (void*) l);
+ break;
+ }
+ dolog ();
+}
+
+void builtin_displaymethodexception(methodinfo *method)
+{
+ sprintf (logtext, " ");
+ sprintf (logtext+methodindent, "exception abort: ");
+ unicode_sprint (logtext+strlen(logtext), method->class->name);
+ sprintf (logtext+strlen(logtext), ".");
+ unicode_sprint (logtext+strlen(logtext), method->name);
+ unicode_sprint (logtext+strlen(logtext), method->descriptor);
+ dolog ();
+}
+
+
+/****************************************************************************
+ SYNCHRONIZATION FUNCTIONS
+*****************************************************************************/
+
+/*
+ * Lock the mutex of an object.
+ */
+#ifdef USE_THREADS
+void
+internal_lock_mutex_for_object (java_objectheader *object)
+{
+ mutexHashEntry *entry;
+ int hashValue;
+
+ assert(object != 0);
+
+ hashValue = MUTEX_HASH_VALUE(object);
+ entry = &mutexHashTable[hashValue];
+
+ if (entry->object != 0)
+ {
+ if (entry->mutex.count == 0 && entry->conditionCount == 0)
+ {
+ entry->object = 0;
+ entry->mutex.holder = 0;
+ entry->mutex.count = 0;
+ entry->mutex.muxWaiters = 0;
+ }
+ else
+ {
+ while (entry->next != 0 && entry->object != object)
+ entry = entry->next;
+
+ if (entry->object != object)
+ {
+ entry->next = firstFreeOverflowEntry;
+ firstFreeOverflowEntry = firstFreeOverflowEntry->next;
+
+ entry = entry->next;
+ entry->object = 0;
+ entry->next = 0;
+ assert(entry->conditionCount == 0);
+ }
+ }
+ }
+ else
+ {
+ entry->mutex.holder = 0;
+ entry->mutex.count = 0;
+ entry->mutex.muxWaiters = 0;
+ }
+
+ if (entry->object == 0)
+ entry->object = object;
+
+ internal_lock_mutex(&entry->mutex);
+}
+#endif
+
+
+/*
+ * Unlocks the mutex of an object.
+ */
+#ifdef USE_THREADS
+void
+internal_unlock_mutex_for_object (java_objectheader *object)
+{
+ int hashValue;
+ mutexHashEntry *entry;
+
+ hashValue = MUTEX_HASH_VALUE(object);
+ entry = &mutexHashTable[hashValue];
+
+ if (entry->object == object)
+ internal_unlock_mutex(&entry->mutex);
+ else
+ {
+ while (entry->next != 0 && entry->next->object != object)
+ entry = entry->next;
+
+ assert(entry->next != 0);
+
+ internal_unlock_mutex(&entry->next->mutex);
+
+ if (entry->next->mutex.count == 0 && entry->conditionCount == 0)
+ {
+ mutexHashEntry *unlinked = entry->next;
+
+ entry->next = unlinked->next;
+ unlinked->next = firstFreeOverflowEntry;
+ firstFreeOverflowEntry = unlinked;
+ }
+ }
+}
+#endif
+
+void
+builtin_monitorenter (java_objectheader *o)
+{
+#ifdef USE_THREADS
+ int hashValue;
+
+ assert(blockInts == 0);
+
+ ++blockInts;
+
+ hashValue = MUTEX_HASH_VALUE(o);
+ if (mutexHashTable[hashValue].object == o
+ && mutexHashTable[hashValue].mutex.holder == currentThread)
+ ++mutexHashTable[hashValue].mutex.count;
+ else
+ internal_lock_mutex_for_object(o);
+
+ --blockInts;
+
+ assert(blockInts == 0);
+#endif
+}
+
+void builtin_monitorexit (java_objectheader *o)
+{
+#ifdef USE_THREADS
+ int hashValue;
+
+ assert(blockInts == 0);
+
+ ++blockInts;
+
+ hashValue = MUTEX_HASH_VALUE(o);
+ if (mutexHashTable[hashValue].object == o)
+ {
+ if (mutexHashTable[hashValue].mutex.count == 1
+ && mutexHashTable[hashValue].mutex.muxWaiters != 0)
+ internal_unlock_mutex_for_object(o);
+ else
+ --mutexHashTable[hashValue].mutex.count;
+ }
+ else
+ internal_unlock_mutex_for_object(o);
+
+ --blockInts;
+
+ assert(blockInts == 0);
+#endif
+}
+
+
+/*****************************************************************************
+ DIVERSE HILFSFUNKTIONEN
+*****************************************************************************/
+
+
+
+/*********** Funktionen f"ur die Integerdivision *****************************
+
+ Auf manchen Systemen (z.B. DEC ALPHA) wird durch die CPU keine Integer-
+ division unterst"utzt.
+ Daf"ur gibt es dann diese Hilfsfunktionen
+
+******************************************************************************/
+
+s4 builtin_idiv (s4 a, s4 b) { return a/b; }
+s4 builtin_irem (s4 a, s4 b) { return a%b; }
+
+
+/************** Funktionen f"ur Long-Arithmetik *******************************
+
+ Auf Systemen, auf denen die CPU keine 64-Bit-Integers unterst"utzt,
+ werden diese Funktionen gebraucht
+
+******************************************************************************/
+
+
+s8 builtin_ladd (s8 a, s8 b)
+{
+#if U8_AVAILABLE
+ return a+b;
+#else
+ return builtin_i2l(0);
+#endif
+}
+
+s8 builtin_lsub (s8 a, s8 b)
+{
+#if U8_AVAILABLE
+ return a-b;
+#else
+ return builtin_i2l(0);
+#endif
+}
+
+s8 builtin_lmul (s8 a, s8 b)
+{
+#if U8_AVAILABLE
+ return a*b;
+#else
+ return builtin_i2l(0);
+#endif
+}
+
+s8 builtin_ldiv (s8 a, s8 b)
+{
+#if U8_AVAILABLE
+ return a/b;
+#else
+ return builtin_i2l(0);
+#endif
+}
+
+s8 builtin_lrem (s8 a, s8 b)
+{
+#if U8_AVAILABLE
+ return a%b;
+#else
+ return builtin_i2l(0);
+#endif
+}
+
+s8 builtin_lshl (s8 a, s4 b)
+{
+#if U8_AVAILABLE
+ return a<<(b&63);
+#else
+ return builtin_i2l(0);
+#endif
+}
+
+s8 builtin_lshr (s8 a, s4 b)
+{
+#if U8_AVAILABLE
+ return a>>(b&63);
+#else
+ return builtin_i2l(0);
+#endif
+}
+
+s8 builtin_lushr (s8 a, s4 b)
+{
+#if U8_AVAILABLE
+ return ((u8)a)>>(b&63);
+#else
+ return builtin_i2l(0);
+#endif
+}
+
+s8 builtin_land (s8 a, s8 b)
+{
+#if U8_AVAILABLE
+ return a&b;
+#else
+ return builtin_i2l(0);
+#endif
+}
+
+s8 builtin_lor (s8 a, s8 b)
+{
+#if U8_AVAILABLE
+ return a|b;
+#else
+ return builtin_i2l(0);
+#endif
+}
+
+s8 builtin_lxor (s8 a, s8 b)
+{
+#if U8_AVAILABLE
+ return a^b;
+#else
+ return builtin_i2l(0);
+#endif
+}
+
+s8 builtin_lneg (s8 a)
+{
+#if U8_AVAILABLE
+ return -a;
+#else
+ return builtin_i2l(0);
+#endif
+}
+
+s4 builtin_lcmp (s8 a, s8 b)
+{
+#if U8_AVAILABLE
+ if (a<b) return -1;
+ if (a>b) return 1;
+ return 0;
+#else
+ return 0;
+#endif
+}
+
+
+
+
+
+/*********** Funktionen f"ur die Floating-Point-Operationen ******************/
+
+float builtin_fadd (float a, float b)
+{
+ if (isnanf(a)) return FLT_NAN;
+ if (isnanf(b)) return FLT_NAN;
+ if (finitef(a)) {
+ if (finitef(b)) return a+b;
+ else return b;
+ }
+ else {
+ if (finitef(b)) return a;
+ else {
+ if (copysignf(1.0, a)==copysignf(1.0, b)) return a;
+ else return FLT_NAN;
+ }
+ }
+}
+
+float builtin_fsub (float a, float b)
+{
+ return builtin_fadd (a, builtin_fneg(b));
+}
+
+float builtin_fmul (float a, float b)
+{
+ if (isnanf(a)) return FLT_NAN;
+ if (isnanf(b)) return FLT_NAN;
+ if (finitef(a)) {
+ if (finitef(b)) return a*b;
+ else {
+ if (a==0) return FLT_NAN;
+ else return copysignf(b, copysignf(1.0, b)*a);
+ }
+ }
+ else {
+ if (finitef(b)) {
+ if (b==0) return FLT_NAN;
+ else return copysignf(a, copysignf(1.0, a)*b);
+ }
+ else {
+ return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
+ }
+ }
+}
+
+float builtin_fdiv (float a, float b)
+{
+ if (finitef(a) && finitef(b)) {
+ if (b != 0)
+ return a / b;
+ else {
+ if (a > 0)
+ return FLT_POSINF;
+ else if (a < 0)
+ return FLT_NEGINF;
+ }
+ }
+ return FLT_NAN;
+}
+
+float builtin_frem (float a, float b)
+{
+
+/* return (float) builtin_drem((double) a, (double) b); */
+
+ float f;
+
+ if (finite((double) a) && finite((double) b)) {
+ f = a / b;
+ if (finite((double) f))
+ return fmodf(a, b);
+ return FLT_NAN;
+ }
+ if (isnan((double) b))
+ return FLT_NAN;
+ if (finite((double) a))
+ return a;
+ return FLT_NAN;
+
+/* float f;
+
+ if (finitef(a) && finitef(b)) {
+ f = a / b;
+ if (finitef(f))
+ return a - floorf(f) * b;
+ return FLT_NAN;
+ }
+ if (isnanf(b))
+ return FLT_NAN;
+ if (finitef(a))
+ return a;
+ return FLT_NAN; */
+}
+
+
+float builtin_fneg (float a)
+{
+ if (isnanf(a)) return a;
+ else {
+ if (finitef(a)) return -a;
+ else return copysignf(a,-copysignf(1.0, a));
+ }
+}
+
+s4 builtin_fcmpl (float a, float b)
+{
+ if (isnanf(a)) return -1;
+ if (isnanf(b)) return -1;
+ if (!finitef(a) || !finitef(b)) {
+ a = finitef(a) ? 0 : copysignf(1.0, a);
+ b = finitef(b) ? 0 : copysignf(1.0, b);
+ }
+ if (a>b) return 1;
+ if (a==b) return 0;
+ return -1;
+}
+
+s4 builtin_fcmpg (float a, float b)
+{
+ if (isnanf(a)) return 1;
+ if (isnanf(b)) return 1;
+ if (!finitef(a) || !finitef(b)) {
+ a = finitef(a) ? 0 : copysignf(1.0, a);
+ b = finitef(b) ? 0 : copysignf(1.0, b);
+ }
+ if (a>b) return 1;
+ if (a==b) return 0;
+ return -1;
+}
+
+
+
+/*********** Funktionen f"ur doppelt genaue Fliesskommazahlen ***************/
+
+double builtin_dadd (double a, double b)
+{
+ if (isnan(a)) return DBL_NAN;
+ if (isnan(b)) return DBL_NAN;
+ if (finite(a)) {
+ if (finite(b)) return a+b;
+ else return b;
+ }
+ else {
+ if (finite(b)) return a;
+ else {
+ if (copysign(1.0, a)==copysign(1.0, b)) return a;
+ else return DBL_NAN;
+ }
+ }
+}
+
+double builtin_dsub (double a, double b)
+{
+ return builtin_dadd (a, builtin_dneg(b));
+}
+
+double builtin_dmul (double a, double b)
+{
+ if (isnan(a)) return DBL_NAN;
+ if (isnan(b)) return DBL_NAN;
+ if (finite(a)) {
+ if (finite(b)) return a*b;
+ else {
+ if (a==0) return DBL_NAN;
+ else return copysign(b, copysign(1.0, b)*a);
+ }
+ }
+ else {
+ if (finite(b)) {
+ if (b==0) return DBL_NAN;
+ else return copysign(a, copysign(1.0, a)*b);
+ }
+ else {
+ return copysign(a, copysign(1.0, a)*copysign(1.0, b));
+ }
+ }
+}
+
+double builtin_ddiv (double a, double b)
+{
+ if (finite(a) && finite(b)) {
+ if (b != 0)
+ return a / b;
+ else {
+ if (a > 0)
+ return DBL_POSINF;
+ else if (a < 0)
+ return DBL_NEGINF;
+ }
+ }
+ return DBL_NAN;
+}
+
+double builtin_drem (double a, double b)
+{
+ double d;
+
+ if (finite(a) && finite(b)) {
+ d = a / b;
+ if (finite(d)) {
+ if ((d < 1.0) && (d > 0.0))
+ return a;
+ return fmod(a, b);
+ }
+ return DBL_NAN;
+ }
+ if (isnan(b))
+ return DBL_NAN;
+ if (finite(a))
+ return a;
+ return DBL_NAN;
+}
+
+double builtin_dneg (double a)
+{
+ if (isnan(a)) return a;
+ else {
+ if (finite(a)) return -a;
+ else return copysign(a,-copysign(1.0, a));
+ }
+}
+
+s4 builtin_dcmpl (double a, double b)
+{
+ if (isnan(a)) return -1;
+ if (isnan(b)) return -1;
+ if (!finite(a) || !finite(b)) {
+ a = finite(a) ? 0 : copysign(1.0, a);
+ b = finite(b) ? 0 : copysign(1.0, b);
+ }
+ if (a>b) return 1;
+ if (a==b) return 0;
+ return -1;
+}
+
+s4 builtin_dcmpg (double a, double b)
+{
+ if (isnan(a)) return 1;
+ if (isnan(b)) return 1;
+ if (!finite(a) || !finite(b)) {
+ a = finite(a) ? 0 : copysign(1.0, a);
+ b = finite(b) ? 0 : copysign(1.0, b);
+ }
+ if (a>b) return 1;
+ if (a==b) return 0;
+ return -1;
+}
+
+
+/*********************** Umwandlungsoperationen ****************************/
+
+s8 builtin_i2l (s4 i)
+{
+#if U8_AVAILABLE
+ return i;
+#else
+ s8 v; v.high = 0; v.low=i; return v;
+#endif
+}
+
+float builtin_i2f (s4 a)
+{
+float f = (float) a;
+return f;
+}
+
+double builtin_i2d (s4 a)
+{
+double d = (double) a;
+return d;
+}
+
+
+s4 builtin_l2i (s8 l)
+{
+#if U8_AVAILABLE
+ return (s4) l;
+#else
+ return l.low;
+#endif
+}
+
+float builtin_l2f (s8 a)
+{
+#if U8_AVAILABLE
+ float f = (float) a;
+ return f;
+#else
+ return 0.0;
+#endif
+}
+
+double builtin_l2d (s8 a)
+{
+#if U8_AVAILABLE
+ double d = (double) a;
+ return d;
+#else
+ return 0.0;
+#endif
+}
+
+
+s4 builtin_f2i(float a)
+{
+
+return builtin_d2i((double) a);
+
+/* float f;
+
+ if (isnanf(a))
+ return 0;
+ if (finitef(a)) {
+ if (a > 2147483647)
+ return 2147483647;
+ if (a < (-2147483648))
+ return (-2147483648);
+ return (s4) a;
+ }
+ f = copysignf((float) 1.0, a);
+ if (f > 0)
+ return 2147483647;
+ return (-2147483648); */
+}
+
+
+s8 builtin_f2l (float a)
+{
+
+return builtin_d2l((double) a);
+
+/* float f;
+
+ if (finitef(a)) {
+ if (a > 9223372036854775807L)
+ return 9223372036854775807L;
+ if (a < (-9223372036854775808L))
+ return (-9223372036854775808L);
+ return (s8) a;
+ }
+ if (isnanf(a))
+ return 0;
+ f = copysignf((float) 1.0, a);
+ if (f > 0)
+ return 9223372036854775807L;
+ return (-9223372036854775808L); */
+}
+
+
+double builtin_f2d (float a)
+{
+ if (finitef(a)) return (double) a;
+ else {
+ if (isnanf(a)) return DBL_NAN;
+ else return copysign(DBL_POSINF, (double) copysignf(1.0, a) );
+ }
+}
+
+
+s4 builtin_d2i (double a)
+{
+ double d;
+
+ if (finite(a)) {
+ if (a >= 2147483647)
+ return 2147483647;
+ if (a <= (-2147483648))
+ return (-2147483648);
+ return (s4) a;
+ }
+ if (isnan(a))
+ return 0;
+ d = copysign(1.0, a);
+ if (d > 0)
+ return 2147483647;
+ return (-2147483648);
+}
+
+
+s8 builtin_d2l (double a)
+{
+ double d;
+
+ if (finite(a)) {
+ if (a >= 9223372036854775807L)
+ return 9223372036854775807L;
+ if (a <= (-9223372036854775807L-1))
+ return (-9223372036854775807L-1);
+ return (s8) a;
+ }
+ if (isnan(a))
+ return 0;
+ d = copysign(1.0, a);
+ if (d > 0)
+ return 9223372036854775807L;
+ return (-9223372036854775807L-1);
+}
+
+
+float builtin_d2f (double a)
+{
+ if (finite(a)) return (float) a;
+ else {
+ if (isnan(a)) return FLT_NAN;
+ else return copysignf (FLT_POSINF, (float) copysign(1.0, a));
+ }
+}
+
--- /dev/null
+/****************************** builtin.h **************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Contains the prototypes for the functions of file builtin.c which has
+ a more detailed description.
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1996/11/14
+
+*******************************************************************************/
+
+
+/***************************** Prototypes *************************************/
+
+typedef struct builtin_descriptor {
+ functionptr bptr;
+ char *name;
+ } builtin_descriptor;
+
+extern builtin_descriptor builtin_desc[];
+
+s4 builtin_instanceof(java_objectheader *obj, classinfo *class);
+s4 builtin_checkcast(java_objectheader *obj, classinfo *class);
+s4 new_builtin_checkcast(java_objectheader *obj, classinfo *class);
+s4 builtin_arrayinstanceof
+ (java_objectheader *obj, constant_arraydescriptor *desc);
+s4 builtin_checkarraycast
+ (java_objectheader *obj, constant_arraydescriptor *desc);
+s4 new_builtin_checkarraycast
+ (java_objectheader *obj, constant_arraydescriptor *desc);
+
+java_objectheader *builtin_throw_exception (java_objectheader *exception);
+java_objectheader *builtin_trace_exception (java_objectheader *exceptionptr,
+ methodinfo *method, int *pos, int noindent);
+
+java_objectheader *builtin_new (classinfo *c);
+
+
+java_objectarray *builtin_anewarray (s4 size, classinfo *elementtype);
+java_arrayarray *builtin_newarray_array
+ (s4 size, constant_arraydescriptor *elementdesc);
+java_booleanarray *builtin_newarray_boolean (s4 size);
+java_chararray *builtin_newarray_char (s4 size);
+java_floatarray *builtin_newarray_float (s4 size);
+java_doublearray *builtin_newarray_double (s4 size);
+java_bytearray *builtin_newarray_byte (s4 size);
+java_shortarray *builtin_newarray_short (s4 size);
+java_intarray *builtin_newarray_int (s4 size);
+java_longarray *builtin_newarray_long (s4 size);
+java_arrayheader *builtin_multianewarray (java_intarray *dims,
+ constant_arraydescriptor *desc);
+java_arrayheader *builtin_nmultianewarray (int size,
+ constant_arraydescriptor *desc, long *dims);
+
+s4 builtin_canstore (java_objectarray *a, java_objectheader *o);
+s4 builtin_aastore (java_objectarray *a, s4 index, java_objectheader *o);
+void new_builtin_aastore (java_objectarray *a, s4 index, java_objectheader *o);
+
+void builtin_trace_args(long a0, long a1, long a2, long a3, long a4, long a5, methodinfo *method);
+void builtin_displaymethodstart(methodinfo *method);
+void builtin_displaymethodstop(methodinfo *method, long l, double d);
+/* void builtin_displaymethodstop(methodinfo *method); */
+void builtin_displaymethodexception(methodinfo *method);
+
+void builtin_monitorenter (java_objectheader *o);
+void new_builtin_monitorenter (java_objectheader *o);
+void builtin_monitorexit (java_objectheader *o);
+void new_builtin_monitorexit (java_objectheader *o);
+
+s4 builtin_idiv (s4 a, s4 b);
+s4 new_builtin_idiv (s4 a, s4 b);
+s4 builtin_irem (s4 a, s4 b);
+s4 new_builtin_irem (s4 a, s4 b);
+
+s8 builtin_ladd (s8 a, s8 b);
+s8 builtin_lsub (s8 a, s8 b);
+s8 builtin_lmul (s8 a, s8 b);
+s8 builtin_ldiv (s8 a, s8 b);
+s8 new_builtin_ldiv (s8 a, s8 b);
+s8 builtin_lrem (s8 a, s8 b);
+s8 new_builtin_lrem (s8 a, s8 b);
+s8 builtin_lshl (s8 a, s4 b);
+s8 builtin_lshr (s8 a, s4 b);
+s8 builtin_lushr (s8 a, s4 b);
+s8 builtin_land (s8 a, s8 b);
+s8 builtin_lor (s8 a, s8 b);
+s8 builtin_lxor (s8 a, s8 b);
+s8 builtin_lneg (s8 a);
+s4 builtin_lcmp (s8 a, s8 b);
+
+float builtin_fadd (float a, float b);
+float builtin_fsub (float a, float b);
+float builtin_fmul (float a, float b);
+float builtin_fdiv (float a, float b);
+float builtin_frem (float a, float b);
+float builtin_fneg (float a);
+s4 builtin_fcmpl (float a, float b);
+s4 builtin_fcmpg (float a, float b);
+
+double builtin_dadd (double a, double b);
+double builtin_dsub (double a, double b);
+double builtin_dmul (double a, double b);
+double builtin_ddiv (double a, double b);
+double builtin_drem (double a, double b);
+double builtin_dneg (double a);
+s4 builtin_dcmpl (double a, double b);
+s4 builtin_dcmpg (double a, double b);
+
+s8 builtin_i2l (s4 i);
+float builtin_i2f (s4 i);
+double builtin_i2d (s4 i);
+s4 builtin_l2i (s8 l);
+float builtin_l2f (s8 l);
+double builtin_l2d (s8 l);
+s4 builtin_f2i (float a);
+s8 builtin_f2l (float a);
+double builtin_f2d (float a);
+s4 builtin_d2i (double a);
+s8 builtin_d2l (double a);
+float builtin_d2f (double a);
+
--- /dev/null
+/****************************** global.h ***************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Contains global definitions which are used in the whole program, includes
+ some files and contains global used macros.
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+ Chages: Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
+ Mark Probst EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1997/10/28
+
+*******************************************************************************/
+
+#ifndef __global_h_
+#define __global_h_ /* schani */
+
+#define STATISTICS /* andi */
+
+/***************************** standard includes ******************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "toolbox/memory.h"
+#include "toolbox/chain.h"
+#include "toolbox/list.h"
+#include "toolbox/loging.h"
+
+
+/**************************** system dependent types **************************/
+
+#include "sysdep/types.h"
+
+
+/**************************** additional data types ***************************/
+
+typedef void *voidptr; /* generic pointer */
+
+
+typedef u1 bool; /* boolean data type */
+
+#define true 1
+#define false 0
+
+typedef void (*functionptr) (); /* generic function pointer */
+
+
+#define MAX_ALIGN 8 /* most generic alignment for JavaVM values */
+
+
+/**************************** shutdown function *******************************/
+
+void cacao_shutdown(s4 status);
+
+
+/**************************** basic data types ********************************/
+
+#define TYPE_INT 0 /* the JavaVM types must numbered in the */
+#define TYPE_LONG 1 /* same order as the ICMD_Ixxx to ICMD_Axxx */
+#define TYPE_FLOAT 2 /* instructions (LOAD and STORE) */
+#define TYPE_DOUBLE 3 /* integer, long, float, double, address */
+#define TYPE_ADDRESS 4 /* all other types can be numbered arbitrarily*/
+
+#define TYPE_VOID 10
+
+
+/**************************** Java class file constants ***********************/
+
+#define MAGIC 0xcafebabe
+#define MINOR_VERSION 3
+#define MAJOR_VERSION 45
+
+#define CONSTANT_Class 7
+#define CONSTANT_Fieldref 9
+#define CONSTANT_Methodref 10
+#define CONSTANT_InterfaceMethodref 11
+#define CONSTANT_String 8
+#define CONSTANT_Integer 3
+#define CONSTANT_Float 4
+#define CONSTANT_Long 5
+#define CONSTANT_Double 6
+#define CONSTANT_NameAndType 12
+#define CONSTANT_Utf8 1
+
+#define CONSTANT_Arraydescriptor 13
+#define CONSTANT_UNUSED 0
+
+
+#define ACC_PUBLIC 0x0001
+#define ACC_PRIVATE 0x0002
+#define ACC_PROTECTED 0x0004
+#define ACC_STATIC 0x0008
+#define ACC_FINAL 0x0010
+#define ACC_SYNCHRONIZED 0x0020
+#define ACC_VOLATILE 0x0040
+#define ACC_TRANSIENT 0x0080
+#define ACC_NATIVE 0x0100
+#define ACC_INTERFACE 0x0200
+#define ACC_ABSTRACT 0x0400
+
+
+
+/**************************** resolve typedef-cycles **************************/
+
+typedef struct unicode unicode;
+typedef struct classinfo classinfo;
+typedef struct vftbl vftbl;
+typedef u1* methodptr;
+
+
+/********************** data structures of UNICODE symbol *********************/
+
+struct unicode {
+ unicode *hashlink; /* externe Verkettung f"ur die unicode-Hashtabelle */
+ u4 key; /* Hash-Schl"ussel (h"angt nur vom Text ab) */
+ int length; /* L"ange des Textes */
+ u2 *text; /* Zeiger auf den Text (jeder Buchstabe 16 Bit) */
+ classinfo *class; /* gegebenenfalls Referenz auf die Klasse dieses
+ Namens (oder NULL, wenn es keine solche gibt) */
+ struct java_objectheader *string;
+ /* gegebenenfalls Referenz auf einen konstanten
+ String mit dem entsprechenden Wert */
+ };
+
+ /* Alle Unicode-Symbole werden in einer einzigen globalen Tabelle
+ (Hashtabelle) verwaltet, jedes Symbol wird nur einmal angelegt.
+ -> Speicherersparnis, und "Uberpr"ufung auf Gleichheit durch einfachen
+ Zeigervergleich */
+
+
+/************ data structures of remaining constant pool entries **************/
+
+
+typedef struct {
+ classinfo *class;
+ unicode *name;
+ unicode *descriptor;
+ } constant_FMIref;
+
+
+typedef struct {
+ s4 value;
+ } constant_integer;
+
+typedef struct {
+ float value;
+ } constant_float;
+
+typedef struct {
+ s8 value;
+ } constant_long;
+
+typedef struct {
+ double value;
+ } constant_double;
+
+
+typedef struct {
+ unicode *name;
+ unicode *descriptor;
+ } constant_nameandtype;
+
+
+typedef struct constant_arraydescriptor {
+ int arraytype;
+ classinfo *objectclass;
+ struct constant_arraydescriptor *elementdescriptor;
+ } constant_arraydescriptor;
+
+ /* Mit einem Arraydescriptor kann ein Array-Typ dargestellt werden.
+ Bei normalen Arrays (z.B. Array von Bytes,...) gen"ugt dazu,
+ dass das Feld arraytype die entsprechende Kennzahl enth"alt
+ (z.B. ARRAYTYPE_BYTE).
+ Bei Arrays von Objekten (arraytype=ARRAYTYPE_OBJECT) muss das
+ Feld objectclass auf die Klassenstruktur der m"oglichen
+ Element-Objekte zeigen.
+ Bei Arrays von Arrays (arraytype=ARRAYTYPE_ARRAY) muss das
+ Feld elementdescriptor auf eine weiter arraydescriptor-Struktur
+ zeigen, die die Element-Typen beschreibt.
+ */
+
+
+
+/********* Anmerkungen zum Constant-Pool:
+
+ Die Typen der Eintr"age in den Constant-Pool werden durch die oben
+ definierten CONSTANT_.. Werte angegeben.
+ Bei allen Typen muss zus"atzlich noch eine Datenstruktur hinzugef"ugt
+ werden, die den wirklichen Wert angibt.
+ Bei manchen Typen reicht es, einen Verweis auf eine schon bereits
+ existierende Struktur (z.B. unicode-Texte) einzutragen, bei anderen
+ muss diese Struktur erst extra erzeugt werden.
+ Ich habe folgende Datenstrukturen f"ur diese Typen verwendet:
+
+ Typ Struktur extra erzeugt?
+ ----------------------------------------------------------------------
+ CONSTANT_Class classinfo nein
+ CONSTANT_Fieldref constant_FMIref ja
+ CONSTANT_Methodref constant_FMIref ja
+ CONSTANT_InterfaceMethodref constant_FMIref ja
+ CONSTANT_String unicode nein
+ CONSTANT_Integer constant_integer ja
+ CONSTANT_Float constant_float ja
+ CONSTANT_Long constant_long ja
+ CONSTANT_Double constant_double ja
+ CONSTANT_NameAndType constant_nameandtype ja
+ CONSTANT_Utf8 unicode nein
+ CONSTANT_Arraydescriptor constant_arraydescriptor ja
+ CONSTANT_UNUSED -
+
+*******************************/
+
+
+
+/***************** Die Datenstrukturen fuer das Laufzeitsystem ***************/
+
+
+ /********* Objekte **********
+
+ Alle Objekte (und Arrays), die am Heap gespeichert werden, m"ussen eine
+ folgende spezielle Datenstruktur ganz vorne stehen haben:
+
+ */
+
+typedef struct java_objectheader { /* Der Header f"ur alle Objekte */
+ vftbl *vftbl; /* Zeiger auf die Function Table */
+} java_objectheader;
+
+
+
+ /********* Arrays ***********
+
+ Alle Arrays in Java sind auch gleichzeitig Objekte (d.h. sie haben auch
+ den obligatorischen Object-Header und darin einen Verweis auf eine Klasse)
+ Es gibt aber (der Einfachheit halber) nur eine einzige Klasse f"ur alle
+ m"oglichen Typen von Arrays, deshalb wird der tats"achliche Typ in einem
+ Feld im Array-Objekt selbst gespeichert.
+ Die Typen sind: */
+
+#define ARRAYTYPE_INT 0
+#define ARRAYTYPE_LONG 1
+#define ARRAYTYPE_FLOAT 2
+#define ARRAYTYPE_DOUBLE 3
+#define ARRAYTYPE_BYTE 4
+#define ARRAYTYPE_CHAR 5
+#define ARRAYTYPE_SHORT 6
+#define ARRAYTYPE_BOOLEAN 7
+#define ARRAYTYPE_OBJECT 8
+#define ARRAYTYPE_ARRAY 9
+
+
+ /** Der Header f"ur ein Java-Array **/
+
+typedef struct java_arrayheader { /* Der Arrayheader f"ur alle Arrays */
+ java_objectheader objheader; /* Der Object-Header */
+ s4 size; /* Gr"osse des Arrays */
+ s4 arraytype; /* Typ der Elemente */
+} java_arrayheader;
+
+
+
+ /** Die Unterschiedlichen Strukturen f"ur alle Typen von Arrays **/
+
+typedef struct java_chararray {
+ java_arrayheader header;
+ u2 data[1];
+} java_chararray;
+
+typedef struct java_floatheader {
+ java_arrayheader header;
+ float data[1];
+} java_floatarray;
+
+typedef struct java_doublearray {
+ java_arrayheader header;
+ double data[1];
+} java_doublearray;
+
+
+ /* achtung: die beiden Stukturen booleanarray und bytearray m"ussen
+ identisches memory-layout haben, weil mit den selben Funktionen
+ darauf zugegriffen wird */
+
+typedef struct java_booleanarray {
+ java_arrayheader header;
+ u1 data[1];
+} java_booleanarray;
+
+typedef struct java_bytearray {
+ java_arrayheader header;
+ s1 data[1];
+} java_bytearray;
+
+typedef struct java_shortarray {
+ java_arrayheader header;
+ s2 data[1];
+} java_shortarray;
+
+typedef struct java_intarray {
+ java_arrayheader header;
+ s4 data[1];
+} java_intarray;
+
+typedef struct java_longarray {
+ java_arrayheader header;
+ s8 data[1];
+} java_longarray;
+
+
+ /* ACHTUNG: die beiden folgenden Strukturen m"ussen unbedingt gleiches
+ Memory-Layout haben, weil mit ein und der selben Funktion auf die
+ data-Eintr"age beider Typen zugegriffen wird !!!! */
+
+typedef struct java_objectarray {
+ java_arrayheader header;
+ classinfo *elementtype;
+ java_objectheader *data[1];
+} java_objectarray;
+
+typedef struct java_arrayarray {
+ java_arrayheader header;
+ constant_arraydescriptor *elementdescriptor;
+ java_arrayheader *data[1];
+} java_arrayarray;
+
+
+
+
+/************** Strukturen f"ur Klassen, Felder & Methoden *****************/
+
+
+ /*** Struktur: fieldinfo ***/
+
+typedef struct fieldinfo { /* Struktur f"ur ein Feld einer Klasse */
+ s4 flags; /* die ACC-Flags */
+ s4 type; /* Grunddatentyp */
+ unicode *name; /* Name des Felds */
+ unicode *descriptor; /* Typedescriptor in JavaVM-Form */
+
+ s4 offset; /* Offset vom Anfang des Objektes */
+ /* (bei Instanzvariablen) */
+
+ union { /* Speicher f"ur den Wert */
+ s4 i; /* (bei Klassenvariablen) */
+ s8 l;
+ float f;
+ double d;
+ void *a;
+ } value;
+
+ } fieldinfo;
+
+
+ /*** Struktur: exceptiontable ***/
+
+typedef struct exceptiontable { /* Exceptionhandler-Eintrag in einer Methode */
+ s4 startpc; /* Anfang des G"ultigkeitsbereichs */
+ s4 endpc; /* Ende des Bereichs (exklusive) */
+ s4 handlerpc; /* JavaVM-Position des Handlers */
+ classinfo *catchtype; /* Typ der behandelten Exceptions (oder
+ NULL, wenn alle behandelt werden sollen) */
+ } exceptiontable;
+
+
+
+ /*** Struktur: methodinfo ***/
+
+typedef struct methodinfo { /* Struktur f"ur eine Methode einer Klasse */
+ s4 flags; /* die ACC-Flags */
+ unicode *name; /* Name der Methode */
+ unicode *descriptor; /* der JavaVM-Descriptorstring f"ur Methoden */
+ s4 returntype; /* only temporary valid, return type */
+ s4 paramcount; /* only temporary valid, number of parameters */
+ u1 *paramtypes; /* only temporary valid, parameter types */
+ classinfo *class; /* Die Klasse, der die Methode geh"ort */
+ u4 vftblindex; /* Index dieser Methode f"ur die Virtual
+ Function Table (wenn es keine statische
+ Methode ist) */
+
+ s4 maxstack; /* maximale Stacktiefe des JavaVM-Codes */
+ s4 maxlocals; /* maximale Anzahl der JavaVM-Variablen */
+ u4 jcodelength; /* L"ange des JavaVM-Codes */
+ u1 *jcode; /* und Zeiger auf den JavaVM-Code */
+
+ s4 exceptiontablelength; /* L"ange der Exceptintable */
+ exceptiontable *exceptiontable; /* Die Exceptiontable selber */
+
+ u1 *stubroutine; /* STUB-Routine for compiling or calling
+ natives */
+ u4 mcodelength; /* L"ange des generierten Maschinencodes */
+ u1 *mcode; /* Zeiger auf den Maschinencode */
+ u1 *entrypoint; /* Entrypoint to the Maschine-Code */
+
+
+ } methodinfo;
+
+
+ /*** Struktur: classinfo ***/
+
+struct classinfo { /* Datenstruktur f"ur eine Klasse */
+ java_objectheader header; /* Weil auch Klassen als Objekte angesprochen
+ werden */
+
+ s4 flags; /* Die ACC-Flags */
+ unicode *name; /* Name der Klasse */
+
+ s4 cpcount; /* Anzahl der Eintr"age im Constant-Pool */
+ u1 *cptags; /* Die TAGs f"ur den Constant-Pool */
+ voidptr *cpinfos; /* Die Zeiger auf die Info-Strukturen */
+
+ classinfo *super; /* Zeiger auf die "ubergeordnete Klasse */
+
+ s4 interfacescount; /* Anzahl der Interfaces */
+ classinfo **interfaces; /* Zeiger auf die Interfaces */
+
+ s4 fieldscount; /* Anzahl der Felder */
+ fieldinfo *fields; /* Die Tabelle der Felder */
+
+ s4 methodscount; /* Anzahl der Methoden */
+ methodinfo *methods; /* Die Tabelle der Methoden */
+
+
+ listnode listnode; /* Verkettungsstruktur (f"ur Listen) */
+
+ bool initialized; /* true, wenn Klasse bereits Initialisiert */
+ bool linked; /* wird von `class_link` auf true gesetzt */
+ s4 index; /* Hierarchietiefe (bei normalen Klassen)
+ oder fortlaufende Nummer (bei Interfaces)*/
+ u4 instancesize; /* Gr"osse eines Objektes dieser Klasse */
+
+ vftbl *vftbl;
+
+ methodinfo *finalizer; /* Finalizer-Methode f"ur die Klasse */
+ };
+
+
+struct vftbl {
+ classinfo *class; /* Class, the function table belongs to */
+
+ s4 vftbllength; /* L"aenge der Virtual Function Table */
+
+ s4 interfacetablelength; /* L"ange der Interfacetable */
+ u4 *interfacevftbllength; /* -> siehe unten */
+ methodptr **interfacevftbl;
+
+ methodptr table[1];
+ };
+
+/*********** Anmerkungen zur Interfacetable:
+
+ "Ahnlich wie die 'normalen' virtuellen Methoden k"onnen auch die
+ Interface-Methoden mit Hilfe einer Art Virtual Function Table
+ aufgerufen werden.
+ Dazu werden alle Interfaces im System fortlaufend nummeriert (beginnend
+ bei 0), und f"ur jede Klasse wird eine ganze Tabelle von
+ Virtual Function Tables erzeugt, n"amlich zu jedem Interface, das die
+ Klasse implementiert, eine.
+
+ z.B. Nehmen wir an, eine Klasse implementiert zwei Interfaces (die durch
+ die Nummerierung die Indizes 0 und 3 bekommen haben)
+
+ Das sieht dann ungef"ahr so aus:
+ -------------- -------------
+ interfacevftbl ---> | Eintrag 0 |---------> | Methode 0 |---> Methode X
+ | Eintrag 1 |--> NULL | Methode 1 |---> Methode Y
+ | Eintrag 2 |--> NULL | Methode 2 |---> Methode Z
+ | Eintrag 3 |-----+ -------------
+ -------------- |
+ +---> -------------
+ | Methode 0 |---> Methode X
+ | Methode 1 |---> Methode A
+ -------------
+ ---------------
+ interfacevftlblength ---> | Wert 0 = 3 |
+ | Wert 1 = 0 |
+ | Wert 2 = 0 |
+ | Wert 3 = 2 |
+ ---------------
+
+ Der Aufruf einer Interface-Methode geht dann so vor sich:
+ Zur Compilezeit steht der Index (i) des Interfaces und die Stelle (s), wo
+ in der entsprechenden Untertabelle die Methode eingetragen ist, schon fest.
+ Also muss zur Laufzeit nur mehr der n-te Eintrag aus der Interfacetable
+ gelesen werden, von dieser Tabelle aus wird der s-te Eintrag geholt,
+ und diese Methode wird angesprungen.
+
+****************/
+
+
+
+/************************* Referenzen auf die wichtigen Systemklassen ********************/
+
+extern classinfo *class_java_lang_Object;
+extern classinfo *class_java_lang_String;
+extern classinfo *class_java_lang_ClassCastException;
+extern classinfo *class_java_lang_NullPointerException;
+extern classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
+extern classinfo *class_java_lang_NegativeArraySizeException;
+extern classinfo *class_java_lang_OutOfMemoryError;
+extern classinfo *class_java_lang_ArithmeticException;
+extern classinfo *class_java_lang_ArrayStoreException;
+extern classinfo *class_java_lang_ThreadDeath; /* schani */
+
+extern classinfo *class_array;
+
+
+/********************** Vorgefertigte Instanzen einiger Systemklassen ********************/
+
+extern java_objectheader *proto_java_lang_ClassCastException;
+extern java_objectheader *proto_java_lang_NullPointerException;
+extern java_objectheader *proto_java_lang_ArrayIndexOutOfBoundsException;
+extern java_objectheader *proto_java_lang_NegativeArraySizeException;
+extern java_objectheader *proto_java_lang_OutOfMemoryError;
+extern java_objectheader *proto_java_lang_ArithmeticException;
+extern java_objectheader *proto_java_lang_ArrayStoreException;
+extern java_objectheader *proto_java_lang_ThreadDeath; /* schani */
+
+
+/********************** flag variables *********************/
+
+extern bool compileall;
+extern bool runverbose;
+extern bool verbose;
+
+
+/********************** trace variables ********************/
+
+extern int count_class_infos;
+extern int count_const_pool_len;
+extern int count_vftbl_len;
+extern int count_unicode_len;
+extern int count_all_methods;
+extern int count_vmcode_len;
+extern int count_extable_len;
+
+#endif
--- /dev/null
+/****************************** asmpart.h **************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Headerfile for asmpart.S. asmpart.S contains the machine dependent
+ Java - C interface functions.
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+ Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1997/10/15
+
+*******************************************************************************/
+
+int has_no_x_instr_set();
+ /* determines if the byte support instruction set (21164a and higher)
+ is available. */
+
+void synchronize_caches();
+
+
+void asm_call_jit_compiler ();
+ /* invokes the compiler for untranslated JavaVM methods.
+ Register R0 contains a pointer to the method info structure
+ (prepared by createcompilerstub). */
+
+java_objectheader *asm_calljavamethod (methodinfo *m, void *arg1, void*arg2,
+ void*arg3, void*arg4);
+ /* This function calls a Java-method (which possibly needs compilation)
+ with up to 4 parameters. This function calls a Java-method (which
+ possibly needs compilation) with up to 4 parameters. */
+
+
+void asm_dumpregistersandcall ( functionptr f);
+ /* This funtion saves all callee saved registers and calls the function
+ which is passed as parameter.
+ This function is needed by the garbage collector, which needs to access
+ all registers which are stored on the stack. Unused registers are
+ cleared to avoid interferances with the GC. */
--- /dev/null
+/* -*- mode: c; tab-width: 4; c-basic-offset: 4 -*- */
+/****************************** loader.c ***************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Contains the functions of the class loader.
+
+ Author: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+ Changes: Mark Probst EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1997/06/03
+
+*******************************************************************************/
+
+
+#include <assert.h>
+
+#include "global.h"
+#include "loader.h"
+
+#include "tables.h"
+#include "native.h"
+#include "builtin.h"
+#include "compiler.h"
+#include "asmpart.h"
+
+#include "threads/thread.h" /* schani */
+
+
+/*************************** globale Variablen *******************************/
+
+extern bool newcompiler;
+
+int count_class_infos = 0;
+int count_const_pool_len = 0;
+int count_vftbl_len = 0;
+int count_all_methods = 0;
+int count_vmcode_len = 0;
+int count_extable_len = 0;
+
+bool loadverbose = false; /* Switches f"ur mehr Debug-Meldungen */
+bool linkverbose = false;
+bool initverbose = false;
+
+bool makeinitializations = true;
+
+bool getloadingtime = false;
+long int loadingtime = 0;
+
+
+static u4 interfaceindex; /* fortlaufende Nummer f"ur Interfaces */
+
+static list unloadedclasses; /* Liste alle referenzierten, aber noch nicht
+ geladenen Klassen */
+static list unlinkedclasses; /* Liste aller geladenen, aber noch nicht
+ gelinkten Klassen */
+ list linkedclasses; /* Liste aller fertig gelinkten Klassen */
+
+
+
+/***************** die Referenzen auf die wichtigen Systemklassen ************/
+
+classinfo *class_java_lang_Object;
+classinfo *class_java_lang_String;
+classinfo *class_java_lang_ClassCastException;
+classinfo *class_java_lang_NullPointerException;
+classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
+classinfo *class_java_lang_NegativeArraySizeException;
+classinfo *class_java_lang_OutOfMemoryError;
+classinfo *class_java_lang_ArithmeticException;
+classinfo *class_java_lang_ArrayStoreException;
+classinfo *class_java_lang_ThreadDeath; /* schani */
+
+classinfo *class_array;
+
+
+/************ einige vorgefertigte Instanzen wichtiger Systemklassen *********/
+
+java_objectheader *proto_java_lang_ClassCastException;
+java_objectheader *proto_java_lang_NullPointerException;
+java_objectheader *proto_java_lang_ArrayIndexOutOfBoundsException;
+java_objectheader *proto_java_lang_NegativeArraySizeException;
+java_objectheader *proto_java_lang_OutOfMemoryError;
+java_objectheader *proto_java_lang_ArithmeticException;
+java_objectheader *proto_java_lang_ArrayStoreException;
+java_objectheader *proto_java_lang_ThreadDeath; /* schani */
+
+
+
+
+/****************************************************************************/
+/******************* Einige Support-Funkionen *******************************/
+/****************************************************************************/
+
+
+/********** interne Funktion: printflags (nur zu Debug-Zwecken) ************/
+
+static void printflags (u2 f)
+{
+ if ( f & ACC_PUBLIC ) printf (" PUBLIC");
+ if ( f & ACC_PRIVATE ) printf (" PRIVATE");
+ if ( f & ACC_PROTECTED ) printf (" PROTECTED");
+ if ( f & ACC_STATIC ) printf (" STATIC");
+ if ( f & ACC_FINAL ) printf (" FINAL");
+ if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
+ if ( f & ACC_VOLATILE ) printf (" VOLATILE");
+ if ( f & ACC_TRANSIENT ) printf (" TRANSIENT");
+ if ( f & ACC_NATIVE ) printf (" NATIVE");
+ if ( f & ACC_INTERFACE ) printf (" INTERFACE");
+ if ( f & ACC_ABSTRACT ) printf (" ABSTRACT");
+}
+
+
+/************************* Funktion: skipattribute ****************************
+
+ "uberliest im ClassFile eine (1) 'attribute'-Struktur
+
+******************************************************************************/
+
+static void skipattribute ()
+{
+ u4 len;
+
+ suck_u2 ();
+ len = suck_u4 ();
+ skip_nbytes (len);
+}
+
+/********************** Funktion: skipattributebody ***************************
+
+ "uberliest im Classfile ein attribut, wobei die 16-bit - attribute_name -
+ Referenz schon gelesen worden ist.
+
+******************************************************************************/
+
+static void skipattributebody ()
+{
+ u4 len = suck_u4 ();
+ skip_nbytes (len);
+}
+
+
+/************************* Funktion: skipattributes ***************************
+
+ "uberliest im ClassFile eine gew"unschte Anzahl von attribute-Strukturen
+
+******************************************************************************/
+
+static void skipattributes (u4 num)
+{
+ u4 i;
+ for (i=0; i<num; i++) skipattribute();
+}
+
+
+
+/************************** Funktion: loadUtf8 ********************************
+
+ liest aus dem ClassFile einen Utf8-String (=komprimierter unicode-text)
+ und legt daf"ur ein unicode-Symbol an.
+ Return: Zeiger auf das Symbol
+
+******************************************************************************/
+
+#define MAXUNICODELEN 5000
+static u2 unicodebuffer[MAXUNICODELEN];
+
+static unicode *loadUtf8 ()
+{
+ u4 unicodelen;
+ u4 letter;
+
+ u4 utflen;
+ u4 b1,b2,b3;
+
+ unicodelen = 0;
+
+ utflen = suck_u2 ();
+ while (utflen > 0) {
+ b1 = suck_u1 ();
+ utflen --;
+ if (b1<0x80) letter = b1;
+ else {
+ b2 = suck_u1 ();
+ utflen --;
+ if (b1<0xe0) letter = ((b1 & 0x1f) << 6) | (b2 & 0x3f);
+ else {
+ b3 = suck_u1 ();
+ utflen --;
+ letter = ((b1 & 0x0f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f);
+ }
+ }
+
+
+ if (unicodelen >= MAXUNICODELEN) {
+ panic ("String constant too long");
+ }
+
+ unicodebuffer[unicodelen++] = letter;
+ }
+
+
+ return unicode_new_u2 (unicodebuffer, unicodelen);
+}
+
+
+
+/******************** interne Funktion: checkfieldtype ***********************/
+
+static void checkfieldtype (u2 *text, u4 *count, u4 length)
+{
+ u4 l;
+
+ if (*count >= length) panic ("Type-descriptor exceeds unicode length");
+
+ l = text[(*count)++];
+
+ switch (l) {
+ default: panic ("Invalid symbol in type descriptor");
+ return;
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'F':
+ case 'I':
+ case 'J':
+ case 'S':
+ case 'Z': return;
+
+ case '[': checkfieldtype (text, count, length);
+ return;
+
+ case 'L':
+ {
+ u4 tlen,tstart = *count;
+
+ if (*count >= length)
+ panic ("Objecttype descriptor of length zero");
+
+ while ( text[*count] != ';' ) {
+ (*count)++;
+ if (*count >= length)
+ panic ("Missing ';' in objecttype-descriptor");
+ }
+
+ tlen = (*count) - tstart;
+ (*count)++;
+
+ if (tlen == 0) panic ("Objecttype descriptor with empty name");
+
+ class_get ( unicode_new_u2 (text+tstart, tlen) );
+ }
+ }
+}
+
+
+/******************* Funktion: checkfielddescriptor ***************************
+
+ "uberpr"uft, ob ein Field-Descriptor ein g"ultiges Format hat.
+ Wenn nicht, dann wird das System angehalten.
+ Au"serdem werden alle Klassen, die hier referenziert werden,
+ in die Liste zu ladender Klassen eingetragen.
+
+******************************************************************************/
+
+void checkfielddescriptor (unicode *d)
+{
+ u4 count=0;
+ checkfieldtype (d->text, &count, d->length);
+ if (count != d->length) panic ("Invalid type-descritor encountered");
+}
+
+
+/******************* Funktion: checkmethoddescriptor **************************
+
+ "uberpr"uft, ob ein Method-Descriptor ein g"ultiges Format hat.
+ Wenn nicht, dann wird das System angehalten.
+ Au"serdem werden alle Klassen, die hier referenziert werden,
+ in die Liste zu ladender Klassen eingetragen.
+
+******************************************************************************/
+
+void checkmethoddescriptor (unicode *d)
+{
+ u2 *text=d->text;
+ u4 length=d->length;
+ u4 count=0;
+
+ if (length<2) panic ("Method descriptor too short");
+ if (text[0] != '(') panic ("Missing '(' in method descriptor");
+ count=1;
+
+ while (text[count] != ')') {
+ checkfieldtype (text,&count,length);
+ if ( count > length-2 ) panic ("Unexpected end of descriptor");
+ }
+
+ count++;
+ if (text[count] == 'V') count++;
+ else checkfieldtype (text, &count,length);
+
+ if (count != length) panic ("Method-descriptor has exceeding chars");
+}
+
+
+/******************** Funktion: buildarraydescriptor ****************************
+
+ erzeugt zu einem namentlich als u2-String vorliegenden Arraytyp eine
+ entsprechende constant_arraydescriptor - Struktur
+
+********************************************************************************/
+
+static constant_arraydescriptor * buildarraydescriptor(u2 *name, u4 namelen)
+{
+ constant_arraydescriptor *d;
+
+ if (name[0]!='[') panic ("Attempt to build arraydescriptor for non-array");
+ d = NEW (constant_arraydescriptor);
+ d -> objectclass = NULL;
+ d -> elementdescriptor = NULL;
+
+#ifdef STATISTICS
+ count_const_pool_len += sizeof(constant_arraydescriptor);
+#endif
+
+ switch (name[1]) {
+ case 'Z': d -> arraytype = ARRAYTYPE_BOOLEAN; break;
+ case 'B': d -> arraytype = ARRAYTYPE_BYTE; break;
+ case 'C': d -> arraytype = ARRAYTYPE_CHAR; break;
+ case 'D': d -> arraytype = ARRAYTYPE_DOUBLE; break;
+ case 'F': d -> arraytype = ARRAYTYPE_FLOAT; break;
+ case 'I': d -> arraytype = ARRAYTYPE_INT; break;
+ case 'J': d -> arraytype = ARRAYTYPE_LONG; break;
+ case 'S': d -> arraytype = ARRAYTYPE_SHORT; break;
+
+ case '[':
+ d -> arraytype = ARRAYTYPE_ARRAY;
+ d -> elementdescriptor = buildarraydescriptor (name+1, namelen-1);
+ break;
+
+ case 'L':
+ d -> arraytype = ARRAYTYPE_OBJECT;
+ d -> objectclass = class_get ( unicode_new_u2 (name+2, namelen-3) );
+ break;
+ }
+ return d;
+}
+
+
+/******************* Funktion: freearraydescriptor ****************************
+
+ entfernt eine mit buildarraydescriptor erzeugte Struktur wieder
+ aus dem Speicher
+
+*******************************************************************************/
+
+static void freearraydescriptor (constant_arraydescriptor *d)
+{
+ while (d) {
+ constant_arraydescriptor *n = d->elementdescriptor;
+ FREE (d, constant_arraydescriptor);
+ d = n;
+ }
+}
+
+/*********************** Funktion: displayarraydescriptor *********************/
+
+static void displayarraydescriptor (constant_arraydescriptor *d)
+{
+ switch (d->arraytype) {
+ case ARRAYTYPE_BOOLEAN: printf ("boolean[]"); break;
+ case ARRAYTYPE_BYTE: printf ("byte[]"); break;
+ case ARRAYTYPE_CHAR: printf ("char[]"); break;
+ case ARRAYTYPE_DOUBLE: printf ("double[]"); break;
+ case ARRAYTYPE_FLOAT: printf ("float[]"); break;
+ case ARRAYTYPE_INT: printf ("int[]"); break;
+ case ARRAYTYPE_LONG: printf ("long[]"); break;
+ case ARRAYTYPE_SHORT: printf ("short[]"); break;
+ case ARRAYTYPE_ARRAY: displayarraydescriptor(d->elementdescriptor); printf("[]"); break;
+ case ARRAYTYPE_OBJECT: unicode_display(d->objectclass->name); printf("[]"); break;
+ }
+}
+
+
+
+/*****************************************************************************/
+/******************** Funktionen fuer Fields *********************************/
+/*****************************************************************************/
+
+
+/************************ Funktion: field_load ********************************
+
+ l"adt alle Informationen f"ur eine Feld einer Methode aus dem ClassFile,
+ und f"ullt mit diesen Infos eine schon existierende 'fieldinfo'-Struktur.
+ Bei 'static'-Fields wird auch noch ein Platz auf dem Datensegment
+ reserviert.
+
+******************************************************************************/
+
+static void field_load (fieldinfo *f, classinfo *c)
+{
+ u4 attrnum,i;
+ u4 jtype;
+
+ f -> flags = suck_u2 ();
+ f -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
+ f -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
+ f -> type = jtype = desc_to_type (f->descriptor);
+ f -> offset = 0;
+
+ switch (f->type) {
+ case TYPE_INT: f->value.i = 0; break;
+ case TYPE_FLOAT: f->value.f = 0.0; break;
+ case TYPE_DOUBLE: f->value.d = 0.0; break;
+ case TYPE_ADDRESS: f->value.a = NULL;
+ heap_addreference (&(f->value.a));
+ break;
+ case TYPE_LONG:
+#if U8_AVAILABLE
+ f->value.l = 0; break;
+#else
+ f->value.l.low = 0; f->value.l.high = 0; break;
+#endif
+ }
+
+ attrnum = suck_u2();
+ for (i=0; i<attrnum; i++) {
+ u4 pindex;
+ unicode *aname;
+
+ aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
+
+ if ( aname != unicode_new_char ("ConstantValue") ) {
+ skipattributebody ();
+ }
+ else {
+ suck_u4();
+ pindex = suck_u2();
+
+ switch (jtype) {
+ case TYPE_INT: {
+ constant_integer *ci =
+ class_getconstant(c, pindex, CONSTANT_Integer);
+ f->value.i = ci -> value;
+ }
+ break;
+
+ case TYPE_LONG: {
+ constant_long *cl =
+ class_getconstant(c, pindex, CONSTANT_Long);
+
+ f->value.l = cl -> value;
+ }
+ break;
+
+ case TYPE_FLOAT: {
+ constant_float *cf =
+ class_getconstant(c, pindex, CONSTANT_Float);
+
+ f->value.f = cf->value;
+ }
+ break;
+
+ case TYPE_DOUBLE: {
+ constant_double *cd =
+ class_getconstant(c, pindex, CONSTANT_Double);
+
+ f->value.d = cd->value;
+ }
+ break;
+
+ case TYPE_ADDRESS: {
+ unicode *u =
+ class_getconstant(c, pindex, CONSTANT_String);
+ f->value.a = literalstring_new(u);
+ }
+ break;
+
+ default:
+ log_text ("Invalid Constant - Type");
+
+ }
+
+ }
+ }
+
+}
+
+
+/********************** Funktion: field_free *********************************/
+
+static void field_free (fieldinfo *f)
+{
+}
+
+
+/************** Funktion: field_display (nur zu Debug-Zwecken) ***************/
+
+static void field_display (fieldinfo *f)
+{
+ printf (" ");
+ printflags (f -> flags);
+ printf (" ");
+ unicode_display (f -> name);
+ printf (" ");
+ unicode_display (f -> descriptor);
+ printf (" offset: %ld\n", (long int) (f -> offset) );
+}
+
+
+
+
+/*****************************************************************************/
+/************************* Funktionen f"ur Methods ***************************/
+/*****************************************************************************/
+
+
+/*********************** Funktion: method_load ********************************
+
+ l"adt die Infos f"ur eine Methode aus dem ClassFile und f"ullt damit
+ eine schon existierende 'methodinfo'-Struktur aus.
+ Bei allen native-Methoden wird au"serdem gleich der richtige
+ Funktionszeiger eingetragen, bei JavaVM-Methoden einstweilen ein
+ Zeiger auf den Compiler
+
+******************************************************************************/
+
+static void method_load (methodinfo *m, classinfo *c)
+{
+ u4 attrnum,i,e;
+
+#ifdef STATISTICS
+ count_all_methods++;
+#endif
+
+ m -> class = c;
+
+ m -> flags = suck_u2 ();
+ m -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
+ m -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
+
+ m -> jcode = NULL;
+ m -> exceptiontable = NULL;
+ m -> entrypoint = NULL;
+ m -> mcode = NULL;
+ m -> stubroutine = NULL;
+
+ if (! (m->flags & ACC_NATIVE) ) {
+ m -> stubroutine = createcompilerstub (m);
+ }
+ else {
+ functionptr f = native_findfunction
+ (c->name, m->name, m->descriptor, (m->flags & ACC_STATIC) != 0);
+ if (f) {
+ if (newcompiler)
+ m -> stubroutine = ncreatenativestub (f, m);
+ else
+ m -> stubroutine = createnativestub (f, m);
+ }
+ }
+
+
+ attrnum = suck_u2();
+ for (i=0; i<attrnum; i++) {
+ unicode *aname;
+
+ aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
+
+ if ( aname != unicode_new_char("Code")) {
+ skipattributebody ();
+ }
+ else {
+ if (m -> jcode) panic ("Two code-attributes for one method!");
+
+ suck_u4();
+ m -> maxstack = suck_u2();
+ m -> maxlocals = suck_u2();
+ m -> jcodelength = suck_u4();
+ m -> jcode = MNEW (u1, m->jcodelength);
+ suck_nbytes (m->jcode, m->jcodelength);
+ m -> exceptiontablelength = suck_u2 ();
+ m -> exceptiontable =
+ MNEW (exceptiontable, m->exceptiontablelength);
+
+#ifdef STATISTICS
+ count_vmcode_len += m->jcodelength + 18;
+ count_extable_len += 8 * m->exceptiontablelength;
+#endif
+
+ for (e=0; e < m->exceptiontablelength; e++) {
+ u4 idx;
+ m -> exceptiontable[e].startpc = suck_u2();
+ m -> exceptiontable[e].endpc = suck_u2();
+ m -> exceptiontable[e].handlerpc = suck_u2();
+
+ idx = suck_u2();
+ if (!idx) m -> exceptiontable[e].catchtype = NULL;
+ else {
+ m -> exceptiontable[e].catchtype =
+ class_getconstant (c, idx, CONSTANT_Class);
+ }
+ }
+
+ skipattributes ( suck_u2() );
+ }
+
+ }
+
+
+}
+
+
+/********************* Funktion: method_free **********************************
+
+ gibt allen Speicher, der extra f"ur eine Methode angefordert wurde,
+ wieder frei
+
+******************************************************************************/
+
+static void method_free (methodinfo *m)
+{
+ if (m->jcode) MFREE (m->jcode, u1, m->jcodelength);
+ if (m->exceptiontable)
+ MFREE (m->exceptiontable, exceptiontable, m->exceptiontablelength);
+ if (m->mcode) CFREE (m->mcode, m->mcodelength);
+ if (m->stubroutine) {
+ if (m->flags & ACC_NATIVE) removenativestub (m->stubroutine);
+ else removecompilerstub (m->stubroutine);
+ }
+}
+
+
+/************** Funktion: method_display (nur zu Debug-Zwecken) *************/
+
+void method_display (methodinfo *m)
+{
+ printf (" ");
+ printflags (m -> flags);
+ printf (" ");
+ unicode_display (m -> name);
+ printf (" ");
+ unicode_display (m -> descriptor);
+ printf ("\n");
+}
+
+
+/******************** Funktion: method_canoverwrite ***************************
+
+ "uberpr"ft, ob eine Methode mit einer anderen typ- und namensidentisch
+ ist (also mit einer Methodendefinition eine andere "uberschrieben
+ werden kann).
+
+******************************************************************************/
+
+static bool method_canoverwrite (methodinfo *m, methodinfo *old)
+{
+ if (m->name != old->name) return false;
+ if (m->descriptor != old->descriptor) return false;
+ if (m->flags & ACC_STATIC) return false;
+ return true;
+}
+
+
+
+
+/*****************************************************************************/
+/************************ Funktionen fuer Class ******************************/
+/*****************************************************************************/
+
+
+/******************** Funktion: class_get *************************************
+
+ Sucht im System die Klasse mit dem gew"unschten Namen, oder erzeugt
+ eine neue 'classinfo'-Struktur (und h"angt sie in die Liste der zu
+ ladenen Klassen ein).
+
+******************************************************************************/
+
+classinfo *class_get (unicode *u)
+{
+ classinfo *c;
+
+ if (u->class) return u->class;
+
+#ifdef STATISTICS
+ count_class_infos += sizeof(classinfo);
+#endif
+
+ c = NEW (classinfo);
+ c -> flags = 0;
+ c -> name = u;
+ c -> cpcount = 0;
+ c -> cptags = NULL;
+ c -> cpinfos = NULL;
+ c -> super = NULL;
+ c -> interfacescount = 0;
+ c -> interfaces = NULL;
+ c -> fieldscount = 0;
+ c -> fields = NULL;
+ c -> methodscount = 0;
+ c -> methods = NULL;
+ c -> linked = false;
+ c -> index = 0;
+ c -> instancesize = 0;
+ c -> vftbl = NULL;
+ c -> initialized = false;
+
+ unicode_setclasslink (u,c);
+ list_addlast (&unloadedclasses, c);
+
+ return c;
+}
+
+
+
+/******************** Funktion: class_getconstant *****************************
+
+ holt aus dem ConstantPool einer Klasse den Wert an der Stelle 'pos'.
+ Der Wert mu"s vom Typ 'ctype' sein, sonst wird das System angehalten.
+
+******************************************************************************/
+
+voidptr class_getconstant (classinfo *c, u4 pos, u4 ctype)
+{
+ if (pos >= c->cpcount)
+ panic ("Attempt to access constant outside range");
+ if (c->cptags[pos] != ctype) {
+ sprintf (logtext, "Type mismatch on constant: %d requested, %d here",
+ (int) ctype, (int) c->cptags[pos] );
+ error();
+ }
+
+ return c->cpinfos[pos];
+}
+
+
+/********************* Funktion: class_constanttype ***************************
+
+ Findet heraus, welchen Typ ein Eintrag in den ConstantPool einer
+ Klasse hat.
+
+******************************************************************************/
+
+u4 class_constanttype (classinfo *c, u4 pos)
+{
+ if (pos >= c->cpcount)
+ panic ("Attempt to access constant outside range");
+ return c->cptags[pos];
+}
+
+
+/******************** Funktion: class_loadcpool *******************************
+
+ l"adt den gesammten ConstantPool einer Klasse.
+
+ Dabei werden die einzelnen Eintr"age in ein wesentlich einfachers
+ Format gebracht (Klassenreferenzen werden aufgel"ost, ...)
+ F"ur eine genaue "Ubersicht "uber das kompakte Format siehe: 'global.h'
+
+******************************************************************************/
+
+static void class_loadcpool (classinfo *c)
+{
+
+ typedef struct forward_class { /* Diese Strukturen dienen dazu, */
+ struct forward_class *next; /* die Infos, die beim ersten */
+ u2 thisindex; /* Durchgang durch den ConstantPool */
+ u2 name_index; /* gelesen werden, aufzunehmen. */
+ } forward_class; /* Erst nachdem der ganze Pool */
+ /* gelesen wurde, k"onnen alle */
+ typedef struct forward_string { /* Felder kompletiert werden */
+ struct forward_string *next; /* (und das auch nur in der richtigen */
+ u2 thisindex; /* Reihenfolge) */
+ u2 string_index;
+ } forward_string;
+
+ typedef struct forward_nameandtype {
+ struct forward_nameandtype *next;
+ u2 thisindex;
+ u2 name_index;
+ u2 sig_index;
+ } forward_nameandtype;
+
+ typedef struct forward_fieldmethint {
+ struct forward_fieldmethint *next;
+ u2 thisindex;
+ u1 tag;
+ u2 class_index;
+ u2 nameandtype_index;
+ } forward_fieldmethint;
+
+
+
+ u4 idx;
+ long int dumpsize = dump_size ();
+
+ forward_class *forward_classes = NULL;
+ forward_string *forward_strings = NULL;
+ forward_nameandtype *forward_nameandtypes = NULL;
+ forward_fieldmethint *forward_fieldmethints = NULL;
+
+ u4 cpcount = c -> cpcount = suck_u2();
+ u1 *cptags = c -> cptags = MNEW (u1, cpcount);
+ voidptr *cpinfos = c -> cpinfos = MNEW (voidptr, cpcount);
+
+#ifdef STATISTICS
+ count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
+#endif
+
+
+ for (idx=0; idx<cpcount; idx++) {
+ cptags[idx] = CONSTANT_UNUSED;
+ cpinfos[idx] = NULL;
+ }
+
+
+ /******* Erster Durchgang *******/
+ /* Alle Eintr"age, die nicht unmittelbar aufgel"ost werden k"onnen,
+ werden einmal `auf Vorrat' in tempor"are Strukturen eingelesen,
+ und dann am Ende nocheinmal durchgegangen */
+
+ idx = 1;
+ while (idx < cpcount) {
+ u4 t = suck_u1 ();
+ switch ( t ) {
+
+ case CONSTANT_Class: {
+ forward_class *nfc = DNEW(forward_class);
+
+ nfc -> next = forward_classes;
+ forward_classes = nfc;
+
+ nfc -> thisindex = idx;
+ nfc -> name_index = suck_u2 ();
+
+ idx++;
+ break;
+ }
+
+ case CONSTANT_Fieldref:
+ case CONSTANT_Methodref:
+ case CONSTANT_InterfaceMethodref: {
+ forward_fieldmethint *nff = DNEW (forward_fieldmethint);
+
+ nff -> next = forward_fieldmethints;
+ forward_fieldmethints = nff;
+
+ nff -> thisindex = idx;
+ nff -> tag = t;
+ nff -> class_index = suck_u2 ();
+ nff -> nameandtype_index = suck_u2 ();
+
+ idx ++;
+ break;
+ }
+
+ case CONSTANT_String: {
+ forward_string *nfs = DNEW (forward_string);
+
+ nfs -> next = forward_strings;
+ forward_strings = nfs;
+
+ nfs -> thisindex = idx;
+ nfs -> string_index = suck_u2 ();
+
+ idx ++;
+ break;
+ }
+
+ case CONSTANT_NameAndType: {
+ forward_nameandtype *nfn = DNEW (forward_nameandtype);
+
+ nfn -> next = forward_nameandtypes;
+ forward_nameandtypes = nfn;
+
+ nfn -> thisindex = idx;
+ nfn -> name_index = suck_u2 ();
+ nfn -> sig_index = suck_u2 ();
+
+ idx ++;
+ break;
+ }
+
+ case CONSTANT_Integer: {
+ constant_integer *ci = NEW (constant_integer);
+
+#ifdef STATISTICS
+ count_const_pool_len += sizeof(constant_integer);
+#endif
+
+ ci -> value = suck_s4 ();
+ cptags [idx] = CONSTANT_Integer;
+ cpinfos [idx] = ci;
+ idx ++;
+
+ break;
+ }
+
+ case CONSTANT_Float: {
+ constant_float *cf = NEW (constant_float);
+
+#ifdef STATISTICS
+ count_const_pool_len += sizeof(constant_float);
+#endif
+
+ cf -> value = suck_float ();
+ cptags [idx] = CONSTANT_Float;
+ cpinfos[idx] = cf;
+ idx ++;
+ break;
+ }
+
+ case CONSTANT_Long: {
+ constant_long *cl = NEW(constant_long);
+
+#ifdef STATISTICS
+ count_const_pool_len += sizeof(constant_long);
+#endif
+
+ cl -> value = suck_s8 ();
+ cptags [idx] = CONSTANT_Long;
+ cpinfos [idx] = cl;
+ idx += 2;
+ break;
+ }
+
+ case CONSTANT_Double: {
+ constant_double *cd = NEW(constant_double);
+
+#ifdef STATISTICS
+ count_const_pool_len += sizeof(constant_double);
+#endif
+
+ cd -> value = suck_double ();
+ cptags [idx] = CONSTANT_Double;
+ cpinfos [idx] = cd;
+ idx += 2;
+ break;
+ }
+
+ case CONSTANT_Utf8: {
+ unicode *u;
+
+ u = loadUtf8 ();
+
+ cptags [idx] = CONSTANT_Utf8;
+ cpinfos [idx] = u;
+ idx++;
+ break;
+ }
+
+ default:
+ sprintf (logtext, "Unkown constant type: %d",(int) t);
+ error ();
+
+ } /* end switch */
+
+ } /* end while */
+
+
+
+ /* Aufl"osen der noch unfertigen Eintr"age */
+
+ while (forward_classes) {
+ unicode *name =
+ class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8);
+
+ if ( (name->length>0) && (name->text[0]=='[') ) {
+ checkfielddescriptor (name);
+
+ cptags [forward_classes -> thisindex] = CONSTANT_Arraydescriptor;
+ cpinfos [forward_classes -> thisindex] =
+ buildarraydescriptor(name->text, name->length);
+
+ }
+ else {
+ cptags [forward_classes -> thisindex] = CONSTANT_Class;
+ cpinfos [forward_classes -> thisindex] = class_get (name);
+ }
+ forward_classes = forward_classes -> next;
+
+ }
+
+ while (forward_strings) {
+ unicode *text =
+ class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8);
+
+ cptags [forward_strings -> thisindex] = CONSTANT_String;
+ cpinfos [forward_strings -> thisindex] = text;
+
+ forward_strings = forward_strings -> next;
+ }
+
+ while (forward_nameandtypes) {
+ constant_nameandtype *cn = NEW (constant_nameandtype);
+
+#ifdef STATISTICS
+ count_const_pool_len += sizeof(constant_nameandtype);
+#endif
+
+ cn -> name = class_getconstant
+ (c, forward_nameandtypes -> name_index, CONSTANT_Utf8);
+ cn -> descriptor = class_getconstant
+ (c, forward_nameandtypes -> sig_index, CONSTANT_Utf8);
+
+ cptags [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
+ cpinfos [forward_nameandtypes -> thisindex] = cn;
+
+ forward_nameandtypes = forward_nameandtypes -> next;
+ }
+
+
+ while (forward_fieldmethints) {
+ constant_nameandtype *nat;
+ constant_FMIref *fmi = NEW (constant_FMIref);
+
+#ifdef STATISTICS
+ count_const_pool_len += sizeof(constant_FMIref);
+#endif
+
+ nat = class_getconstant
+ (c, forward_fieldmethints -> nameandtype_index, CONSTANT_NameAndType);
+
+ fmi -> class = class_getconstant
+ (c, forward_fieldmethints -> class_index, CONSTANT_Class);
+ fmi -> name = nat -> name;
+ fmi -> descriptor = nat -> descriptor;
+
+ cptags [forward_fieldmethints -> thisindex] = forward_fieldmethints -> tag;
+ cpinfos [forward_fieldmethints -> thisindex] = fmi;
+
+ switch (forward_fieldmethints -> tag) {
+ case CONSTANT_Fieldref: checkfielddescriptor (fmi->descriptor);
+ break;
+ case CONSTANT_InterfaceMethodref:
+ case CONSTANT_Methodref: checkmethoddescriptor (fmi->descriptor);
+ break;
+ }
+
+ forward_fieldmethints = forward_fieldmethints -> next;
+
+ }
+
+
+ dump_release (dumpsize);
+}
+
+
+/********************** Funktion: class_load **********************************
+
+ l"adt alle Infos f"ur eine ganze Klasse aus einem ClassFile. Die
+ 'classinfo'-Struktur mu"s bereits angelegt worden sein.
+
+ Die Superklasse und die Interfaces, die diese Klasse implementiert,
+ m"ussen zu diesem Zeitpunkt noch nicht geladen sein, die
+ Verbindung dazu wird sp"ater in der Funktion 'class_link' hergestellt.
+
+ Die gelesene Klasse wird dann aus der Liste 'unloadedclasses' ausgetragen
+ und in die Liste 'unlinkedclasses' eingh"angt.
+
+******************************************************************************/
+
+static void class_load (classinfo *c)
+{
+ u4 i;
+ u4 mi,ma;
+
+
+ if (loadverbose) {
+ sprintf (logtext, "Loading class: ");
+ unicode_sprint (logtext+strlen(logtext), c->name );
+ dolog();
+ }
+
+
+ suck_start (c->name);
+
+ if (suck_u4() != MAGIC) panic("Can not find class-file signature");
+ mi = suck_u2();
+ ma = suck_u2();
+ if (ma != MAJOR_VERSION) {
+ sprintf (logtext, "Can only support major version %d, but not %d",
+ MAJOR_VERSION, (int) ma);
+ error();
+ }
+ if (mi > MINOR_VERSION) {
+ sprintf (logtext, "Minor version %d is not yet supported.", (int) mi);
+ error();
+ }
+
+
+ class_loadcpool (c);
+
+ c -> flags = suck_u2 ();
+ suck_u2 (); /* this */
+
+ if ( (i = suck_u2 () ) ) {
+ c -> super = class_getconstant (c, i, CONSTANT_Class);
+ }
+ else {
+ c -> super = NULL;
+ }
+
+ c -> interfacescount = suck_u2 ();
+ c -> interfaces = MNEW (classinfo*, c -> interfacescount);
+ for (i=0; i < c -> interfacescount; i++) {
+ c -> interfaces [i] =
+ class_getconstant (c, suck_u2(), CONSTANT_Class);
+ }
+
+ c -> fieldscount = suck_u2 ();
+ c -> fields = MNEW (fieldinfo, c -> fieldscount);
+ for (i=0; i < c -> fieldscount; i++) {
+ field_load (&(c->fields[i]), c);
+ }
+
+ c -> methodscount = suck_u2 ();
+ c -> methods = MNEW (methodinfo, c -> methodscount);
+ for (i=0; i < c -> methodscount; i++) {
+ method_load (&(c -> methods [i]), c);
+ }
+
+#ifdef STATISTICS
+ count_class_infos += sizeof(classinfo*) * c -> interfacescount;
+ count_class_infos += sizeof(fieldinfo) * c -> fieldscount;
+ count_class_infos += sizeof(methodinfo) * c -> methodscount;
+#endif
+
+
+ skipattributes ( suck_u2() );
+
+
+ suck_stop ();
+
+ list_remove (&unloadedclasses, c);
+ list_addlast (&unlinkedclasses, c);
+}
+
+
+
+/************** interne Funktion: class_highestinterface **********************
+
+ wird von der Funktion class_link ben"otigt, um festzustellen, wie gro"s
+ die Interfacetable einer Klasse sein mu"s.
+
+******************************************************************************/
+
+static s4 class_highestinterface (classinfo *c)
+{
+ s4 h;
+ s4 i;
+
+ if ( ! (c->flags & ACC_INTERFACE) ) {
+ sprintf (logtext, "Interface-methods count requested for non-interface: ");
+ unicode_sprint (logtext+strlen(logtext), c->name);
+ error();
+ }
+
+ h = c->index;
+ for (i=0; i<c->interfacescount; i++) {
+ s4 h2 = class_highestinterface (c->interfaces[i]);
+ if (h2>h) h=h2;
+ }
+ return h;
+}
+
+
+/**************** Funktion: class_addinterface ********************************
+
+ wird von der Funktion class_link ben"otigt, um eine Virtual Function
+ Table f"ur ein Interface (und alle weiteren von diesem Interface
+ implementierten Interfaces) in eine Klasse einzutragen.
+
+******************************************************************************/
+
+static void class_addinterface (classinfo *c, classinfo *ic)
+{
+ u4 i = ic->index;
+ u4 j,m;
+ vftbl *vftbl = c->vftbl;
+
+ if (i>=vftbl->interfacetablelength) panic ("Interfacetable-Overflow");
+ if (vftbl->interfacevftbl[i]) return;
+
+ if (ic->methodscount==0) { /* wenn interface keine Methoden hat, dann
+ trotzdem eine Tabelle mit L"ange 1 anlegen,
+ wegen Subclass-Tests */
+ vftbl -> interfacevftbllength[i] = 1;
+ vftbl -> interfacevftbl[i] = MNEW(methodptr, 1);
+ vftbl -> interfacevftbl[i][0] = NULL;
+ }
+ else {
+ vftbl -> interfacevftbllength[i] = ic -> methodscount;
+ vftbl -> interfacevftbl[i] = MNEW(methodptr, ic -> methodscount);
+
+#ifdef STATISTICS
+ count_vftbl_len += sizeof(methodptr) * ic -> methodscount;
+#endif
+
+ for (j=0; j<ic->methodscount; j++) {
+ classinfo *sc = c;
+ while (sc) {
+ for (m=0; m<sc->methodscount; m++) {
+ methodinfo *mi = &(sc->methods[m]);
+ if (method_canoverwrite (mi, &(ic->methods[j])) ) {
+ vftbl->interfacevftbl[i][j] =
+ vftbl->table[mi->vftblindex];
+ goto foundmethod;
+ }
+ }
+ sc = sc->super;
+ }
+ foundmethod: ;
+ }
+ }
+
+ for (j=0; j<ic->interfacescount; j++)
+ class_addinterface(c, ic->interfaces[j]);
+}
+
+
+/********************** Funktion: class_link **********************************
+
+ versucht, eine Klasse in das System voll zu integrieren (linken). Dazu
+ m"ussen sowol die Superklasse, als auch alle implementierten
+ Interfaces schon gelinkt sein.
+ Diese Funktion berechnet sowohl die L"ange (in Bytes) einer Instanz
+ dieser Klasse, als auch die Virtual Function Tables f"ur normale
+ Methoden als auch Interface-Methoden.
+
+ Wenn die Klasse erfolgreich gelinkt werden kann, dann wird sie aus
+ der Liste 'unlinkedclasses' ausgeh"angt, und in die Klasse 'linkedclasses'
+ eingetragen.
+ Wenn nicht, dann wird sie ans Ende der Liste 'unlinkedclasses' gestellt.
+
+ Achtung: Bei zyklischen Klassendefinitionen ger"at das Programm hier in
+ eine Endlosschleife!! (Da muss ich mir noch was einfallen lassen)
+
+******************************************************************************/
+
+static void class_link (classinfo *c)
+{
+ u4 supervftbllength; /* L"ange der VFTBL der Superklasse */
+ u4 vftbllength; /* L"ange der VFTBL dieser Klasse */
+ classinfo *super = c->super;
+ classinfo *ic,*c2; /* Hilfsvariablen */
+ vftbl *v;
+ u4 i;
+
+
+ /* schauen, ob alle "ubergeordneten Klassen schon fertig sind,
+ und richtiges Initialisieren der lokalen Variablen */
+
+ for ( i=0; i<c->interfacescount; i++) {
+ ic = c->interfaces[i];
+ if ( !ic -> linked) {
+ list_remove (&unlinkedclasses,c );
+ list_addlast (&unlinkedclasses,c );
+ return;
+ }
+ }
+
+ if (! super) {
+ c -> index = 0;
+ c -> instancesize = sizeof (java_objectheader);
+
+ vftbllength = supervftbllength = 0;
+
+ c -> finalizer = NULL;
+ }
+ else {
+ if ( !super -> linked ) {
+ list_remove (&unlinkedclasses,c );
+ list_addlast (&unlinkedclasses,c );
+ return;
+ }
+
+ if ( c->flags & ACC_INTERFACE) c -> index = interfaceindex++;
+ else c -> index = super -> index + 1;
+
+ c -> instancesize = super -> instancesize;
+
+ vftbllength = supervftbllength = super -> vftbl -> vftbllength;
+
+ c -> finalizer = super -> finalizer;
+ }
+
+
+ if (linkverbose) {
+ sprintf (logtext, "Linking Class: ");
+ unicode_sprint (logtext+strlen(logtext), c->name );
+ dolog ();
+ }
+
+ /* Erstellen der Virtual Function Table */
+
+ for (i=0; i < c->methodscount; i++) {
+ methodinfo *m = &(c->methods[i]);
+
+ if (! (m->flags & ACC_STATIC) ) {
+ classinfo *sc = super;
+ while (sc) {
+ int j;
+ for (j=0; j < sc->methodscount; j++) {
+ if ( method_canoverwrite (m, &(sc->methods[j])) ) {
+ m -> vftblindex = sc->methods[j].vftblindex;
+ goto foundvftblindex;
+ }
+ }
+ sc = sc->super;
+ }
+ m -> vftblindex = (vftbllength++);
+ foundvftblindex: ;
+ }
+ }
+
+#ifdef STATISTICS
+ count_vftbl_len += sizeof(vftbl) + sizeof(methodptr)*(vftbllength-1);
+#endif
+
+ c -> vftbl = v = (vftbl*)
+ mem_alloc (sizeof(vftbl) + sizeof(methodptr)*(vftbllength-1));
+ v -> class = c;
+ v -> vftbllength = vftbllength;
+ v -> interfacetablelength = 0;
+
+ for (i=0; i < supervftbllength; i++)
+ v -> table[i] = super -> vftbl -> table[i];
+
+ for (i=0; i < c->methodscount; i++) {
+ methodinfo *m = &(c->methods[i]);
+ if ( ! (m->flags & ACC_STATIC) ) {
+ v -> table[m->vftblindex] = m -> stubroutine;
+ }
+ }
+
+
+ /* Berechnen der Instanzengr"o"se und der Offsets der einzelnen
+ Felder */
+
+ for (i=0; i < c->fieldscount; i++) {
+ u4 dsize;
+ fieldinfo *f = &(c -> fields[i]);
+
+ if ( ! (f->flags & ACC_STATIC) ) {
+ dsize = desc_typesize (f->descriptor);
+ c -> instancesize = ALIGN ( c->instancesize, dsize);
+ f -> offset = c -> instancesize;
+ c -> instancesize += dsize;
+ }
+
+ }
+
+
+ /* Berechnen der Virtual Function Tables f"ur alle Interfaces */
+
+ c2 = c;
+ while (c2) {
+ for (i=0; i<c2->interfacescount; i++) {
+ s4 h = class_highestinterface (c2->interfaces[i]) + 1;
+ if ( h > v->interfacetablelength) v->interfacetablelength = h;
+ }
+ c2 = c2->super;
+ }
+ v -> interfacevftbllength = MNEW (u4, v->interfacetablelength);
+ v -> interfacevftbl = MNEW (methodptr *, v->interfacetablelength);
+
+#ifdef STATISTICS
+ count_vftbl_len += (4 + sizeof(methodptr*)) * v->interfacetablelength;
+#endif
+
+ for (i=0; i < v->interfacetablelength; i++) {
+ v -> interfacevftbllength[i] = 0;
+ v -> interfacevftbl[i] = NULL;
+ }
+
+ c2 = c;
+ while (c2) {
+ for (i=0; i<c2->interfacescount; i++) {
+ class_addinterface (c, c2->interfaces[i]);
+ }
+ c2 = c2->super;
+ }
+
+
+
+ /* Die finalizer-Methode suchen und eintragen (wenn vorhanden),
+ aber nur bei Objekten ausser java.lang.Object */
+
+ if (super) {
+ methodinfo *fi;
+ static unicode *finame=NULL,*fidesc=NULL;
+
+ if (!finame) finame = unicode_new_char ("finalize");
+ if (!fidesc) fidesc = unicode_new_char ("()V");
+
+ fi = class_findmethod (c, finame, fidesc);
+ if (fi) {
+ if (! (fi->flags & ACC_STATIC) ) {
+ c -> finalizer = fi;
+ }
+ }
+ }
+
+
+ /* Abschlie"sende Aktionen */
+
+ c -> linked = true;
+
+ list_remove (&unlinkedclasses, c);
+ list_addlast (&linkedclasses, c);
+}
+
+
+/******************* Funktion: class_freepool *********************************
+
+ Gibt alle Resourcen, die der ConstantPool einer Klasse ben"otigt,
+ wieder frei.
+
+******************************************************************************/
+
+static void class_freecpool (classinfo *c)
+{
+ u4 idx;
+ u4 tag;
+ voidptr info;
+
+ for (idx=0; idx < c->cpcount; idx++) {
+ tag = c->cptags[idx];
+ info = c->cpinfos[idx];
+
+ if (info != NULL) {
+ switch (tag) {
+ case CONSTANT_Fieldref:
+ case CONSTANT_Methodref:
+ case CONSTANT_InterfaceMethodref:
+ FREE (info, constant_FMIref);
+ break;
+ case CONSTANT_Integer:
+ FREE (info, constant_integer);
+ break;
+ case CONSTANT_Float:
+ FREE (info, constant_float);
+ break;
+ case CONSTANT_Long:
+ FREE (info, constant_long);
+ break;
+ case CONSTANT_Double:
+ FREE (info, constant_double);
+ break;
+ case CONSTANT_NameAndType:
+ FREE (info, constant_nameandtype);
+ break;
+ case CONSTANT_Arraydescriptor:
+ freearraydescriptor (info);
+ break;
+ }
+ }
+ }
+
+ MFREE (c -> cptags, u1, c -> cpcount);
+ MFREE (c -> cpinfos, voidptr, c -> cpcount);
+}
+
+
+/*********************** Funktion: class_free *********************************
+
+ Gibt alle Resourcen, die eine ganze Klasse ben"otigt, frei
+
+******************************************************************************/
+
+static void class_free (classinfo *c)
+{
+ u4 i;
+ vftbl *v;
+
+ unicode_unlinkclass (c->name);
+
+ class_freecpool (c);
+
+ MFREE (c->interfaces, classinfo*, c->interfacescount);
+
+ for (i=0; i < c->fieldscount; i++) field_free ( &(c->fields[i]) );
+ MFREE (c->fields, fieldinfo, c->fieldscount);
+
+ for (i=0; i < c->methodscount; i++) method_free ( &(c->methods[i]) );
+ MFREE (c->methods, methodinfo, c->methodscount);
+
+ if ( (v = c->vftbl) ) {
+ for (i=0; i<v->interfacetablelength; i++) {
+ MFREE (v->interfacevftbl[i], methodptr, v->interfacevftbllength[i]);
+ }
+ MFREE (v->interfacevftbllength, u4, v->interfacetablelength);
+ MFREE (v->interfacevftbl, methodptr*, v->interfacetablelength);
+
+ mem_free (v, sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1));
+ }
+
+ FREE (c, classinfo);
+}
+
+
+/************************* Funktion: class_findfield *************************
+
+ sucht in einer 'classinfo'-Struktur nach einem Feld mit gew"unschtem
+ Namen und Typ.
+
+*****************************************************************************/
+
+fieldinfo *class_findfield (classinfo *c, unicode *name, unicode *desc)
+{
+ u4 i;
+ for (i=0; i < c->fieldscount; i++) {
+ if ( (c->fields[i].name == name) && (c->fields[i].descriptor == desc) )
+ return &(c->fields[i]);
+ }
+ panic ("Can not find field given in CONSTANT_Fieldref");
+ return NULL;
+}
+
+
+/************************* Funktion: class_findmethod *************************
+
+ sucht in einer 'classinfo'-Struktur nach einer Methode mit gew"unschtem
+ Namen und Typ.
+ Wenn als Typ NULL angegeben wird, dann ist der Typ egal.
+
+*****************************************************************************/
+
+methodinfo *class_findmethod (classinfo *c, unicode *name, unicode *desc)
+{
+ u4 i;
+ for (i=0; i < c->methodscount; i++) {
+ if ( (c->methods[i].name == name)
+ && ( (desc == NULL)
+ || (c->methods[i].descriptor == desc)
+ )
+ )
+ return &(c->methods[i]);
+ }
+ return NULL;
+}
+
+
+/************************* Funktion: class_resolvemethod *************************
+
+ sucht eine Klasse und alle Superklassen ab, um eine Methode zu finden.
+
+*****************************************************************************/
+
+
+methodinfo *class_resolvemethod (classinfo *c, unicode *name, unicode *desc)
+{
+ while (c) {
+ methodinfo *m = class_findmethod (c, name, desc);
+ if (m) return m;
+ c = c->super;
+ }
+ return NULL;
+}
+
+
+
+/************************* Funktion: class_issubclass ************************
+
+ "uberpr"uft, ob eine Klasse von einer anderen Klasse abgeleitet ist.
+
+*****************************************************************************/
+
+bool class_issubclass (classinfo *sub, classinfo *super)
+{
+ for (;;) {
+ if (!sub) return false;
+ if (sub==super) return true;
+ sub = sub -> super;
+ }
+}
+
+
+
+/****************** Initialisierungsfunktion f"ur eine Klasse ****************
+
+ In Java kann jede Klasse ein statische Initialisierungsfunktion haben.
+ Diese Funktion mu"s aufgerufen werden, BEVOR irgendwelche Methoden der
+ Klasse aufgerufen werden, oder auf statische Variablen zugegriffen
+ wird.
+
+******************************************************************************/
+
+#ifdef USE_THREADS
+extern int blockInts;
+#endif
+
+void class_init (classinfo *c)
+{
+ methodinfo *m;
+ java_objectheader *exceptionptr;
+ s4 i;
+ int b;
+
+ if (!makeinitializations) return;
+ if (c->initialized) return;
+ c -> initialized = true;
+
+ if (c->super) class_init (c->super);
+ for (i=0; i < c->interfacescount; i++) class_init(c->interfaces[i]);
+
+ m = class_findmethod (c,
+ unicode_new_char ("<clinit>"),
+ unicode_new_char ("()V"));
+ if (!m) {
+ if (initverbose) {
+ sprintf (logtext, "Class ");
+ unicode_sprint (logtext+strlen(logtext), c->name);
+ sprintf (logtext+strlen(logtext), " has no initializer");
+ dolog ();
+ }
+ return;
+ }
+
+ if (! (m->flags & ACC_STATIC)) panic ("Class initializer is not static!");
+
+ if (initverbose) {
+ sprintf (logtext, "Starting initializer for class: ");
+ unicode_sprint (logtext+strlen(logtext), c->name);
+ dolog ();
+ }
+
+#ifdef USE_THREADS
+ b = blockInts;
+ blockInts = 0;
+#endif
+
+ exceptionptr = asm_calljavamethod (m, NULL,NULL,NULL,NULL);
+
+#ifdef USE_THREADS
+ assert(blockInts == 0);
+ blockInts = b;
+#endif
+
+ if (exceptionptr) {
+ printf ("#### Initializer has thrown: ");
+ unicode_display (exceptionptr->vftbl->class->name);
+ printf ("\n");
+ fflush (stdout);
+ }
+
+ if (initverbose) {
+ sprintf (logtext, "Finished initializer for class: ");
+ unicode_sprint (logtext+strlen(logtext), c->name);
+ dolog ();
+ }
+
+}
+
+
+
+
+/********* Funktion: class_showconstantpool (nur f"ur Debug-Zwecke) ********/
+
+void class_showconstantpool (classinfo *c)
+{
+ u4 i;
+ voidptr e;
+
+ printf ("---- dump of constant pool ----\n");
+
+ for (i=0; i<c->cpcount; i++) {
+ printf ("#%d: ", (int) i);
+
+ e = c -> cpinfos [i];
+ if (e) {
+
+ switch (c -> cptags [i]) {
+ case CONSTANT_Class:
+ printf ("Classreference -> ");
+ unicode_display ( ((classinfo*)e) -> name );
+ break;
+
+ case CONSTANT_Fieldref:
+ printf ("Fieldref -> "); goto displayFMI;
+ case CONSTANT_Methodref:
+ printf ("Methodref -> "); goto displayFMI;
+ case CONSTANT_InterfaceMethodref:
+ printf ("InterfaceMethod -> "); goto displayFMI;
+ displayFMI:
+ {
+ constant_FMIref *fmi = e;
+ unicode_display ( fmi->class->name );
+ printf (".");
+ unicode_display ( fmi->name);
+ printf (" ");
+ unicode_display ( fmi->descriptor );
+ }
+ break;
+
+ case CONSTANT_String:
+ printf ("String -> ");
+ unicode_display (e);
+ break;
+ case CONSTANT_Integer:
+ printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
+ break;
+ case CONSTANT_Float:
+ printf ("Float -> %f", ((constant_float*)e) -> value);
+ break;
+ case CONSTANT_Double:
+ printf ("Double -> %f", ((constant_double*)e) -> value);
+ break;
+ case CONSTANT_Long:
+ {
+ u8 v = ((constant_long*)e) -> value;
+#if U8_AVAILABLE
+ printf ("Long -> %ld", (long int) v);
+#else
+ printf ("Long -> HI: %ld, LO: %ld\n",
+ (long int) v.high, (long int) v.low);
+#endif
+ }
+ break;
+ case CONSTANT_NameAndType:
+ { constant_nameandtype *cnt = e;
+ printf ("NameAndType: ");
+ unicode_display (cnt->name);
+ printf (" ");
+ unicode_display (cnt->descriptor);
+ }
+ break;
+ case CONSTANT_Utf8:
+ printf ("Utf8 -> ");
+ unicode_display (e);
+ break;
+ case CONSTANT_Arraydescriptor: {
+ printf ("Arraydescriptor: ");
+ displayarraydescriptor (e);
+ }
+ break;
+ default:
+ panic ("Invalid type of ConstantPool-Entry");
+ }
+
+ }
+
+ printf ("\n");
+ }
+
+}
+
+
+
+/********** Funktion: class_showmethods (nur f"ur Debug-Zwecke) ************/
+
+void class_showmethods (classinfo *c)
+{
+ u4 i;
+
+ printf ("--------- Fields and Methods ----------------\n");
+ printf ("Flags: "); printflags (c->flags); printf ("\n");
+
+ printf ("This: "); unicode_display (c->name); printf ("\n");
+ if (c->super) {
+ printf ("Super: "); unicode_display (c->super->name); printf ("\n");
+ }
+ printf ("Index: %d\n", c->index);
+
+ printf ("interfaces:\n");
+ for (i=0; i < c-> interfacescount; i++) {
+ printf (" ");
+ unicode_display (c -> interfaces[i] -> name);
+ printf (" (%d)\n", c->interfaces[i] -> index);
+ }
+
+ printf ("fields:\n");
+ for (i=0; i < c -> fieldscount; i++) {
+ field_display (&(c -> fields[i]));
+ }
+
+ printf ("methods:\n");
+ for (i=0; i < c -> methodscount; i++) {
+ methodinfo *m = &(c->methods[i]);
+ if ( !(m->flags & ACC_STATIC))
+ printf ("vftblindex: %d ", m->vftblindex);
+
+ method_display ( m );
+
+ }
+
+ printf ("Virtual function table:\n");
+ for (i=0; i<c->vftbl->vftbllength; i++) {
+ printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
+ }
+
+}
+
+
+
+/*****************************************************************************/
+/******************* Funktionen fuer den Class-loader generell ***************/
+/*****************************************************************************/
+
+
+/********************* Funktion: loader_load **********************************
+
+ l"adt und linkt die ge"unschte Klasse und alle davon
+ referenzierten Klassen und Interfaces
+ Return: Einen Zeiger auf diese Klasse
+
+******************************************************************************/
+
+classinfo *loader_load (unicode *topname)
+{
+ classinfo *top;
+ classinfo *c;
+ long int starttime=0,stoptime=0;
+
+ intsDisable(); /* schani */
+
+ if (getloadingtime) starttime = getcputime();
+
+
+ top = class_get (topname);
+
+ while ( (c = list_first(&unloadedclasses)) ) {
+ class_load (c);
+ }
+
+ while ( (c = list_first(&unlinkedclasses)) ) {
+ class_link (c);
+ }
+
+
+ synchronize_caches ();
+
+
+
+ if (getloadingtime) {
+ stoptime = getcputime();
+ loadingtime += (stoptime-starttime);
+ }
+
+ intsRestore(); /* schani */
+
+ return top;
+}
+
+
+/******************* interne Funktion: loader_createarrayclass ****************
+
+ Erzeugt (und linkt) eine Klasse f"ur die Arrays.
+
+******************************************************************************/
+
+static classinfo *loader_createarrayclass ()
+{
+ classinfo *c;
+ c = class_get ( unicode_new_char ("The_Array_Class") );
+
+ list_remove (&unloadedclasses, c);
+ list_addlast (&unlinkedclasses, c);
+ c -> super = class_java_lang_Object;
+
+ class_link (c);
+ return c;
+}
+
+
+
+/********************** Funktion: loader_init *********************************
+
+ Initialisiert alle Listen und l"adt alle Klassen, die vom System
+ und vom Compiler direkt ben"otigt werden.
+
+******************************************************************************/
+
+void loader_init ()
+{
+ interfaceindex = 0;
+
+ list_init (&unloadedclasses, OFFSET(classinfo, listnode) );
+ list_init (&unlinkedclasses, OFFSET(classinfo, listnode) );
+ list_init (&linkedclasses, OFFSET(classinfo, listnode) );
+
+
+ class_java_lang_Object =
+ loader_load ( unicode_new_char ("java/lang/Object") );
+ class_java_lang_String =
+ loader_load ( unicode_new_char ("java/lang/String") );
+ class_java_lang_ClassCastException =
+ loader_load ( unicode_new_char ("java/lang/ClassCastException") );
+ class_java_lang_NullPointerException =
+ loader_load ( unicode_new_char ("java/lang/NullPointerException") );
+ class_java_lang_ArrayIndexOutOfBoundsException = loader_load (
+ unicode_new_char ("java/lang/ArrayIndexOutOfBoundsException") );
+ class_java_lang_NegativeArraySizeException = loader_load (
+ unicode_new_char ("java/lang/NegativeArraySizeException") );
+ class_java_lang_OutOfMemoryError = loader_load (
+ unicode_new_char ("java/lang/OutOfMemoryError") );
+ class_java_lang_ArrayStoreException =
+ loader_load ( unicode_new_char ("java/lang/ArrayStoreException") );
+ class_java_lang_ArithmeticException =
+ loader_load ( unicode_new_char ("java/lang/ArithmeticException") );
+ class_java_lang_ThreadDeath = /* schani */
+ loader_load ( unicode_new_char ("java/lang/ThreadDeath") );
+
+ class_array = loader_createarrayclass ();
+
+
+ proto_java_lang_ClassCastException =
+ builtin_new(class_java_lang_ClassCastException);
+ heap_addreference ( (void**) &proto_java_lang_ClassCastException);
+
+ proto_java_lang_NullPointerException =
+ builtin_new(class_java_lang_NullPointerException);
+ heap_addreference ( (void**) &proto_java_lang_NullPointerException);
+
+ proto_java_lang_ArrayIndexOutOfBoundsException =
+ builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
+ heap_addreference ( (void**) &proto_java_lang_ArrayIndexOutOfBoundsException);
+
+ proto_java_lang_NegativeArraySizeException =
+ builtin_new(class_java_lang_NegativeArraySizeException);
+ heap_addreference ( (void**) &proto_java_lang_NegativeArraySizeException);
+
+ proto_java_lang_OutOfMemoryError =
+ builtin_new(class_java_lang_OutOfMemoryError);
+ heap_addreference ( (void**) &proto_java_lang_OutOfMemoryError);
+
+ proto_java_lang_ArithmeticException =
+ builtin_new(class_java_lang_ArithmeticException);
+ heap_addreference ( (void**) &proto_java_lang_ArithmeticException);
+
+ proto_java_lang_ArrayStoreException =
+ builtin_new(class_java_lang_ArrayStoreException);
+ heap_addreference ( (void**) &proto_java_lang_ArrayStoreException);
+
+ proto_java_lang_ThreadDeath = /* schani */
+ builtin_new(class_java_lang_ThreadDeath);
+ heap_addreference ( (void**) &proto_java_lang_ThreadDeath);
+}
+
+
+
+
+/********************* Funktion: loader_initclasses ****************************
+
+ initialisiert alle geladenen aber noch nicht initialisierten Klassen
+
+******************************************************************************/
+
+void loader_initclasses ()
+{
+ classinfo *c;
+
+ intsDisable(); /* schani */
+
+ if (makeinitializations) {
+ c = list_first (&linkedclasses);
+ while (c) {
+ class_init (c);
+ c = list_next (&linkedclasses, c);
+ }
+ }
+
+ intsRestore(); /* schani */
+}
+
+
+
+/******************** Funktion: loader_close **********************************
+
+ gibt alle Resourcen wieder frei
+
+******************************************************************************/
+
+void loader_close ()
+{
+ classinfo *c;
+
+ while ( (c=list_first(&unloadedclasses)) ) {
+ list_remove (&unloadedclasses,c);
+ class_free (c);
+ }
+ while ( (c=list_first(&unlinkedclasses)) ) {
+ list_remove (&unlinkedclasses,c);
+ class_free (c);
+ }
+ while ( (c=list_first(&linkedclasses)) ) {
+ list_remove (&linkedclasses,c);
+ class_free (c);
+ }
+}
+
--- /dev/null
+/******************************* loader.h **************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Contains the prototypes for the class loader.
+
+ Author: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1997/11/14
+
+*******************************************************************************/
+
+
+/************************* program switches ***********************************/
+
+extern bool loadverbose; /* Debug-Meldungen beim Laden ausgeben */
+extern bool linkverbose;
+extern bool initverbose; /* Meldungen ausgeben, wenn Klasse
+ initialisiert wird */
+extern bool makeinitializations; /* Klassen automatisch initialisieren */
+
+extern bool getloadingtime;
+extern long int loadingtime; /* CPU-Zeit f"urs Laden der Klassen */
+
+extern list linkedclasses; /* Liste aller fertig gelinkten Klassen */
+
+
+/************************ prototypes ******************************************/
+
+void loader_init ();
+void loader_close ();
+
+classinfo *loader_load (unicode *topname);
+void loader_initclasses ();
+
+classinfo *class_get (unicode *name);
+voidptr class_getconstant (classinfo *class, u4 pos, u4 ctype);
+u4 class_constanttype (classinfo *class, u4 pos);
+
+fieldinfo *class_findfield (classinfo *c, unicode *name, unicode *desc);
+methodinfo *class_findmethod (classinfo *c, unicode *name, unicode *desc);
+
+methodinfo *class_resolvemethod (classinfo *c, unicode *name, unicode *dest);
+
+bool class_issubclass (classinfo *sub, classinfo *super);
+
+void class_init (classinfo *c);
+
+void class_showmethods (classinfo *c);
+void class_showconstantpool (classinfo *c);
+
--- /dev/null
+/* -*- mode: c; tab-width: 4; c-basic-offset: 4 -*- */
+/****************************** tables.c ***************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Enth"alt Supportfunktionen f"ur:
+ - Lesen von JavaClass-Files
+ - unicode-Symbole
+ - den Heap
+ - zus"atzliche Support-Funktionen
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+ Changes: Mark Probst EMAIL: cacao@complang.tuwien.ac.at
+ Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1998/03/24
+
+*******************************************************************************/
+
+#include <assert.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include "global.h"
+#include "tables.h"
+#include "asmpart.h"
+#include "callargs.h"
+
+#include "threads/thread.h" /* schani */
+#include "threads/locks.h"
+
+
+bool runverbose = false;
+
+int count_unicode_len = 0;
+
+
+/******************************************************************************
+************************* Der Dateien-Sauger **********************************
+*******************************************************************************
+
+ dient zum Behandeln von Java-ClassFiles ("offnen, schlie"sen,
+ einlesen von 8-, 16-, 32-, 64-bit Integers und 32-, 64- bit Floats)
+
+******************************************************************************/
+
+static FILE *classfile = NULL; /* File-handle der gerade gelesenen Datei */
+static char *classpath = ""; /* Suchpfad f"ur die ClassFiles */
+
+
+
+/************************** Funktion: suck_init ******************************
+
+ Wird zu Programmstart einmal aufgerufen und setzt den Suchpfad f"ur
+ Klassenfiles
+
+******************************************************************************/
+
+void suck_init (char *cpath)
+{
+ classfile = NULL;
+ classpath = cpath;
+}
+
+
+/************************** Funktion: suck_start ******************************
+
+ "Offnet die Datei f"ur die Klasse des gegebenen Namens zum Lesen.
+ Dabei werden alle im Suchpfad angegebenen Verzeichnisse durchsucht,
+ bis eine entsprechende Datei ( <classname>.class) gefunden wird.
+
+******************************************************************************/
+
+bool suck_start (unicode *classname)
+{
+#define MAXFILENAME 1000 /* Maximale Langes des Dateinamens plus Pfad */
+
+ char filename[MAXFILENAME+10]; /* Platz fuer '.class' */
+ u2 filenamelen;
+ char *pathpos;
+ u2 i,c;
+
+
+ pathpos = classpath;
+
+ while (*pathpos) {
+ while ( *pathpos == ':' ) pathpos++;
+
+ filenamelen=0;
+ while ( (*pathpos) && (*pathpos!=':') ) {
+ PANICIF (filenamelen >= MAXFILENAME, "Filename too long") ;
+
+ filename[filenamelen++] = *(pathpos++);
+ }
+
+ filename[filenamelen++] = '/';
+
+ for (i=0; i < classname -> length; i++) {
+ PANICIF (filenamelen >= MAXFILENAME, "Filename too long");
+
+ c = classname -> text [i];
+ if (c=='/') c = '/'; /* Slashes im Namen passen zu UNIX */
+ else {
+ if ( c<=' ' || c>'z') {
+ c = '?';
+ }
+ }
+
+ filename[filenamelen++] = c;
+ }
+
+ strcpy (filename+filenamelen, ".class");
+
+ classfile = fopen(filename, "r");
+ if (classfile) {
+ return true;
+ }
+
+
+ }
+
+ sprintf (logtext,"Can not open class file '%s'", filename);
+ error();
+ return false;
+}
+
+
+/************************** Funktion: suck_stop *******************************
+
+ Schlie"st die offene Datei wieder.
+
+******************************************************************************/
+
+void suck_stop ()
+{
+ u4 rest=0;
+ u1 dummy;
+
+ while ( fread (&dummy, 1,1, classfile) > 0) rest++;
+ if (rest) {
+ sprintf (logtext,"There are %d access bytes at end of classfile",
+ (int) rest);
+ dolog();
+ }
+
+ fclose (classfile);
+ classfile = NULL;
+}
+
+
+
+/************************** Lesefunktionen ***********************************
+
+ Lesen von der Datei in verschieden grossen Paketen
+ (8,16,32,64-bit Integer oder Float)
+
+*****************************************************************************/
+
+void suck_nbytes (u1 *buffer, u4 len)
+{
+ if ( fread (buffer, 1, len, classfile) != len) panic ("Unexpected EOF");
+}
+
+
+void skip_nbytes (u4 len)
+{
+ u4 i;
+ for (i=0; i<len; i++) suck_u1 ();
+}
+
+
+u1 suck_u1 ()
+{
+ u1 b;
+ if ( fread (&b, 1,1, classfile) != 1) panic ("Unexpected EOF");
+ return b;
+}
+
+s1 suck_s1 ()
+{
+ s1 b;
+ if ( fread (&b, 1,1, classfile) != 1) panic ("Unexpected EOF");
+ return b;
+}
+
+
+u2 suck_u2 ()
+{
+ u1 b[2];
+ if ( fread (b, 1,2, classfile) != 2) panic ("Unexpected EOF");
+ return (b[0]<<8) + b[1];
+}
+
+s2 suck_s2 ()
+{
+ return suck_u2 ();
+}
+
+
+u4 suck_u4 ()
+{
+ u1 b[4];
+ u4 v;
+ if ( fread (b, 1,4, classfile) != 4) panic ("Unexpected EOF");
+ v = ( ((u4)b[0]) <<24) + ( ((u4)b[1])<<16) + ( ((u4)b[2])<<8) + ((u4)b[3]);
+ return v;
+}
+
+s4 suck_s4 ()
+{
+ s4 v = suck_u4 ();
+ return v;
+}
+
+u8 suck_u8 ()
+{
+#if U8_AVAILABLE
+ u8 lo,hi;
+ hi = suck_u4();
+ lo = suck_u4();
+ return (hi<<32) + lo;
+#else
+ u8 v;
+ v.high = suck_u4();
+ v.low = suck_u4();
+ return v;
+#endif
+}
+
+s8 suck_s8 ()
+{
+ return suck_u8 ();
+}
+
+
+float suck_float ()
+{
+ float f;
+
+#if !WORDS_BIGENDIAN
+ u1 buffer[4];
+ u2 i;
+ for (i=0; i<4; i++) buffer[3-i] = suck_u1 ();
+ memcpy ( (u1*) (&f), buffer, 4);
+#else
+ suck_nbytes ( (u1*) (&f), 4 );
+#endif
+
+ PANICIF (sizeof(float) != 4, "Incompatible float-format");
+
+ return f;
+}
+
+
+double suck_double ()
+{
+ double d;
+
+#if !WORDS_BIGENDIAN
+ u1 buffer[8];
+ u2 i;
+ for (i=0; i<8; i++) buffer[7-i] = suck_u1 ();
+ memcpy ( (u1*) (&d), buffer, 8);
+#else
+ suck_nbytes ( (u1*) (&d), 8 );
+#endif
+
+ PANICIF (sizeof(double) != 8, "Incompatible double-format" );
+
+ return d;
+}
+
+
+
+
+/******************************************************************************
+******************** Der Unicode-Symbol-Verwalter *****************************
+*******************************************************************************
+
+ legt eine Hashtabelle f"ur unicode-Symbole an und verwaltet
+ das Eintragen neuer Symbole
+
+******************************************************************************/
+
+
+
+#define UNICODESTART 2187 /* Startgr"osse: moeglichst gross und prim */
+
+static u4 unicodeentries; /* Anzahl der Eintr"age in der Tabelle */
+static u4 unicodehashsize; /* Gr"osse der Tabelle */
+static unicode ** unicodehash; /* Zeiger auf die Tabelle selbst */
+
+
+/*********************** Funktion: unicode_init ******************************
+
+ Initialisiert die unicode-Symboltabelle (muss zu Systemstart einmal
+ aufgerufen werden)
+
+*****************************************************************************/
+
+void unicode_init ()
+{
+ u4 i;
+
+#ifdef STATISTICS
+ count_unicode_len += sizeof(unicode*) * unicodehashsize;
+#endif
+
+ unicodeentries = 0;
+ unicodehashsize = UNICODESTART;
+ unicodehash = MNEW (unicode*, unicodehashsize);
+ for (i=0; i<unicodehashsize; i++) unicodehash[i] = NULL;
+}
+
+
+/*********************** Funktion: unicode_close *****************************
+
+ Gibt allen Speicher der Symboltabellen frei.
+ Parameter: Ein Zeiger auf eine Funktion, die dazu n"otig ist,
+ Stringkonstanten (die mit 'unicode_setstringlink'
+ Unicode-Symbole gebunden wurden) wieder freizugeben
+
+*****************************************************************************/
+
+void unicode_close (stringdeleter del)
+{
+ unicode *u;
+ u4 i;
+
+ for (i=0; i<unicodehashsize; i++) {
+ u = unicodehash[i];
+ while (u) {
+ unicode *nextu = u->hashlink;
+
+ if (u->string) del (u->string);
+
+ MFREE (u->text, u2, u->length);
+ FREE (u, unicode);
+ u = nextu;
+ }
+ }
+ MFREE (unicodehash, unicode*, unicodehashsize);
+}
+
+
+/********************* Funktion: unicode_display ******************************
+
+ Gibt ein unicode-Symbol auf stdout aus (zu Debugzwecken)
+
+******************************************************************************/
+
+void unicode_display (unicode *u)
+{
+ u2 i,c;
+ for (i=0; i < u->length; i++) {
+ c = u->text[i];
+ if (c>=32 && c<=127) printf ("%c",c);
+ else printf ("?");
+ }
+ fflush (stdout);
+}
+
+
+/********************* Funktion: unicode_sprint ******************************
+
+ Schreibt ein unicode-Symbol in einen C-String
+
+******************************************************************************/
+
+void unicode_sprint (char *buffer, unicode *u)
+{
+ u2 i;
+ for (i=0; i < u->length; i++) buffer[i] = u->text[i];
+ buffer[i] = '\0';
+}
+
+
+/********************* Funktion: unicode_fprint ******************************
+
+ Schreibt ein unicode-Symbol auf eine Datei aus
+
+******************************************************************************/
+
+void unicode_fprint (FILE *file, unicode *u)
+{
+ u2 i;
+ for (i=0; i < u->length; i++) putc (u->text[i], file);
+}
+
+
+/****************** interne Funktion: u_hashkey ******************************/
+
+static u4 u_hashkey (u2 *text, u2 length)
+{
+ u4 k = 0;
+ u2 i,sh=0;
+
+ for (i=0; i<length; i++) {
+ k ^= ( ((u4) (text[i])) << sh );
+ if (sh<16) sh++;
+ else sh=0;
+ }
+
+ return k;
+}
+
+/*************** interne Funktion: u_reorganizehash **************************/
+
+static void u_reorganizehash ()
+{
+ u4 i;
+ unicode *u;
+
+ u4 newhashsize = unicodehashsize*2;
+ unicode **newhash = MNEW (unicode*, newhashsize);
+
+#ifdef STATISTICS
+ count_unicode_len += sizeof(unicode*) * unicodehashsize;
+#endif
+
+ for (i=0; i<newhashsize; i++) newhash[i] = NULL;
+
+ for (i=0; i<unicodehashsize; i++) {
+ u = unicodehash[i];
+ while (u) {
+ unicode *nextu = u -> hashlink;
+ u4 slot = (u->key) % newhashsize;
+
+ u->hashlink = newhash[slot];
+ newhash[slot] = u;
+
+ u = nextu;
+ }
+ }
+
+ MFREE (unicodehash, unicode*, unicodehashsize);
+ unicodehash = newhash;
+ unicodehashsize = newhashsize;
+}
+
+
+/****************** Funktion: unicode_new_u2 **********************************
+
+ Legt ein neues unicode-Symbol an. Der Text des Symbols wird dieser
+ Funktion als u2-Array "ubergeben
+
+******************************************************************************/
+
+unicode *unicode_new_u2 (u2 *text, u2 length)
+{
+ u4 key = u_hashkey (text, length);
+ u4 slot = key % unicodehashsize;
+ unicode *u = unicodehash[slot];
+ u2 i;
+
+ while (u) {
+ if (u->key == key) {
+ if (u->length == length) {
+ for (i=0; i<length; i++) {
+ if (text[i] != u->text[i]) goto nomatch;
+ }
+ return u;
+ }
+ }
+ nomatch:
+ u = u->hashlink;
+ }
+
+#ifdef STATISTICS
+ count_unicode_len += sizeof(unicode) + 2 * length;
+#endif
+
+ u = NEW (unicode);
+ u->key = key;
+ u->length = length;
+ u->text = MNEW (u2, length);
+ u->class = NULL;
+ u->string = NULL;
+ u->hashlink = unicodehash[slot];
+ unicodehash[slot] = u;
+ for (i=0; i<length; i++) u->text[i] = text[i];
+
+ unicodeentries++;
+
+ if ( unicodeentries > (unicodehashsize/2)) u_reorganizehash();
+
+ return u;
+}
+
+
+/********************* Funktion: unicode_new_char *****************************
+
+ Legt ein neues unicode-Symbol an. Der Text des Symbols wird dieser
+ Funktion als C-String ( = char* ) "ubergeben
+
+******************************************************************************/
+
+unicode *unicode_new_char (char *text)
+{
+#define MAXNEWCHAR 500
+ u2 buffer[MAXNEWCHAR];
+ u2 length = 0;
+ u1 c;
+
+ while ( (c = *text) != '\0' ) {
+ if (length>=MAXNEWCHAR) panic ("Text too long in unicode_new_char");
+ buffer[length++] = c;
+ text ++;
+ }
+ return unicode_new_u2 (buffer, length);
+}
+
+
+/********************** Funktion: unicode_setclasslink ************************
+
+ H"angt einen Verweis auf eine Klasse an ein unicode-Symbol an.
+
+******************************************************************************/
+
+void unicode_setclasslink (unicode *u, classinfo *class)
+{
+ PANICIF (u->class, "Attempt to attach class to already attached symbol");
+ u->class = class;
+}
+
+/********************** Funktion: unicode_getclasslink ************************
+
+ Sucht den Verweis von einem unicode-Symbol auf eine Klasse.
+ Wenn keine solche Klasse existiert, dann wird ein Fehler
+ ausgegeben.
+
+******************************************************************************/
+
+classinfo *unicode_getclasslink (unicode *u)
+{
+ PANICIF (!u->class, "Attempt to get unknown class-reference");
+ return u->class;
+}
+
+
+
+/********************* Funktion: unicode_unlinkclass *************************
+
+ Entfernt den Verweis auf eine Klasse wieder von einem Symbol
+
+******************************************************************************/
+
+void unicode_unlinkclass (unicode *u)
+{
+ PANICIF (!u->class, "Attempt to unlink not yet linked symbol");
+ u -> class = NULL;
+}
+
+
+
+/******************* Funktion> unicode_setstringlink *********************
+
+ H"angt einen Verweis auf einen konstanten String an ein
+ Unicode-Symbol
+
+*************************************************************************/
+
+void unicode_setstringlink (unicode *u, java_objectheader *str)
+{
+ PANICIF (u->string, "Attempt to attach string to already attached symbol");
+ u->string = str;
+}
+
+
+/********************* Funktion: unicode_unlinkstring *************************
+
+ Entfernt den Verweis auf einen String wieder von einem Symbol
+
+******************************************************************************/
+
+void unicode_unlinkstring (unicode *u)
+{
+ PANICIF (!u->class, "Attempt to unlink not yet linked symbol");
+ u -> string = NULL;
+}
+
+
+
+/*********************** Funktion: unicode_show ******************************
+
+ gibt eine Aufstellung aller Symbol im unicode-hash auf stdout aus.
+ (nur f"ur Debug-Zwecke)
+
+*****************************************************************************/
+
+void unicode_show ()
+{
+ unicode *u;
+ u4 i;
+
+ printf ("UNICODE-HASH: %d slots for %d entries\n",
+ (int) unicodehashsize, (int) unicodeentries );
+
+ for (i=0; i<unicodehashsize; i++) {
+ u = unicodehash[i];
+ if (u) {
+ printf ("SLOT %d: ", (int) i);
+ while (u) {
+ printf ("'");
+ unicode_display (u);
+ printf ("' ");
+ if (u->string) printf ("(string) ");
+ u = u->hashlink;
+ }
+ printf ("\n");
+ }
+
+ }
+}
+
+
+
+/******************************************************************************
+*********************** Diverse Support-Funktionen ****************************
+******************************************************************************/
+
+
+/******************** Funktion: desc_to_type **********************************
+
+ Findet zu einem gegebenen Typdescriptor den entsprechenden
+ Java-Grunddatentyp.
+
+******************************************************************************/
+
+u2 desc_to_type (unicode *descriptor)
+{
+ if (descriptor->length < 1) panic ("Type-Descriptor is empty string");
+
+ switch (descriptor->text[0]) {
+ case 'B':
+ case 'C':
+ case 'I':
+ case 'S':
+ case 'Z': return TYPE_INT;
+ case 'D': return TYPE_DOUBLE;
+ case 'F': return TYPE_FLOAT;
+ case 'J': return TYPE_LONG;
+ case 'L':
+ case '[': return TYPE_ADDRESS;
+ }
+
+ sprintf (logtext, "Invalid Type-Descriptor: ");
+ unicode_sprint (logtext+strlen(logtext), descriptor);
+ error ();
+ return 0;
+}
+
+
+/********************** Funktion: desc_typesize *******************************
+
+ Berechnet die L"ange (in Byte) eines Datenelements gegebenen Typs,
+ der durch den Typdescriptor gegeben ist.
+
+******************************************************************************/
+
+u2 desc_typesize (unicode *descriptor)
+{
+ switch (desc_to_type(descriptor)) {
+ case TYPE_INT: return 4;
+ case TYPE_LONG: return 8;
+ case TYPE_FLOAT: return 4;
+ case TYPE_DOUBLE: return 8;
+ case TYPE_ADDRESS: return sizeof(voidptr);
+ default: return 0;
+ }
+}
+
+
+
+
+
+/******************************************************************************
+********************* Der garbage-collected Heap ******************************
+*******************************************************************************
+
+ verwaltet einen Heap mit automatischer Speicherfreigabe.
+
+ (eine ausf"uhrliche Dokumentation findet sich in der Datei:
+ collect.doc)
+
+******************************************************************************/
+
+
+bool collectverbose = false; /* soll Meldung beim GC ausgegeben werden? */
+
+
+#define BLOCKSIZE 8 /* Gr"osse eines Speicherblockes */
+typedef u8 heapblock; /* Datentyp mit der Gr"osse eines Speicherblocks */
+
+#if U8_AVAILABLE && SUPPORT_LONG
+#define bitfieldtype u8
+#define BITFIELDBITS 64
+#else
+#define bitfieldtype u4
+#define BITFIELDBITS 32
+#endif
+
+u4 heapsize; /* Gr"osse des Heap in Blocks */
+u4 topofheap; /* Bisherige Obergrenze Heaps */
+heapblock *heap; /* Speicher f"ur den Heap selbst */
+
+bitfieldtype *startbits; /* Bitfeld f"ur Bereichsstartkennung */
+bitfieldtype *markbits; /* Bitfeld f"ur Markierung */
+bitfieldtype *referencebits; /* Bitfeld f"ur Folgereferenzenkennung */
+
+u4 heapfillgrade; /* Menge der Daten im Heap */
+u4 collectthreashold; /* Schwellwert f"ur n"achstes GC */
+
+void **bottom_of_stack; /* Zeiger auf Untergrenze des C-Stacks */
+chain *allglobalreferences; /* Liste f"ur alle globalen Zeiger */
+
+typedef struct finalizernode {
+ struct finalizernode *next;
+ u4 objstart;
+ methodinfo *finalizer;
+ } finalizernode;
+
+finalizernode *livefinalizees;
+finalizernode *deadfinalizees;
+
+
+typedef struct memarea { /* Datenstruktur f"ur einen Freispeicherbereich */
+ struct memarea *next;
+ } memarea;
+
+typedef struct bigmemarea { /* Datenstruktur f"ur einen */
+ struct bigmemarea *next; /* Freispeicherbereich variabler L"ange */
+ u4 size;
+ } bigmemarea;
+
+#define DIFFERENTSIZES 128 /* Anzahl der 'kleinen' Freispeicherlisten */
+memarea *memlist[DIFFERENTSIZES]; /* Die 'kleinen' Freispeicherlisten */
+bitfieldtype memlistbits[DIFFERENTSIZES/BITFIELDBITS];
+ /* Bitfeld, in dem jeweils ein Bit gesetzt */
+ /* ist, wenn eine Liste noch etwas enth"alt */
+
+bigmemarea *bigmemlist; /* Liste der gr"osseren Freispeicherbereiche */
+
+
+
+
+/**************** Hilfsfunktion: lowest **************************************
+
+liefert als Ergebnis die Nummer des niederwertigsten Bits einer
+Zahl vom Typ bitfieldtype, das 1 ist.
+Wenn die ganze Zahl keine 1en enth"alt, dann ist egal, was f"ur einen
+Wert die Funktion l"iefert.
+z.B.: lowest(1) = 0, lowest(12) = 2, lowest(1024) = 10
+
+*****************************************************************************/
+
+static u1 lowesttable[256] = {
+ 255, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 5, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 6, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 5, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 7, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 5, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 6, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 5, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 };
+
+static int lowest(bitfieldtype i)
+{
+#if BITFIELDBITS==64
+ u8 i1 = i<<32;
+ if (i1) {
+ u8 i11 = i1<<16;
+ if (i11) {
+ u8 i111 = i11<<8;
+ if (i111) return lowesttable[i111>>56];
+ else return 8+lowesttable[i11>>56];
+ }
+ else {
+ u8 i112 = i1<<8;
+ if (i112) return 16+lowesttable[i112>>56];
+ else return 24+lowesttable[i1>>56];
+ }
+ }
+ else {
+ u8 i12 = i<<16;
+ if (i12) {
+ u8 i121 = i12<<8;
+ if (i121) return 32+lowesttable[i121>>56];
+ else return 40+lowesttable[i12>>56];
+ }
+ else {
+ u8 i122 = i<<8;
+ if (i122) return 48+lowesttable[i122>>56];
+ else return 56+lowesttable[i>>56];
+ }
+ }
+#else
+ u4 i1 = i<<16;
+ if (i1) {
+ u4 i11 = i1<<8;
+ if (i11) return lowesttable[i11>>24];
+ else return 8+lowesttable[i1>>24];
+ }
+ else {
+ u4 i12 = i<<8;
+ if (i12) return 16+lowesttable[i12>>24];
+ else return 24+lowesttable[i>>24];
+ }
+#endif
+}
+
+
+/******** Funktionen zum Setzen und L"oschen von Bits in Bitfeldern ***********/
+
+static void setbit(bitfieldtype *bitfield, u4 bitnumber)
+{
+ bitfield[bitnumber/BITFIELDBITS] |=
+ ((bitfieldtype) 1) << (bitnumber%BITFIELDBITS);
+}
+
+static void clearbit(bitfieldtype *bitfield, u4 bitnumber)
+{
+ bitfield[bitnumber/BITFIELDBITS] &=
+ ~((bitfieldtype) 1) << (bitnumber%BITFIELDBITS);
+}
+
+static bool isbitset(bitfieldtype *bitfield, u4 bitnumber)
+{
+ return ( bitfield[bitnumber/BITFIELDBITS] &
+ ( ((bitfieldtype) 1) << (bitnumber%BITFIELDBITS) ) ) != 0;
+}
+
+static bool isbitclear(bitfieldtype *bitfield, u4 bitnumber)
+{
+ return ( bitfield[bitnumber/BITFIELDBITS] &
+ ( ((bitfieldtype) 1) << (bitnumber%BITFIELDBITS) ) ) == 0;
+}
+
+
+/***************** Funktion: clearbitfield ************************************
+
+ l"oscht ein ganzes Bitfeld
+
+******************************************************************************/
+
+static void clearbitfield(bitfieldtype *bitfield, u4 fieldsize)
+{
+ u4 i,t;
+ t = ALIGN(fieldsize, BITFIELDBITS) / BITFIELDBITS;
+ for (i=0; i<t; i++) bitfield[i] = 0;
+}
+
+/************** Funktion: maskfieldwithfield **********************************
+
+ Verkn"upft zwei Bitfelder bitweise mit UND, das erste Bitfeld
+ wird mit dem Ergebnis "uberschrieben
+
+******************************************************************************/
+
+static void maskfieldwithfield (bitfieldtype* bitfield,
+ bitfieldtype *maskfield, u4 fieldsize)
+{
+ u4 i,t;
+ t = ALIGN(fieldsize, BITFIELDBITS) / BITFIELDBITS;
+ for (i=0; i<t; i++) bitfield[i] &= maskfield[i];
+}
+
+
+/************** Funktion: findnextsetbit **************************************
+
+ Sucht in einem Bitfeld ab einer Stelle das n"achste gesetzte Bit
+ und liefert die Nummer dieses Bits.
+ Wenn kein Bit mehr zwischen 'bitnumber' und 'fieldsize' gesetzt
+ ist, dann wird fieldsize zur"uckgeliefte.
+
+******************************************************************************/
+
+static u4 findnextsetbit(bitfieldtype* bitfield, u4 fieldsize, u4 bitnumber)
+{
+ bitfieldtype pattern;
+
+ for (;;) {
+ if (bitnumber >= fieldsize) return fieldsize;
+
+ pattern = bitfield[bitnumber/BITFIELDBITS];
+ pattern >>= (bitnumber%BITFIELDBITS);
+ if (pattern) return bitnumber + lowest(pattern);
+
+ bitnumber = ((bitnumber + BITFIELDBITS) / BITFIELDBITS) * BITFIELDBITS;
+ }
+}
+
+
+/************ Funktion: findnextcombination_set_unset *************************
+
+ funktioniert wie findnextsetbit, allerdings sucht diese Funktion
+ nach einer Stelle, an der gleichzeitig ein Bit im ersten
+ Bitfeld gesetzt ist und im zweiten Bitfeld das entsprechende
+ Bit nicht gesetzt ist.
+
+******************************************************************************/
+
+static u4 findnextcombination_set_unset
+ (bitfieldtype *bitfield1, bitfieldtype* bitfield2, u4 fieldsize, u4 bitnumber)
+{
+ bitfieldtype pattern;
+
+ for (;;) {
+ if (bitnumber >= fieldsize) return fieldsize;
+
+ pattern = bitfield1[bitnumber/BITFIELDBITS]
+ & (~bitfield2[bitnumber/BITFIELDBITS]);
+ pattern >>= (bitnumber%BITFIELDBITS);
+ if (pattern) return bitnumber + lowest(pattern);
+
+ bitnumber = ((bitnumber + BITFIELDBITS) / BITFIELDBITS) * BITFIELDBITS;
+ }
+}
+
+
+
+/************** Funktion: memlist_init ****************************************
+
+ initialisiert die Freispeicherlisten (zum nachfolgenden Eintragen
+ mit memlist_addrange).
+
+******************************************************************************/
+
+static void memlist_init ()
+{
+ u4 i;
+ for (i=0; i<DIFFERENTSIZES; i++) memlist[i] = NULL;
+ clearbitfield (memlistbits, DIFFERENTSIZES);
+ bigmemlist = NULL;
+}
+
+
+/************** Funktion: memlist_addrange ************************************
+
+ f"ugt einen Bereich von Heap-Bl"ocken zur Freispeicherliste
+ hinzu (in die freien Heap-Bl"ocke werden dabei verschiedene
+ Verkettungszeiger hineingeschrieben).
+
+******************************************************************************/
+
+static void memlist_addrange (u4 freestart, u4 freesize)
+{
+ if (freesize>=DIFFERENTSIZES) {
+ bigmemarea *m = (bigmemarea*) (heap+freestart);
+ m -> next = bigmemlist;
+ m -> size = freesize;
+ bigmemlist = m;
+ }
+ else {
+ if (freesize*BLOCKSIZE>=sizeof(memarea)) {
+ memarea *m = (memarea*) (heap+freestart);
+ m -> next = memlist[freesize];
+ memlist[freesize] = m;
+ setbit (memlistbits, freesize);
+ }
+ }
+}
+
+
+/************** Funktion: memlist_getsuitable *********************************
+
+ sucht in der Freispeicherliste einen Speicherbereich, der m"oglichst
+ genau die gew"unschte L"ange hat.
+ Der Bereich wird dabei auf jeden Fall aus der Liste ausgetragen.
+ (Wenn der Bereich zu lang sein sollte, dann kann der Aufrufer den
+ Rest wieder mit 'memlist_addrange' in die Liste einh"angen)
+
+ Return (in Referenzparametern):
+ *freestart: Anfang des freien Speichers
+ *freelength: L"ange dieses Speicherbereiches
+
+ Wenn kein passender Speicherblock mehr gefunden werden kann, dann
+ wird in '*freelength' 0 hineingeschrieben.
+
+******************************************************************************/
+
+static void memlist_getsuitable (u4 *freestart, u4 *freelength, u4 length)
+{
+ bigmemarea *m;
+ bigmemarea *prevm = NULL;
+
+ if (length<DIFFERENTSIZES) {
+ u4 firstfreelength;
+
+ if (memlist[length]) {
+ firstfreelength = length;
+ }
+ else {
+ firstfreelength = findnextsetbit
+ (memlistbits, DIFFERENTSIZES, length+3);
+ /* wenn kein passender Block da ist, dann gleich nach */
+ /* einem etwas gr"osseren suchen, damit keine kleinen */
+ /* St"uckchen "ubrigbleiben */
+ }
+
+ if (firstfreelength<DIFFERENTSIZES) {
+ memarea *m = memlist[firstfreelength];
+ memlist[firstfreelength] = m->next;
+ if (!m->next) clearbit (memlistbits, firstfreelength);
+ *freestart = ((heapblock*) m) - heap;
+ *freelength = firstfreelength;
+ return;
+ }
+ }
+
+ m = bigmemlist;
+ while (m) {
+ if (m->size >= length) {
+ if (prevm) prevm->next = m->next;
+ else bigmemlist = m->next;
+
+ *freestart = ((heapblock*) m) - heap;
+ *freelength = m->size;
+ return ;
+ }
+
+ prevm = m;
+ m = m->next;
+ }
+
+ *freelength=0;
+}
+
+
+
+
+
+/******************* Funktion: mark *******************************************
+
+ Markiert ein m"oglicherweise g"ultiges Objekt.
+ Sollte sich herausstellen, dass der Zeiger gar nicht auf ein Objekt
+ am Heap zeigt, dann wird eben gar nichts markiert.
+
+******************************************************************************/
+
+static void markreferences (void **rstart, void **rend);
+
+static void mark (heapblock *obj)
+{
+ u4 blocknum,objectend;
+
+ if ((long) obj & (BLOCKSIZE-1)) return;
+
+ if (obj<heap) return;
+ if (obj>=(heap+topofheap) ) return;
+
+ blocknum = obj-heap;
+ if ( isbitclear(startbits, blocknum) ) return;
+ if ( isbitset(markbits, blocknum) ) return;
+
+ setbit (markbits, blocknum);
+
+ if ( isbitclear(referencebits, blocknum) ) return;
+
+ objectend = findnextsetbit (startbits, topofheap, blocknum+1);
+ markreferences ((void**)obj, (void**) (heap+objectend) );
+}
+
+
+/******************** Funktion: markreferences ********************************
+
+ Geht einen Speicherbereich durch, und markiert alle Objekte, auf
+ die von diesem Bereich aus irgendeine Referenz existiert.
+
+******************************************************************************/
+
+static void markreferences (void **rstart, void **rend)
+{
+ void **ptr;
+
+ for (ptr=rstart; ptr<rend; ptr++) mark (*ptr);
+}
+
+
+/******************* Funktion: markstack **************************************
+
+ Marks all objects that are referenced by the (C-)stacks of
+ all live threads.
+
+ (The stack-bottom is to be specified in the call to heap_init).
+
+******************************************************************************/
+
+static void markstack () /* schani */
+{
+ void *dummy;
+ void **top_of_stack = &dummy;
+
+#ifdef USE_THREADS
+ thread *aThread;
+
+ for (aThread = liveThreads; aThread != 0; aThread = CONTEXT(aThread).nextlive) {
+ mark((heapblock*)aThread);
+ if (aThread == currentThread) {
+ if (top_of_stack > (void**)CONTEXT(aThread).stackEnd)
+ markreferences ((void**)CONTEXT(aThread).stackEnd, top_of_stack);
+ else
+ markreferences (top_of_stack, (void**)CONTEXT(aThread).stackEnd);
+ }
+ else {
+ if (CONTEXT(aThread).usedStackTop > CONTEXT(aThread).stackEnd)
+ markreferences ((void**)CONTEXT(aThread).stackEnd,
+ (void**)CONTEXT(aThread).usedStackTop + 16);
+ else
+ markreferences ((void**)CONTEXT(aThread).usedStackTop - 16,
+ (void**)CONTEXT(aThread).stackEnd);
+ }
+ }
+
+ markreferences((void**)&threadQhead[0], (void**)&threadQhead[MAX_THREAD_PRIO]);
+#else
+ if (top_of_stack > bottom_of_stack)
+ markreferences(bottom_of_stack, top_of_stack);
+ else
+ markreferences(top_of_stack, bottom_of_stack);
+#endif
+}
+
+
+
+/**************** Funktion: searchlivefinalizees *****************************
+
+ geht die Liste aller Objekte durch, die noch finalisiert werden m"ussen
+ (livefinalizees), und tr"agt alle nicht mehr markierten in die
+ Liste deadfinalizess ein (allerdings werden sie vorher noch als
+ erreicht markiert, damit sie nicht jetzt gleich gel"oscht werden).
+
+*****************************************************************************/
+
+static void searchlivefinalizees ()
+{
+ finalizernode *fn = livefinalizees;
+ finalizernode *lastlive = NULL;
+
+ while (fn) {
+
+ /* alle zu finalisierenden Objekte, die nicht mehr markiert sind: */
+ if (isbitclear (markbits, fn->objstart)) {
+ finalizernode *nextfn = fn->next;
+
+ mark (heap + fn->objstart);
+
+ if (lastlive) lastlive -> next = nextfn;
+ else livefinalizees = nextfn;
+
+ fn -> next = deadfinalizees;
+ deadfinalizees = fn;
+
+ fn = nextfn;
+ }
+ else {
+ lastlive = fn;
+ fn = fn->next;
+ }
+ }
+}
+
+
+
+/********************** Funktion: finalizedead *******************************
+
+ ruft die 'finalize'-Methode aller Objekte in der 'deadfinalizees'-
+ Liste auf.
+ Achtung: Es kann hier eventuell zu neuerlichen Speicheranforderungen
+ (mit potentiell notwendigem GC) kommen, deshalb m"ussen manche
+ globalen Variablen in lokale Variblen kopiert werden
+ (Reentrant-F"ahigkeit!!!)
+
+******************************************************************************/
+
+static void finalizedead()
+{
+ finalizernode *fn = deadfinalizees;
+ deadfinalizees = NULL;
+
+ while (fn) {
+ finalizernode *nextfn = fn->next;
+
+ asm_calljavamethod (fn->finalizer, heap+fn->objstart, NULL,NULL,NULL);
+ FREE (fn, finalizernode);
+
+ fn = nextfn;
+ }
+
+}
+
+
+
+/****************** Funktion: heap_docollect **********************************
+
+ F"uhrt eine vollst"andige Garbage Collection durch
+
+******************************************************************************/
+
+static void heap_docollect ()
+{
+ u4 freestart,freeend;
+ void **p;
+ bitfieldtype *dummy;
+ u4 heapfreemem;
+ u4 oldfillgrade;
+
+
+ if (runverbose) {
+ fprintf(stderr, "doing garbage collection\n");
+ }
+ /* alle Markierungsbits l"oschen */
+ clearbitfield (markbits, topofheap);
+
+ /* Alle vom Stack referenzierten Objekte markieren */
+ asm_dumpregistersandcall (markstack);
+
+ /* Alle von globalen Variablen erreichbaren Objekte markieren */
+ p = chain_first (allglobalreferences);
+ while (p) {
+ mark (*p);
+ p = chain_next (allglobalreferences);
+ }
+
+ /* alle Objekte durchsehen, die eine finalizer-Methode haben */
+ searchlivefinalizees();
+
+ /* alle Reference-Bits l"oschen, deren Objekte nicht */
+ /* mehr erreichbar sind */
+ maskfieldwithfield (referencebits, markbits, topofheap);
+
+
+ /* Freispeicherliste initialisieren */
+ memlist_init ();
+
+
+ /* Heap schrittweise durchgehen, und alle freien Bl"ocke merken */
+
+ heapfreemem = 0;
+ freeend=0;
+ for (;;) {
+ /* Anfang des n"achsten freien Bereiches suchen */
+ freestart = findnextcombination_set_unset
+ (startbits, markbits, topofheap, freeend);
+
+ /* Wenn es keinen freien Bereich mehr gibt -> fertig */
+ if (freestart>=topofheap) goto freememfinished;
+
+ /* Anfang des freien Bereiches markieren */
+ setbit (markbits, freestart);
+
+ /* Ende des freien Bereiches suchen */
+ freeend = findnextsetbit (markbits, topofheap, freestart+1);
+
+ /* Freien Bereich in Freispeicherliste einh"angen */
+ memlist_addrange (freestart, freeend-freestart);
+
+ /* Menge des freien Speichers mitnotieren */
+ heapfreemem += (freeend-freestart);
+ }
+
+ freememfinished:
+
+ /* Die Rollen von markbits und startbits vertauschen */
+ dummy = markbits;
+ markbits = startbits;
+ startbits = dummy;
+
+
+ /* Threashold-Wert f"ur n"achstes Collect */
+ oldfillgrade = heapfillgrade;
+ heapfillgrade = topofheap - heapfreemem;
+ collectthreashold = heapfillgrade*3; /* eine nette Heuristik */
+
+ /* Eventuell eine Meldung ausgeben */
+ if (collectverbose) {
+ sprintf (logtext, "Garbage Collection: previous/now = %d / %d ",
+ (int) (oldfillgrade * BLOCKSIZE),
+ (int) (heapfillgrade * BLOCKSIZE) );
+ dolog ();
+ }
+
+
+
+ /* alle gerade unerreichbar gewordenen Objekte mit
+ finalize-Methoden jetzt finalisieren.
+ Achtung: Diese Funktion kann zu neuerlichem GC f"uhren!! */
+ finalizedead ();
+
+}
+
+/************************* Function: gc_init **********************************
+
+ Initializes the garbage collection thread mechanism.
+
+******************************************************************************/
+
+#ifdef USE_THREADS
+iMux gcStartMutex;
+iMux gcThreadMutex;
+iCv gcConditionStart;
+iCv gcConditionDone;
+
+void
+gc_init (void)
+{
+ gcStartMutex.holder = 0;
+ gcStartMutex.count = 0;
+ gcStartMutex.muxWaiters = 0;
+
+ gcThreadMutex.holder = 0;
+ gcThreadMutex.count = 0;
+ gcThreadMutex.muxWaiters = 0;
+
+ gcConditionStart.cvWaiters = 0;
+ gcConditionStart.mux = 0;
+
+ gcConditionDone.cvWaiters = 0;
+ gcConditionDone.mux = 0;
+}
+#else
+void
+gc_init (void)
+{
+}
+#endif
+
+/************************* Function: gc_thread ********************************
+
+ In an endless loop waits for a condition to be posted, then
+ garbage collects the heap.
+
+******************************************************************************/
+
+#ifdef USE_THREADS
+void
+gc_thread (void)
+{
+ intsRestore(); /* all threads start with interrupts disabled */
+
+ assert(blockInts == 0);
+
+ lock_mutex(&gcThreadMutex);
+
+ for (;;)
+ {
+ wait_cond(&gcThreadMutex, &gcConditionStart, 0);
+
+ intsDisable();
+ heap_docollect();
+ intsRestore();
+
+ signal_cond(&gcConditionDone);
+ }
+}
+#endif
+
+void
+gc_call (void)
+{
+#ifdef USE_THREADS
+ lock_mutex(&gcThreadMutex);
+
+ signal_cond(&gcConditionStart);
+ wait_cond(&gcThreadMutex, &gcConditionDone, 0);
+
+ unlock_mutex(&gcThreadMutex);
+#else
+ heap_docollect();
+#endif
+}
+
+
+/************************* Funktion: heap_init ********************************
+
+ Initialisiert den Garbage Collector.
+ Parameter:
+ heapbytesize: Maximale Gr"osse des Heap (in Bytes)
+ heapbytestartsize: Gr"osse des Heaps, bei dem zum ersten mal eine
+ GC durchgef"uhrt werden soll.
+ stackbottom: Ein Zeiger auf die Untergrenze des Stacks, im dem
+ Referenzen auf Objekte stehen k"onnen.
+
+******************************************************************************/
+
+void heap_init (u4 heapbytesize, u4 heapbytestartsize, void **stackbottom)
+{
+
+#ifdef TRACECALLARGS
+
+ heapsize = ALIGN (heapbytesize, getpagesize());
+ heapsize = heapsize/BLOCKSIZE;
+ heap = (void*) mmap ((void*) 0x10000000, (size_t) (heapsize * BLOCKSIZE),
+ PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, (off_t) 0);
+ if (heap != (void *) 0x10000000) {
+ perror("mmap");
+ printf("address = %p\n", heap);
+ panic("mmap failed\n");
+ }
+
+#else
+
+ heapsize = ALIGN (heapbytesize, 1024);
+ heapsize = heapsize/BLOCKSIZE;
+ heap = MNEW (heapblock, heapsize);
+
+#endif
+
+ topofheap = 0;
+ startbits = MNEW (bitfieldtype, heapsize/BITFIELDBITS);
+ markbits = MNEW (bitfieldtype, heapsize/BITFIELDBITS);
+ referencebits = MNEW (bitfieldtype, heapsize/BITFIELDBITS);
+ clearbitfield (startbits, heapsize);
+ clearbitfield (markbits, heapsize);
+ clearbitfield (referencebits, heapsize);
+
+ heapfillgrade = 0;
+ collectthreashold = heapbytestartsize/BLOCKSIZE;
+ allglobalreferences = chain_new ();
+ bottom_of_stack = stackbottom;
+
+ livefinalizees = NULL;
+ deadfinalizees = NULL;
+}
+
+
+/****************** Funktion: heap_close **************************************
+
+ Gibt allen ben"otigten Speicher frei
+
+******************************************************************************/
+
+void heap_close ()
+{
+#ifndef TRACECALLARGS
+ MFREE (heap, heapblock, heapsize); */
+#endif
+ MFREE (startbits, bitfieldtype, heapsize/BITFIELDBITS);
+ MFREE (markbits, bitfieldtype, heapsize/BITFIELDBITS);
+ MFREE (referencebits, bitfieldtype, heapsize/BITFIELDBITS);
+ chain_free (allglobalreferences);
+
+ while (livefinalizees) {
+ finalizernode *n = livefinalizees->next;
+ FREE (livefinalizees, finalizernode);
+ livefinalizees = n;
+ }
+}
+
+
+/***************** Funktion: heap_addreference ********************************
+
+ Teilt dem GC eine Speicherstelle mit, an der eine globale Referenz
+ auf Objekte gespeichert sein kann.
+
+******************************************************************************/
+
+void heap_addreference (void **reflocation)
+{
+ intsDisable(); /* schani */
+
+ chain_addlast (allglobalreferences, reflocation);
+
+ intsRestore(); /* schani */
+}
+
+
+
+/***************** Funktion: heap_allocate ************************************
+
+ Fordert einen Speicher vom Heap an, der eine gew"unschte Gr"osse
+ (in Byte angegeben) haben muss.
+ Wenn kein Speicher mehr vorhanden ist (auch nicht nach einem
+ Garbage Collection-Durchlauf), dann wird NULL zur"uckgegeben.
+ Zus"atzlich wird durch den Parameter 'references' angegeben, ob
+ in das angelegte Objekt Referenzen auf andere Objekte eingetragen
+ werden k"onnten.
+ (Wichtig wegen Beschleunigung des Mark&Sweep-Durchlauf)
+ Im Zweifelsfalle immer references=true verwenden.
+
+******************************************************************************/
+
+void *heap_allocate (u4 bytelength, bool references, methodinfo *finalizer)
+{
+ u4 freestart,freelength;
+ u4 length = ALIGN(bytelength, BLOCKSIZE) / BLOCKSIZE;
+
+ intsDisable(); /* schani */
+
+ memlist_getsuitable (&freestart, &freelength, length);
+
+onemoretry:
+ if (!freelength) {
+ if ( (topofheap+length > collectthreashold)
+ || (topofheap+length > heapsize) ) {
+
+ intsRestore();
+ gc_call();
+ intsDisable();
+
+ memlist_getsuitable (&freestart, &freelength, length);
+ if (freelength) goto onemoretry;
+ }
+
+ if (topofheap+length > heapsize) {
+ sprintf (logtext, "Heap-Allocation failed for %d bytes",
+ (int) bytelength);
+ dolog();
+ intsRestore(); /* schani */
+ return NULL;
+ }
+
+ freestart = topofheap;
+ freelength = length;
+ setbit (startbits, topofheap);
+ topofheap += length;
+ }
+ else {
+ if (freelength>length) {
+ setbit (startbits, freestart+length);
+ memlist_addrange (freestart+length, freelength-length);
+ }
+ }
+
+ if (references) setbit (referencebits, freestart);
+
+ heapfillgrade += length;
+
+ if (finalizer) {
+ finalizernode *n = NEW(finalizernode);
+ n -> next = livefinalizees;
+ n -> objstart = freestart;
+ n -> finalizer = finalizer;
+ livefinalizees = n;
+ }
+
+ intsRestore(); /* schani */
+
+ if (runverbose) {
+ sprintf (logtext, "new returns: %lx", (long) (heap + freestart));
+ dolog ();
+ }
+
+ return (void*) (heap + freestart);
+}
+
+
+
+
--- /dev/null
+/****************************** tables.h ***************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Author: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1996/11/20
+
+*******************************************************************************/
+
+extern bool collectverbose;
+
+
+#define CLASS(name) (unicode_getclasslink(unicode_new_char(name)))
+
+typedef void (*stringdeleter) ( java_objectheader *string );
+
+
+void suck_init (char *classpath);
+bool suck_start (unicode *name);
+void suck_stop ();
+void suck_nbytes (u1 *buffer, u4 len);
+void skip_nbytes (u4 len);
+u1 suck_u1 ();
+s1 suck_s1 ();
+u2 suck_u2 ();
+s2 suck_s2 ();
+u4 suck_u4 ();
+s4 suck_s4 ();
+u8 suck_u8 ();
+s8 suck_s8 ();
+float suck_float ();
+double suck_double ();
+
+
+void unicode_init ();
+void unicode_close (stringdeleter del);
+void unicode_display (unicode *u);
+void unicode_sprint (char *buffer, unicode *u);
+void unicode_fprint (FILE *file, unicode *u);
+unicode *unicode_new_u2 (u2 *text, u2 length);
+unicode *unicode_new_char (char *text);
+void unicode_setclasslink (unicode *u, classinfo *class);
+classinfo *unicode_getclasslink (unicode *u);
+void unicode_unlinkclass (unicode *u);
+void unicode_setstringlink (unicode *u, java_objectheader *str);
+void unicode_unlinkstring (unicode *u);
+void unicode_show ();
+
+u2 desc_to_type (unicode *descriptor);
+u2 desc_typesize (unicode *descriptor);
+
+
+void heap_init (u4 size, u4 startsize, void **stackbottom);
+void heap_close ();
+void *heap_allocate (u4 bytelength, bool references, methodinfo *finalizer);
+void heap_addreference (void **reflocation);
+
+void gc_init (void);
+void gc_thread (void);
+void gc_call (void);
--- /dev/null
+/* -*- mode: c; tab-width: 4; c-basic-offset: 4 -*- */
+/****************************** tables.c ***************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Enth"alt Supportfunktionen f"ur:
+ - Lesen von JavaClass-Files
+ - unicode-Symbole
+ - den Heap
+ - zus"atzliche Support-Funktionen
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+ Changes: Mark Probst EMAIL: cacao@complang.tuwien.ac.at
+ Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1998/03/24
+
+*******************************************************************************/
+
+#include <assert.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include "global.h"
+#include "tables.h"
+#include "asmpart.h"
+#include "callargs.h"
+
+#include "threads/thread.h" /* schani */
+#include "threads/locks.h"
+
+
+bool runverbose = false;
+
+int count_unicode_len = 0;
+
+
+/******************************************************************************
+************************* Der Dateien-Sauger **********************************
+*******************************************************************************
+
+ dient zum Behandeln von Java-ClassFiles ("offnen, schlie"sen,
+ einlesen von 8-, 16-, 32-, 64-bit Integers und 32-, 64- bit Floats)
+
+******************************************************************************/
+
+static FILE *classfile = NULL; /* File-handle der gerade gelesenen Datei */
+static char *classpath = ""; /* Suchpfad f"ur die ClassFiles */
+
+
+
+/************************** Funktion: suck_init ******************************
+
+ Wird zu Programmstart einmal aufgerufen und setzt den Suchpfad f"ur
+ Klassenfiles
+
+******************************************************************************/
+
+void suck_init (char *cpath)
+{
+ classfile = NULL;
+ classpath = cpath;
+}
+
+
+/************************** Funktion: suck_start ******************************
+
+ "Offnet die Datei f"ur die Klasse des gegebenen Namens zum Lesen.
+ Dabei werden alle im Suchpfad angegebenen Verzeichnisse durchsucht,
+ bis eine entsprechende Datei ( <classname>.class) gefunden wird.
+
+******************************************************************************/
+
+bool suck_start (unicode *classname)
+{
+#define MAXFILENAME 1000 /* Maximale Langes des Dateinamens plus Pfad */
+
+ char filename[MAXFILENAME+10]; /* Platz fuer '.class' */
+ u2 filenamelen;
+ char *pathpos;
+ u2 i,c;
+
+
+ pathpos = classpath;
+
+ while (*pathpos) {
+ while ( *pathpos == ':' ) pathpos++;
+
+ filenamelen=0;
+ while ( (*pathpos) && (*pathpos!=':') ) {
+ PANICIF (filenamelen >= MAXFILENAME, "Filename too long") ;
+
+ filename[filenamelen++] = *(pathpos++);
+ }
+
+ filename[filenamelen++] = '/';
+
+ for (i=0; i < classname -> length; i++) {
+ PANICIF (filenamelen >= MAXFILENAME, "Filename too long");
+
+ c = classname -> text [i];
+ if (c=='/') c = '/'; /* Slashes im Namen passen zu UNIX */
+ else {
+ if ( c<=' ' || c>'z') {
+ c = '?';
+ }
+ }
+
+ filename[filenamelen++] = c;
+ }
+
+ strcpy (filename+filenamelen, ".class");
+
+ classfile = fopen(filename, "r");
+ if (classfile) {
+ return true;
+ }
+
+
+ }
+
+ sprintf (logtext,"Can not open class file '%s'", filename);
+ error();
+ return false;
+}
+
+
+/************************** Funktion: suck_stop *******************************
+
+ Schlie"st die offene Datei wieder.
+
+******************************************************************************/
+
+void suck_stop ()
+{
+ u4 rest=0;
+ u1 dummy;
+
+ while ( fread (&dummy, 1,1, classfile) > 0) rest++;
+ if (rest) {
+ sprintf (logtext,"There are %d access bytes at end of classfile",
+ (int) rest);
+ dolog();
+ }
+
+ fclose (classfile);
+ classfile = NULL;
+}
+
+
+
+/************************** Lesefunktionen ***********************************
+
+ Lesen von der Datei in verschieden grossen Paketen
+ (8,16,32,64-bit Integer oder Float)
+
+*****************************************************************************/
+
+void suck_nbytes (u1 *buffer, u4 len)
+{
+ if ( fread (buffer, 1, len, classfile) != len) panic ("Unexpected EOF");
+}
+
+
+void skip_nbytes (u4 len)
+{
+ u4 i;
+ for (i=0; i<len; i++) suck_u1 ();
+}
+
+
+u1 suck_u1 ()
+{
+ u1 b;
+ if ( fread (&b, 1,1, classfile) != 1) panic ("Unexpected EOF");
+ return b;
+}
+
+s1 suck_s1 ()
+{
+ s1 b;
+ if ( fread (&b, 1,1, classfile) != 1) panic ("Unexpected EOF");
+ return b;
+}
+
+
+u2 suck_u2 ()
+{
+ u1 b[2];
+ if ( fread (b, 1,2, classfile) != 2) panic ("Unexpected EOF");
+ return (b[0]<<8) + b[1];
+}
+
+s2 suck_s2 ()
+{
+ return suck_u2 ();
+}
+
+
+u4 suck_u4 ()
+{
+ u1 b[4];
+ u4 v;
+ if ( fread (b, 1,4, classfile) != 4) panic ("Unexpected EOF");
+ v = ( ((u4)b[0]) <<24) + ( ((u4)b[1])<<16) + ( ((u4)b[2])<<8) + ((u4)b[3]);
+ return v;
+}
+
+s4 suck_s4 ()
+{
+ s4 v = suck_u4 ();
+ return v;
+}
+
+u8 suck_u8 ()
+{
+#if U8_AVAILABLE
+ u8 lo,hi;
+ hi = suck_u4();
+ lo = suck_u4();
+ return (hi<<32) + lo;
+#else
+ u8 v;
+ v.high = suck_u4();
+ v.low = suck_u4();
+ return v;
+#endif
+}
+
+s8 suck_s8 ()
+{
+ return suck_u8 ();
+}
+
+
+float suck_float ()
+{
+ float f;
+
+#if !WORDS_BIGENDIAN
+ u1 buffer[4];
+ u2 i;
+ for (i=0; i<4; i++) buffer[3-i] = suck_u1 ();
+ memcpy ( (u1*) (&f), buffer, 4);
+#else
+ suck_nbytes ( (u1*) (&f), 4 );
+#endif
+
+ PANICIF (sizeof(float) != 4, "Incompatible float-format");
+
+ return f;
+}
+
+
+double suck_double ()
+{
+ double d;
+
+#if !WORDS_BIGENDIAN
+ u1 buffer[8];
+ u2 i;
+ for (i=0; i<8; i++) buffer[7-i] = suck_u1 ();
+ memcpy ( (u1*) (&d), buffer, 8);
+#else
+ suck_nbytes ( (u1*) (&d), 8 );
+#endif
+
+ PANICIF (sizeof(double) != 8, "Incompatible double-format" );
+
+ return d;
+}
+
+
+
+
+/******************************************************************************
+******************** Der Unicode-Symbol-Verwalter *****************************
+*******************************************************************************
+
+ legt eine Hashtabelle f"ur unicode-Symbole an und verwaltet
+ das Eintragen neuer Symbole
+
+******************************************************************************/
+
+
+
+#define UNICODESTART 2187 /* Startgr"osse: moeglichst gross und prim */
+
+static u4 unicodeentries; /* Anzahl der Eintr"age in der Tabelle */
+static u4 unicodehashsize; /* Gr"osse der Tabelle */
+static unicode ** unicodehash; /* Zeiger auf die Tabelle selbst */
+
+
+/*********************** Funktion: unicode_init ******************************
+
+ Initialisiert die unicode-Symboltabelle (muss zu Systemstart einmal
+ aufgerufen werden)
+
+*****************************************************************************/
+
+void unicode_init ()
+{
+ u4 i;
+
+#ifdef STATISTICS
+ count_unicode_len += sizeof(unicode*) * unicodehashsize;
+#endif
+
+ unicodeentries = 0;
+ unicodehashsize = UNICODESTART;
+ unicodehash = MNEW (unicode*, unicodehashsize);
+ for (i=0; i<unicodehashsize; i++) unicodehash[i] = NULL;
+}
+
+
+/*********************** Funktion: unicode_close *****************************
+
+ Gibt allen Speicher der Symboltabellen frei.
+ Parameter: Ein Zeiger auf eine Funktion, die dazu n"otig ist,
+ Stringkonstanten (die mit 'unicode_setstringlink'
+ Unicode-Symbole gebunden wurden) wieder freizugeben
+
+*****************************************************************************/
+
+void unicode_close (stringdeleter del)
+{
+ unicode *u;
+ u4 i;
+
+ for (i=0; i<unicodehashsize; i++) {
+ u = unicodehash[i];
+ while (u) {
+ unicode *nextu = u->hashlink;
+
+ if (u->string) del (u->string);
+
+ MFREE (u->text, u2, u->length);
+ FREE (u, unicode);
+ u = nextu;
+ }
+ }
+ MFREE (unicodehash, unicode*, unicodehashsize);
+}
+
+
+/********************* Funktion: unicode_display ******************************
+
+ Gibt ein unicode-Symbol auf stdout aus (zu Debugzwecken)
+
+******************************************************************************/
+
+void unicode_display (unicode *u)
+{
+ u2 i,c;
+ for (i=0; i < u->length; i++) {
+ c = u->text[i];
+ if (c>=32 && c<=127) printf ("%c",c);
+ else printf ("?");
+ }
+ fflush (stdout);
+}
+
+
+/********************* Funktion: unicode_sprint ******************************
+
+ Schreibt ein unicode-Symbol in einen C-String
+
+******************************************************************************/
+
+void unicode_sprint (char *buffer, unicode *u)
+{
+ u2 i;
+ for (i=0; i < u->length; i++) buffer[i] = u->text[i];
+ buffer[i] = '\0';
+}
+
+
+/********************* Funktion: unicode_fprint ******************************
+
+ Schreibt ein unicode-Symbol auf eine Datei aus
+
+******************************************************************************/
+
+void unicode_fprint (FILE *file, unicode *u)
+{
+ u2 i;
+ for (i=0; i < u->length; i++) putc (u->text[i], file);
+}
+
+
+/****************** interne Funktion: u_hashkey ******************************/
+
+static u4 u_hashkey (u2 *text, u2 length)
+{
+ u4 k = 0;
+ u2 i,sh=0;
+
+ for (i=0; i<length; i++) {
+ k ^= ( ((u4) (text[i])) << sh );
+ if (sh<16) sh++;
+ else sh=0;
+ }
+
+ return k;
+}
+
+/*************** interne Funktion: u_reorganizehash **************************/
+
+static void u_reorganizehash ()
+{
+ u4 i;
+ unicode *u;
+
+ u4 newhashsize = unicodehashsize*2;
+ unicode **newhash = MNEW (unicode*, newhashsize);
+
+#ifdef STATISTICS
+ count_unicode_len += sizeof(unicode*) * unicodehashsize;
+#endif
+
+ for (i=0; i<newhashsize; i++) newhash[i] = NULL;
+
+ for (i=0; i<unicodehashsize; i++) {
+ u = unicodehash[i];
+ while (u) {
+ unicode *nextu = u -> hashlink;
+ u4 slot = (u->key) % newhashsize;
+
+ u->hashlink = newhash[slot];
+ newhash[slot] = u;
+
+ u = nextu;
+ }
+ }
+
+ MFREE (unicodehash, unicode*, unicodehashsize);
+ unicodehash = newhash;
+ unicodehashsize = newhashsize;
+}
+
+
+/****************** Funktion: unicode_new_u2 **********************************
+
+ Legt ein neues unicode-Symbol an. Der Text des Symbols wird dieser
+ Funktion als u2-Array "ubergeben
+
+******************************************************************************/
+
+unicode *unicode_new_u2 (u2 *text, u2 length)
+{
+ u4 key = u_hashkey (text, length);
+ u4 slot = key % unicodehashsize;
+ unicode *u = unicodehash[slot];
+ u2 i;
+
+ while (u) {
+ if (u->key == key) {
+ if (u->length == length) {
+ for (i=0; i<length; i++) {
+ if (text[i] != u->text[i]) goto nomatch;
+ }
+ return u;
+ }
+ }
+ nomatch:
+ u = u->hashlink;
+ }
+
+#ifdef STATISTICS
+ count_unicode_len += sizeof(unicode) + 2 * length;
+#endif
+
+ u = NEW (unicode);
+ u->key = key;
+ u->length = length;
+ u->text = MNEW (u2, length);
+ u->class = NULL;
+ u->string = NULL;
+ u->hashlink = unicodehash[slot];
+ unicodehash[slot] = u;
+ for (i=0; i<length; i++) u->text[i] = text[i];
+
+ unicodeentries++;
+
+ if ( unicodeentries > (unicodehashsize/2)) u_reorganizehash();
+
+ return u;
+}
+
+
+/********************* Funktion: unicode_new_char *****************************
+
+ Legt ein neues unicode-Symbol an. Der Text des Symbols wird dieser
+ Funktion als C-String ( = char* ) "ubergeben
+
+******************************************************************************/
+
+unicode *unicode_new_char (char *text)
+{
+#define MAXNEWCHAR 500
+ u2 buffer[MAXNEWCHAR];
+ u2 length = 0;
+ u1 c;
+
+ while ( (c = *text) != '\0' ) {
+ if (length>=MAXNEWCHAR) panic ("Text too long in unicode_new_char");
+ buffer[length++] = c;
+ text ++;
+ }
+ return unicode_new_u2 (buffer, length);
+}
+
+
+/********************** Funktion: unicode_setclasslink ************************
+
+ H"angt einen Verweis auf eine Klasse an ein unicode-Symbol an.
+
+******************************************************************************/
+
+void unicode_setclasslink (unicode *u, classinfo *class)
+{
+ PANICIF (u->class, "Attempt to attach class to already attached symbol");
+ u->class = class;
+}
+
+/********************** Funktion: unicode_getclasslink ************************
+
+ Sucht den Verweis von einem unicode-Symbol auf eine Klasse.
+ Wenn keine solche Klasse existiert, dann wird ein Fehler
+ ausgegeben.
+
+******************************************************************************/
+
+classinfo *unicode_getclasslink (unicode *u)
+{
+ PANICIF (!u->class, "Attempt to get unknown class-reference");
+ return u->class;
+}
+
+
+
+/********************* Funktion: unicode_unlinkclass *************************
+
+ Entfernt den Verweis auf eine Klasse wieder von einem Symbol
+
+******************************************************************************/
+
+void unicode_unlinkclass (unicode *u)
+{
+ PANICIF (!u->class, "Attempt to unlink not yet linked symbol");
+ u -> class = NULL;
+}
+
+
+
+/******************* Funktion> unicode_setstringlink *********************
+
+ H"angt einen Verweis auf einen konstanten String an ein
+ Unicode-Symbol
+
+*************************************************************************/
+
+void unicode_setstringlink (unicode *u, java_objectheader *str)
+{
+ PANICIF (u->string, "Attempt to attach string to already attached symbol");
+ u->string = str;
+}
+
+
+/********************* Funktion: unicode_unlinkstring *************************
+
+ Entfernt den Verweis auf einen String wieder von einem Symbol
+
+******************************************************************************/
+
+void unicode_unlinkstring (unicode *u)
+{
+ PANICIF (!u->class, "Attempt to unlink not yet linked symbol");
+ u -> string = NULL;
+}
+
+
+
+/*********************** Funktion: unicode_show ******************************
+
+ gibt eine Aufstellung aller Symbol im unicode-hash auf stdout aus.
+ (nur f"ur Debug-Zwecke)
+
+*****************************************************************************/
+
+void unicode_show ()
+{
+ unicode *u;
+ u4 i;
+
+ printf ("UNICODE-HASH: %d slots for %d entries\n",
+ (int) unicodehashsize, (int) unicodeentries );
+
+ for (i=0; i<unicodehashsize; i++) {
+ u = unicodehash[i];
+ if (u) {
+ printf ("SLOT %d: ", (int) i);
+ while (u) {
+ printf ("'");
+ unicode_display (u);
+ printf ("' ");
+ if (u->string) printf ("(string) ");
+ u = u->hashlink;
+ }
+ printf ("\n");
+ }
+
+ }
+}
+
+
+
+/******************************************************************************
+*********************** Diverse Support-Funktionen ****************************
+******************************************************************************/
+
+
+/******************** Funktion: desc_to_type **********************************
+
+ Findet zu einem gegebenen Typdescriptor den entsprechenden
+ Java-Grunddatentyp.
+
+******************************************************************************/
+
+u2 desc_to_type (unicode *descriptor)
+{
+ if (descriptor->length < 1) panic ("Type-Descriptor is empty string");
+
+ switch (descriptor->text[0]) {
+ case 'B':
+ case 'C':
+ case 'I':
+ case 'S':
+ case 'Z': return TYPE_INT;
+ case 'D': return TYPE_DOUBLE;
+ case 'F': return TYPE_FLOAT;
+ case 'J': return TYPE_LONG;
+ case 'L':
+ case '[': return TYPE_ADDRESS;
+ }
+
+ sprintf (logtext, "Invalid Type-Descriptor: ");
+ unicode_sprint (logtext+strlen(logtext), descriptor);
+ error ();
+ return 0;
+}
+
+
+/********************** Funktion: desc_typesize *******************************
+
+ Berechnet die L"ange (in Byte) eines Datenelements gegebenen Typs,
+ der durch den Typdescriptor gegeben ist.
+
+******************************************************************************/
+
+u2 desc_typesize (unicode *descriptor)
+{
+ switch (desc_to_type(descriptor)) {
+ case TYPE_INT: return 4;
+ case TYPE_LONG: return 8;
+ case TYPE_FLOAT: return 4;
+ case TYPE_DOUBLE: return 8;
+ case TYPE_ADDRESS: return sizeof(voidptr);
+ default: return 0;
+ }
+}
+
+
+
+
+
+/******************************************************************************
+********************* Der garbage-collected Heap ******************************
+*******************************************************************************
+
+ verwaltet einen Heap mit automatischer Speicherfreigabe.
+
+ (eine ausf"uhrliche Dokumentation findet sich in der Datei:
+ collect.doc)
+
+******************************************************************************/
+
+
+bool collectverbose = false; /* soll Meldung beim GC ausgegeben werden? */
+
+
+#define BLOCKSIZE 8 /* Gr"osse eines Speicherblockes */
+typedef u8 heapblock; /* Datentyp mit der Gr"osse eines Speicherblocks */
+
+#if U8_AVAILABLE && SUPPORT_LONG
+#define bitfieldtype u8
+#define BITFIELDBITS 64
+#else
+#define bitfieldtype u4
+#define BITFIELDBITS 32
+#endif
+
+u4 heapsize; /* Gr"osse des Heap in Blocks */
+u4 topofheap; /* Bisherige Obergrenze Heaps */
+heapblock *heap; /* Speicher f"ur den Heap selbst */
+
+bitfieldtype *startbits; /* Bitfeld f"ur Bereichsstartkennung */
+bitfieldtype *markbits; /* Bitfeld f"ur Markierung */
+bitfieldtype *referencebits; /* Bitfeld f"ur Folgereferenzenkennung */
+
+u4 heapfillgrade; /* Menge der Daten im Heap */
+u4 collectthreashold; /* Schwellwert f"ur n"achstes GC */
+
+void **bottom_of_stack; /* Zeiger auf Untergrenze des C-Stacks */
+chain *allglobalreferences; /* Liste f"ur alle globalen Zeiger */
+
+typedef struct finalizernode {
+ struct finalizernode *next;
+ u4 objstart;
+ methodinfo *finalizer;
+ } finalizernode;
+
+finalizernode *livefinalizees;
+finalizernode *deadfinalizees;
+
+
+typedef struct memarea { /* Datenstruktur f"ur einen Freispeicherbereich */
+ struct memarea *next;
+ } memarea;
+
+typedef struct bigmemarea { /* Datenstruktur f"ur einen */
+ struct bigmemarea *next; /* Freispeicherbereich variabler L"ange */
+ u4 size;
+ } bigmemarea;
+
+#define DIFFERENTSIZES 128 /* Anzahl der 'kleinen' Freispeicherlisten */
+memarea *memlist[DIFFERENTSIZES]; /* Die 'kleinen' Freispeicherlisten */
+bitfieldtype memlistbits[DIFFERENTSIZES/BITFIELDBITS];
+ /* Bitfeld, in dem jeweils ein Bit gesetzt */
+ /* ist, wenn eine Liste noch etwas enth"alt */
+
+bigmemarea *bigmemlist; /* Liste der gr"osseren Freispeicherbereiche */
+
+
+
+
+/**************** Hilfsfunktion: lowest **************************************
+
+liefert als Ergebnis die Nummer des niederwertigsten Bits einer
+Zahl vom Typ bitfieldtype, das 1 ist.
+Wenn die ganze Zahl keine 1en enth"alt, dann ist egal, was f"ur einen
+Wert die Funktion l"iefert.
+z.B.: lowest(1) = 0, lowest(12) = 2, lowest(1024) = 10
+
+*****************************************************************************/
+
+static u1 lowesttable[256] = {
+ 255, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 5, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 6, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 5, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 7, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 5, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 6, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 5, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 };
+
+static int lowest(bitfieldtype i)
+{
+#if BITFIELDBITS==64
+ u8 i1 = i<<32;
+ if (i1) {
+ u8 i11 = i1<<16;
+ if (i11) {
+ u8 i111 = i11<<8;
+ if (i111) return lowesttable[i111>>56];
+ else return 8+lowesttable[i11>>56];
+ }
+ else {
+ u8 i112 = i1<<8;
+ if (i112) return 16+lowesttable[i112>>56];
+ else return 24+lowesttable[i1>>56];
+ }
+ }
+ else {
+ u8 i12 = i<<16;
+ if (i12) {
+ u8 i121 = i12<<8;
+ if (i121) return 32+lowesttable[i121>>56];
+ else return 40+lowesttable[i12>>56];
+ }
+ else {
+ u8 i122 = i<<8;
+ if (i122) return 48+lowesttable[i122>>56];
+ else return 56+lowesttable[i>>56];
+ }
+ }
+#else
+ u4 i1 = i<<16;
+ if (i1) {
+ u4 i11 = i1<<8;
+ if (i11) return lowesttable[i11>>24];
+ else return 8+lowesttable[i1>>24];
+ }
+ else {
+ u4 i12 = i<<8;
+ if (i12) return 16+lowesttable[i12>>24];
+ else return 24+lowesttable[i>>24];
+ }
+#endif
+}
+
+
+/******** Funktionen zum Setzen und L"oschen von Bits in Bitfeldern ***********/
+
+static void setbit(bitfieldtype *bitfield, u4 bitnumber)
+{
+ bitfield[bitnumber/BITFIELDBITS] |=
+ ((bitfieldtype) 1) << (bitnumber%BITFIELDBITS);
+}
+
+static void clearbit(bitfieldtype *bitfield, u4 bitnumber)
+{
+ bitfield[bitnumber/BITFIELDBITS] &=
+ ~((bitfieldtype) 1) << (bitnumber%BITFIELDBITS);
+}
+
+static bool isbitset(bitfieldtype *bitfield, u4 bitnumber)
+{
+ return ( bitfield[bitnumber/BITFIELDBITS] &
+ ( ((bitfieldtype) 1) << (bitnumber%BITFIELDBITS) ) ) != 0;
+}
+
+static bool isbitclear(bitfieldtype *bitfield, u4 bitnumber)
+{
+ return ( bitfield[bitnumber/BITFIELDBITS] &
+ ( ((bitfieldtype) 1) << (bitnumber%BITFIELDBITS) ) ) == 0;
+}
+
+
+/***************** Funktion: clearbitfield ************************************
+
+ l"oscht ein ganzes Bitfeld
+
+******************************************************************************/
+
+static void clearbitfield(bitfieldtype *bitfield, u4 fieldsize)
+{
+ u4 i,t;
+ t = ALIGN(fieldsize, BITFIELDBITS) / BITFIELDBITS;
+ for (i=0; i<t; i++) bitfield[i] = 0;
+}
+
+/************** Funktion: maskfieldwithfield **********************************
+
+ Verkn"upft zwei Bitfelder bitweise mit UND, das erste Bitfeld
+ wird mit dem Ergebnis "uberschrieben
+
+******************************************************************************/
+
+static void maskfieldwithfield (bitfieldtype* bitfield,
+ bitfieldtype *maskfield, u4 fieldsize)
+{
+ u4 i,t;
+ t = ALIGN(fieldsize, BITFIELDBITS) / BITFIELDBITS;
+ for (i=0; i<t; i++) bitfield[i] &= maskfield[i];
+}
+
+
+/************** Funktion: findnextsetbit **************************************
+
+ Sucht in einem Bitfeld ab einer Stelle das n"achste gesetzte Bit
+ und liefert die Nummer dieses Bits.
+ Wenn kein Bit mehr zwischen 'bitnumber' und 'fieldsize' gesetzt
+ ist, dann wird fieldsize zur"uckgeliefte.
+
+******************************************************************************/
+
+static u4 findnextsetbit(bitfieldtype* bitfield, u4 fieldsize, u4 bitnumber)
+{
+ bitfieldtype pattern;
+
+ for (;;) {
+ if (bitnumber >= fieldsize) return fieldsize;
+
+ pattern = bitfield[bitnumber/BITFIELDBITS];
+ pattern >>= (bitnumber%BITFIELDBITS);
+ if (pattern) return bitnumber + lowest(pattern);
+
+ bitnumber = ((bitnumber + BITFIELDBITS) / BITFIELDBITS) * BITFIELDBITS;
+ }
+}
+
+
+/************ Funktion: findnextcombination_set_unset *************************
+
+ funktioniert wie findnextsetbit, allerdings sucht diese Funktion
+ nach einer Stelle, an der gleichzeitig ein Bit im ersten
+ Bitfeld gesetzt ist und im zweiten Bitfeld das entsprechende
+ Bit nicht gesetzt ist.
+
+******************************************************************************/
+
+static u4 findnextcombination_set_unset
+ (bitfieldtype *bitfield1, bitfieldtype* bitfield2, u4 fieldsize, u4 bitnumber)
+{
+ bitfieldtype pattern;
+
+ for (;;) {
+ if (bitnumber >= fieldsize) return fieldsize;
+
+ pattern = bitfield1[bitnumber/BITFIELDBITS]
+ & (~bitfield2[bitnumber/BITFIELDBITS]);
+ pattern >>= (bitnumber%BITFIELDBITS);
+ if (pattern) return bitnumber + lowest(pattern);
+
+ bitnumber = ((bitnumber + BITFIELDBITS) / BITFIELDBITS) * BITFIELDBITS;
+ }
+}
+
+
+
+/************** Funktion: memlist_init ****************************************
+
+ initialisiert die Freispeicherlisten (zum nachfolgenden Eintragen
+ mit memlist_addrange).
+
+******************************************************************************/
+
+static void memlist_init ()
+{
+ u4 i;
+ for (i=0; i<DIFFERENTSIZES; i++) memlist[i] = NULL;
+ clearbitfield (memlistbits, DIFFERENTSIZES);
+ bigmemlist = NULL;
+}
+
+
+/************** Funktion: memlist_addrange ************************************
+
+ f"ugt einen Bereich von Heap-Bl"ocken zur Freispeicherliste
+ hinzu (in die freien Heap-Bl"ocke werden dabei verschiedene
+ Verkettungszeiger hineingeschrieben).
+
+******************************************************************************/
+
+static void memlist_addrange (u4 freestart, u4 freesize)
+{
+ if (freesize>=DIFFERENTSIZES) {
+ bigmemarea *m = (bigmemarea*) (heap+freestart);
+ m -> next = bigmemlist;
+ m -> size = freesize;
+ bigmemlist = m;
+ }
+ else {
+ if (freesize*BLOCKSIZE>=sizeof(memarea)) {
+ memarea *m = (memarea*) (heap+freestart);
+ m -> next = memlist[freesize];
+ memlist[freesize] = m;
+ setbit (memlistbits, freesize);
+ }
+ }
+}
+
+
+/************** Funktion: memlist_getsuitable *********************************
+
+ sucht in der Freispeicherliste einen Speicherbereich, der m"oglichst
+ genau die gew"unschte L"ange hat.
+ Der Bereich wird dabei auf jeden Fall aus der Liste ausgetragen.
+ (Wenn der Bereich zu lang sein sollte, dann kann der Aufrufer den
+ Rest wieder mit 'memlist_addrange' in die Liste einh"angen)
+
+ Return (in Referenzparametern):
+ *freestart: Anfang des freien Speichers
+ *freelength: L"ange dieses Speicherbereiches
+
+ Wenn kein passender Speicherblock mehr gefunden werden kann, dann
+ wird in '*freelength' 0 hineingeschrieben.
+
+******************************************************************************/
+
+static void memlist_getsuitable (u4 *freestart, u4 *freelength, u4 length)
+{
+ bigmemarea *m;
+ bigmemarea *prevm = NULL;
+
+ if (length<DIFFERENTSIZES) {
+ u4 firstfreelength;
+
+ if (memlist[length]) {
+ firstfreelength = length;
+ }
+ else {
+ firstfreelength = findnextsetbit
+ (memlistbits, DIFFERENTSIZES, length+3);
+ /* wenn kein passender Block da ist, dann gleich nach */
+ /* einem etwas gr"osseren suchen, damit keine kleinen */
+ /* St"uckchen "ubrigbleiben */
+ }
+
+ if (firstfreelength<DIFFERENTSIZES) {
+ memarea *m = memlist[firstfreelength];
+ memlist[firstfreelength] = m->next;
+ if (!m->next) clearbit (memlistbits, firstfreelength);
+ *freestart = ((heapblock*) m) - heap;
+ *freelength = firstfreelength;
+ return;
+ }
+ }
+
+ m = bigmemlist;
+ while (m) {
+ if (m->size >= length) {
+ if (prevm) prevm->next = m->next;
+ else bigmemlist = m->next;
+
+ *freestart = ((heapblock*) m) - heap;
+ *freelength = m->size;
+ return ;
+ }
+
+ prevm = m;
+ m = m->next;
+ }
+
+ *freelength=0;
+}
+
+
+
+
+
+/******************* Funktion: mark *******************************************
+
+ Markiert ein m"oglicherweise g"ultiges Objekt.
+ Sollte sich herausstellen, dass der Zeiger gar nicht auf ein Objekt
+ am Heap zeigt, dann wird eben gar nichts markiert.
+
+******************************************************************************/
+
+static void markreferences (void **rstart, void **rend);
+
+static void mark (heapblock *obj)
+{
+ u4 blocknum,objectend;
+
+ if ((long) obj & (BLOCKSIZE-1)) return;
+
+ if (obj<heap) return;
+ if (obj>=(heap+topofheap) ) return;
+
+ blocknum = obj-heap;
+ if ( isbitclear(startbits, blocknum) ) return;
+ if ( isbitset(markbits, blocknum) ) return;
+
+ setbit (markbits, blocknum);
+
+ if ( isbitclear(referencebits, blocknum) ) return;
+
+ objectend = findnextsetbit (startbits, topofheap, blocknum+1);
+ markreferences ((void**)obj, (void**) (heap+objectend) );
+}
+
+
+/******************** Funktion: markreferences ********************************
+
+ Geht einen Speicherbereich durch, und markiert alle Objekte, auf
+ die von diesem Bereich aus irgendeine Referenz existiert.
+
+******************************************************************************/
+
+static void markreferences (void **rstart, void **rend)
+{
+ void **ptr;
+
+ for (ptr=rstart; ptr<rend; ptr++) mark (*ptr);
+}
+
+
+/******************* Funktion: markstack **************************************
+
+ Marks all objects that are referenced by the (C-)stacks of
+ all live threads.
+
+ (The stack-bottom is to be specified in the call to heap_init).
+
+******************************************************************************/
+
+static void markstack () /* schani */
+{
+ void *dummy;
+ void **top_of_stack = &dummy;
+
+#ifdef USE_THREADS
+ thread *aThread;
+
+ for (aThread = liveThreads; aThread != 0; aThread = CONTEXT(aThread).nextlive) {
+ mark((heapblock*)aThread);
+ if (aThread == currentThread) {
+ if (top_of_stack > (void**)CONTEXT(aThread).stackEnd)
+ markreferences ((void**)CONTEXT(aThread).stackEnd, top_of_stack);
+ else
+ markreferences (top_of_stack, (void**)CONTEXT(aThread).stackEnd);
+ }
+ else {
+ if (CONTEXT(aThread).usedStackTop > CONTEXT(aThread).stackEnd)
+ markreferences ((void**)CONTEXT(aThread).stackEnd,
+ (void**)CONTEXT(aThread).usedStackTop + 16);
+ else
+ markreferences ((void**)CONTEXT(aThread).usedStackTop - 16,
+ (void**)CONTEXT(aThread).stackEnd);
+ }
+ }
+
+ markreferences((void**)&threadQhead[0], (void**)&threadQhead[MAX_THREAD_PRIO]);
+#else
+ if (top_of_stack > bottom_of_stack)
+ markreferences(bottom_of_stack, top_of_stack);
+ else
+ markreferences(top_of_stack, bottom_of_stack);
+#endif
+}
+
+
+
+/**************** Funktion: searchlivefinalizees *****************************
+
+ geht die Liste aller Objekte durch, die noch finalisiert werden m"ussen
+ (livefinalizees), und tr"agt alle nicht mehr markierten in die
+ Liste deadfinalizess ein (allerdings werden sie vorher noch als
+ erreicht markiert, damit sie nicht jetzt gleich gel"oscht werden).
+
+*****************************************************************************/
+
+static void searchlivefinalizees ()
+{
+ finalizernode *fn = livefinalizees;
+ finalizernode *lastlive = NULL;
+
+ while (fn) {
+
+ /* alle zu finalisierenden Objekte, die nicht mehr markiert sind: */
+ if (isbitclear (markbits, fn->objstart)) {
+ finalizernode *nextfn = fn->next;
+
+ mark (heap + fn->objstart);
+
+ if (lastlive) lastlive -> next = nextfn;
+ else livefinalizees = nextfn;
+
+ fn -> next = deadfinalizees;
+ deadfinalizees = fn;
+
+ fn = nextfn;
+ }
+ else {
+ lastlive = fn;
+ fn = fn->next;
+ }
+ }
+}
+
+
+
+/********************** Funktion: finalizedead *******************************
+
+ ruft die 'finalize'-Methode aller Objekte in der 'deadfinalizees'-
+ Liste auf.
+ Achtung: Es kann hier eventuell zu neuerlichen Speicheranforderungen
+ (mit potentiell notwendigem GC) kommen, deshalb m"ussen manche
+ globalen Variablen in lokale Variblen kopiert werden
+ (Reentrant-F"ahigkeit!!!)
+
+******************************************************************************/
+
+static void finalizedead()
+{
+ finalizernode *fn = deadfinalizees;
+ deadfinalizees = NULL;
+
+ while (fn) {
+ finalizernode *nextfn = fn->next;
+
+ asm_calljavamethod (fn->finalizer, heap+fn->objstart, NULL,NULL,NULL);
+ FREE (fn, finalizernode);
+
+ fn = nextfn;
+ }
+
+}
+
+
+
+/****************** Funktion: heap_docollect **********************************
+
+ F"uhrt eine vollst"andige Garbage Collection durch
+
+******************************************************************************/
+
+static void heap_docollect ()
+{
+ u4 freestart,freeend;
+ void **p;
+ bitfieldtype *dummy;
+ u4 heapfreemem;
+ u4 oldfillgrade;
+
+
+ if (runverbose) {
+ fprintf(stderr, "doing garbage collection\n");
+ }
+ /* alle Markierungsbits l"oschen */
+ clearbitfield (markbits, topofheap);
+
+ /* Alle vom Stack referenzierten Objekte markieren */
+ asm_dumpregistersandcall (markstack);
+
+ /* Alle von globalen Variablen erreichbaren Objekte markieren */
+ p = chain_first (allglobalreferences);
+ while (p) {
+ mark (*p);
+ p = chain_next (allglobalreferences);
+ }
+
+ /* alle Objekte durchsehen, die eine finalizer-Methode haben */
+ searchlivefinalizees();
+
+ /* alle Reference-Bits l"oschen, deren Objekte nicht */
+ /* mehr erreichbar sind */
+ maskfieldwithfield (referencebits, markbits, topofheap);
+
+
+ /* Freispeicherliste initialisieren */
+ memlist_init ();
+
+
+ /* Heap schrittweise durchgehen, und alle freien Bl"ocke merken */
+
+ heapfreemem = 0;
+ freeend=0;
+ for (;;) {
+ /* Anfang des n"achsten freien Bereiches suchen */
+ freestart = findnextcombination_set_unset
+ (startbits, markbits, topofheap, freeend);
+
+ /* Wenn es keinen freien Bereich mehr gibt -> fertig */
+ if (freestart>=topofheap) goto freememfinished;
+
+ /* Anfang des freien Bereiches markieren */
+ setbit (markbits, freestart);
+
+ /* Ende des freien Bereiches suchen */
+ freeend = findnextsetbit (markbits, topofheap, freestart+1);
+
+ /* Freien Bereich in Freispeicherliste einh"angen */
+ memlist_addrange (freestart, freeend-freestart);
+
+ /* Menge des freien Speichers mitnotieren */
+ heapfreemem += (freeend-freestart);
+ }
+
+ freememfinished:
+
+ /* Die Rollen von markbits und startbits vertauschen */
+ dummy = markbits;
+ markbits = startbits;
+ startbits = dummy;
+
+
+ /* Threashold-Wert f"ur n"achstes Collect */
+ oldfillgrade = heapfillgrade;
+ heapfillgrade = topofheap - heapfreemem;
+ collectthreashold = heapfillgrade*3; /* eine nette Heuristik */
+
+ /* Eventuell eine Meldung ausgeben */
+ if (collectverbose) {
+ sprintf (logtext, "Garbage Collection: previous/now = %d / %d ",
+ (int) (oldfillgrade * BLOCKSIZE),
+ (int) (heapfillgrade * BLOCKSIZE) );
+ dolog ();
+ }
+
+
+
+ /* alle gerade unerreichbar gewordenen Objekte mit
+ finalize-Methoden jetzt finalisieren.
+ Achtung: Diese Funktion kann zu neuerlichem GC f"uhren!! */
+ finalizedead ();
+
+}
+
+/************************* Function: gc_init **********************************
+
+ Initializes the garbage collection thread mechanism.
+
+******************************************************************************/
+
+#ifdef USE_THREADS
+iMux gcStartMutex;
+iMux gcThreadMutex;
+iCv gcConditionStart;
+iCv gcConditionDone;
+
+void
+gc_init (void)
+{
+ gcStartMutex.holder = 0;
+ gcStartMutex.count = 0;
+ gcStartMutex.muxWaiters = 0;
+
+ gcThreadMutex.holder = 0;
+ gcThreadMutex.count = 0;
+ gcThreadMutex.muxWaiters = 0;
+
+ gcConditionStart.cvWaiters = 0;
+ gcConditionStart.mux = 0;
+
+ gcConditionDone.cvWaiters = 0;
+ gcConditionDone.mux = 0;
+}
+#else
+void
+gc_init (void)
+{
+}
+#endif
+
+/************************* Function: gc_thread ********************************
+
+ In an endless loop waits for a condition to be posted, then
+ garbage collects the heap.
+
+******************************************************************************/
+
+#ifdef USE_THREADS
+void
+gc_thread (void)
+{
+ intsRestore(); /* all threads start with interrupts disabled */
+
+ assert(blockInts == 0);
+
+ lock_mutex(&gcThreadMutex);
+
+ for (;;)
+ {
+ wait_cond(&gcThreadMutex, &gcConditionStart, 0);
+
+ intsDisable();
+ heap_docollect();
+ intsRestore();
+
+ signal_cond(&gcConditionDone);
+ }
+}
+#endif
+
+void
+gc_call (void)
+{
+#ifdef USE_THREADS
+ lock_mutex(&gcThreadMutex);
+
+ signal_cond(&gcConditionStart);
+ wait_cond(&gcThreadMutex, &gcConditionDone, 0);
+
+ unlock_mutex(&gcThreadMutex);
+#else
+ heap_docollect();
+#endif
+}
+
+
+/************************* Funktion: heap_init ********************************
+
+ Initialisiert den Garbage Collector.
+ Parameter:
+ heapbytesize: Maximale Gr"osse des Heap (in Bytes)
+ heapbytestartsize: Gr"osse des Heaps, bei dem zum ersten mal eine
+ GC durchgef"uhrt werden soll.
+ stackbottom: Ein Zeiger auf die Untergrenze des Stacks, im dem
+ Referenzen auf Objekte stehen k"onnen.
+
+******************************************************************************/
+
+void heap_init (u4 heapbytesize, u4 heapbytestartsize, void **stackbottom)
+{
+
+#ifdef TRACECALLARGS
+
+ heapsize = ALIGN (heapbytesize, getpagesize());
+ heapsize = heapsize/BLOCKSIZE;
+ heap = (void*) mmap ((void*) 0x10000000, (size_t) (heapsize * BLOCKSIZE),
+ PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, (off_t) 0);
+ if (heap != (void *) 0x10000000) {
+ perror("mmap");
+ printf("address = %p\n", heap);
+ panic("mmap failed\n");
+ }
+
+#else
+
+ heapsize = ALIGN (heapbytesize, 1024);
+ heapsize = heapsize/BLOCKSIZE;
+ heap = MNEW (heapblock, heapsize);
+
+#endif
+
+ topofheap = 0;
+ startbits = MNEW (bitfieldtype, heapsize/BITFIELDBITS);
+ markbits = MNEW (bitfieldtype, heapsize/BITFIELDBITS);
+ referencebits = MNEW (bitfieldtype, heapsize/BITFIELDBITS);
+ clearbitfield (startbits, heapsize);
+ clearbitfield (markbits, heapsize);
+ clearbitfield (referencebits, heapsize);
+
+ heapfillgrade = 0;
+ collectthreashold = heapbytestartsize/BLOCKSIZE;
+ allglobalreferences = chain_new ();
+ bottom_of_stack = stackbottom;
+
+ livefinalizees = NULL;
+ deadfinalizees = NULL;
+}
+
+
+/****************** Funktion: heap_close **************************************
+
+ Gibt allen ben"otigten Speicher frei
+
+******************************************************************************/
+
+void heap_close ()
+{
+#ifndef TRACECALLARGS
+ MFREE (heap, heapblock, heapsize); */
+#endif
+ MFREE (startbits, bitfieldtype, heapsize/BITFIELDBITS);
+ MFREE (markbits, bitfieldtype, heapsize/BITFIELDBITS);
+ MFREE (referencebits, bitfieldtype, heapsize/BITFIELDBITS);
+ chain_free (allglobalreferences);
+
+ while (livefinalizees) {
+ finalizernode *n = livefinalizees->next;
+ FREE (livefinalizees, finalizernode);
+ livefinalizees = n;
+ }
+}
+
+
+/***************** Funktion: heap_addreference ********************************
+
+ Teilt dem GC eine Speicherstelle mit, an der eine globale Referenz
+ auf Objekte gespeichert sein kann.
+
+******************************************************************************/
+
+void heap_addreference (void **reflocation)
+{
+ intsDisable(); /* schani */
+
+ chain_addlast (allglobalreferences, reflocation);
+
+ intsRestore(); /* schani */
+}
+
+
+
+/***************** Funktion: heap_allocate ************************************
+
+ Fordert einen Speicher vom Heap an, der eine gew"unschte Gr"osse
+ (in Byte angegeben) haben muss.
+ Wenn kein Speicher mehr vorhanden ist (auch nicht nach einem
+ Garbage Collection-Durchlauf), dann wird NULL zur"uckgegeben.
+ Zus"atzlich wird durch den Parameter 'references' angegeben, ob
+ in das angelegte Objekt Referenzen auf andere Objekte eingetragen
+ werden k"onnten.
+ (Wichtig wegen Beschleunigung des Mark&Sweep-Durchlauf)
+ Im Zweifelsfalle immer references=true verwenden.
+
+******************************************************************************/
+
+void *heap_allocate (u4 bytelength, bool references, methodinfo *finalizer)
+{
+ u4 freestart,freelength;
+ u4 length = ALIGN(bytelength, BLOCKSIZE) / BLOCKSIZE;
+
+ intsDisable(); /* schani */
+
+ memlist_getsuitable (&freestart, &freelength, length);
+
+onemoretry:
+ if (!freelength) {
+ if ( (topofheap+length > collectthreashold)
+ || (topofheap+length > heapsize) ) {
+
+ intsRestore();
+ gc_call();
+ intsDisable();
+
+ memlist_getsuitable (&freestart, &freelength, length);
+ if (freelength) goto onemoretry;
+ }
+
+ if (topofheap+length > heapsize) {
+ sprintf (logtext, "Heap-Allocation failed for %d bytes",
+ (int) bytelength);
+ dolog();
+ intsRestore(); /* schani */
+ return NULL;
+ }
+
+ freestart = topofheap;
+ freelength = length;
+ setbit (startbits, topofheap);
+ topofheap += length;
+ }
+ else {
+ if (freelength>length) {
+ setbit (startbits, freestart+length);
+ memlist_addrange (freestart+length, freelength-length);
+ }
+ }
+
+ if (references) setbit (referencebits, freestart);
+
+ heapfillgrade += length;
+
+ if (finalizer) {
+ finalizernode *n = NEW(finalizernode);
+ n -> next = livefinalizees;
+ n -> objstart = freestart;
+ n -> finalizer = finalizer;
+ livefinalizees = n;
+ }
+
+ intsRestore(); /* schani */
+
+ if (runverbose) {
+ sprintf (logtext, "new returns: %lx", (long) (heap + freestart));
+ dolog ();
+ }
+
+ return (void*) (heap + freestart);
+}
+
+
+
+
--- /dev/null
+/****************************** tables.h ***************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Author: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1996/11/20
+
+*******************************************************************************/
+
+extern bool collectverbose;
+
+
+#define CLASS(name) (unicode_getclasslink(unicode_new_char(name)))
+
+typedef void (*stringdeleter) ( java_objectheader *string );
+
+
+void suck_init (char *classpath);
+bool suck_start (unicode *name);
+void suck_stop ();
+void suck_nbytes (u1 *buffer, u4 len);
+void skip_nbytes (u4 len);
+u1 suck_u1 ();
+s1 suck_s1 ();
+u2 suck_u2 ();
+s2 suck_s2 ();
+u4 suck_u4 ();
+s4 suck_s4 ();
+u8 suck_u8 ();
+s8 suck_s8 ();
+float suck_float ();
+double suck_double ();
+
+
+void unicode_init ();
+void unicode_close (stringdeleter del);
+void unicode_display (unicode *u);
+void unicode_sprint (char *buffer, unicode *u);
+void unicode_fprint (FILE *file, unicode *u);
+unicode *unicode_new_u2 (u2 *text, u2 length);
+unicode *unicode_new_char (char *text);
+void unicode_setclasslink (unicode *u, classinfo *class);
+classinfo *unicode_getclasslink (unicode *u);
+void unicode_unlinkclass (unicode *u);
+void unicode_setstringlink (unicode *u, java_objectheader *str);
+void unicode_unlinkstring (unicode *u);
+void unicode_show ();
+
+u2 desc_to_type (unicode *descriptor);
+u2 desc_typesize (unicode *descriptor);
+
+
+void heap_init (u4 size, u4 startsize, void **stackbottom);
+void heap_close ();
+void *heap_allocate (u4 bytelength, bool references, methodinfo *finalizer);
+void heap_addreference (void **reflocation);
+
+void gc_init (void);
+void gc_thread (void);
+void gc_call (void);
--- /dev/null
+import java.util.*;
+import java.io.*;
+
+class SubClass1 extends Object {
+}
+
+class SubClass2 extends Object {
+ int a,b,c;
+
+ SubClass2 (int aa, int ab, int ac) {
+ a = aa;
+ b = ab;
+ c = ac;
+ }
+
+ public void methodWithLocalAccess () {
+ int la,lb,lc;
+ for (int i=0; i<JavaPerformance.MAXCOUNT; i++) {
+ la = 5;
+ lb = 6;
+ lc = 7;
+ }
+ }
+
+ public void methodWithInstanceAccess () {
+ for (int i=0; i<JavaPerformance.MAXCOUNT; i++) {
+ a = 5;
+ b = 6;
+ c = 7;
+ }
+ }
+}
+
+class List extends Object {
+
+ static Random r = new Random();
+
+ List[] data;
+ char[] memory;
+
+ List (int depth) {
+ memory = new char[512];
+ if (depth>0) {
+ int length = 1+Math.abs(r.nextInt())%5;
+ data = new List[length];
+ for (int i=0; i<length; i++)
+ data[i] = new List (depth-1);
+ }
+ }
+}
+
+public class JavaPerformance {
+
+ static final int MAXCOUNT = 500000;
+ static Throwable aThrowable = new Throwable ();
+
+ public JavaPerformance () {
+ super();
+ }
+
+ // static
+
+ static public int staticCall () {
+ return 0;
+ }
+
+ static public final int staticFinalCall () {
+ return 0;
+ }
+
+ static public synchronized int synchronizedStaticCall () {
+ return 0;
+ }
+
+ static public void throwingStaticCall () throws Throwable {
+ throw new Throwable ();
+ }
+
+ // methods
+
+ public int methodCall () {
+ return 0;
+ }
+
+ public final int finalMethodCall () {
+ return 0;
+ }
+
+ static public synchronized int synchronizedMethodCall () {
+ return 0;
+ }
+
+ static public void throwingMethodCall () throws Throwable {
+ throw new Throwable ();
+ }
+
+ // ggT
+
+ public static int ggT (int x, int y) {
+ while (x!=y) {
+ if (x<y) y = y-x; else x = x-y;
+ }
+ return x;
+ }
+
+ public static long fak (long x) {
+ if (x>1)
+ return x*fak(x-1);
+ else
+ return 1;
+ }
+
+ public static void arithmeticTest () {
+ System.out.println ("Arithmetic time");
+ System.out.println ();
+
+ System.out.print ("ggT (24,42)...");
+ long l = System.currentTimeMillis();
+ for (int i = 0; i<MAXCOUNT; i++)
+ ggT (24,42);
+ long e = System.currentTimeMillis();
+ System.out.print ("(");
+ System.out.print (((double) e-l)/MAXCOUNT);
+ System.out.print ("ms ");
+ System.out.print(e-l);
+ System.out.print ("ms/");
+ System.out.print (MAXCOUNT);
+ System.out.println (")");
+
+ System.out.print ("13!...");
+ l = System.currentTimeMillis();
+ for (int i = 0; i<MAXCOUNT; i++)
+ fak (13);
+ e = System.currentTimeMillis();
+ System.out.print ("(");
+ System.out.print (((double) e-l)/MAXCOUNT);
+ System.out.print ("ms ");
+ System.out.print(e-l);
+ System.out.print ("ms/");
+ System.out.print (MAXCOUNT);
+ System.out.println (")");
+ }
+
+ public static void memoryTest () {
+ System.out.println ("Memory time");
+ System.out.println ();
+
+ System.out.print ("Object creation...");
+ long l = System.currentTimeMillis();
+ for (int i = 0; i<MAXCOUNT; i++)
+ new Object ();
+ long e = System.currentTimeMillis();
+ System.out.print ("(");
+ System.out.print (((double) e-l)/MAXCOUNT);
+ System.out.print ("ms ");
+ System.out.print(e-l);
+ System.out.print ("ms/");
+ System.out.print (MAXCOUNT);
+ System.out.println (")");
+
+ System.out.print ("Subclass creation...");
+ l = System.currentTimeMillis();
+ for (int i = 0; i<MAXCOUNT; i++)
+ new SubClass1 ();
+ e = System.currentTimeMillis();
+ System.out.print ("(");
+ System.out.print (((double) e-l)/MAXCOUNT);
+ System.out.print ("ms ");
+ System.out.print(e-l);
+ System.out.print ("ms/");
+ System.out.print (MAXCOUNT);
+ System.out.println (")");
+
+ System.out.print ("Subclass creation with constructor call...");
+ l = System.currentTimeMillis();
+ for (int i = 0; i<MAXCOUNT; i++)
+ new SubClass2 (1,2,3);
+ e = System.currentTimeMillis();
+ System.out.print ("(");
+ System.out.print (((double) e-l)/MAXCOUNT);
+ System.out.print ("ms ");
+ System.out.print(e-l);
+ System.out.print ("ms/");
+ System.out.print (MAXCOUNT);
+ System.out.println (")");
+
+ System.out.print ("List generation (GC test)...");
+ l = System.currentTimeMillis();
+ for (int i = 0; i<250; i++)
+ new List (5);
+ e = System.currentTimeMillis();
+ System.out.print ("(");
+ System.out.print (((double) e-l)/250);
+ System.out.print ("ms ");
+ System.out.print(e-l);
+ System.out.print ("ms/");
+ System.out.print (250);
+ System.out.println (")");
+
+ }
+
+ public static void methodTest () {
+ SubClass2 object = new SubClass2 (1,2,3);
+
+ System.out.println ("Method execution time");
+ System.out.println ();
+
+ System.out.print ("Method with access only to local variables...");
+ long l = System.currentTimeMillis();
+ object.methodWithLocalAccess ();
+ long e = System.currentTimeMillis();
+ System.out.print ("(");
+ System.out.print (((double) e-l)/MAXCOUNT);
+ System.out.print ("ms ");
+ System.out.print(e-l);
+ System.out.print ("ms/");
+ System.out.print (MAXCOUNT);
+ System.out.println (")");
+
+ System.out.print ("Method with access only to instance variables...");
+ l = System.currentTimeMillis();
+ object.methodWithInstanceAccess ();
+ e = System.currentTimeMillis();
+ System.out.print ("(");
+ System.out.print (((double) e-l)/MAXCOUNT);
+ System.out.print ("ms ");
+ System.out.print(e-l);
+ System.out.print ("ms/");
+ System.out.print (MAXCOUNT);
+ System.out.println (")");
+ }
+
+ public static void callTest () {
+ JavaPerformance object = new JavaPerformance ();
+
+ System.out.println ("Calling time");
+ System.out.println ();
+ System.out.print ("Static function call...");
+ long l = System.currentTimeMillis();
+ for (int i = 0; i<MAXCOUNT; i++)
+ staticCall ();
+ long e = System.currentTimeMillis();
+ System.out.print ("(");
+ System.out.print (((double) e-l)/MAXCOUNT);
+ System.out.print ("ms ");
+ System.out.print(e-l);
+ System.out.print ("ms/");
+ System.out.print (MAXCOUNT);
+ System.out.println (")");
+
+ System.out.print ("Static final function call...");
+ l = System.currentTimeMillis();
+ for (int i = 0; i<MAXCOUNT; i++)
+ staticFinalCall ();
+ e = System.currentTimeMillis();
+ System.out.print ("(");
+ System.out.print (((double) e-l)/MAXCOUNT);
+ System.out.print ("ms ");
+ System.out.print(e-l);
+ System.out.print ("ms/");
+ System.out.print (MAXCOUNT);
+ System.out.println (")");
+
+ System.out.print ("Static synchronized function call...");
+ l = System.currentTimeMillis();
+ for (int i = 0; i<MAXCOUNT; i++)
+ synchronizedStaticCall();
+ e = System.currentTimeMillis();
+ System.out.print ("(");
+ System.out.print (((double) e-l)/MAXCOUNT);
+ System.out.print ("ms ");
+ System.out.print(e-l);
+ System.out.print ("ms/");
+ System.out.print (MAXCOUNT);
+ System.out.println (")");
+
+ System.out.print ("Static function call in try catch block...");
+ l = System.currentTimeMillis();
+ for (int i = 0; i<MAXCOUNT; i++)
+ try {
+ staticCall ();
+ } catch (Throwable a) {
+ }
+ e = System.currentTimeMillis();
+ System.out.print ("(");
+ System.out.print (((double) e-l)/MAXCOUNT);
+ System.out.print ("ms ");
+ System.out.print(e-l);
+ System.out.print ("ms/");
+ System.out.print (MAXCOUNT);
+ System.out.println (")");
+
+ System.out.print ("Static exception throwing function call...");
+ l = System.currentTimeMillis();
+ for (int i = 0; i<5000; i++)
+ try {
+ throwingStaticCall ();
+ } catch (Throwable exp) {
+ }
+ e = System.currentTimeMillis();
+ System.out.print ("(");
+ System.out.print (((double) e-l)/5000);
+ System.out.print ("ms ");
+ System.out.print(e-l);
+ System.out.print ("ms/");
+ System.out.print (5000);
+ System.out.println (")");
+
+
+ System.out.print ("Method call...");
+ l = System.currentTimeMillis();
+ for (int i = 0; i<MAXCOUNT; i++)
+ object.methodCall ();
+ e = System.currentTimeMillis();
+ System.out.print ("(");
+ System.out.print (((double) e-l)/MAXCOUNT);
+ System.out.print ("ms ");
+ System.out.print(e-l);
+ System.out.print ("ms/");
+ System.out.print (MAXCOUNT);
+ System.out.println (")");
+
+ System.out.print ("Final method call...");
+ l = System.currentTimeMillis();
+ for (int i = 0; i<MAXCOUNT; i++)
+ object.finalMethodCall ();
+ e = System.currentTimeMillis();
+ System.out.print ("(");
+ System.out.print (((double) e-l)/MAXCOUNT);
+ System.out.print ("ms ");
+ System.out.print(e-l);
+ System.out.print ("ms/");
+ System.out.print (MAXCOUNT);
+ System.out.println (")");
+
+ System.out.print ("Synchronized method call...");
+ l = System.currentTimeMillis();
+ for (int i = 0; i<MAXCOUNT; i++)
+ object.synchronizedMethodCall();
+ e = System.currentTimeMillis();
+ System.out.print ("(");
+ System.out.print (((double) e-l)/MAXCOUNT);
+ System.out.print ("ms ");
+ System.out.print(e-l);
+ System.out.print ("ms/");
+ System.out.print (MAXCOUNT);
+ System.out.println (")");
+
+ System.out.print ("Method call in try catch block...");
+ l = System.currentTimeMillis();
+ for (int i = 0; i<MAXCOUNT; i++)
+ try {
+ object.methodCall ();
+ } catch (Throwable a) {
+ }
+ e = System.currentTimeMillis();
+ System.out.print ("(");
+ System.out.print (((double) e-l)/MAXCOUNT);
+ System.out.print ("ms ");
+ System.out.print(e-l);
+ System.out.print ("ms/");
+ System.out.print (MAXCOUNT);
+ System.out.println (")");
+
+ System.out.print ("Exception throwing method call...");
+ l = System.currentTimeMillis();
+ for (int i = 0; i<50000; i++)
+ try {
+ object.throwingMethodCall ();
+ } catch (Throwable exp) {
+ }
+ e = System.currentTimeMillis();
+ System.out.print ("(");
+ System.out.print (((double) e-l)/5000);
+ System.out.print ("ms ");
+ System.out.print(e-l);
+ System.out.print ("ms/");
+ System.out.print (5000);
+ System.out.println (")");
+ }
+
+ public static final void main (String[] args) {
+ long l = System.currentTimeMillis();
+ arithmeticTest ();
+ System.out.println ();
+ callTest ();
+ System.out.println ();
+ methodTest ();
+ System.out.println ();
+ memoryTest ();
+ System.out.println ();
+ System.out.print ("Overall time ");
+ System.out.print(System.currentTimeMillis()-l);
+ System.out.println ("ms");
+ }
+}
--- /dev/null
+public interface a extends b
+{
+ public void do_a ();
+ public void do_a2 ();
+}
--- /dev/null
+public class array extends Object
+{
+ public static void main (String args[])
+ {
+ System.out.println(args[0]);
+ }
+}
--- /dev/null
+public interface b
+{
+ public void do_b ();
+}
--- /dev/null
+public class counter {
+ static public void main (String [] s) {
+
+ int n = Integer.parseInt (s[0]);
+
+ System.out.print ("Counting ");
+ System.out.print (n);
+ System.out.println (" times from 0 to 9999...");
+
+ int i,j;
+ for (j=0; j<n; j++)
+ for (i=0; i<10000; i++) {
+ }
+
+ System.out.println ("... done");
+ }
+
+ }
+
+
\ No newline at end of file
--- /dev/null
+import java.io.*;
+
+public class extest extends Object
+{
+ public static void main (String args[])
+ {
+ try
+ {
+ RandomAccessFile file = new RandomAccessFile("test.file", "rw");
+
+ file.seek(file.length());
+ }
+ catch (Exception exc)
+ {
+ System.out.println("could not open file");
+ }
+ }
+}
--- /dev/null
+import java.io.*;
+
+
+public class filter {
+ public static void main(String argv[]) {
+
+ DataInputStream in = new DataInputStream(System.in);
+
+
+ try {
+ while (true) {
+ byte b = in.readByte();
+ if (b <= 128) {
+ int x = b;
+ System.out.println("BYTE: " + x);
+ } else {
+ String x = "non ascii: " + b;
+ System.out.println(x);
+ }
+ }
+ }
+ catch (IOException e) {
+ System.out.println("-- END OF FILE --");
+ }
+ finally {
+ System.out.println("--- Cool finally ---");
+ }
+ }
+}
--- /dev/null
+public class fintest {
+ public int num;
+
+ public fintest (int n) { num = n; }
+
+ public void finalize () {
+ System.out.print ("finalized ");
+ System.out.print (num);
+ System.out.println (". object");
+ }
+
+ public static void main (String[] s) {
+ int i;
+ fintest f=null;
+
+ for (i=0; i<100; i++) {
+ System.out.print (i);
+ System.out.println (". Objekt wird angelegt");
+ f = new fintest(i);
+ byte[] b = new byte[1000000];
+ b[0] = 0;
+ }
+
+ Runtime.getRuntime().exit(0);
+
+ }
+
+ }
+
+
\ No newline at end of file
--- /dev/null
+public class fp {
+ public static void main(String [] s) {
+
+ float a=10,b=10;
+ int i;
+
+ for (i=0; i<1000; i++) {
+ a*=b;
+ p(a);
+ }
+
+ for (a=0; a<1; a+=0.2) {
+ for (b=0; b<1; b+=0.2) {
+ System.out.println ("-----------");
+ p(a);
+ p(b);
+ p(a+b);
+ p(a-b);
+ p(a*b);
+ p(a/b);
+ }
+ }
+ }
+
+
+ public static void p(double d) {
+ System.out.println (d);
+ }
+ public static void p(float d) {
+ System.out.println (d);
+ }
+
+ }
--- /dev/null
+/***************************** alpha/ngen.c ************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Contains the codegenerator for an Alpha processor.
+ This module generates Alpha machine code for a sequence of
+ pseudo commands (ICMDs).
+
+ Authors: Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
+ Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1998/08/10
+
+*******************************************************************************/
+
+public class fptest {
+ public static void main(String [] s) {
+
+ float fnan = Float.NaN;
+ float fpinf = Float.POSITIVE_INFINITY;
+ float fninf = Float.NEGATIVE_INFINITY;
+ float fmax = Float.MAX_VALUE;
+ float fmin = Float.MIN_VALUE;
+ float f1 = 0F;
+ float f2 = 0F;
+
+ double dnan = Double.NaN;
+ double dpinf = Double.POSITIVE_INFINITY;
+ double dninf = Double.NEGATIVE_INFINITY;
+ double dmax = Double.MAX_VALUE;
+ double dmin = Double.MIN_VALUE;
+ double d1 = 0D;
+ double d2 = 0D;
+
+ p("---------------------------- tests NaNs and Infs -------------------");
+ p("------------------- print NaNs and Infs");
+
+ p("NaNQ ", fnan);
+ p("+INF ", fpinf);
+ p("-INF ", fninf);
+
+ p("NaNQ ", dnan);
+ p("+INF ", dpinf);
+ p("-INF ", dninf);
+
+ p("------------------- test zero division");
+
+ zerodiv("0 / 0 = NaNQ ", 0F, f1);
+ zerodiv("+ / 0 = +INF ", 5F, f1);
+ zerodiv("- / 0 = -INF ", -5F, f1);
+
+ zerodiv("0 / 0 = NaNQ ", 0D, d1);
+ zerodiv("+ / 0 = +INF ", 5D, d1);
+ zerodiv("- / 0 = -INF ", -5D, d1);
+
+ p("------------------- test conversions");
+ testfcvt("NaNQ", fnan, dnan);
+ testfcvt("+INF", fpinf, dpinf);
+ testfcvt("-INF", fninf, dninf);
+ testfcvt(" MAX", fmax, dmax);
+ testfcvt(" MIN", fmin, dmin);
+ testfcvt("MAXINT-1", 2147483646.0F, 2147483646.0D);
+ testfcvt("MAXINT+0", 2147483647.0F, 2147483647.0D);
+ testfcvt("MAXINT+1", 2147483648.0F, 2147483648.0D);
+ testfcvt("-MAXINT+1", -2147483647.0F, -2147483647.0D);
+ testfcvt("-MAXINT+0", -2147483648.0F, -2147483648.0D);
+ testfcvt("-MAXINT-1", -2147483649.0F, -2147483649.0D);
+ testfcvt("MAXLNG-1", 9223372036854775806.0F, 9223372036854775806.0D);
+ testfcvt("MAXLNG+0", 9223372036854775807.0F, 9223372036854775807.0D);
+ testfcvt("MAXLNG+1", 9223372036854775808.0F, 9223372036854775808.0D);
+ testfcvt("-MAXLNG+1", -9223372036854775807.0F, -9223372036854775807.0D);
+ testfcvt("-MAXLNG+0", -9223372036854775808.0F, -9223372036854775808.0D);
+ testfcvt("-MAXLNG-1", -9223372036854775809.0F, -9223372036854775809.0D);
+
+ p("------------------- test NaNQ op value");
+ testfops("NaNQ", "5.0", fnan, 5F, dnan, 5D);
+ testfcmp("NaNQ", "5.0", fnan, 5F, dnan, 5D);
+
+ p("------------------- test value op NaNQ");
+ testfops("5.0", "NaNQ", 5F, fnan, 5D, dnan);
+ testfcmp("5.0", "NaNQ", 5F, fnan, 5D, dnan);
+
+ p("------------------- test +INF op value");
+ testfops("+INF", "5.0", fpinf, 5F, dpinf, 5D);
+ testfcmp("+INF", "5.0", fpinf, 5F, dpinf, 5D);
+
+ p("------------------- test +INF op value");
+ testfops("5.0", "+INF", 5F, fpinf, 5D, dpinf);
+ testfcmp("5.0", "+INF", 5F, fpinf, 5D, dpinf);
+
+ p("------------------- test -INF op value");
+ testfops("-INF", "5.0", fninf, 5F, dninf, 5D);
+ testfcmp("-INF", "5.0", fninf, 5F, dninf, 5D);
+
+ p("------------------- test -INF op value");
+ testfops("5.0", "-INF", 5F, fninf, 5D, dninf);
+ testfcmp("5.0", "-INF", 5F, fninf, 5D, dninf);
+
+ p("------------------- test MAX op value");
+ testfops("MAX", "5.0", fmax, 5F, dmax, 5D);
+
+ p("------------------- test value op MAX");
+ testfops("5.0", "MAX", 5F, fmax, 5D, dmax);
+
+ p("------------------- test MIN op value");
+ testfops("MIN", "5.0", fmin, 5F, dmin, 5D);
+
+ p("------------------- test value op MIN");
+ testfops("5.0", "MIN", 5F, fmin, 5D, dmin);
+
+ }
+
+ public static void zerodiv(String s, float f1, float f2) {
+ p(s, f1 / f2);
+ }
+
+ public static void zerodiv(String s, double d1, double d2) {
+ p(s, d1 / d2);
+ }
+
+ public static void testfcvt(String s1, float f1, double d1) {
+ p("convert " + s1 + " (" + f1 + "," + d1 + ") to ", (int) f1);
+ p("convert " + s1 + " (" + f1 + "," + d1 + ") to ", (int) d1);
+ p("convert " + s1 + " (" + f1 + "," + d1 + ") to ", (long) f1);
+ p("convert " + s1 + " (" + f1 + "," + d1 + ") to ", (long) d1);
+ }
+
+ public static void testfops(String s1, String s2, float f1, float f2,
+ double d1, double d2) {
+ p(s1 + " + " + s2 + " = ", f1 + f2);
+ p(s1 + " - " + s2 + " = ", f1 - f2);
+ p(s1 + " * " + s2 + " = ", f1 * f2);
+ p(s1 + " / " + s2 + " = ", f1 / f2);
+ p(s1 + " % " + s2 + " = ", f1 % f2);
+ p(s1 + " + " + s2 + " = ", d1 + d2);
+ p(s1 + " - " + s2 + " = ", d1 - d2);
+ p(s1 + " * " + s2 + " = ", d1 * d2);
+ p(s1 + " / " + s2 + " = ", d1 / d2);
+ p(s1 + " % " + s2 + " = ", d1 % d2);
+ }
+
+ public static void testfcmp(String s1, String s2, float f1, float f2,
+ double d1, double d2) {
+
+ if ( (f1 == f2)) p(" (" + s1 + " == " + s2 + ") = true");
+ else p(" (" + s1 + " == " + s2 + ") = false");
+ if ( (f1 != f2)) p(" (" + s1 + " != " + s2 + ") = true");
+ else p(" (" + s1 + " != " + s2 + ") = false");
+ if ( (f1 < f2)) p(" (" + s1 + " < " + s2 + ") = true");
+ else p(" (" + s1 + " < " + s2 + ") = false");
+ if ( (f1 <= f2)) p(" (" + s1 + " <= " + s2 + ") = true");
+ else p(" (" + s1 + " <= " + s2 + ") = false");
+ if ( (f1 > f2)) p(" (" + s1 + " > " + s2 + ") = true");
+ else p(" (" + s1 + " > " + s2 + ") = false");
+ if ( (f1 >= f2)) p(" (" + s1 + " >= " + s2 + ") = true");
+ else p(" (" + s1 + " >= " + s2 + ") = false");
+
+ if (!(f1 == f2)) p("!(" + s1 + " == " + s2 + ") = true");
+ else p("!(" + s1 + " == " + s2 + ") = false");
+ if (!(f1 != f2)) p("!(" + s1 + " != " + s2 + ") = true");
+ else p("!(" + s1 + " != " + s2 + ") = false");
+ if (!(f1 < f2)) p("!(" + s1 + " < " + s2 + ") = true");
+ else p("!(" + s1 + " < " + s2 + ") = false");
+ if (!(f1 <= f2)) p("!(" + s1 + " <= " + s2 + ") = true");
+ else p("!(" + s1 + " <= " + s2 + ") = false");
+ if (!(f1 > f2)) p("!(" + s1 + " > " + s2 + ") = true");
+ else p("!(" + s1 + " > " + s2 + ") = false");
+ if (!(f1 >= f2)) p("!(" + s1 + " >= " + s2 + ") = true");
+ else p("!(" + s1 + " >= " + s2 + ") = false");
+
+ if ( (d1 == d2)) p(" (" + s1 + " == " + s2 + ") = true");
+ else p(" (" + s1 + " == " + s2 + ") = false");
+ if ( (d1 != d2)) p(" (" + s1 + " != " + s2 + ") = true");
+ else p(" (" + s1 + " != " + s2 + ") = false");
+ if ( (d1 < d2)) p(" (" + s1 + " < " + s2 + ") = true");
+ else p(" (" + s1 + " < " + s2 + ") = false");
+ if ( (d1 <= d2)) p(" (" + s1 + " <= " + s2 + ") = true");
+ else p(" (" + s1 + " <= " + s2 + ") = false");
+ if ( (d1 > d2)) p(" (" + s1 + " > " + s2 + ") = true");
+ else p(" (" + s1 + " > " + s2 + ") = false");
+ if ( (d1 >= d2)) p(" (" + s1 + " >= " + s2 + ") = true");
+ else p(" (" + s1 + " >= " + s2 + ") = false");
+
+ if (!(d1 == d2)) p("!(" + s1 + " == " + s2 + ") = true");
+ else p("!(" + s1 + " == " + s2 + ") = false");
+ if (!(d1 != d2)) p("!(" + s1 + " != " + s2 + ") = true");
+ else p("!(" + s1 + " != " + s2 + ") = false");
+ if (!(d1 < d2)) p("!(" + s1 + " < " + s2 + ") = true");
+ else p("!(" + s1 + " < " + s2 + ") = false");
+ if (!(d1 <= d2)) p("!(" + s1 + " <= " + s2 + ") = true");
+ else p("!(" + s1 + " <= " + s2 + ") = false");
+ if (!(d1 > d2)) p("!(" + s1 + " > " + s2 + ") = true");
+ else p("!(" + s1 + " > " + s2 + ") = false");
+ if (!(d1 >= d2)) p("!(" + s1 + " >= " + s2 + ") = true");
+ else p("!(" + s1 + " >= " + s2 + ") = false");
+ }
+
+ // ********************* output methods ****************************
+
+ public static int linenum = 0;
+
+ public static void pnl() {
+ int i;
+
+ System.out.println();
+ for (i = 4 - Integer.toString(linenum).length(); i > 0; i--)
+ System.out.print(' ');
+ System.out.print(linenum);
+ System.out.print(". ");
+ linenum++;
+ }
+
+ public static void p(String a) {
+ System.out.print(a); pnl();
+ }
+ public static void p(boolean a) {
+ System.out.print(a); pnl();
+ }
+ public static void p(int a) {
+ System.out.print("int: "); System.out.print(a); pnl();
+ }
+ public static void p(long a) {
+ System.out.print("long: "); System.out.print(a); pnl();
+ }
+ public static void p(short a) {
+ System.out.print("short: "); System.out.print(a); pnl();
+ }
+ public static void p(byte a) {
+ System.out.print("byte: "); System.out.print(a); pnl();
+ }
+ public static void p(char a) {
+ System.out.print("char: "); System.out.print((int)a); pnl();
+ }
+ public static void p(float a) {
+ System.out.print("float: "); System.out.print(a); pnl();
+ }
+ public static void p(double a) {
+ System.out.print("double: "); System.out.print(a); pnl();
+ }
+
+ public static void p(String s, boolean i) {
+ System.out.print(s); p(i);
+ }
+ public static void p(String s, int i) {
+ System.out.print(s); p(i);
+ }
+ public static void p(String s, byte i) {
+ System.out.print(s); p(i);
+ }
+ public static void p(String s, char i) {
+ System.out.print(s); p(i);
+ }
+ public static void p(String s, short i) {
+ System.out.print(s); p(i);
+ }
+ public static void p(String s, long l) {
+ System.out.print(s); p(l);
+ }
+ public static void p(String s, float f) {
+ System.out.print(s); p(f);
+ }
+ public static void p(String s, double d) {
+ System.out.print(s); p(d);
+ }
+
+ }
--- /dev/null
+import java.awt.*;
+
+public class ftest {
+ public static void main(String [] s) {
+
+// Frame f = new Frame(s[0]);
+
+// f.show();
+
+// System.getProperties().list (System.out);
+
+ System.out.println ("-- default toolkit ---");
+ System.out.println (Toolkit.getDefaultToolkit().
+ getClass().getName() );
+
+ }
+ }
+
+
\ No newline at end of file
--- /dev/null
+public class hello {
+ public static void main(String[] s) {
+ System.out.println ("Hello world");
+ }
+ }
--- /dev/null
+
+public class helper {
+ }
--- /dev/null
+public class hi {
+ public static void Ausgabe() {
+ System.out.println ("eine Zeile Text");
+ }
+
+ public static void main(String[] args) {
+ int i;
+ for (i=0; i<10; i++) Ausgabe();
+
+ System.out.println ("Juhu, das funktioniert");
+ }
+}
--- /dev/null
+
+// Primzahlen sieben, Java-Version
+
+public class intsieve {
+
+ static void sievenumber(int n, int[] no_prime, int p) {
+ int i;
+ for (i = p*2; i <= n; i += p)
+ no_prime[i] = 1;
+ }
+
+ static void sieving(int n, int[] no_prime) {
+ int p;
+ for (p = 2; p <= n; p++) {
+ if (no_prime[p] != 0) sievenumber(n, no_prime, p);
+ }
+ }
+
+ static public void main(String [] s) {
+
+ int count=0;
+ int p;
+
+ int n = Integer.parseInt (s[0]);
+ int times = Integer.parseInt (s[1]);
+
+ int no_prime[] = new int[n+1];
+
+ System.out.print ("Start sieving primes from 2 to ");
+ System.out.print (n);
+ System.out.print (" for ");
+ System.out.print (times);
+ System.out.println (" times");
+
+ for (; times > 0; times--) {
+ for (p = 0; p < n+1; p++)
+ no_prime[p] = 0;
+
+ sieving(n, no_prime);
+
+ count = 0;
+ for (p = 2; p <= n; p++)
+ if (no_prime[p] != 0) count++;
+ }
+
+ System.out.print (".... done, number of primes: ");
+ System.out.println (count);
+ }
+
+
+ }
+
\ No newline at end of file
--- /dev/null
+/************************* test/jctest.java ************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Eine Klasse zum Testen (fast) aller JavaVM-Instruktionen
+ in verschiedenen Konstellationen.
+
+ Die Ausgabe, die dieses Programm generiert, sollte bei allen
+ verschiedenen Java-Interpreter/Compiler-Systemen gleich
+ sein. Wenn nicht, dann ist wahrscheinlich eines der Systeme
+ fehlerhaft.
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1996/12/03
+
+*******************************************************************************/
+
+
+public class jctest implements jcinterface {
+ static int i1=77;
+ static long l1=123456789,l2=987654321,l3=-99999999999999L;
+ static int i2,i3=-100;
+ static float f1=0.1F,f2=0.2F,f3=0.3F;
+ static double d1=0.001,d2=0.002,d3=0.003;
+ static String s1,s2="der konstante String";
+
+ int n_i1,n_i2,n_i3;
+ long n_l1,n_l2,n_l3,n_l4;
+ float n_f1,n_f2,n_f3,n_f4;
+ int n_i4;
+ double n_d1,n_d2,n_d3,n_d4;
+
+
+ public static void main(String[] s) {
+ p ("=================== JavaVM - Tester ========================");
+
+ p ("------------------- test arguments");
+ int i;
+ for (i=0; i<s.length; i++) p(s[i]);
+
+ testgeneral();
+ testtables();
+ testcasts();
+ testspecialnullpointers();
+ testarrays();
+
+ p ("------------------- test consts");
+ testconst ( 1, 1);
+ testconst (-1, -1);
+ testconst (-24123, -4918923241323L);
+ testconst (-243511, -4423423234231423L);
+ testconst (0x7fffffff, 0x7fffffffffffffffL);
+
+ p ("------------------- test ints");
+ testint (1,2);
+ testint (-1,17);
+ testint (-24351,24123);
+ testint (4918923,-441423);
+ testint (0,0);
+ testint (-1,-1);
+ testint (1423487,123444444);
+ testint (0x7fffffff,1);
+ testint (0,0x7fffffff);
+ testint (0x3333,143444);
+ testint (4444441,12342);
+
+ p ("------------------- test longs");
+ testlong (1,2);
+ testlong (-1,17);
+ testlong (-24351,24123);
+ testlong (4918923241323L,-4423423234231423L);
+ testlong (0,0);
+ testlong (-1,-1);
+ testlong (1423487,123444442344L);
+ testlong (0x7fffffffffffffffL,1);
+ testlong (0,0x7fffffffffffffffL);
+ testlong (0x3333,143444);
+ testlong (4444441,12342);
+
+ p ("------------------- test floats");
+ testfloat ((float) 1,(float) 2.042);
+ testfloat ((float) -1.234,(float) 17.44);
+ testfloat ((float) -24351,(float) 24123);
+ testfloat ((float) 0.1,(float) 1243);
+ testfloat ((float) 0.0,(float) -555.4132);
+ testfloat ((float) 77.0,(float) -555);
+ testfloat ((float) 2147483000.0,(float) -555234);
+
+ p ("------------------- test doubles");
+ testdouble (1,2.042);
+ testdouble (-1.234,17.44);
+ testdouble (-24351,24123);
+ testdouble (0.1,1243);
+ testdouble (0.0,-555.4132);
+ testdouble (77.0,-555);
+ testdouble (2147483000.0,-555234);
+
+
+ p ("=================== end of test =========================");
+ }
+
+
+ static /* init */ {
+ p ("successful initialisation");
+ }
+
+
+
+ public static void testgeneral() {
+
+ int i;
+ // ******************** basic data types *******************************
+
+ p ("------------------- test int-PUSH-STORE-LOAD");
+ int j = -1;
+ p(j); p (0); p(2); p(17); p(-100);
+ p (500); p(-32768); p(-32769); p(32767); p(32768);
+ p (90000); p(-1000000000);
+
+ p ("------------------- test long-PUSH-STORE-LOAD");
+ long l = 3L;
+ p ( l ); p ( 0L ); p ( 99L );
+ p (500L); p(-32768L); p(-32769L); p(32767L); p(32768L);
+ p ( 6900000000000L ); p ( 349827389478173274L );
+
+ p ("------------------- test float-PUSH-STORE-LOAD");
+ float f = 99.444F;
+ p ( f ); p (0.0F); p (1.0F); p (342323423478.2223434234232334F);
+
+ p ("------------------- test double-PUSH-STORE-LOAD");
+ double d = 99234.42D;
+ p ( d ); p (0.0D); p (1.0D); p (342323423478.2223434234232334D);
+
+
+ // ******************** static variables *******************************
+
+ p ("------------------- test static variables");
+ i1 = i1+i2+i3;
+ l2 = l1+l2+l3;
+ f1 = f1*f2;
+ p (i1); p(i2); p(i3);
+ p (l1); p(l2); p(l3);
+ p (f1); p(f2); p(f3);
+ p (d1); p(d2); p(d3);
+
+ // ******************** arithmetic test ********************************
+
+ p ("------------------- test arithmetic");
+ i1 = 17;
+ i2 = 0x7fffffff;
+ p (i2);
+ p (i2+1);
+ p (i1-i2);
+ l1 = 0x7fffffffffffffffL;
+ p (l1);
+ p (l1+1);
+ p (l1+0x7fffffffffffffffL);
+
+
+ // ******************** test method calls ******************************
+
+ p ("statische methode");
+ jctest ttt = new jctest ();
+ ttt.p_manyparam (19,18,17,16, 88,77,66,55,
+ 0.1F,0.2F,0.3F,0.4F, -2.0D,-3.0D,-4.0D,-5.0D );
+ jcinterface ttt2 = ttt;
+ ttt2.p_nonstatic ("interface method");
+
+ }
+
+
+
+ // ************************ test tables ************************************
+
+ public static void testtables() {
+ int i;
+
+ p ("------------------- test tableswitch");
+
+ for (i = -5; i < 15; i++) {
+ switch (i) {
+ case 2: p ("-> 2"); break;
+ case 3: p ("-> 3"); break;
+ case 5: p ("-> 5"); break;
+ case 6: p ("-> 6"); break;
+ case 7: p ("-> 7"); break;
+ case 8: p ("-> 8"); break;
+ case 10: p ("-> 10"); break;
+ default: p ("default"); break;
+ }
+ }
+
+ p ("------------------- test lookupswitch");
+
+ for (i = -5; i < 15; i++) {
+ switch (i) {
+ case 2: p ("-> 2"); break;
+ case 8: p ("-> 8"); break;
+ case 14: p ("-> 14"); break;
+ case -4: p ("-> -4"); break;
+ default: p ("default"); break;
+ }
+ }
+ }
+
+
+ // ****************** test type casts and array stores *********************
+
+ public static void testcasts() {
+ Object o = new Object();
+ Object oi = new Integer(0);
+ Object[] oa = new Object [1];
+ Object[] oia = new Integer[1];
+ Integer i = new Integer(0);
+ Integer[] ia;
+
+ p ("------------------- test casts");
+
+ try {
+ p ("type cast check: Integer = Object(Integer)");
+ i = (Integer) oi;
+ p ("type cast check: Integer = Object");
+ i = (Integer) o;
+ p ("error: class cast exception not thrown");
+ }
+ catch (ClassCastException c) {
+ p ("exception: class cast");
+ }
+
+ try {
+ p ("type cast check: Integer[] = Object(Integer)[]");
+ ia = (Integer[]) oia;
+ p ("type cast check: Integer[] = Object[]");
+ ia = (Integer[]) oa;
+ p ("error: class cast exception not thrown");
+ }
+ catch (ClassCastException c) {
+ p ("exception: class cast");
+ }
+
+ try {
+ p ("array store check: Object(Integer)[0] = Integer");
+ oia[0] = i;
+ p ("array store check: Object(Integer)[0] = Object");
+ oia[0] = o;
+ p ("error: array store exception not thrown");
+ }
+ catch (ArrayStoreException c) {
+ p ("exception: array store");
+ }
+ }
+
+
+ // ****************** test special null pointers ***************************
+
+ public static void testspecialnullpointers() {
+ int i = 0;
+ jctest c = null;
+ jcinterface f = null;
+
+ p ("------------------- test special null pointers");
+
+ try {
+ p ("null pointer check: put field");
+ c.n_i1 = 0;
+ p ("error: put field null pointer exception not thrown");
+ }
+ catch (NullPointerException x) {
+ p ("exception: null pointer");
+ }
+
+ try {
+ p ("null pointer check: get field");
+ i = c.n_i1;
+ p ("error: get field null pointer exception not thrown");
+ }
+ catch (NullPointerException x) {
+ p ("exception: null pointer");
+ }
+
+ try {
+ p ("null pointer check: invokevirtual");
+ c.p_nonstatic("invokevirtual");
+ p ("error: invokevirtual null pointer exception not thrown");
+ }
+ catch (NullPointerException x) {
+ p ("exception: null pointer");
+ }
+
+ try {
+ p ("null pointer check: invokeinterface");
+ f.p_nonstatic("invokeinterface");
+ p ("error: invokeinterface null pointer exception not thrown");
+ }
+ catch (NullPointerException x) {
+ p ("exception: null pointer");
+ }
+
+ try {
+ p ("null pointer check: monitorenter");
+ synchronized (c) {
+ p ("error: monitorenter null pointer exception not thrown");
+ }
+ }
+ catch (NullPointerException x) {
+ p ("exception: null pointer");
+ }
+ }
+
+
+ // ************************ test array bounds ******************************
+
+ public static void testarraybounds(byte[] ba, int i) {
+
+ p ("testarraybounds: " + (i - 10));
+ ba[i-10] = 0;
+ p ("testarraybounds: " + (i - 5));
+ ba[i-5] = 0;
+ p ("testarraybounds: " + (i));
+ ba[i] = 0;
+ p ("testarraybounds: " + (i + 5));
+ ba[i+5] = 0;
+ p ("testarraybounds: " + (i + 10));
+ ba[i+10] = 0;
+ }
+
+
+ // ************************ test arrays ************************************
+
+ public static void testarrays() {
+ int i;
+ long l;
+ float f;
+ double d;
+ String s;
+
+ p ("------------------- test byte arrays");
+
+ byte[] ba = null;
+
+ try {
+ p ("null pointer check: byte array store");
+ ba[1] = 0;
+ p ("error: null pointer exception not thrown");
+ }
+ catch (NullPointerException c) {
+ p ("exception: null pointer");
+ }
+ try {
+ p ("null pointer check: byte array load");
+ i = ba[1];
+ p ("error: null pointer exception not thrown");
+ }
+ catch (NullPointerException c) {
+ p ("exception: null pointer");
+ }
+
+ try {
+ p ("negative array size check: byte array");
+ ba = new byte [-2];
+ p ("error: negative array size exception not thrown");
+ }
+ catch (NegativeArraySizeException c) {
+ p ("exception: negative array size");
+ }
+
+ ba = new byte [100];
+
+
+ try {
+ p ("array bound check: byte array store");
+ ba[-1] = 0;
+ p ("error: exception not thrown");
+ }
+ catch (ArrayIndexOutOfBoundsException c) {
+ p ("exception: out of bounds: "+(-1));
+ }
+ try {
+ p ("array bound check: byte array load");
+ i = ba[-1];
+ p ("error: exception not thrown");
+ }
+ catch (ArrayIndexOutOfBoundsException c) {
+ p ("exception: out of bounds: "+(-1));
+ }
+
+ try {
+ testarraybounds(ba, 5);
+ }
+ catch (ArrayIndexOutOfBoundsException c) {
+ p ("exception: out of bounds: "+5);
+ }
+ try {
+ testarraybounds(ba, 50);
+ }
+ catch (ArrayIndexOutOfBoundsException c) {
+ p ("exception: out of bounds: "+50);
+ }
+ try {
+ testarraybounds(ba, 100);
+ }
+ catch (ArrayIndexOutOfBoundsException c) {
+ p ("exception: out of bounds: "+100);
+ }
+
+ try {
+ ba[-4] = 0;
+ }
+ catch (ArrayIndexOutOfBoundsException c) {
+ p ("exception: out of bounds: "+(-4));
+ }
+ try {
+ ba[-3] = 0;
+ }
+ catch (ArrayIndexOutOfBoundsException c) {
+ p ("exception: out of bounds: "+(-3));
+ }
+ for (i=-2; i<102; i++) {
+ try {
+ ba[i] = (byte) (i-50);
+ }
+ catch (ArrayIndexOutOfBoundsException c) {
+ p ("exception: out of bounds: "+i);
+ }
+ }
+ try {
+ ba[102] = 0;
+ }
+ catch (ArrayIndexOutOfBoundsException c) {
+ p ("exception: out of bounds: "+102);
+ }
+ try {
+ ba[103] = 0;
+ }
+ catch (ArrayIndexOutOfBoundsException c) {
+ p ("exception: out of bounds: "+103);
+ }
+ for (i=0; i<100; i++) p (ba[i]);
+
+
+ p ("-------- test short arrays");
+
+ short[] sa = null;
+
+ try {
+ p ("null pointer check: short array store");
+ sa[1] = 0;
+ p ("error: null pointer exception not thrown");
+ }
+ catch (NullPointerException c) {
+ p ("exception: null pointer");
+ }
+ try {
+ p ("null pointer check: short array load");
+ i = sa[1];
+ p ("error: null pointer exception not thrown");
+ }
+ catch (NullPointerException c) {
+ p ("exception: null pointer");
+ }
+
+ sa = new short [100];
+
+ try {
+ p ("array bound check: short array store");
+ sa[-1] = 0;
+ p ("error: exception not thrown");
+ }
+ catch (ArrayIndexOutOfBoundsException c) {
+ p ("exception: out of bounds: "+(-1));
+ }
+ try {
+ p ("array bound check: short array load");
+ i = sa[-1];
+ p ("error: exception not thrown");
+ }
+ catch (ArrayIndexOutOfBoundsException c) {
+ p ("exception: out of bounds: "+(-1));
+ }
+
+ for (i=0; i<100; i++) sa[i] = (short) (i-50);
+ for (i=0; i<100; i++) p (sa[i]);
+
+
+ p ("-------- test int arrays");
+
+ int[] ia = null;
+
+ try {
+ p ("null pointer check: int array store");
+ ia[1] = 0;
+ p ("error: null pointer exception not thrown");
+ }
+ catch (NullPointerException c) {
+ p ("exception: null pointer");
+ }
+ try {
+ p ("null pointer check: int array load");
+ i = ia[1];
+ p ("error: null pointer exception not thrown");
+ }
+ catch (NullPointerException c) {
+ p ("exception: null pointer");
+ }
+
+ ia = new int [50];
+
+ try {
+ p ("array bound check: int array store");
+ ia[-1] = 0;
+ p ("error: exception not thrown");
+ }
+ catch (ArrayIndexOutOfBoundsException c) {
+ p ("exception: out of bounds: "+(-1));
+ }
+ try {
+ p ("array bound check: int array load");
+ i = ia[-1];
+ p ("error: exception not thrown");
+ }
+ catch (ArrayIndexOutOfBoundsException c) {
+ p ("exception: out of bounds: "+(-1));
+ }
+
+ for (i=0; i<10; i++) ia[i] = (123456 + i);
+ for (i=0; i<10; i++) p (ia[i]);
+
+
+
+ p ("-------- test long arrays");
+
+ long[] la = null;
+
+ try {
+ p ("null pointer check: long array store");
+ la[1] = 0;
+ p ("error: null pointer exception not thrown");
+ }
+ catch (NullPointerException c) {
+ p ("exception: null pointer");
+ }
+ try {
+ p ("null pointer check: long array load");
+ l = la[1];
+ p ("error: null pointer exception not thrown");
+ }
+ catch (NullPointerException c) {
+ p ("exception: null pointer");
+ }
+
+ la = new long [10];
+
+ try {
+ p ("array bound check: long array store");
+ la[-1] = 0;
+ p ("error: exception not thrown");
+ }
+ catch (ArrayIndexOutOfBoundsException c) {
+ p ("exception: out of bounds: "+(-1));
+ }
+ try {
+ p ("array bound check: long array load");
+ l = la[-1];
+ p ("error: exception not thrown");
+ }
+ catch (ArrayIndexOutOfBoundsException c) {
+ p ("exception: out of bounds: "+(-1));
+ }
+
+ for (i=0; i<10; i++) la[i] = (1234567890123L + i);
+ for (i=0; i<10; i++) p (la[i]);
+
+
+ p ("-------- test char arrays");
+
+ char[] ca = null;
+
+ try {
+ p ("null pointer check: char array store");
+ ca[1] = 0;
+ p ("error: null pointer exception not thrown");
+ }
+ catch (NullPointerException c) {
+ p ("exception: null pointer");
+ }
+ try {
+ p ("null pointer check: char array load");
+ i = ca[1];
+ p ("error: null pointer exception not thrown");
+ }
+ catch (NullPointerException c) {
+ p ("exception: null pointer");
+ }
+
+ ca = new char [50];
+
+ try {
+ p ("array bound check: char array store");
+ ca[-1] = 0;
+ p ("error: exception not thrown");
+ }
+ catch (ArrayIndexOutOfBoundsException c) {
+ p ("exception: out of bounds: "+(-1));
+ }
+ try {
+ p ("array bound check: char array load");
+ i = ca[-1];
+ p ("error: exception not thrown");
+ }
+ catch (ArrayIndexOutOfBoundsException c) {
+ p ("exception: out of bounds: "+(-1));
+ }
+
+ for (i=0; i<50; i++) ca[i] = (char) ('A' + i);
+ for (i=0; i<50; i++) p (ca[i]);
+
+ p ("-------- test address arrays");
+
+ String[] sta = null;
+
+ try {
+ p ("null pointer check: address array store");
+ sta[1] = null;
+ p ("error: null pointer exception not thrown");
+ }
+ catch (NullPointerException c) {
+ p ("exception: null pointer");
+ }
+ try {
+ p ("null pointer check: address array load");
+ s = sta[1];
+ p ("error: null pointer exception not thrown");
+ }
+ catch (NullPointerException c) {
+ p ("exception: null pointer");
+ }
+
+ try {
+ p ("negative array size check: address array");
+ sta = new String[-3];
+ p ("error: negative array size exception not thrown");
+ }
+ catch (NegativeArraySizeException c) {
+ p ("exception: negative array size");
+ }
+
+ sta = new String[5];
+
+ try {
+ p ("array bound check: address array store");
+ sta[-1] = null;
+ p ("error: exception not thrown");
+ }
+ catch (ArrayIndexOutOfBoundsException c) {
+ p ("exception: out of bounds: "+(-1));
+ }
+ try {
+ p ("array bound check: address array load");
+ s = sta[-1];
+ p ("error: exception not thrown");
+ }
+ catch (ArrayIndexOutOfBoundsException c) {
+ p ("exception: out of bounds: "+(-1));
+ }
+
+ for (i=0; i<5; i++) sta[i] = Integer.toString(i) + ". Zeile";
+ for (i=0; i<5; i++) p (sta[i]);
+
+ p ("-------- test multi dimensional arrays");
+
+ int [][][] iaaa = null;
+
+ try {
+ p ("negative array size check: multi dimensional array");
+ iaaa = new int[2][3][-4];
+ p ("error: negative array size exception not thrown");
+ }
+ catch (NegativeArraySizeException c) {
+ p ("exception: negative array size");
+ }
+
+ iaaa = new int[2][3][4];
+ long [][][] laaa = new long[2][3][6];
+ float [][][] faaa = new float[2][3][4];
+ double [][][] daaa = new double[3][4][7];
+ for (i=0; i<2; i++) {
+ int i2; for (i2=0; i2<3; i2++) {
+ int i3; for (i3=0; i3<4; i3++) {
+ iaaa[i][i2][i3] = i*i*i + i2*i2 + i3;
+ laaa[i][i2][i3] = i*i*i + i2*i2 + i3 + 7;
+ faaa[i][i2][i3] = i*i*i + i2*i2 + i3 + 0.4F;
+ daaa[i][i2][i3] = i*i*i + i2*i2 + i3 - 47.0001;
+ p (iaaa[i][i2][i3]);
+ p (laaa[i][i2][i3]);
+ p (faaa[i][i2][i3]);
+ p (daaa[i][i2][i3]);
+ }
+ }
+ }
+
+
+
+ }
+
+
+ static public void testconst(int i, long l) {
+ p ("TESTCONST CALLED WITH ", i);
+ p (" AND ", l);
+
+ if (!(i == (0))) p("not IF_ICMPEQ", (0));
+ if (!(i != (0))) p("not IF_ICMPNE", (0));
+ if (!(i < (0))) p("not IF_ICMPLT", (0));
+ if (!(i <= (0))) p("not IF_ICMPLE", (0));
+ if (!(i > (0))) p("not IF_ICMPGT", (0));
+ if (!(i >= (0))) p("not IF_ICMPGE", (0));
+
+ if (!(l == (0))) p("not IF_LCMPEQ", (0));
+ if (!(l != (0))) p("not IF_LCMPNE", (0));
+ if (!(l < (0))) p("not IF_LCMPLT", (0));
+ if (!(l <= (0))) p("not IF_LCMPLE", (0));
+ if (!(l > (0))) p("not IF_LCMPGT", (0));
+ if (!(l >= (0))) p("not IF_LCMPGE", (0));
+
+ p("IADDCONST: ", i + (-1));
+ p("ISUBCONST: ", i - (-1));
+ p("IMULCONST: ", i * (-1));
+ p("ISHLCONST: ", i << (-1));
+ p("ISHRCONST: ", i >> (-1));
+ p("IUSHRCONST: ", i >>> (-1));
+ p("IANDCONST: ", i & (-1));
+ p("IORCONST: ", i | (-1));
+ p("IXORCONST: ", i ^ (-1));
+
+ if (!(i == (-1))) p("not IF_ICMPEQ", (-1));
+ if (!(i != (-1))) p("not IF_ICMPNE", (-1));
+ if (!(i < (-1))) p("not IF_ICMPLT", (-1));
+ if (!(i <= (-1))) p("not IF_ICMPLE", (-1));
+ if (!(i > (-1))) p("not IF_ICMPGT", (-1));
+ if (!(i >= (-1))) p("not IF_ICMPGE", (-1));
+
+ p("LADDCONST: ", l + (-1));
+ p("LSUBCONST: ", l - (-1));
+ p("LMULCONST: ", l * (-1));
+ p("LSHLCONST: ", l << (-1));
+ p("LSHRCONST: ", l >> (-1));
+ p("LUSHRCONST: ", l >>> (-1));
+ p("LANDCONST: ", l & (-1));
+ p("LORCONST: ", l | (-1));
+ p("LXORCONST: ", l ^ (-1));
+
+ if (!(l == (-1))) p("not IF_LCMPEQ", (-1));
+ if (!(l != (-1))) p("not IF_LCMPNE", (-1));
+ if (!(l < (-1))) p("not IF_LCMPLT", (-1));
+ if (!(l <= (-1))) p("not IF_LCMPLE", (-1));
+ if (!(l > (-1))) p("not IF_LCMPGT", (-1));
+ if (!(l >= (-1))) p("not IF_LCMPGE", (-1));
+
+ p("IADDCONST: ", i + (1));
+ p("ISUBCONST: ", i - (1));
+ p("IMULCONST: ", i * (1));
+ p("ISHLCONST: ", i << (1));
+ p("ISHRCONST: ", i >> (1));
+ p("IUSHRCONST: ", i >>> (1));
+ p("IANDCONST: ", i & (1));
+ p("IORCONST: ", i | (1));
+ p("IXORCONST: ", i ^ (1));
+
+ if (!(i == (1))) p("not IF_ICMPEQ", (1));
+ if (!(i != (1))) p("not IF_ICMPNE", (1));
+ if (!(i < (1))) p("not IF_ICMPLT", (1));
+ if (!(i <= (1))) p("not IF_ICMPLE", (1));
+ if (!(i > (1))) p("not IF_ICMPGT", (1));
+ if (!(i >= (1))) p("not IF_ICMPGE", (1));
+
+ p("LADDCONST: ", l + (1));
+ p("LSUBCONST: ", l - (1));
+ p("LMULCONST: ", l * (1));
+ p("LSHLCONST: ", l << (1));
+ p("LSHRCONST: ", l >> (1));
+ p("LUSHRCONST: ", l >>> (1));
+ p("LANDCONST: ", l & (1));
+ p("LORCONST: ", l | (1));
+ p("LXORCONST: ", l ^ (1));
+
+ if (!(l == (1))) p("not IF_LCMPEQ", (1));
+ if (!(l != (1))) p("not IF_LCMPNE", (1));
+ if (!(l < (1))) p("not IF_LCMPLT", (1));
+ if (!(l <= (1))) p("not IF_LCMPLE", (1));
+ if (!(l > (1))) p("not IF_LCMPGT", (1));
+ if (!(l >= (1))) p("not IF_LCMPGE", (1));
+
+ p("IADDCONST: ", i + (255));
+ p("ISUBCONST: ", i - (255));
+ p("IMULCONST: ", i * (255));
+ p("ISHLCONST: ", i << (255));
+ p("ISHRCONST: ", i >> (255));
+ p("IUSHRCONST: ", i >>> (255));
+ p("IANDCONST: ", i & (255));
+ p("IORCONST: ", i | (255));
+ p("IXORCONST: ", i ^ (255));
+
+ if (!(i == (255))) p("not IF_ICMPEQ", (255));
+ if (!(i != (255))) p("not IF_ICMPNE", (255));
+ if (!(i < (255))) p("not IF_ICMPLT", (255));
+ if (!(i <= (255))) p("not IF_ICMPLE", (255));
+ if (!(i > (255))) p("not IF_ICMPGT", (255));
+ if (!(i >= (255))) p("not IF_ICMPGE", (255));
+
+ p("LADDCONST: ", l + (255));
+ p("LSUBCONST: ", l - (255));
+ p("LMULCONST: ", l * (255));
+ p("LSHLCONST: ", l << (255));
+ p("LSHRCONST: ", l >> (255));
+ p("LUSHRCONST: ", l >>> (255));
+ p("LANDCONST: ", l & (255));
+ p("LORCONST: ", l | (255));
+ p("LXORCONST: ", l ^ (255));
+
+ if (!(l == (255))) p("not IF_LCMPEQ", (255));
+ if (!(l != (255))) p("not IF_LCMPNE", (255));
+ if (!(l < (255))) p("not IF_LCMPLT", (255));
+ if (!(l <= (255))) p("not IF_LCMPLE", (255));
+ if (!(l > (255))) p("not IF_LCMPGT", (255));
+ if (!(l >= (255))) p("not IF_LCMPGE", (255));
+
+ p("IADDCONST: ", i + (256));
+ p("ISUBCONST: ", i - (256));
+ p("IMULCONST: ", i * (256));
+ p("ISHLCONST: ", i << (256));
+ p("ISHRCONST: ", i >> (256));
+ p("IUSHRCONST: ", i >>> (256));
+ p("IANDCONST: ", i & (256));
+ p("IORCONST: ", i | (256));
+ p("IXORCONST: ", i ^ (256));
+
+ if (!(i == (256))) p("not IF_ICMPEQ", (256));
+ if (!(i != (256))) p("not IF_ICMPNE", (256));
+ if (!(i < (256))) p("not IF_ICMPLT", (256));
+ if (!(i <= (256))) p("not IF_ICMPLE", (256));
+ if (!(i > (256))) p("not IF_ICMPGT", (256));
+ if (!(i >= (256))) p("not IF_ICMPGE", (256));
+
+ p("LADDCONST: ", l + (256));
+ p("LSUBCONST: ", l - (256));
+ p("LMULCONST: ", l * (256));
+ p("LSHLCONST: ", l << (256));
+ p("LSHRCONST: ", l >> (256));
+ p("LUSHRCONST: ", l >>> (256));
+ p("LANDCONST: ", l & (256));
+ p("LORCONST: ", l | (256));
+ p("LXORCONST: ", l ^ (256));
+
+ if (!(l == (256))) p("not IF_LCMPEQ", (256));
+ if (!(l != (256))) p("not IF_LCMPNE", (256));
+ if (!(l < (256))) p("not IF_LCMPLT", (256));
+ if (!(l <= (256))) p("not IF_LCMPLE", (256));
+ if (!(l > (256))) p("not IF_LCMPGT", (256));
+ if (!(l >= (256))) p("not IF_LCMPGE", (256));
+
+ p("IADDCONST: ", i + (32767));
+ p("ISUBCONST: ", i - (32767));
+ p("IMULCONST: ", i * (32767));
+ p("ISHLCONST: ", i << (32767));
+ p("ISHRCONST: ", i >> (32767));
+ p("IUSHRCONST: ", i >>> (32767));
+ p("IANDCONST: ", i & (32767));
+ p("IORCONST: ", i | (32767));
+ p("IXORCONST: ", i ^ (32767));
+
+ if (!(i == (32767))) p("not IF_ICMPEQ", (32767));
+ if (!(i != (32767))) p("not IF_ICMPNE", (32767));
+ if (!(i < (32767))) p("not IF_ICMPLT", (32767));
+ if (!(i <= (32767))) p("not IF_ICMPLE", (32767));
+ if (!(i > (32767))) p("not IF_ICMPGT", (32767));
+ if (!(i >= (32767))) p("not IF_ICMPGE", (32767));
+
+ p("LADDCONST: ", l + (32767));
+ p("LSUBCONST: ", l - (32767));
+ p("LMULCONST: ", l * (32767));
+ p("LSHLCONST: ", l << (32767));
+ p("LSHRCONST: ", l >> (32767));
+ p("LUSHRCONST: ", l >>> (32767));
+ p("LANDCONST: ", l & (32767));
+ p("LORCONST: ", l | (32767));
+ p("LXORCONST: ", l ^ (32767));
+
+ if (!(l == (32767))) p("not IF_LCMPEQ", (32767));
+ if (!(l != (32767))) p("not IF_LCMPNE", (32767));
+ if (!(l < (32767))) p("not IF_LCMPLT", (32767));
+ if (!(l <= (32767))) p("not IF_LCMPLE", (32767));
+ if (!(l > (32767))) p("not IF_LCMPGT", (32767));
+ if (!(l >= (32767))) p("not IF_LCMPGE", (32767));
+
+ p("IADDCONST: ", i + (32768));
+ p("ISUBCONST: ", i - (32768));
+ p("IMULCONST: ", i * (32768));
+ p("ISHLCONST: ", i << (32768));
+ p("ISHRCONST: ", i >> (32768));
+ p("IUSHRCONST: ", i >>> (32768));
+ p("IANDCONST: ", i & (32768));
+ p("IORCONST: ", i | (32768));
+ p("IXORCONST: ", i ^ (32768));
+
+ if (!(i == (32768))) p("not IF_ICMPEQ", (32768));
+ if (!(i != (32768))) p("not IF_ICMPNE", (32768));
+ if (!(i < (32768))) p("not IF_ICMPLT", (32768));
+ if (!(i <= (32768))) p("not IF_ICMPLE", (32768));
+ if (!(i > (32768))) p("not IF_ICMPGT", (32768));
+ if (!(i >= (32768))) p("not IF_ICMPGE", (32768));
+
+ p("LADDCONST: ", l + (32768));
+ p("LSUBCONST: ", l - (32768));
+ p("LMULCONST: ", l * (32768));
+ p("LSHLCONST: ", l << (32768));
+ p("LSHRCONST: ", l >> (32768));
+ p("LUSHRCONST: ", l >>> (32768));
+ p("LANDCONST: ", l & (32768));
+ p("LORCONST: ", l | (32768));
+ p("LXORCONST: ", l ^ (32768));
+
+ if (!(l == (32768))) p("not IF_LCMPEQ", (32768));
+ if (!(l != (32768))) p("not IF_LCMPNE", (32768));
+ if (!(l < (32768))) p("not IF_LCMPLT", (32768));
+ if (!(l <= (32768))) p("not IF_LCMPLE", (32768));
+ if (!(l > (32768))) p("not IF_LCMPGT", (32768));
+ if (!(l >= (32768))) p("not IF_LCMPGE", (32768));
+
+ p("IADDCONST: ", i + (-32768));
+ p("ISUBCONST: ", i - (-32768));
+ p("IMULCONST: ", i * (-32768));
+ p("ISHLCONST: ", i << (-32768));
+ p("ISHRCONST: ", i >> (-32768));
+ p("IUSHRCONST: ", i >>> (-32768));
+ p("IANDCONST: ", i & (-32768));
+ p("IORCONST: ", i | (-32768));
+ p("IXORCONST: ", i ^ (-32768));
+
+ if (!(i == (-32768))) p("not IF_ICMPEQ", (-32768));
+ if (!(i != (-32768))) p("not IF_ICMPNE", (-32768));
+ if (!(i < (-32768))) p("not IF_ICMPLT", (-32768));
+ if (!(i <= (-32768))) p("not IF_ICMPLE", (-32768));
+ if (!(i > (-32768))) p("not IF_ICMPGT", (-32768));
+ if (!(i >= (-32768))) p("not IF_ICMPGE", (-32768));
+
+ p("LADDCONST: ", l + (-32768));
+ p("LSUBCONST: ", l - (-32768));
+ p("LMULCONST: ", l * (-32768));
+ p("LSHLCONST: ", l << (-32768));
+ p("LSHRCONST: ", l >> (-32768));
+ p("LUSHRCONST: ", l >>> (-32768));
+ p("LANDCONST: ", l & (-32768));
+ p("LORCONST: ", l | (-32768));
+ p("LXORCONST: ", l ^ (-32768));
+
+ if (!(l == (-32768))) p("not IF_LCMPEQ", (-32768));
+ if (!(l != (-32768))) p("not IF_LCMPNE", (-32768));
+ if (!(l < (-32768))) p("not IF_LCMPLT", (-32768));
+ if (!(l <= (-32768))) p("not IF_LCMPLE", (-32768));
+ if (!(l > (-32768))) p("not IF_LCMPGT", (-32768));
+ if (!(l >= (-32768))) p("not IF_LCMPGE", (-32768));
+
+ p("IADDCONST: ", i + (-32769));
+ p("ISUBCONST: ", i - (-32769));
+ p("IMULCONST: ", i * (-32769));
+ p("ISHLCONST: ", i << (-32769));
+ p("ISHRCONST: ", i >> (-32769));
+ p("IUSHRCONST: ", i >>> (-32769));
+ p("IANDCONST: ", i & (-32769));
+ p("IORCONST: ", i | (-32769));
+ p("IXORCONST: ", i ^ (-32769));
+
+ if (!(i == (-32769))) p("not IF_ICMPEQ", (-32769));
+ if (!(i != (-32769))) p("not IF_ICMPNE", (-32769));
+ if (!(i < (-32769))) p("not IF_ICMPLT", (-32769));
+ if (!(i <= (-32769))) p("not IF_ICMPLE", (-32769));
+ if (!(i > (-32769))) p("not IF_ICMPGT", (-32769));
+ if (!(i >= (-32769))) p("not IF_ICMPGE", (-32769));
+
+ p("LADDCONST: ", l + (-32769));
+ p("LSUBCONST: ", l - (-32769));
+ p("LMULCONST: ", l * (-32769));
+ p("LSHLCONST: ", l << (-32769));
+ p("LSHRCONST: ", l >> (-32769));
+ p("LUSHRCONST: ", l >>> (-32769));
+ p("LANDCONST: ", l & (-32769));
+ p("LORCONST: ", l | (-32769));
+ p("LXORCONST: ", l ^ (-32769));
+
+ if (!(l == (-32769))) p("not IF_LCMPEQ", (-32769));
+ if (!(l != (-32769))) p("not IF_LCMPNE", (-32769));
+ if (!(l < (-32769))) p("not IF_LCMPLT", (-32769));
+ if (!(l <= (-32769))) p("not IF_LCMPLE", (-32769));
+ if (!(l > (-32769))) p("not IF_LCMPGT", (-32769));
+ if (!(l >= (-32769))) p("not IF_LCMPGE", (-32769));
+ }
+
+ static public void testint(int a, int b) {
+ p ("TESTINT CALLED WITH ", a);
+ p (" AND ", b);
+
+ p("IADD: ", a+b);
+ p("ISUB: ", a-b);
+ p("IMUL: ", a*b);
+ try { p("IDIV: ", a/b); }
+ catch (ArithmeticException e) { p("divison by zero"); }
+ try { p("IREM: ", a%b); }
+ catch (ArithmeticException e) { p("divison by zero"); }
+ p("INEG: ", -a);
+ p("ISHL: ", a<<b);
+ p("ISHR: ", a>>b);
+ p("IUSHR: ", a>>>b);
+ p("IAND: ", a & b);
+ p("IOR: ", a | b);
+ p("IXOR: ", a ^ b);
+
+ p("I2L: ", (long) a);
+ p("I2F: ", (float) a);
+ p("I2D: ", (double) a);
+ p("INT2BYTE: ", (byte) a);
+ p("INT2CHAR: ", (char) a);
+ p("INT2SHORT: ", (short) a);
+
+ if (!(a==0)) p("not IFEQ");
+ if (!(a!=0)) p("not IFNE");
+ if (!(a<0)) p("not IFLT");
+ if (!(a<=0)) p("not IFLE");
+ if (!(a>0)) p("not IFGT");
+ if (!(a>=0)) p("not IFGE");
+
+ if (!(a==b)) p("not IF_ICMPEQ");
+ if (!(a!=b)) p("not IF_ICMPNE");
+ if (!(a<b)) p("not IF_ICMPLT");
+ if (!(a<=b)) p("not IF_ICMPLE");
+ if (!(a>b)) p("not IF_ICMPGT");
+ if (!(a>=b)) p("not IF_ICMPGE");
+
+ }
+
+ static public void testlong(long a, long b) {
+ p ("TESTLONG called with ", a);
+ p (" AND ", b);
+
+ p("LADD: ", a + b);
+ p("LSUB: ", a - b);
+ p("LMUL: ", a * b);
+ try { p("LDIV: ", a / b); }
+ catch (ArithmeticException e) { p("divison by zero"); }
+ try { p("LREM: ", a % b); }
+ catch (ArithmeticException e) { p("divison by zero"); }
+ p("LNEG: ", -a);
+ p("LSHL: ", a << b);
+ p("LSHR: ", a >> b);
+ p("LUSHR: ", a >>>b);
+ p("LAND: ", a & b);
+ p("LOR: ", a | b);
+ p("LXOR: ", a ^ b);
+
+ p("L2I: ", (int) a);
+ p("L2F: ", (float) a);
+ p("L2D: ", (double) a);
+
+ p("LCMP a == b : ", a == b);
+ p("LCMP a != b : ", a != b);
+ p("LCMP a < b : ", a < b);
+ p("LCMP a <= b : ", a <= b);
+ p("LCMP a > b : ", a > b);
+ p("LCMP a >= b : ", a >= b);
+
+ if ((a==b)) p("not IF_LCMPEQ");
+ if ((a!=b)) p("not IF_LCMPNE");
+ if ((a<b)) p("not IF_LCMPLT");
+ if ((a<=b)) p("not IF_LCMPLE");
+ if ((a>b)) p("not IF_LCMPGT");
+ if ((a>=b)) p("not IF_LCMPGE");
+ }
+
+ static public void testfloat(float a, float b) {
+ p ("TESTFLOAT called with ", a);
+ p (" AND ", b);
+
+ p("FADD: ", a+b);
+ p("FSUB: ", a-b);
+ p("FMUL: ", a*b);
+ p("FDIV: ", a/b);
+ p("FREM: ", a%b);
+
+ p("F2I: ", (int) a);
+ p("F2L: ", (long) a);
+ p("F2D: ", (double) a);
+
+ if ((a==b)) p("FCMP a=b");
+ if ((a!=b)) p("FCMP a!=b");
+ if ((a<b)) p("FCMP a<b");
+ if ((a<=b)) p("FCMP a<=b");
+ if ((a>b)) p("FCMP a>b");
+ if ((a>=b)) p("FCMP a>=b");
+ }
+
+ static public void testdouble(double a, double b) {
+ p ("TESTDOUBLE called with ", a);
+ p (" AND ", b);
+
+ p("DADD: ", a+b);
+ p("DSUB: ", a-b);
+ p("DMUL: ", a*b);
+ p("DDIV: ", a/b);
+ p("DREM: ", a%b);
+
+ p("D2I: ", (int) a);
+ p("D2L: ", (long) a);
+ p("D2F: ", (float) a);
+
+ if ((a==b)) p("DCMP a=b");
+ if ((a!=b)) p("DCMP a!=b");
+ if ((a<b)) p("DCMP a<b");
+ if ((a<=b)) p("DCMP a<=b");
+ if ((a>b)) p("DCMP a>b");
+ if ((a>=b)) p("DCMP a>=b");
+ }
+
+
+ // ********************* output methods ****************************
+
+ public static int linenum = 0;
+ public static void pnl() {
+ System.out.println ();
+ System.out.print (linenum);
+ System.out.print (". ");
+ linenum++;
+ }
+
+ public static void p(String a) { System.out.print(a); pnl(); }
+ public static void p(boolean a) {System.out.print(a);
+ pnl(); }
+ public static void p(int a) { System.out.print ("int: ");
+ System.out.print(a);
+ pnl(); }
+ public static void p(long a) { System.out.print ("long: ");
+ System.out.print(a);
+ pnl(); }
+ public static void p(short a) { System.out.print ("short: ");
+ System.out.print(a);
+ pnl(); }
+ public static void p(byte a) { System.out.print ("byte: ");
+ System.out.print(a);
+ pnl(); }
+ public static void p(char a) { System.out.print ("char: ");
+ System.out.print((int)a);
+ pnl(); }
+ public static void p(float a) { System.out.print ("float: ");
+ System.out.print ( java.lang.Float.floatToIntBits(a) );
+ pnl(); }
+ public static void p(double a) { System.out.print ("double: ");
+ System.out.print( java.lang.Double.doubleToLongBits(a) );
+ pnl(); }
+
+ public static void p(String s,boolean i) {
+ System.out.print(s); p(i);
+ }
+ public static void p(String s,int i) {
+ System.out.print(s); p(i);
+ }
+ public static void p(String s,byte i) {
+ System.out.print(s); p(i);
+ }
+ public static void p(String s,char i) {
+ System.out.print(s); p(i);
+ }
+ public static void p(String s,short i) {
+ System.out.print(s); p(i);
+ }
+ public static void p(String s,long l) {
+ System.out.print(s); p(l);
+ }
+ public static void p(String s,float f) {
+ System.out.print(s); p(f);
+ }
+ public static void p(String s,double d) {
+ System.out.print(s); p(d);
+ }
+
+
+
+
+ // methods for testing interface and method calls
+
+ public void jctest() { p (" <init> wird aktiviert"); };
+ public void p_manyparam (int p_i1,int p_i2,
+ int p_i3, int p_i4,
+ long p_l1,long p_l2,
+ long p_l3,long p_l4,
+ float p_f1, float p_f2,
+ float p_f3, float p_f4,
+ double p_d1, double p_d2,
+ double p_d3, double p_d4) {
+ n_i1 = p_i1;
+ n_i2 = p_i2;
+ n_i3 = p_i3;
+ n_i4 = p_i4;
+ n_l1 = p_l1;
+ n_l2 = p_l2;
+ n_l3 = p_l3;
+ n_l4 = p_l4;
+ n_f1 = p_f1;
+ n_f2 = p_f2;
+ n_f3 = p_f3;
+ n_f4 = p_f4;
+ n_d1 = p_d1;
+ n_d2 = p_d2;
+ n_d3 = p_d3;
+ n_d4 = p_d4;
+ }
+
+ public void p_nonstatic (String a) {
+ p(a);
+ p(n_i1);
+ p(n_i2);
+ p(n_i3);
+ p(n_i4);
+ p(n_l1);
+ p(n_l2);
+ p(n_l3);
+ p(n_l4);
+ p(n_f1);
+ p(n_f2);
+ p(n_f3);
+ p(n_f4);
+ p(n_d1);
+ p(n_d2);
+ p(n_d3);
+ p(n_d4);
+
+ }
+
+ }
+
+
+interface jcinterface {
+ public void p_nonstatic (String a);
+ }
+
+
--- /dev/null
+
+public class leaf {
+
+ public static int makesum (int a, int b, int c) {
+ return a+b+c;
+ }
+
+ public static void main (String[] s) {
+ System.out.println (makesum (1,2,3) );
+ }
+
+
+}
--- /dev/null
+
+public class longtest {
+ public static void main(String []s) {
+ System.out.print ("juhu: ");
+ System.out.println ( (long) 0x12345678901234L );
+ }
+
+}
--- /dev/null
+
+public class main {
+
+ public static void main(String [] s) {
+ System.out.println ("Ausgabe startet");
+ int i;
+
+ float fa[] = new float[5];
+ for (i=0; i<5; i++) fa[i]=47.20F + (float)i;
+ for (i=0; i<5; i++) System.out.println(fa[i]);
+
+ double da[] = new double[5];
+ for (i=0; i<5; i++) da[i]=99.40F + (double)i;
+ for (i=0; i<5; i++) System.out.println(da[i]);
+
+ long la[] = new long[5];
+ for (i=0; i<5; i++) la[i]=11 + i;
+ for (i=0; i<5; i++) System.out.println(la[i]);
+
+ int ia[] = new int[5];
+ for (i=0; i<5; i++) ia[i]=99 + i;
+ for (i=0; i<5; i++) System.out.println(ia[i]);
+
+ short sa[] = new short[5];
+ for (i=0; i<5; i++) sa[i]=(short)(77 + i);
+ for (i=0; i<5; i++) System.out.println(sa[i]);
+
+ byte ba[] = new byte[5];
+ for (i=0; i<5; i++) ba[i]=(byte)(66 + i);
+ for (i=0; i<5; i++) System.out.println(ba[i]);
+
+ boolean boa[] = new boolean[5];
+ for (i=0; i<5; i++) boa[i]=(i<2);
+ for (i=0; i<5; i++) System.out.println(boa[i]);
+
+ char ca[] = new char[5];
+ for (i=0; i<5; i++) ca[i]=(char)('A' + i);
+ for (i=0; i<5; i++) System.out.println(ca[i]);
+
+
+ }
+ }
+
+
\ No newline at end of file
--- /dev/null
+
+public class mem {
+ public int dummy;
+
+ public static void main(String[] s) {
+ int i;
+
+ for (i=0; i<100000000; i++) {
+ try {
+ byte[] b = new byte[10000];
+ b[0]=17;
+ }
+ catch (java.lang.Throwable c) {
+ System.out.print ("Out of mem after ");
+ System.out.print (i);
+ System.out.println (" allocations.");
+ }
+ finally {
+ System.out.println ("OK");
+ }
+ }
+
+
+ }
+
+
+ }
+
\ No newline at end of file
--- /dev/null
+public class memtest {
+ public memtest next;
+
+ public static memtest t;
+
+ public memtest (memtest n) { next = n; }
+ public memtest () { };
+
+ public static void main (String[] s) {
+ int i;
+
+ t = new memtest(new memtest(new memtest()));
+ char c[][] = new char[100][10];
+
+ for (i=0; i<100; i++) {
+ System.out.print (i);
+ System.out.println (". Objekt angelegt");
+ memtest m = new memtest();
+ }
+
+ }
+
+ }
+
+
\ No newline at end of file
--- /dev/null
+
+public class n implements a {
+ public void do_a () { };
+ public void do_a2 () { };
+ public void do_b () { };
+ }
+
\ No newline at end of file
--- /dev/null
+public class nan
+{
+ public static void main(String[] s) {
+ double a,b,c;
+ a = -1;
+ b = 0;
+ c = a/b;
+
+ System.out.println (Long.toString(Double.doubleToLongBits(c)>>>4, 16) );
+ }
+ }
--- /dev/null
+public class prop {
+ public static void main(String [] s) {
+ System.getProperties().save (System.out, "alle properties:");
+ }
+ }
--- /dev/null
+import java.applet.*;
+import java.awt.*;
+
+public class scribble extends Applet {
+ private int last_x=0;
+ private int last_y=0;
+
+
+ public void init()
+ {
+ this.setBackground(Color.white);
+ }
+
+
+ public boolean mouseDown(Event e, int x, int y)
+ {
+ last_x = x; last_y=y;
+ return true;
+ }
+
+ public boolean mouseDrag(Event e, int x, int y)
+ {
+ Graphics g = getGraphics();
+ g.setColor (Color.black);
+ g.drawLine(last_x,last_y,x,y);
+ last_x=x; last_y=y;
+ return true;
+ }
+}
--- /dev/null
+
+// Primzahlen sieben, Java-Version
+
+public class sieve {
+
+ static void sievenumber(int n, boolean[] no_prime, int p) {
+ int i;
+ for (i=p*2; i<=n; i+=p) no_prime[i] = true;
+ }
+
+ static void sieving(int n, boolean[] no_prime) {
+ int p;
+ for (p=2; p<=n; p++) {
+ if (!no_prime[p]) sievenumber(n,no_prime,p);
+ }
+ }
+
+ static public void main(String [] s) {
+
+ int count=0;
+ int p;
+
+ int n = Integer.parseInt (s[0]);
+ int times = Integer.parseInt (s[1]);
+
+ boolean no_prime[] = new boolean[n+1];
+
+ System.out.print ("Start sieving primes from 2 to ");
+ System.out.print (n);
+ System.out.print (" for ");
+ System.out.print (times);
+ System.out.println (" times");
+
+ for (; times>0; times--) {
+ for (p=0; p<n+1; p++) no_prime[p] = false;
+
+ sieving (n,no_prime);
+
+ count=0;
+ for (p=2; p<=n; p++) if (!no_prime[p]) count++;
+
+ }
+
+ System.out.print (".... done, number of primes: ");
+ System.out.println (count);
+ }
+
+
+ }
+
\ No newline at end of file
--- /dev/null
+
+// Zahlen summieren, Java Version
+
+public class sum {
+
+
+ static public void main(String [] arg) {
+
+ int s = 0, i = 0;
+ int inc = 1;
+ int n = Integer.parseInt (arg[0]);
+
+
+ for (i=0; i<n; i+=inc) s+=inc;
+
+ System.out.print (".... done, sum: ");
+ System.out.println (s);
+ }
+
+
+ }
+
\ No newline at end of file
--- /dev/null
+
+// Zahlen summieren, Java Version
+
+public class sum2 {
+
+
+ static public void main(String [] arg) {
+
+ int s1 = 0, s2 = 0, i = 0;
+ int inc = 1;
+ int n = Integer.parseInt (arg[0]);
+
+
+ for (i = n; i > 0; i -= inc) {
+ s1 += inc;
+ s2 -= inc;
+ }
+
+ System.out.print (".... done, sum: ");
+ System.out.println (s1);
+ System.out.println (s2);
+ }
+
+
+ }
+
\ No newline at end of file
--- /dev/null
+
+// Zahlen summieren, Java Version
+
+public class suml {
+
+
+ static public void main(String [] arg) {
+
+ long s1 = 0, s2 = 0;
+ long i = Integer.parseInt (arg[0]);
+
+
+ for (; i > 0; i--) {
+ s1++;
+ s2--;
+ }
+
+ System.out.print (".... done, sum: ");
+ System.out.print (s1);
+ System.out.println (s2);
+ }
+
+
+ }
+
\ No newline at end of file
--- /dev/null
+
+// Zahlen summieren, Java Version
+
+public class sumlempty {
+
+
+ static public void main(String [] arg) {
+
+ long i = Long.parseLong (arg[0]);
+
+
+ for (; i > 0; i--) {
+ }
+
+ System.out.print (".... done, sum: ");
+ System.out.println (i);
+ }
+
+
+ }
+
\ No newline at end of file
--- /dev/null
+
+public class t {
+ public static void main(String [] s) {
+ ausgeber m1 = new m(4711);
+ float a=(float)7.5,b=(float)3.2;
+ double ad=5.3,bd=2.1;
+
+ int i; for (i=0; i<s.length; i++) m1.print (s[i]);
+
+ m1.print (System.getProperty("file.separator"));
+ m1.print (System.getProperty("line.separator"));
+
+ m1.print ();
+ System.out.println ((int) ad);
+ m1.print ( (int) (a) );
+ m1.print ( (int) (ad % bd) );
+ m1.print (17.3);
+ m1.print ((float)9.4);
+ m1.print ("bye");
+ }
+ }
+
+class m implements ausgeber {
+ public int value;
+
+ public m(int v) { value = v; }
+
+ public void print(String s) { System.out.println(s); }
+ public void print(int i) { System.out.println(i); }
+ public void print() { System.out.println(value); }
+ public void print(float f) { System.out.println(f); }
+ public void print(double d) { System.out.println(d); }
+ }
+
+interface ausgeber {
+ public void print(String s);
+ public void print(int i);
+ public void print();
+ public void print(float f);
+ public void print(double d);
+ }
+
+
\ No newline at end of file
--- /dev/null
+
+class tst {
+ public static void Main(String[]s) {
+
+ // storer ( new char[4][3], new char[2] );
+ }
+
+
+
+ public static void storer(Object []a, Object o) {
+ a[1] = o;
+ }
+}
--- /dev/null
+
+import java.io.*;
+
+public class x {
+ static public char[][] text;
+ static public int letters;
+ final static int maxwidth = 200;
+ final static int maxheight = 200;
+
+ static public void main(java.lang.String [] argv) throws
+ FileNotFoundException, IOException {
+
+ int l,c,width,height;
+ char a;
+ int i;
+ FileInputStream input = new FileInputStream ("x.java");
+ PrintStream output = System.out;
+
+ output.println ("Ausgabe startet");
+
+ text = new char[maxheight][maxwidth];
+ output.println ("Feld angelegt");
+
+ for (l=0; l<maxheight; l++) for (c=0; c<maxwidth; c++)
+ text[l][c] = ' ';
+
+ letters = 0;
+ width = 0;
+ height = 0;
+
+ l=0; c=0;
+ try {
+ while ( (i=input.read()) != -1) {
+ if (i == '\n') { c=0; l++; }
+ else {
+ if (i == '\t') { c = ( (c/4 + 1) * 4); }
+ else {
+ if (c<maxwidth && l<maxheight) {
+ a = (char) i;
+ text[l][c] = a;
+ if (c>=width) width=c+1;
+ if (l>=height) height=l+1;
+ }
+ c++;
+ }
+ }
+ }
+ } catch (Throwable e) { };
+
+ output.println ("------------------------------------------------------");
+
+ for (c=width-1; c>=0; c--) {
+ for (l=0; l<height; l++) {
+ if ( (a=text[l][c]) != ' ' ) letters ++;
+ i = a;
+ output.write (i);
+ }
+ output.println ();
+ }
+
+ output.println ("------------------------------------------------------");
+ output.println ("Abdruckbare Buchstaben im Text: " + Integer.toString(letters) );
+
+
+ output.flush();
+
+ }
+
+
+ }
+
--- /dev/null
+
+#######################################################################
+# Makefile f"ur meine programmunabh"angige Toolbox #
+#######################################################################
+
+OBJECTS = locks.o thread.o threadio.o
+CC = gcc
+
+ifeq ($(USE_THREADS),YES)
+THREAD_CFLAGS = -DUSE_THREADS -DEXTERNAL_OVERFLOW -DDONT_FREE_FIRST
+else
+THREAD_CFLAGS =
+endif
+
+CFLAGS = $(THREAD_CFLAGS)
+
+threads.a: $(OBJECTS) Makefile sysdep/threads.h
+ rm -f threads.a
+ ar qcs threads.a $(OBJECTS)
+# ranlib threads.a
+
+locks.o : locks.c
+thread.o : thread.c
+threadio.o : threadio.c
+
+clean:
+ rm -f *.o *.a
--- /dev/null
+/* -*- mode: c; tab-width: 4; c-basic-offset: 4 -*- */
+/*
+ * locks.c
+ * Manage locking system
+ * This include the mutex's and cv's.
+ *
+ * Copyright (c) 1996 T. J. Wilkinson & Associates, London, UK.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * Written by Tim Wilkinson <tim@tjwassoc.demon.co.uk>, 1996.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+
+#include "thread.h"
+#include "locks.h"
+
+#include "../tables.h"
+#include "../native.h"
+#include "../loader.h"
+
+static classinfo *class_java_lang_IllegalMonitorStateException;
+
+#if 1
+#define DBG(s)
+#else
+#define DBG(s) s
+#endif
+
+extern thread* currentThread;
+
+#if defined(USE_INTERNAL_THREADS)
+
+mutexHashEntry *mutexHashTable;
+int mutexHashTableSize;
+long mutexHashMask;
+
+mutexHashEntry *mutexOverflowTable;
+int mutexOverflowTableSize;
+mutexHashEntry *firstFreeOverflowEntry = 0;
+
+conditionHashEntry *conditionHashTable;
+int conditionHashTableSize;
+long conditionHashMask;
+
+/*
+ * Init the tables.
+ */
+void
+initLocks (void)
+{
+ int i;
+
+ mutexHashTableSize = MUTEX_HASH_TABLE_SIZE;
+ mutexHashTable = (mutexHashEntry*)malloc(sizeof(mutexHashEntry) * mutexHashTableSize);
+ mutexHashMask = (mutexHashTableSize - 1) << 3;
+
+ for (i = 0; i < mutexHashTableSize; ++i)
+ {
+ mutexHashTable[i].object = 0;
+ mutexHashTable[i].mutex.holder = 0;
+ mutexHashTable[i].mutex.count = 0;
+ mutexHashTable[i].mutex.muxWaiters = 0;
+ mutexHashTable[i].conditionCount = 0;
+ mutexHashTable[i].next = 0;
+ }
+
+ mutexOverflowTableSize = MUTEX_OVERFLOW_TABLE_SIZE;
+ mutexOverflowTable = (mutexHashEntry*)malloc(sizeof(mutexHashEntry)
+ * mutexOverflowTableSize);
+
+ firstFreeOverflowEntry = &mutexOverflowTable[0];
+
+ for (i = 0; i < mutexOverflowTableSize; ++i)
+ {
+ mutexOverflowTable[i].object = 0;
+ mutexOverflowTable[i].mutex.holder = 0;
+ mutexOverflowTable[i].mutex.count = 0;
+ mutexOverflowTable[i].mutex.muxWaiters = 0;
+ mutexOverflowTable[i].conditionCount = 0;
+ mutexOverflowTable[i].next = &mutexOverflowTable[i + 1];
+ }
+ mutexOverflowTable[i - 1].next = 0;
+
+ conditionHashTableSize = CONDITION_HASH_TABLE_SIZE;
+ conditionHashTable = (conditionHashEntry*)malloc(sizeof(conditionHashEntry)
+ * conditionHashTableSize);
+ conditionHashMask = (conditionHashTableSize - 1) << 3;
+
+ for (i = 0; i < conditionHashTableSize; ++i)
+ {
+ conditionHashTable[i].object = 0;
+ conditionHashTable[i].condition.cvWaiters = 0;
+ conditionHashTable[i].condition.mux = 0;
+ }
+
+ /* Load exception classes */
+ class_java_lang_IllegalMonitorStateException =
+ loader_load(unicode_new_char("java/lang/IllegalMonitorStateException"));
+}
+
+/*
+ * Reorders part of the condition hash table. Must be called after an entry has been deleted.
+ */
+void
+reorderConditionHashTable (int begin)
+{
+ while (conditionHashTable[begin].object != 0)
+ {
+ int hashValue = CONDITION_HASH_VALUE(conditionHashTable[begin].object);
+
+ if (hashValue != begin)
+ {
+ while (conditionHashTable[hashValue].object != 0)
+ {
+ hashValue = CONDITION_HASH_SUCCESSOR(hashValue);
+ if (hashValue == begin)
+ break;
+ }
+ if (hashValue != begin)
+ {
+ conditionHashTable[hashValue] = conditionHashTable[begin];
+ conditionHashTable[begin].object = 0;
+ conditionHashTable[begin].condition.cvWaiters = 0;
+ conditionHashTable[begin].condition.mux = 0;
+ }
+ }
+
+ begin = CONDITION_HASH_SUCCESSOR(begin);
+ }
+}
+
+/*
+ * Looks up an entry in the condition hash table.
+ */
+iCv*
+conditionForObject (java_objectheader *object)
+{
+ int hashValue;
+
+ intsDisable();
+
+ hashValue = CONDITION_HASH_VALUE(object);
+ while (conditionHashTable[hashValue].object != object
+ && conditionHashTable[hashValue].object != 0)
+ hashValue = CONDITION_HASH_SUCCESSOR(hashValue);
+
+ if (conditionHashTable[hashValue].object == 0)
+ {
+ intsRestore();
+ return 0;
+ }
+
+ intsRestore();
+ return &conditionHashTable[hashValue].condition;
+}
+
+/*
+ * Adds a new entry in the condition hash table and returns a pointer to the condition
+ */
+iCv*
+addConditionForObject (java_objectheader *object)
+{
+ int hashValue;
+
+ intsDisable();
+
+ hashValue = CONDITION_HASH_VALUE(object);
+ while (conditionHashTable[hashValue].object != 0)
+ hashValue = CONDITION_HASH_SUCCESSOR(hashValue);
+
+ conditionHashTable[hashValue].object = object;
+
+ intsRestore();
+
+ return &conditionHashTable[hashValue].condition;
+}
+
+/*
+ * Removes an entry from the condition hash table.
+ */
+void
+removeConditionForObject (java_objectheader *object)
+{
+ int hashValue;
+
+ intsDisable();
+
+ hashValue = CONDITION_HASH_VALUE(object);
+ while (conditionHashTable[hashValue].object != object)
+ hashValue = CONDITION_HASH_SUCCESSOR(hashValue);
+
+ conditionHashTable[hashValue].object = 0;
+ conditionHashTable[hashValue].condition.cvWaiters = 0;
+ conditionHashTable[hashValue].condition.mux = 0;
+
+ reorderConditionHashTable(CONDITION_HASH_SUCCESSOR(hashValue));
+
+ intsRestore();
+}
+
+/*
+ * Returns the mutex entry for the specified object and increments its conditionCount.
+ */
+mutexHashEntry*
+conditionLockedMutexForObject (java_objectheader *object)
+{
+ int hashValue;
+ mutexHashEntry *entry;
+
+ assert(object != 0);
+
+ intsDisable();
+
+ hashValue = MUTEX_HASH_VALUE(object);
+ entry = &mutexHashTable[hashValue];
+
+ if (entry->object != 0)
+ {
+ if (entry->mutex.count == 0 && entry->conditionCount == 0)
+ {
+ entry->object = 0;
+ entry->mutex.holder = 0;
+ entry->mutex.count = 0;
+ entry->mutex.muxWaiters = 0;
+ }
+ else
+ {
+ while (entry->next != 0 && entry->object != object)
+ entry = entry->next;
+
+ if (entry->object != object)
+ {
+ entry->next = firstFreeOverflowEntry;
+ firstFreeOverflowEntry = firstFreeOverflowEntry->next;
+
+ entry = entry->next;
+ entry->object = 0;
+ entry->next = 0;
+ assert(entry->conditionCount == 0);
+ }
+ }
+ }
+
+ if (entry->object == 0)
+ entry->object = object;
+
+ ++entry->conditionCount;
+
+ intsRestore();
+
+ return entry;
+}
+
+/*
+ * Wait for the condition of an object to be signalled
+ */
+void
+wait_cond_for_object (java_objectheader *obj, s8 time)
+{
+ iCv *condition;
+ mutexHashEntry *mutexEntry;
+
+ intsDisable();
+
+ mutexEntry = conditionLockedMutexForObject(obj);
+
+ condition = conditionForObject(obj);
+ if (condition == 0)
+ condition = addConditionForObject(obj);
+
+ DBG( fprintf(stderr, "condition of %p is %p\n", obj, condition); );
+
+ internal_wait_cond(&mutexEntry->mutex, condition, time);
+
+ if (condition->cvWaiters == 0 && condition->mux == 0)
+ removeConditionForObject(obj);
+ --mutexEntry->conditionCount;
+
+ intsRestore();
+}
+
+/*
+ * Signal the condition of an object
+ */
+void
+signal_cond_for_object (java_objectheader *obj)
+{
+ iCv *condition;
+
+ intsDisable();
+
+ condition = conditionForObject(obj);
+ if (condition == 0)
+ condition = addConditionForObject(obj);
+
+ DBG( fprintf(stderr, "condition of %p is %p\n", obj, condition); );
+
+ internal_signal_cond(condition);
+
+ if (condition->cvWaiters == 0 && condition->mux == 0)
+ removeConditionForObject(obj);
+
+ intsRestore();
+}
+
+/*
+ * Broadcast the condition of an object.
+ */
+void
+broadcast_cond_for_object (java_objectheader *obj)
+{
+ intsDisable();
+ internal_broadcast_cond_for_object(obj);
+ intsRestore();
+}
+
+/*
+ * Internal: Broadcast the condition of an object.
+ */
+void
+internal_broadcast_cond_for_object (java_objectheader *obj)
+{
+ iCv *condition;
+
+ condition = conditionForObject(obj);
+ if (condition == 0)
+ condition = addConditionForObject(obj);
+
+ internal_broadcast_cond(condition);
+
+ if (condition->cvWaiters == 0 && condition->mux == 0)
+ removeConditionForObject(obj);
+}
+
+/*
+ * Lock a mutex.
+ */
+void
+lock_mutex (iMux *mux)
+{
+ intsDisable();
+ internal_lock_mutex(mux);
+ intsRestore();
+}
+
+/*
+ * Lock the mutex for an object.
+ */
+void
+lock_mutex_for_object (java_objectheader *obj)
+{
+ intsDisable();
+ internal_lock_mutex_for_object(obj);
+ intsRestore();
+}
+
+/*
+ * Unlock a mutex.
+ */
+void
+unlock_mutex (iMux *mux)
+{
+ intsDisable();
+ internal_unlock_mutex(mux);
+ intsRestore();
+}
+
+/*
+ * Unlock the mutex for an object.
+ */
+void
+unlock_mutex_for_object (java_objectheader *obj)
+{
+ intsDisable();
+ internal_unlock_mutex_for_object(obj);
+ intsRestore();
+}
+
+/*
+ * Wait on a condition variable.
+ */
+void
+wait_cond (iMux *mux, iCv *cond, s8 timeout)
+{
+ intsDisable();
+ internal_wait_cond(mux, cond, timeout);
+ intsRestore();
+}
+
+/*
+ * Signal a condition variable.
+ */
+void
+signal_cond (iCv *cond)
+{
+ intsDisable();
+ internal_signal_cond(cond);
+ intsRestore();
+}
+
+/*
+ * Broadcast a condition variable.
+ */
+void
+broadcast_cond (iCv *cond)
+{
+ intsDisable();
+ internal_broadcast_cond(cond);
+ intsRestore();
+}
+
+/*
+ * Internal: Lock a mutex.
+ */
+void
+internal_lock_mutex(iMux* mux)
+{
+ assert(blockInts == 1);
+
+ if (mux->holder == 0)
+ {
+ mux->holder = currentThread;
+ mux->count = 1;
+ DBG( fprintf(stderr, "set holder of %p to %p\n", mux, mux->holder); )
+ }
+ else if (mux->holder == currentThread)
+ {
+ mux->count++;
+ }
+ else
+ {
+ while (mux->holder != 0)
+ {
+ suspendOnQThread(currentThread, &mux->muxWaiters);
+ }
+ mux->holder = currentThread;
+ mux->count = 1;
+ }
+}
+
+/*
+ * Internal: Release a mutex.
+ */
+void
+internal_unlock_mutex(iMux* mux)
+{
+ thread* tid;
+
+ assert(blockInts == 1);
+
+ assert(mux->holder == currentThread);
+
+ mux->count--;
+ if (mux->count == 0)
+ {
+ mux->holder = 0;
+ if (mux->muxWaiters != 0)
+ {
+ tid = mux->muxWaiters;
+ mux->muxWaiters = tid->next;
+ iresumeThread(tid);
+ }
+ }
+}
+
+/*
+ * Internal: Wait on a conditional variable.
+ * (timeout currently ignored)
+ */
+void
+internal_wait_cond(iMux* mux, iCv* cv, s8 timeout)
+{
+ int count;
+ thread* tid;
+
+ DBG( fprintf(stderr, "waiting on %p\n", cv); );
+
+ if (mux->holder != currentThread) {
+ exceptionptr = native_new_and_init(class_java_lang_IllegalMonitorStateException);
+ }
+
+ assert(blockInts == 1);
+
+ count = mux->count;
+ mux->holder = 0;
+ mux->count = 0;
+ cv->mux = mux;
+
+ /* If there's anyone waiting here, wake them up */
+ if (mux->muxWaiters != 0) {
+ tid = mux->muxWaiters;
+ mux->muxWaiters = tid->next;
+ iresumeThread(tid);
+ }
+
+ /* Suspend, and keep suspended until I re-get the lock */
+ suspendOnQThread(currentThread, &cv->cvWaiters);
+ while (mux->holder != 0) {
+ DBG( fprintf(stderr, "woke up\n"); );
+ suspendOnQThread(currentThread, &mux->muxWaiters);
+ }
+
+ mux->holder = currentThread;
+ mux->count = count;
+}
+
+/*
+ * Internal: Wake one thread on a conditional variable.
+ */
+void
+internal_signal_cond (iCv* cv)
+{
+ thread* tid;
+
+ DBG( fprintf(stderr, "signalling on %p\n", cv); );
+
+ /* If 'mux' isn't set then we've never waited on this object. */
+ if (cv->mux == 0) {
+ return;
+ }
+
+ if (cv->mux->holder != currentThread) {
+ exceptionptr = native_new_and_init(class_java_lang_IllegalMonitorStateException);
+ }
+
+ assert(blockInts == 1);
+
+ /* Remove one thread from cv list */
+ if (cv->cvWaiters != 0) {
+ DBG( fprintf(stderr, "releasing a waiter\n"); );
+
+ tid = cv->cvWaiters;
+ cv->cvWaiters = tid->next;
+
+ /* Place it on mux list */
+ tid->next = cv->mux->muxWaiters;
+ cv->mux->muxWaiters = tid;
+ }
+}
+
+/*
+ * Internal: Wake all threads on a conditional variable.
+ */
+void
+internal_broadcast_cond (iCv* cv)
+{
+ thread** tidp;
+
+ /* If 'mux' isn't set then we've never waited on this object. */
+ if (cv->mux == 0) {
+ return;
+ }
+
+ if (cv->mux->holder != currentThread) {
+ exceptionptr = native_new_and_init(class_java_lang_IllegalMonitorStateException);
+ }
+
+ assert(blockInts == 1);
+
+ /* Find the end of the cv list */
+ if (cv->cvWaiters) {
+ for (tidp = &cv->cvWaiters; *tidp != 0; tidp = &(*tidp)->next)
+ ;
+
+ /* Place entire cv list on mux list */
+ (*tidp) = cv->mux->muxWaiters;
+ cv->mux->muxWaiters = cv->cvWaiters;
+ cv->cvWaiters = 0;
+ }
+}
+
+#endif
--- /dev/null
+/*
+ * locks.h
+ * Manage locking system
+ * This include the mutex's and cv's.
+ *
+ * Copyright (c) 1996 T. J. Wilkinson & Associates, London, UK.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * Written by Tim Wilkinson <tim@tjwassoc.demon.co.uk>, 1996.
+ */
+
+#ifndef __locks_h
+#define __locks_h
+
+#ifdef USE_THREADS
+
+#include "../global.h"
+#include "sysdep/defines.h"
+
+#define WAITFOREVER -1
+
+#if defined(USE_INTERNAL_THREADS)
+
+struct _thread;
+
+typedef struct _iMux {
+ struct _thread *holder;
+ int count;
+ struct _thread *muxWaiters;
+} iMux;
+
+typedef struct _iCv {
+ struct _thread* cvWaiters;
+ struct _iMux* mux;
+} iCv;
+
+#define MAX_MUTEXES 256
+
+typedef struct _mutexHashEntry
+{
+ java_objectheader *object;
+ iMux mutex;
+ struct _mutexHashEntry *next;
+ int conditionCount;
+} mutexHashEntry;
+
+#define MUTEX_HASH_TRASH_BITS 3
+#define MUTEX_HASH_SIGN_BITS 10
+
+#define MUTEX_HASH_TABLE_SIZE 1024
+#define MUTEX_OVERFLOW_TABLE_SIZE 1024
+/*
+#define MAX_MUTEX_HASH_TABLE_SIZE 65536
+*/
+
+/*
+#define MUTEX_USE_THRESHOLD 1024
+*/
+
+extern long mutexHashMask;
+extern int mutexHashTableSize;
+extern mutexHashEntry *mutexHashTable;
+
+extern mutexHashEntry *mutexOverflowTable;
+extern int mutexOverflowTableSize;
+extern mutexHashEntry *firstFreeOverflowEntry;
+
+#define MUTEX_HASH_MASK ((MUTEX_HASH_TABLE_SIZE - 1) << 3)
+
+#if 0
+#define MUTEX_HASH_VALUE(a) ((((long)(a)) & MUTEX_HASH_MASK) >> MUTEX_HASH_TRASH_BITS)
+#else
+#define MUTEX_HASH_VALUE(a) (( (((long)(a)) ^ ((long)(a) >> MUTEX_HASH_SIGN_BITS)) & mutexHashMask) >> MUTEX_HASH_TRASH_BITS)
+#endif
+#define MUTEX_HASH_SUCCESSOR(h) (((h) + 7) & (mutexHashTableSize - 1))
+
+typedef struct _conditionHashEntry
+{
+ java_objectheader *object;
+ iCv condition;
+} conditionHashEntry;
+
+#define CONDITION_HASH_TABLE_SIZE 1024
+
+#define CONDITION_HASH_VALUE(a) ((((long)(a)) & conditionHashMask) >> 3)
+#define CONDITION_HASH_SUCCESSOR(h) (((h) + 7) & (conditionHashTableSize - 1))
+
+typedef struct
+{
+ bool free;
+ java_objectheader *object;
+ iMux mutex;
+ iCv condition;
+} object_mutex;
+
+extern void initLocks (void);
+
+mutexHashEntry* conditionLockedMutexForObject (java_objectheader *object);
+
+void reorderConditionHashTable (int begin);
+iCv* conditionForObject (java_objectheader *object);
+iCv* addConditionForObject (java_objectheader *object);
+void removeConditionForObject (java_objectheader *object);
+
+/*
+ * use these functions only outside critical sections (intsEnable/intsRestore).
+ */
+
+void signal_cond_for_object (java_objectheader *obj);
+void broadcast_cond_for_object (java_objectheader *obj);
+void wait_cond_for_object (java_objectheader *obj, s8 time);
+void lock_mutex_for_object (java_objectheader *obj);
+void unlock_mutex_for_object (java_objectheader *obj);
+
+void lock_mutex (iMux*);
+void unlock_mutex (iMux*);
+void wait_cond (iMux*, iCv*, s8);
+void signal_cond (iCv*);
+void broadcast_cond (iCv*);
+
+/*
+ * use these internal functions only in critical sections. blockInts must be exactly
+ * 1.
+ */
+void internal_lock_mutex (iMux*);
+void internal_unlock_mutex (iMux*);
+void internal_wait_cond (iMux*, iCv*, s8);
+void internal_signal_cond (iCv*);
+void internal_broadcast_cond (iCv*);
+
+void internal_lock_mutex_for_object (java_objectheader *obj);
+void internal_unlock_mutex_for_object (java_objectheader *obj);
+void internal_broadcast_cond_for_object (java_objectheader *obj);
+
+#endif
+
+#endif /* USE_THREADS */
+
+#endif /* __locks_h */
--- /dev/null
+/* ------------------------ thread.c -------------------------- */
+
+/*
+ * Put a thread to sleep.
+ */
+void
+sleepThread(int64 time)
+{
+ thread** tidp;
+
+ /* Sleep for no time */
+ if (time == 0) {
+ return;
+ }
+
+ intsDisable();
+
+ /* Get absolute time */
+ currentThread->PrivateInfo->time = time + currentTime();
+
+ /* Find place in alarm list */
+ for (tidp = &alarmList; (*tidp) != 0; tidp = &(*tidp)->next) {
+ if ((*tidp)->PrivateInfo->time > currentThread->PrivateInfo->time) {
+ break;
+ }
+ }
+
+ /* If I'm head of alarm list, restart alarm */
+ if (tidp == &alarmList) {
+ MALARM(time);
+ }
+
+ /* Suspend thread on it */
+ suspendOnQThread(currentThread, tidp);
+
+ intsRestore();
+}
+
+/*
+ * Handle alarm.
+ * This routine uses a different meaning of "blockInts". Formerly, it was just
+ * "don't reschedule if you don't have to". Now it is "don't do ANY
+ * rescheduling actions due to an expired timer". An alternative would be to
+ * block SIGALARM during critical sections (by means of sigprocmask). But
+ * this would be required quite often (for every outmost intsDisable(),
+ * intsRestore()) and therefore would be much more expensive than just
+ * setting an int flag which - sometimes - might cause an additional
+ * setitimer call.
+ */
+static
+void
+alarmException(int sig)
+{
+ thread* tid;
+ int64 time;
+
+ /* Re-enable signal - necessary for SysV */
+ signal(sig, (SIG_T)alarmException);
+
+ /*
+ * If ints are blocked, this might indicate an inconsistent state of
+ * one of the thread queues (either alarmList or threadQhead/tail).
+ * We better don't touch one of them in this case and come back later.
+ */
+ if (blockInts > 0) {
+ MALARM(50);
+ return;
+ }
+
+ intsDisable();
+
+ /* Wake all the threads which need waking */
+ time = currentTime();
+ while (alarmList != 0 && alarmList->PrivateInfo->time <= time) {
+ tid = alarmList;
+ alarmList = alarmList->next;
+ iresumeThread(tid);
+ }
+
+ /* Restart alarm */
+ if (alarmList != 0) {
+ MALARM(alarmList->PrivateInfo->time - time);
+ }
+
+ /*
+ * The next bit is rather tricky. If we don't reschedule then things
+ * are fine, we exit this handler and everything continues correctly.
+ * On the otherhand, if we do reschedule, we will schedule the new
+ * thread with alarms blocked which is wrong. However, we cannot
+ * unblock them here incase we have just set an alarm which goes
+ * off before the reschedule takes place (and we enter this routine
+ * recusively which isn't good). So, we set a flag indicating alarms
+ * are blocked, and allow the rescheduler to unblock the alarm signal
+ * after the context switch has been made. At this point it's safe.
+ */
+ alarmBlocked = true;
+ intsRestore();
+ alarmBlocked = false;
+}
+
+/*
+ * How many stack frames have I invoked?
+ */
+long
+framesThread(thread* tid)
+{
+ long count;
+ THREADFRAMES(tid, count);
+ return (count);
+}
--- /dev/null
+/* -*- mode: c; tab-width: 4; c-basic-offset: 4 -*- */
+/*
+ * thread.c
+ * Thread support.
+ *
+ * Copyright (c) 1996 T. J. Wilkinson & Associates, London, UK.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * Written by Tim Wilkinson <tim@tjwassoc.demon.co.uk>, 1996.
+ */
+
+#include <assert.h>
+
+#include <sys/types.h>
+#include <sys/mman.h> /* for mprotect */
+#include <unistd.h>
+
+#include "thread.h"
+#include "locks.h"
+#include "sysdep/defines.h"
+#include "sysdep/threads.h"
+
+#include "../tables.h"
+#include "../native.h"
+#include "../loader.h"
+#include "../builtin.h"
+#include "../asmpart.h"
+
+static classinfo *class_java_lang_ThreadDeath;
+
+#if 1
+#define DBG(s)
+#define SDBG(s)
+#else
+#define DBG(s) s
+#define SDBG(s) s
+#endif
+
+#if defined(USE_INTERNAL_THREADS)
+
+thread* currentThread;
+thread* threadQhead[MAX_THREAD_PRIO + 1];
+thread* threadQtail[MAX_THREAD_PRIO + 1];
+
+thread* liveThreads;
+thread* alarmList;
+
+thread* gcDaemonThread;
+
+int blockInts;
+bool needReschedule;
+
+ctx contexts[MAXTHREADS];
+
+/* Number of threads alive, also counting daemons */
+static int talive;
+
+/* Number of daemon threads alive */
+static int tdaemon;
+
+static void firstStartThread(void);
+
+void reschedule(void);
+
+/* Setup default thread stack size - this can be overwritten if required */
+int threadStackSize = THREADSTACKSIZE;
+
+static thread* startDaemon(void* func, char* nm, int stackSize);
+
+/*
+ * Allocate the stack for a thread
+ */
+void
+allocThreadStack (thread *tid, int size)
+{
+ int pageSize = getpagesize(),
+ result;
+ unsigned long pageBegin;
+
+ CONTEXT(tid).stackMem = malloc(size + 2 * pageSize);
+ assert(CONTEXT(tid).stackMem != 0);
+ CONTEXT(tid).stackEnd = CONTEXT(tid).stackMem + size + 2 * pageSize;
+
+ pageBegin = (unsigned long)(CONTEXT(tid).stackMem) + pageSize - 1;
+ pageBegin = pageBegin - pageBegin % pageSize;
+
+ result = mprotect((void*)pageBegin, pageSize, PROT_NONE);
+ assert(result == 0);
+
+ CONTEXT(tid).stackBase = (u1*)pageBegin + pageSize;
+}
+
+/*
+ * Free the stack for a thread
+ */
+void
+freeThreadStack (thread *tid)
+{
+ if (!(CONTEXT(tid).flags & THREAD_FLAGS_NOSTACKALLOC))
+ {
+ int pageSize = getpagesize(),
+ result;
+ unsigned long pageBegin;
+
+ pageBegin = (unsigned long)(CONTEXT(tid).stackMem) + pageSize - 1;
+ pageBegin = pageBegin - pageBegin % pageSize;
+
+ result = mprotect((void*)pageBegin, pageSize,
+ PROT_READ | PROT_WRITE | PROT_EXEC);
+ assert(result == 0);
+
+ free(CONTEXT(tid).stackMem);
+ }
+ CONTEXT(tid).stackMem = 0;
+ CONTEXT(tid).stackBase = 0;
+ CONTEXT(tid).stackEnd = 0;
+}
+
+/*
+ * Initialize threads.
+ */
+void
+initThreads(u1 *stackbottom)
+{
+ int i;
+
+ initLocks();
+
+ for (i = 0; i < MAXTHREADS; ++i)
+ contexts[i].free = true;
+
+ /* Allocate a thread to be the main thread */
+ currentThread = (thread*)builtin_new(loader_load(unicode_new_char("java/lang/Thread")));
+ assert(currentThread != 0);
+
+ currentThread->PrivateInfo = 1;
+ CONTEXT(currentThread).free = false;
+
+ liveThreads = currentThread;
+
+ currentThread->name = javastring_new(unicode_new_char("main"));
+ currentThread->priority = NORM_THREAD_PRIO;
+ CONTEXT(currentThread).priority = (u1)currentThread->priority;
+ CONTEXT(currentThread).exceptionptr = 0;
+ currentThread->next = 0;
+ CONTEXT(currentThread).status = THREAD_SUSPENDED;
+ CONTEXT(currentThread).stackBase = CONTEXT(currentThread).stackEnd = stackbottom;
+ THREADINFO(&CONTEXT(currentThread));
+
+ DBG( printf("main thread %p base %p end %p\n",
+ currentThread,
+ CONTEXT(currentThread).stackBase,
+ CONTEXT(currentThread).stackEnd); );
+
+ CONTEXT(currentThread).flags = THREAD_FLAGS_NOSTACKALLOC;
+ CONTEXT(currentThread).nextlive = 0;
+ currentThread->single_step = 0;
+ currentThread->daemon = 0;
+ currentThread->stillborn = 0;
+ currentThread->target = 0;
+ currentThread->interruptRequested = 0;
+ currentThread->group =
+ (threadGroup*)builtin_new(loader_load(unicode_new_char("java/lang/ThreadGroup")));
+ /* we should call the constructor */
+ assert(currentThread->group != 0);
+
+ talive++;
+
+ /* Add thread into runQ */
+ iresumeThread(currentThread);
+
+ /* Start garbage collection thread */
+ gcDaemonThread = startDaemon(gc_thread, "gc", 1024*512);
+ iresumeThread(gcDaemonThread);
+
+ heap_addreference((void**)&gcDaemonThread);
+
+ /* Load exception classes */
+ class_java_lang_ThreadDeath = loader_load(unicode_new_char("java/lang/ThreadDeath"));
+
+ DBG( fprintf(stderr, "finishing initThreads\n"); );
+
+ assert(blockInts == 0);
+}
+
+/*
+ * Start a new thread running.
+ */
+void
+startThread (thread* tid)
+{
+ int i;
+
+ /* Allocate a stack context */
+ for (i = 0; i < MAXTHREADS; ++i)
+ if (contexts[i].free)
+ break;
+
+ if (i == MAXTHREADS)
+ panic("Too many threads");
+
+ tid->PrivateInfo = i + 1;
+ CONTEXT(tid).free = false;
+ CONTEXT(tid).nextlive = liveThreads;
+ liveThreads = tid;
+ allocThreadStack(tid, threadStackSize);
+ CONTEXT(tid).usedStackTop = CONTEXT(tid).stackBase;
+ CONTEXT(tid).flags = THREAD_FLAGS_GENERAL;
+ CONTEXT(tid).status = THREAD_SUSPENDED;
+ CONTEXT(tid).priority = (u1)tid->priority;
+ CONTEXT(tid).exceptionptr = 0;
+
+ /* Construct the initial restore point. */
+ THREADINIT((&CONTEXT(tid)), firstStartThread);
+
+ DBG( printf("new thread %p base %p end %p\n",
+ tid, CONTEXT(tid).stackBase,
+ CONTEXT(tid).stackEnd); );
+
+ talive++;
+ if (tid->daemon)
+ tdaemon++;
+
+ /* Add thread into runQ */
+ iresumeThread(tid);
+}
+
+/*
+ * Start a daemon thread.
+ */
+static thread*
+startDaemon(void* func, char* nm, int stackSize)
+{
+ thread* tid;
+ int i;
+
+ DBG( printf("startDaemon %s\n", nm); );
+
+ tid = (thread*)builtin_new(loader_load(unicode_new_char("java/lang/Thread")));
+ assert(tid != 0);
+
+ for (i = 0; i < MAXTHREADS; ++i)
+ if (contexts[i].free)
+ break;
+ if (i == MAXTHREADS)
+ panic("Too many threads");
+
+ tid->PrivateInfo = i + 1;
+ CONTEXT(tid).free = false;
+ tid->name = 0; /* for the moment */
+ tid->priority = MAX_THREAD_PRIO;
+ CONTEXT(tid).priority = (u1)tid->priority;
+ tid->next = 0;
+ CONTEXT(tid).status = THREAD_SUSPENDED;
+
+ allocThreadStack(tid, stackSize);
+ tid->single_step = 0;
+ tid->daemon = 1;
+ tid->stillborn = 0;
+ tid->target = 0;
+ tid->interruptRequested = 0;
+ tid->group = 0;
+
+ /* Construct the initial restore point. */
+ THREADINIT((&CONTEXT(tid)), func);
+
+ talive++;
+ tdaemon++;
+
+ return tid;
+}
+
+/*
+ * All threads start here.
+ */
+static void
+firstStartThread(void)
+{
+ methodinfo *method;
+
+ DBG( printf("firstStartThread %p\n", currentThread); );
+
+ /* Every thread starts with the interrupts off */
+ intsRestore();
+ assert(blockInts == 0);
+
+ /* Find the run()V method and call it */
+ method = class_findmethod(currentThread->header.vftbl->class,
+ unicode_new_char("run"), unicode_new_char("()V"));
+ if (method == 0)
+ panic("Cannot find method \'void run ()\'");
+ asm_calljavamethod(method, currentThread, NULL, NULL, NULL);
+
+ killThread(0);
+ assert("Thread returned from killThread" == 0);
+}
+
+/*
+ * Resume a thread running.
+ * This routine has to be called only from locations which ensure
+ * run / block queue consistency. There is no check for illegal resume
+ * conditions (like explicitly resuming an IO blocked thread). There also
+ * is no update of any blocking queue. Both has to be done by the caller
+ */
+void
+iresumeThread(thread* tid)
+{
+ DBG( printf("resumeThread %p\n", tid); );
+
+ intsDisable();
+
+ if (CONTEXT(tid).status != THREAD_RUNNING)
+ {
+ CONTEXT(tid).status = THREAD_RUNNING;
+
+ DBG( fprintf(stderr, "prio is %d\n", CONTEXT(tid).priority); );
+
+ /* Place thread on the end of its queue */
+ if (threadQhead[CONTEXT(tid).priority] == 0) {
+ threadQhead[CONTEXT(tid).priority] = tid;
+ threadQtail[CONTEXT(tid).priority] = tid;
+ if (CONTEXT(tid).priority
+ > CONTEXT(currentThread).priority)
+ needReschedule = true;
+ }
+ else
+ {
+ threadQtail[CONTEXT(tid).priority]->next = tid;
+ threadQtail[CONTEXT(tid).priority] = tid;
+ }
+ tid->next = 0;
+ }
+ SDBG( else { printf("Re-resuming %p\n", tid); } );
+
+ intsRestore();
+}
+
+/*
+ * Yield process to another thread of equal priority.
+ */
+void
+yieldThread()
+{
+ intsDisable();
+
+ if (threadQhead[CONTEXT(currentThread).priority]
+ != threadQtail[CONTEXT(currentThread).priority])
+ {
+ /* Get the next thread and move me to the end */
+ threadQhead[CONTEXT(currentThread).priority] = currentThread->next;
+ threadQtail[CONTEXT(currentThread).priority]->next = currentThread;
+ threadQtail[CONTEXT(currentThread).priority] = currentThread;
+ currentThread->next = 0;
+ needReschedule = true;
+ }
+
+ intsRestore();
+}
+
+/*
+ * Explicit request by user to resume a thread
+ * The definition says that it is just legal to call this after a preceeding
+ * suspend (which got through). If the thread was blocked for some other
+ * reason (either sleep or IO or a muxSem), we simply can't do it
+ * We use a new thread flag THREAD_FLAGS_USER_SUSPEND for this purpose
+ * (which is set by suspendThread(.))
+ */
+void
+resumeThread(thread* tid)
+{
+ if ((CONTEXT(tid).flags & THREAD_FLAGS_USER_SUSPEND) != 0)
+ {
+ intsDisable();
+ CONTEXT(tid).flags &= ~THREAD_FLAGS_USER_SUSPEND;
+ iresumeThread(tid);
+ intsRestore();
+ }
+}
+
+/*
+ * Suspend a thread.
+ * This is an explicit user request to suspend the thread - the counterpart
+ * for resumeThreadRequest(.). It is JUST called by the java method
+ * Thread.suspend()
+ * What makes it distinct is the fact that the suspended thread is not contained
+ * in any block queue. Without a special flag (indicating the user suspend), we
+ * can't check s suspended thread for this condition afterwards (which is
+ * required by resumeThreadRequest()). The new thread flag
+ * THREAD_FLAGS_USER_SUSPEND is used for this purpose.
+ */
+void
+suspendThread(thread* tid)
+{
+ thread** ntid;
+
+ intsDisable();
+
+ if (CONTEXT(tid).status != THREAD_SUSPENDED)
+ {
+ CONTEXT(tid).status = THREAD_SUSPENDED;
+
+ /*
+ * This is used to indicate the explicit suspend condition
+ * required by resumeThreadRequest()
+ */
+ CONTEXT(tid).flags |= THREAD_FLAGS_USER_SUSPEND;
+
+ for (ntid = &threadQhead[CONTEXT(tid).priority];
+ *ntid != 0;
+ ntid = &(*ntid)->next)
+ {
+ if (*ntid == tid)
+ {
+ *ntid = tid->next;
+ tid->next = 0;
+ if (tid == currentThread)
+ {
+ reschedule();
+ }
+ break;
+ }
+ }
+ }
+ SDBG( else { printf("Re-suspending %p\n", tid); } );
+
+ intsRestore();
+}
+
+/*
+ * Suspend a thread on a queue.
+ */
+void
+suspendOnQThread(thread* tid, thread** queue)
+{
+ thread** ntid;
+
+ DBG( printf("suspendOnQThread %p %p\n", tid, queue); );
+
+ assert(blockInts == 1);
+
+ if (CONTEXT(tid).status != THREAD_SUSPENDED)
+ {
+ CONTEXT(tid).status = THREAD_SUSPENDED;
+
+ for (ntid = &threadQhead[CONTEXT(tid).priority];
+ *ntid != 0;
+ ntid = &(*ntid)->next)
+ {
+ if (*ntid == tid)
+ {
+ *ntid = tid->next;
+ /* Insert onto head of lock wait Q */
+ tid->next = *queue;
+ *queue = tid;
+ if (tid == currentThread)
+ {
+ DBG( fprintf(stderr, "suspending %p (cur=%p) with prio %d\n",
+ tid, currentThread, CONTEXT(tid).priority); );
+ reschedule();
+ }
+ break;
+ }
+ }
+ }
+ SDBG( else { printf("Re-suspending %p on %p\n", tid, *queue); } );
+}
+
+/*
+ * Kill thread.
+ */
+void
+killThread(thread* tid)
+{
+ thread** ntid;
+
+ intsDisable();
+
+ /* A null tid means the current thread */
+ if (tid == 0)
+ {
+ tid = currentThread;
+ }
+
+ DBG( printf("killThread %p\n", tid); );
+
+ if (CONTEXT(tid).status != THREAD_DEAD)
+ {
+ /* Get thread off runq (if it needs it) */
+ if (CONTEXT(tid).status == THREAD_RUNNING)
+ {
+ for (ntid = &threadQhead[CONTEXT(tid).priority];
+ *ntid != 0;
+ ntid = &(*ntid)->next)
+ {
+ if (*ntid == tid)
+ {
+ *ntid = tid->next;
+ break;
+ }
+ }
+ }
+
+ CONTEXT(tid).status = THREAD_DEAD;
+ talive--;
+ if (tid->daemon) {
+ tdaemon--;
+ }
+
+ /* If we only have daemons left, then everyone is dead. */
+ if (talive == tdaemon) {
+ /* Am I suppose to close things down nicely ?? */
+ exit(0);
+ }
+
+ /* Notify on the object just in case anyone is waiting */
+ internal_lock_mutex_for_object(&tid->header);
+ internal_broadcast_cond_for_object(&tid->header);
+ internal_unlock_mutex_for_object(&tid->header);
+
+ /* Remove thread from live list to it can be garbaged */
+ for (ntid = &liveThreads;
+ *ntid != 0;
+ ntid = &(CONTEXT((*ntid)).nextlive))
+ {
+ if (tid == (*ntid))
+ {
+ (*ntid) = CONTEXT(tid).nextlive;
+ break;
+ }
+ }
+
+ /* Free stack */
+ freeThreadStack(tid);
+
+ /* free context */
+ CONTEXT(tid).free = true;
+
+ /* Run something else */
+ needReschedule = true;
+ }
+ intsRestore();
+}
+
+/*
+ * Change thread priority.
+ */
+void
+setPriorityThread(thread* tid, int prio)
+{
+ thread** ntid;
+
+ if (tid->PrivateInfo == 0) {
+ tid->priority = prio;
+ return;
+ }
+
+ if (CONTEXT(tid).status == THREAD_SUSPENDED) {
+ CONTEXT(tid).priority = (u8)prio;
+ return;
+ }
+
+ intsDisable();
+
+ /* Remove from current thread list */
+ for (ntid = &threadQhead[CONTEXT(tid).priority]; *ntid != 0; ntid = &(*ntid)->next) {
+ if (*ntid == tid) {
+ *ntid = tid->next;
+ break;
+ }
+ }
+
+ /* Insert onto a new one */
+ tid->priority = prio;
+ CONTEXT(tid).priority = (u8)tid->priority;
+ if (threadQhead[prio] == 0) {
+ threadQhead[prio] = tid;
+ threadQtail[prio] = tid;
+ if (prio > CONTEXT(currentThread).priority) {
+ needReschedule = true;
+ }
+ }
+ else {
+ threadQtail[prio]->next = tid;
+ threadQtail[prio] = tid;
+ }
+ tid->next = 0;
+
+ intsRestore();
+}
+
+/*
+ * Is this thread alive?
+ */
+bool
+aliveThread(thread* tid)
+{
+ if (tid->PrivateInfo != 0 && CONTEXT(tid).status != THREAD_DEAD)
+ return (true);
+ else
+ return (false);
+}
+
+/*
+ * Reschedule the thread.
+ * Called whenever a change in the running thread is required.
+ */
+void
+reschedule(void)
+{
+ int i;
+ thread* lastThread;
+ int b;
+ /* sigset_t nsig; */
+
+ /* A reschedule in a non-blocked context is half way to hell */
+ assert(blockInts > 0);
+ b = blockInts;
+
+ /* Check events - we may release a high priority thread */
+ /* Just check IO, no need for a reschedule call by checkEvents() */
+ needReschedule = false;
+ checkEvents(false);
+
+ for (;;)
+ {
+ for (i = MAX_THREAD_PRIO; i >= MIN_THREAD_PRIO; i--)
+ {
+ if (threadQhead[i] != 0)
+ {
+ DBG( fprintf(stderr, "found thread %p in head %d\n", threadQhead[i], i); );
+
+ if (threadQhead[i] != currentThread)
+ {
+ USEDSTACKTOP((CONTEXT(currentThread).usedStackTop));
+
+ lastThread = currentThread;
+ currentThread = threadQhead[i];
+
+ CONTEXT(currentThread).exceptionptr = exceptionptr;
+
+ THREADSWITCH((&CONTEXT(currentThread)),
+ (&CONTEXT(lastThread)));
+ blockInts = b;
+
+ exceptionptr = CONTEXT(currentThread).exceptionptr;
+
+ /* Alarm signal may be blocked - if so
+ * unblock it.
+ */
+ /*
+ if (alarmBlocked == true) {
+ alarmBlocked = false;
+ sigemptyset(&nsig);
+ sigaddset(&nsig, SIGALRM);
+ sigprocmask(SIG_UNBLOCK, &nsig, 0);
+ }
+ */
+
+ /* I might be dying */
+ if ((CONTEXT(lastThread).flags & THREAD_FLAGS_KILLED)
+ != 0)
+ {
+ CONTEXT(lastThread).flags &= ~THREAD_FLAGS_KILLED;
+ exceptionptr = native_new_and_init(class_java_lang_ThreadDeath);
+ }
+ }
+ /* Now we kill the schedule and turn ints
+ back on */
+ needReschedule = false;
+ return;
+ }
+ }
+ /* Nothing to run - wait for external event */
+ DBG( fprintf(stderr, "nothing more to do\n"); );
+ checkEvents(true);
+ }
+}
+
+#endif
--- /dev/null
+/*
+ * thread.h
+ * Thread support.
+ *
+ * Copyright (c) 1996 T. J. Wilkinson & Associates, London, UK.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * Written by Tim Wilkinson <tim@tjwassoc.demon.co.uk>, 1996.
+ */
+
+#ifndef __thread_h
+#define __thread_h
+
+#ifdef USE_THREADS
+
+#include "../global.h"
+
+#define MAXTHREADS 256 /* schani */
+
+#define THREADCLASS "java/lang/Thread"
+#define THREADGROUPCLASS "java/lang/ThreadGroup"
+#define THREADDEATHCLASS "java/lang/ThreadDeath"
+
+#define MIN_THREAD_PRIO 1
+#define NORM_THREAD_PRIO 5
+#define MAX_THREAD_PRIO 10
+
+#define THREAD_SUSPENDED 0
+#define THREAD_RUNNING 1
+#define THREAD_DEAD 2
+#define THREAD_KILL 3
+
+#define THREAD_FLAGS_GENERAL 0
+#define THREAD_FLAGS_NOSTACKALLOC 1
+#define THREAD_FLAGS_USER_SUSPEND 2 /* Flag explicit suspend() call */
+#define THREAD_FLAGS_KILLED 4
+
+struct _thread;
+
+typedef struct _ctx
+{
+ bool free; /* schani */
+ u1 status;
+ u1 priority;
+ u1* restorePoint;
+ u1* stackMem; /* includes guard page */
+ u1* stackBase;
+ u1* stackEnd;
+ u1* usedStackTop;
+ s8 time;
+ java_objectheader *exceptionptr;
+ struct _thread *nextlive;
+ u1 flags;
+} ctx;
+
+/*
+struct _stringClass;
+struct _object;
+*/
+
+/* This structure mirrors java.lang.ThreadGroup.h */
+
+typedef struct _threadGroup
+{
+ java_objectheader header;
+ struct _threadGroup* parent;
+ java_objectheader* name;
+ s4 maxPrio;
+ s4 destroyed;
+ s4 daemon;
+ s4 nthreads;
+ java_objectheader* threads;
+ s4 ngroups;
+ java_objectheader* groups;
+} threadGroup;
+
+/* This structure mirrors java.lang.Thread.h */
+typedef struct _thread
+{
+ java_objectheader header;
+ java_objectheader* name;
+ s4 priority;
+ struct _thread* next;
+ s8 PrivateInfo;
+ struct java_lang_Object* eetop; /* ??? */
+ s4 single_step;
+ s4 daemon;
+ s4 stillborn;
+ java_objectheader* target;
+ s4 interruptRequested;
+ threadGroup* group;
+} thread;
+
+void initThreads(u1 *stackbottom);
+void startThread(thread*);
+void resumeThread(thread*);
+void iresumeThread(thread*);
+void suspendThread(thread*);
+void suspendOnQThread(thread*, thread**);
+void yieldThread(void);
+void killThread(thread*);
+void setPriorityThread(thread*, int);
+
+void sleepThread(s8);
+bool aliveThread(thread*);
+long framesThread(thread*);
+
+void reschedule(void);
+
+void checkEvents(bool block);
+
+extern int blockInts;
+extern bool needReschedule;
+extern thread *currentThread;
+extern ctx contexts[];
+extern int threadStackSize;
+
+extern thread *liveThreads;
+
+extern thread *threadQhead[MAX_THREAD_PRIO + 1];
+
+#define CONTEXT(_t) \
+ (contexts[(_t)->PrivateInfo - 1])
+
+#if 1
+#define intsDisable() blockInts++
+#define intsRestore() if (blockInts == 1 && needReschedule) { \
+ reschedule(); \
+ } \
+ blockInts--
+#else
+#define intsDisable() do { blockInts++; fprintf(stderr, "++: %d (%s:%d)\n", blockInts, __FILE__, __LINE__); } while (0)
+#define intsRestore() do { \
+ if (blockInts == 1 && needReschedule) { \
+ reschedule(); \
+ } \
+ blockInts--; \
+ fprintf(stderr, "--: %d (%s:%d)\n", blockInts, __FILE__, __LINE__); \
+ } while (0)
+#endif
+
+#else
+
+#define intsDisable()
+#define intsRestore()
+
+#endif
+
+#endif
--- /dev/null
+/*
+ * threadCalls.c
+ * Support for threaded ops which may block (read, write, connect, etc.).
+ *
+ * Copyright (c) 1996 T. J. Wilkinson & Associates, London, UK.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * Written by Tim Wilkinson <tim@tjwassoc.demon.co.uk>, 1996.
+ */
+
+#define DBG(s)
+
+#include "sysdep/defines.h"
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <assert.h>
+#include <unistd.h>
+
+#include "thread.h"
+
+/*
+ * We only need this stuff is we are using the internal thread system.
+ */
+#if defined(USE_INTERNAL_THREADS)
+
+#define TH_READ 0
+#define TH_WRITE 1
+#define TH_ACCEPT TH_READ
+#define TH_CONNECT TH_WRITE
+
+static int maxFd;
+static fd_set readsPending;
+static fd_set writesPending;
+static thread* readQ[FD_SETSIZE];
+static thread* writeQ[FD_SETSIZE];
+static struct timeval tm = { 0, 0 };
+
+void blockOnFile(int, int);
+void waitOnEvents(void);
+
+extern thread* currentThread;
+
+/* These are undefined because we do not yet support async I/O */
+#undef F_SETOWN
+#undef FIOSETOWN
+#undef O_ASYNC
+#undef FIOASYNC
+
+/*
+ * Create a threaded file descriptor.
+ */
+int
+threadedFileDescriptor(int fd)
+{
+#if !defined(BLOCKING_CALLS)
+ int r;
+ int on = 1;
+ int pid;
+
+ /* Make non-blocking */
+#if defined(HAVE_FCNTL) && defined(O_NONBLOCK)
+ r = fcntl(fd, F_GETFL, 0);
+ r = fcntl(fd, F_SETFL, r|O_NONBLOCK);
+#elif defined(HAVE_IOCTL) && defined(FIONBIO)
+ r = ioctl(fd, FIONBIO, &on);
+#else
+ r = 0;
+#endif
+ if (r < 0)
+ {
+ return (r);
+ }
+
+ /* Allow socket to signal this process when new data is available */
+ pid = getpid();
+#if defined(HAVE_FCNTL) && defined(F_SETOWN)
+ r = fcntl(fd, F_SETOWN, pid);
+#elif defined(HAVE_IOCTL) && defined(FIOSETOWN)
+ r = ioctl(fd, FIOSETOWN, &pid);
+#else
+ r = 0;
+#endif
+ if (r < 0)
+ {
+ return (r);
+ }
+
+#if defined(HAVE_FCNTL) && defined(O_ASYNC)
+ r = fcntl(fd, F_GETFL, 0);
+ r = fcntl(fd, F_SETFL, r|O_ASYNC);
+#elif defined(HAVE_IOCTL) && defined(FIOASYNC)
+ r = ioctl(fd, FIOASYNC, &on);
+#else
+ r = 0;
+#endif
+ if (r < 0)
+ {
+ return (r);
+ }
+#endif
+ return (fd);
+}
+
+/*
+ * Threaded create socket.
+ */
+int
+threadedSocket(int af, int type, int proto)
+{
+ int fd;
+ int r;
+ int on = 1;
+ int pid;
+
+ fd = socket(af, type, proto);
+ return (threadedFileDescriptor(fd));
+}
+
+/*
+ * Threaded file open.
+ */
+int
+threadedOpen(char* path, int flags, int mode)
+{
+ int fd;
+ int r;
+ int on = 1;
+ int pid;
+
+ fd = open(path, flags, mode);
+ return (threadedFileDescriptor(fd));
+}
+
+/*
+ * Threaded socket connect.
+ */
+int
+threadedConnect(int fd, struct sockaddr* addr, int len)
+{
+ int r;
+
+ r = connect(fd, addr, len);
+#if !defined(BLOCKING_CALLS)
+ if ((r < 0)
+ && (errno == EINPROGRESS || errno == EALREADY
+ || errno == EWOULDBLOCK)) {
+ blockOnFile(fd, TH_CONNECT);
+ r = 0; /* Assume it's okay when we get released */
+ }
+#endif
+
+ return (r);
+}
+
+/*
+ * Threaded socket accept.
+ */
+int
+threadedAccept(int fd, struct sockaddr* addr, int* len)
+{
+ int r;
+ int on = 1;
+
+ for (;;)
+ {
+#if defined(BLOCKING_CALLS)
+ blockOnFile(fd, TH_ACCEPT);
+#endif
+ r = accept(fd, addr, len);
+ if (r >= 0
+ || !(errno == EINPROGRESS || errno == EALREADY
+ || errno == EWOULDBLOCK))
+ {
+ break;
+ }
+#if !defined(BLOCKING_CALLS)
+ blockOnFile(fd, TH_ACCEPT);
+#endif
+ }
+ return (threadedFileDescriptor(r));
+}
+
+/*
+ * Read but only if we can.
+ */
+int
+threadedRead(int fd, char* buf, int len)
+{
+ int r;
+
+ DBG( printf("threadedRead\n"); )
+
+#if defined(BLOCKING_CALLS)
+ blockOnFile(fd, TH_READ);
+#endif
+ for (;;)
+ {
+ r = read(fd, buf, len);
+ if (r < 0
+ && (errno == EAGAIN || errno == EWOULDBLOCK
+ || errno == EINTR))
+ {
+ blockOnFile(fd, TH_READ);
+ continue;
+ }
+ return (r);
+ }
+}
+
+/*
+ * Write but only if we can.
+ */
+int
+threadedWrite(int fd, char* buf, int len)
+{
+ int r;
+ char* ptr;
+
+ ptr = buf;
+ r = 1;
+
+ DBG( printf("threadedWrite %dbytes\n",len); )
+
+ while (len > 0 && r > 0)
+ {
+#if defined(BLOCKING_CALLS)
+ blockOnFile(fd, TH_WRITE);
+#endif
+ r = write(fd, ptr, len);
+ if (r < 0
+ && (errno == EAGAIN || errno == EWOULDBLOCK
+ || errno == EINTR))
+ {
+#if !defined(BLOCKING_CALLS)
+ blockOnFile(fd, TH_WRITE);
+#endif
+ r = 1;
+ }
+ else
+ {
+ ptr += r;
+ len -= r;
+ }
+ }
+ return (ptr - buf);
+}
+
+/*
+ * An attempt to access a file would block, so suspend the thread until
+ * it will happen.
+ */
+void
+blockOnFile(int fd, int op)
+{
+DBG( printf("blockOnFile()\n"); )
+
+ intsDisable();
+
+ if (fd > maxFd)
+ {
+ maxFd = fd;
+ }
+ if (op == TH_READ)
+ {
+ FD_SET(fd, &readsPending);
+ suspendOnQThread(currentThread, &readQ[fd]);
+ FD_CLR(fd, &readsPending);
+ }
+ else
+ {
+ FD_SET(fd, &writesPending);
+ suspendOnQThread(currentThread, &writeQ[fd]);
+ FD_CLR(fd, &writesPending);
+ }
+
+ intsRestore();
+}
+
+/*
+ * Check if some file descriptor or other event to become ready.
+ * Block if required (but make sure we can still take timer interrupts).
+ */
+void
+checkEvents(bool block)
+{
+ int r;
+ fd_set rd;
+ fd_set wr;
+ thread* tid;
+ thread* ntid;
+ int i;
+ int b;
+
+DBG( printf("checkEvents block:%d\n", block); )
+
+#if defined(FD_COPY)
+ FD_COPY(&readsPending, &rd);
+ FD_COPY(&writesPending, &wr);
+#else
+ memcpy(&rd, &readsPending, sizeof(rd));
+ memcpy(&wr, &writesPending, sizeof(wr));
+#endif
+
+ /*
+ * If select() is called with indefinite wait, we have to make sure
+ * we can get interrupted by timer events.
+ */
+ if (block == true)
+ {
+ b = blockInts;
+ blockInts = 0;
+ r = select(maxFd+1, &rd, &wr, 0, 0);
+ blockInts = b;
+ }
+ else
+ {
+ r = select(maxFd+1, &rd, &wr, 0, &tm);
+ }
+
+ /* We must be holding off interrupts before we start playing with
+ * the read and write queues. This should be already done but a
+ * quick check never hurt anyone.
+ */
+ assert(blockInts > 0);
+
+DBG( printf("Select returns %d\n", r); )
+
+ for (i = 0; r > 0 && i <= maxFd; i++)
+ {
+ if (readQ[i] != 0 && FD_ISSET(i, &rd))
+ {
+ for (tid = readQ[i]; tid != 0; tid = ntid)
+ {
+ ntid = tid->next;
+ iresumeThread(tid);
+ }
+ readQ[i] = 0;
+ r--;
+ }
+ if (writeQ[i] != 0 && FD_ISSET(i, &wr))
+ {
+ for (tid = writeQ[i]; tid != 0; tid = ntid)
+ {
+ ntid = tid->next;
+ iresumeThread(tid);
+ }
+ writeQ[i] = 0;
+ r--;
+ }
+ }
+}
+#endif
--- /dev/null
+/* -*- c -*- */
+
+#ifndef __threadio_h_
+#define __threadio_h_
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include "../global.h"
+
+#ifdef USE_THREADS
+int threadedFileDescriptor(int fd);
+int threadedSocket(int af, int type, int proto);
+int threadedOpen(char* path, int flags, int mode);
+int threadedConnect(int fd, struct sockaddr* addr, int len);
+int threadedAccept(int fd, struct sockaddr* addr, int* len);
+int threadedRead(int fd, char* buf, int len);
+int threadedWrite(int fd, char* buf, int len);
+#else
+#define threadedFileDescriptor(fd)
+#define threadedRead(fd,buf,len) read(fd,buf,len)
+#define threadedWrite(fd,buf,len) write(fd,buf,len)
+#endif
+
+
+#endif
--- /dev/null
+################################################################################
+# Makefile for the program independent toolbox #
+################################################################################
+#
+# Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+#
+# See the file COPYRIGHT for information on usage and disclaimer of warranties
+#
+# Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+#
+# Last Change: 1997/10/30
+#
+################################################################################
+
+OBJECTS = memory.o loging.o chain.o tree.o list.o
+
+toolbox.a: $(OBJECTS) Makefile
+ rm -f toolbox.a
+ ar qcs toolbox.a $(OBJECTS)
+
+memory.o: memory.c memory.h loging.h
+loging.o: loging.c loging.h
+chain.o: chain.c chain.h memory.h
+tree.o: tree.c tree.h memory.h
+list.o: list.c list.h
+
+clean:
+ rm -f *.o *.a
--- /dev/null
+/************************* toolbox/chain.c *************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Not documented, see chain.h.
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1996/10/03
+
+*******************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "memory.h"
+#include "chain.h"
+
+
+
+chain *chain_new ()
+{
+ chain *c;
+
+ c = NEW (chain);
+ c -> usedump = 0;
+ c -> first = NULL;
+ c -> last = NULL;
+ c -> active = NULL;
+
+ return c;
+}
+
+chain *chain_dnew ()
+{
+ chain *c;
+
+ c = DNEW (chain);
+ c -> usedump = 1;
+ c -> first = NULL;
+ c -> last = NULL;
+ c -> active = NULL;
+
+ return c;
+}
+
+
+void chain_free (chain *c)
+{
+ chainlink *l;
+
+ assert (! c->usedump);
+
+ l = c->first;
+ while (l) {
+ chainlink *nextl = l->next;
+
+ FREE (l, chainlink);
+ l = nextl;
+ }
+
+ FREE (c, chain);
+}
+
+
+void chain_addafter(chain *c, void *element)
+{
+ chainlink *active,*newlink;
+
+ active = c->active;
+
+ if (c -> usedump) newlink = DNEW (chainlink);
+ else newlink = NEW (chainlink);
+
+ newlink -> element = element;
+
+ if (active) {
+ newlink -> next = active -> next;
+ newlink -> prev = active;
+
+ active -> next = newlink;
+ if (newlink -> next) newlink -> next -> prev = newlink;
+ else c -> last = newlink;
+ }
+ else {
+ newlink -> next = NULL;
+ newlink -> prev = NULL;
+
+ c -> active = newlink;
+ c -> first = newlink;
+ c -> last = newlink;
+ }
+}
+
+
+void chain_addbefore(chain *c, void *element)
+{
+ chainlink *active,*newlink;
+
+ active = c->active;
+
+ if (c -> usedump) newlink = DNEW (chainlink);
+ else newlink = NEW (chainlink);
+
+ newlink -> element = element;
+
+ if (active) {
+ newlink -> next = active;
+ newlink -> prev = active -> prev;
+
+ active -> prev = newlink;
+ if (newlink -> prev) newlink -> prev -> next = newlink;
+ else c -> first = newlink;
+ }
+ else {
+ newlink -> next = NULL;
+ newlink -> prev = NULL;
+
+ c -> active = newlink;
+ c -> first = newlink;
+ c -> last = newlink;
+ }
+}
+
+void chain_addlast (chain *c, void *e)
+{
+ chain_last (c);
+ chain_addafter (c, e);
+}
+
+void chain_addfirst (chain *c, void *e)
+{
+ chain_first (c);
+ chain_addbefore (c, e);
+}
+
+
+void chain_remove (chain *c)
+{
+ chainlink *active;
+
+ active = c -> active;
+ assert (active);
+
+ if (active -> next) {
+ active -> next -> prev = active -> prev;
+ }
+ else {
+ c -> last = active -> prev;
+ }
+
+ if (active -> prev) {
+ active -> prev -> next = active -> next;
+ }
+ else {
+ c -> first = active -> next;
+ }
+
+
+ if (active->prev)
+ c -> active = active->prev;
+ else
+ c -> active = active->next;
+
+ if (! c -> usedump) FREE (active, chainlink);
+}
+
+
+void *chain_remove_go_prev (chain *c)
+{
+ chain_remove (c);
+ return chain_this (c);
+}
+
+
+
+void chain_removespecific(chain *c, void *e)
+{
+ void *ce;
+
+ ce = chain_first (c);
+ while (ce) {
+ if (e == ce) { chain_remove (c); return; }
+ ce = chain_next (c);
+ }
+
+}
+
+void *chain_next(chain *c)
+{
+ chainlink *active;
+
+ active = c -> active;
+ if (!active) return NULL;
+
+ if (active -> next) {
+ c -> active = active -> next;
+ return c -> active -> element;
+ }
+
+ return NULL;
+}
+
+void *chain_prev(chain *c)
+{
+ chainlink *active;
+
+ active = c -> active;
+ if (!active) return NULL;
+
+ if (active -> prev) {
+ c -> active = active -> prev;
+ return c -> active -> element;
+ }
+
+ return NULL;
+}
+
+
+void *chain_this(chain *c)
+{
+ if (c -> active) return c -> active -> element;
+ return NULL;
+}
+
+
+void *chain_first(chain *c)
+{
+ c -> active = c -> first;
+ if (c -> active) return c -> active -> element;
+ return NULL;
+}
+
+void *chain_last(chain *c)
+{
+ c -> active = c -> last;
+ if (c -> active) return c -> active -> element;;
+ return NULL;
+}
+
--- /dev/null
+/************************* toolbox/chain.h *************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ dient zur Verwaltung doppelt verketteter Listen mit externer Verkettung
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1996/10/03
+
+*******************************************************************************/
+
+typedef struct chainlink { /* Struktur f"ur ein Listenelement */
+ struct chainlink *next,*prev;
+ void *element;
+ } chainlink;
+
+typedef struct chain { /* Struktur f"ur eine Liste */
+ int usedump;
+
+ chainlink *first,*last;
+ chainlink *active;
+ } chain;
+
+
+chain *chain_new ();
+chain *chain_dnew ();
+void chain_free(chain *c);
+
+void chain_addafter(chain *c, void *element);
+void chain_addbefore(chain *c, void *element);
+void chain_addlast (chain *c, void *element);
+void chain_addfirst (chain *c, void *element);
+
+void chain_remove(chain *c);
+void *chain_remove_go_prev(chain *c);
+void chain_removespecific(chain *c, void *element);
+
+void *chain_next(chain *c);
+void *chain_prev(chain *c);
+void *chain_this(chain *c);
+
+void *chain_first(chain *c);
+void *chain_last(chain *c);
+
+
+/*
+--------------------------- Schnittstellenbeschreibung ------------------------
+
+Bei Verwendung dieser Funktionen f"ur die Listenverwaltung mu"s, im
+Gegenstatz zum Modul 'list', keine zus"atzliche Vorbereitung in den
+Element-Strukturen gemacht werden.
+
+Diese Funktionen sind daher auch ein wenig langsamer und brauchen
+mehr Speicher.
+
+Eine neue Liste wird mit
+ chain_new
+ oder chain_dnew
+angelegt. Der Unterschied ist, da"s bei der zweiten Variante alle
+zus"atzlichen Datenstrukturen am DUMP-Speicher angelegt werden (was
+schneller geht, und ein explizites Freigeben am Ende der Verarbeitung
+unn"otig macht). Dabei mu"s man aber achtgeben, da"s man nicht
+versehentlich Teile dieser Strukturen durch ein verfr"uhtes 'dump_release'
+freigibt.
+
+Eine nicht mehr verwendete Liste kann mit
+ chain_free
+freigegeben werden (nur verwenden, wenn mit 'chain_new' angefordert)
+
+
+Das Eintragen neuer Elemente geht sehr einfach mit:
+ chain_addafter, chain_addlast, chain_addbefore, chain_addfirst
+
+Durchsuchen der Liste mit:
+ chain_first, chain_last, chain_prev, chain_next, chain_this
+
+L"oschen von Elementen aus der Liste:
+ chain_remove, chain_remove_go_prev, chain_removespecific
+
+
+ACHTUNG: In den zu verkettenden Elementen gibt es ja (wie oben gesagt) keine
+ Referenzen auf die Liste oder irgendwelche Listenknoten, deshalb k"onnen
+ die Elemente nicht als Ortsangabe innerhalb der Liste fungieren.
+ Es gibt vielmehr ein Art 'Cursor', der ein Element als das gerade
+ aktuelle festh"alt, und alle Ein-/und Ausf"ugeoperationen geschehen
+ relativ zu diesem Cursor.
+
+*/
+
--- /dev/null
+/************************** toolbox/list.c *************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Not documented, see chain.h.
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1996/10/03
+
+*******************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "list.h"
+
+
+void list_init (list *l, int nodeoffset)
+{
+ l->first = NULL;
+ l->last = NULL;
+ l->nodeoffset = nodeoffset;
+}
+
+void list_addlast (list *l, void *element)
+{
+ listnode *n = (listnode*) ( ((char*) element) + l->nodeoffset );
+
+ if (l->last) {
+ n->prev = l->last;
+ n->next = NULL;
+ l->last->next = n;
+ l->last = n;
+ }
+ else {
+ n->prev = NULL;
+ n->next = NULL;
+ l->last = n;
+ l->first = n;
+ }
+}
+
+void list_addfirst (list *l, void *element)
+{
+ listnode *n = (listnode*) ( ((char*) element) + l->nodeoffset );
+
+ if (l->first) {
+ n->prev = NULL;
+ n->next = l->first;
+ l->first->prev = n;
+ l->first = n;
+ }
+ else {
+ n->prev = NULL;
+ n->next = NULL;
+ l->last = n;
+ l->first = n;
+ }
+}
+
+
+void list_remove (list *l, void *element)
+{
+ listnode *n = (listnode*) ( ((char*) element) + l->nodeoffset );
+
+ if (n->next) n->next->prev = n->prev;
+ else l->last = n->prev;
+ if (n->prev) n->prev->next = n->next;
+ else l->first = n->next;
+}
+
+
+void *list_first (list *l)
+{
+ if (!l->first) return NULL;
+ return ((char*) l->first) - l->nodeoffset;
+}
+
+
+void *list_last (list *l)
+{
+ if (!l->last) return NULL;
+ return ((char*) l->last) - l->nodeoffset;
+}
+
+
+void *list_next (list *l, void *element)
+{
+ listnode *n;
+ n = (listnode*) ( ((char*) element) + l->nodeoffset );
+ if (!n->next) return NULL;
+ return ((char*) n->next) - l->nodeoffset;
+}
+
+
+void *list_prev (list *l, void *element)
+{
+ listnode *n;
+ n = (listnode*) ( ((char*) element) + l->nodeoffset );
+ if (!n->prev) return NULL;
+ return ((char*) n->prev) - l->nodeoffset;
+}
+
--- /dev/null
+/************************** toolbox/list.h *************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Verwaltung von doppelt verketteten Listen.
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1996/10/03
+
+*******************************************************************************/
+
+typedef struct listnode { /* Struktur f"ur ein Listenelement */
+ struct listnode *next,*prev;
+ } listnode;
+
+typedef struct list { /* Struktur f"ur den Listenkopf */
+ listnode *first,*last;
+ int nodeoffset;
+ } list;
+
+
+void list_init (list *l, int nodeoffset);
+
+void list_addlast (list *l, void *element);
+void list_addfirst (list *l, void *element);
+
+void list_remove (list *l, void *element);
+
+void *list_first (list *l);
+void *list_last (list *l);
+
+void *list_next (list *l, void *element);
+void *list_prev (list *l, void *element);
+
+
+/*
+---------------------- Schnittstellenbeschreibung -----------------------------
+
+Die Listenverwaltung mit diesem Modul geht so vor sich:
+
+ - jede Struktur, die in die Liste eingeh"angt werden soll, mu"s
+ eine Komponente vom Typ 'listnode' haben.
+
+ - es mu"s ein Struktur vom Typ 'list' bereitgestellt werden.
+
+ - die Funktion list_init (l, nodeoffset) initialisiert diese Struktur,
+ dabei gibt der nodeoffset den Offset der 'listnode'-Komponente in
+ den Knotenstrukturen an.
+
+ - Einf"ugen, Aush"angen und Suchen von Elementen der Liste geht mit
+ den "ubrigen Funktionen.
+
+Zum besseren Verst"andnis ein kleines Beispiel:
+
+
+ void bsp() {
+ struct node {
+ listnode linkage;
+ int value;
+ } a,b,c, *el;
+
+ list l;
+
+ a.value = 7;
+ b.value = 9;
+ c.value = 11;
+
+ list_init (&l, OFFSET(struct node,linkage) );
+ list_addlast (&l, a);
+ list_addlast (&l, b);
+ list_addlast (&l, c);
+
+ e = list_first (&l);
+ while (e) {
+ printf ("Element: %d\n", e->value);
+ e = list_next (&l,e);
+ }
+ }
+
+
+ Dieses Programm w"urde also folgendes ausgeben:
+ 7
+ 9
+ 11
+
+
+
+Der Grund, warum beim Initialisieren der Liste der Offset mitangegeben
+werden mu"s, ist der da"s ein und das selbe Datenelement gleichzeitig
+in verschiedenen Listen eingeh"angt werden kann (f"ur jede Liste mu"s
+also eine Komponente vom Typ 'listnode' im Element enthalten sein).
+
+*/
+
--- /dev/null
+/************************* toolbox/loging.c ************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Not documented, see loging.h.
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1996/10/03
+
+*******************************************************************************/
+
+#include <stdio.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#include "loging.h"
+
+/***************************************************************************
+ LOGFILE - BEHANDLUNG
+***************************************************************************/
+
+char logtext[MAXLOGTEXT]; /* Musz mit dem gewuenschten Text vor */
+ /* Aufruf von dolog() beschrieben werden */
+
+
+FILE *logfile = NULL;
+
+
+
+
+void log_init(char *fname)
+{
+ if (fname) {
+ if (fname[0]) {
+ logfile = fopen(fname, "w");
+ }
+ }
+}
+
+
+
+/*********************** Funktion: dolog ************************************
+
+Gibt den in logtext stehenden Text auf die Protokollierungsdatei
+aus (wenn sie offen ist) und auszerdem auf stdout.
+
+**************************************************************************/
+
+void dolog()
+{
+ if (logfile) {
+ fprintf (logfile, "%s\n",logtext);
+ fflush (logfile);
+ }
+ else {
+ printf ("LOG: %s\n",logtext);
+ fflush (stdout);
+ }
+}
+
+/********************* Funktion: log_text ********************************/
+
+void log_text (char *text)
+{
+ sprintf (logtext, "%s",text);
+ dolog();
+}
+
+
+/********************* Funktion: log_cputime ****************************/
+
+void log_cputime ()
+{
+ long int t;
+ int sec,usec;
+
+ t = getcputime();
+ sec = t/1000000;
+ usec = t%1000000;
+
+ sprintf (logtext, "Total CPU usage: %d seconds and %d milliseconds",
+ sec,usec/1000);
+ dolog();
+}
+
+
+
+/************************** Funktion: error *******************************
+
+Wie dolog(), aber das Programm wird auszerdem sofort terminiert.
+
+**************************************************************************/
+
+void error()
+{
+ if (logfile) {
+ fprintf (logfile, "ERROR: %s\n", logtext);
+ }
+ printf ("ERROR: %s\n",logtext);
+ exit(10);
+}
+
+
+/************************ Funktion: panic (txt) ****************************
+
+ Wie error(), jedoch wird der auszugebende Text als Argument uebergeben
+
+***************************************************************************/
+
+void panic(char *txt)
+{
+ sprintf (logtext, "%s", txt);
+ error();
+}
+
+
+/********************** Funktion: getcputime ********************************
+
+ liefert die verbrauchte CPU-Zeit im Mikrosekunden
+
+****************************************************************************/
+
+long int getcputime()
+{
+ struct rusage ru;
+ int sec,usec;
+
+ getrusage (RUSAGE_SELF, &ru);
+ sec = ru.ru_utime.tv_sec + ru.ru_stime.tv_sec;
+ usec = ru.ru_utime.tv_usec + ru.ru_stime.tv_usec;
+ return sec*1000000 + usec;
+}
+
--- /dev/null
+/************************* toolbox/loging.h ************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Stellt Funktionen f"urs Logging zur Verf"ugung
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1996/10/03
+
+*******************************************************************************/
+
+#define PANICIF(when,txt) if(when)panic(txt)
+
+#define MAXLOGTEXT 500
+extern char logtext[MAXLOGTEXT];
+
+void log_init(char *fname);
+void log_text(char *txt);
+
+void log_cputime();
+
+void dolog();
+void error();
+void panic(char *txt);
+
+long int getcputime();
+
+
+/*
+
+-------------------------- Schnittstellenbeschreibung -------------------------
+
+log_init .... Initialisiert das Logfile-System
+ fname ....... Dateiname f"ur die Protokollierungsdatei
+ keepfile .... 1, wenn die alte Datei nicht gel"oscht werden soll
+ echostdout .. 1, wenn auch auf stdout ausgegeben werden soll
+
+log_text .... Gibt einen Text auf das Logfile aus
+log_cputime . Gibt eine Information "uber die verbrauchte CPU-Zeit aus
+dolog ....... Gibt den Inhalt von logtext aus
+error ....... Gibt den Inhalt von logtext aus, und stoppt das System
+panic ....... Gibt eine Text auf das Logfile aus
+
+logtext ..... dieses globale Array mu"s vor Benutzung der Funktionen 'log'
+ oder 'error' mit dem auszugebenen Text bef"ullt werden.
+
+getcputimew . gibt die vom Programm verbrauchte CPU-Zeit in
+ Mikrosekunden zur"uck
+
+*/
--- /dev/null
+/************************* toolbox/memory.c ************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Not documented, see memory.h.
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1996/10/03
+
+*******************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+#include "../callargs.h"
+#include "loging.h"
+#include "memory.h"
+
+
+ /********* allgemeine Typen, Variablen und Hilfsfunktionen *********/
+
+#define DUMPBLOCKSIZE (2<<18)
+#define ALIGNSIZE 8
+
+typedef struct dumplist {
+ struct dumplist *prev;
+ char *dumpmem;
+} dumplist;
+
+
+
+long int memoryusage = 0;
+
+long int dumpsize = 0;
+long int dumpspace = 0;
+dumplist *topdumpblock = NULL;
+
+long int maxmemusage = 0;
+long int maxdumpsize = 0;
+
+/* #define TRACECALLARGS */
+
+#ifdef TRACECALLARGS
+static char nomallocmem[16777216];
+static char *nomalloctop = nomallocmem + 16777216;
+static char *nomallocptr = nomallocmem;
+
+static void *lit_checked_alloc (int length)
+{
+ void *m;
+
+ nomallocptr = (void*) ALIGN ((long) nomallocptr, ALIGNSIZE);
+
+ m = nomallocptr;
+ nomallocptr += length;
+ if (nomallocptr > nomalloctop) panic ("Out of memory");
+ return m;
+}
+
+#else
+
+static void *lit_checked_alloc (int length)
+{
+ void *m = malloc(length);
+ if (!m) panic ("Out of memory");
+ return m;
+}
+
+#endif
+
+
+static void *checked_alloc (int length)
+{
+ void *m = malloc(length);
+ if (!m) panic ("Out of memory");
+ return m;
+}
+
+static int mmapcodesize = 0;
+static void *mmapcodeptr = NULL;
+
+void *mem_mmap(int length)
+{
+ void *retptr;
+
+ length = (ALIGN(length,ALIGNSIZE));
+ if (length > mmapcodesize) {
+ mmapcodesize = 0x10000;
+ if (length > mmapcodesize)
+ mmapcodesize = length;
+ mmapcodesize = (ALIGN(mmapcodesize, getpagesize()));
+ mmapcodeptr = mmap (NULL, (size_t) mmapcodesize,
+ PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, (off_t) 0);
+ if (mmapcodeptr == (void*) -1)
+ panic ("Out of memory");
+ }
+ retptr = mmapcodeptr;
+ mmapcodeptr = (void*) ((char*) mmapcodeptr + length);
+ mmapcodesize -= length;
+ return retptr;
+}
+
+
+#ifdef DEBUG
+
+ /************ Sichere Version des Speichermanages **************/
+
+
+typedef struct memblock {
+ struct memblock *prev,*next;
+ int length;
+} memblock;
+
+#define BLOCKOFFSET (ALIGN(sizeof(memblock),ALIGNSIZE))
+
+struct memblock *firstmemblock;
+
+
+
+void *mem_alloc(int length)
+{
+ memblock *mb;
+
+ if (length==0) return NULL;
+ mb = checked_alloc (length + BLOCKOFFSET);
+
+ mb -> prev = NULL;
+ mb -> next = firstmemblock;
+ mb -> length = length;
+
+ if (firstmemblock) firstmemblock -> prev = mb;
+ firstmemblock = mb;
+
+ memoryusage += length;
+ if (memoryusage > maxmemusage) maxmemusage = memoryusage;
+
+ return ((char*) mb) + BLOCKOFFSET;
+}
+
+
+void *lit_mem_alloc(int length)
+{
+ memblock *mb;
+
+ if (length==0) return NULL;
+ mb = lit_checked_alloc (length + BLOCKOFFSET);
+
+ mb -> prev = NULL;
+ mb -> next = firstmemblock;
+ mb -> length = length;
+
+ if (firstmemblock) firstmemblock -> prev = mb;
+ firstmemblock = mb;
+
+ memoryusage += length;
+ if (memoryusage > maxmemusage) maxmemusage = memoryusage;
+
+ return ((char*) mb) + BLOCKOFFSET;
+}
+
+
+void mem_free(void *m, int length)
+{
+ memblock *mb;
+ if (!m) {
+ if (length==0) return;
+ panic ("returned memoryblock with address NULL, length != 0");
+ }
+
+ mb = (memblock*) (((char*) m) - BLOCKOFFSET);
+
+ if (mb->length != length) {
+ sprintf (logtext,
+ "Memory block of size %d has been return as size %d",
+ mb->length, length);
+ error();
+ }
+
+ if (mb->prev) mb->prev->next = mb->next;
+ else firstmemblock = mb->next;
+ if (mb->next) mb->next->prev = mb->prev;
+
+ free (mb);
+
+ memoryusage -= length;
+}
+
+
+void lit_mem_free(void *m, int length)
+{
+ memblock *mb;
+ if (!m) {
+ if (length==0) return;
+ panic ("returned memoryblock with address NULL, length != 0");
+ }
+
+ mb = (memblock*) (((char*) m) - BLOCKOFFSET);
+
+ if (mb->length != length) {
+ sprintf (logtext,
+ "Memory block of size %d has been return as size %d",
+ mb->length, length);
+ error();
+ }
+
+ if (mb->prev) mb->prev->next = mb->next;
+ else firstmemblock = mb->next;
+ if (mb->next) mb->next->prev = mb->prev;
+
+#ifdef TRACECALLARGS
+#else
+ free (mb);
+#endif
+
+ memoryusage -= length;
+}
+
+
+void *mem_realloc (void *m1, int len1, int len2)
+{
+ void *m2;
+
+ m2 = mem_alloc (len2);
+ memcpy (m2, m1, len1);
+ mem_free (m1, len1);
+
+ return m2;
+}
+
+
+
+
+static void mem_characterlog (unsigned char *m, int len)
+{
+# define LINESIZE 16
+ int z,i;
+
+ for (z=0; z<len; z+=LINESIZE) {
+ sprintf (logtext, " ");
+
+ for (i=z; i<(z+LINESIZE) && i<len; i++) {
+ sprintf (logtext+strlen(logtext), "%2x ", m[i]);
+ }
+ for (; i<(z+LINESIZE); i++) {
+ sprintf (logtext+strlen(logtext), " ");
+ }
+
+ sprintf (logtext+strlen(logtext)," ");
+ for (i=z; i<(z+LINESIZE) && i<len; i++) {
+ sprintf (logtext+strlen(logtext),
+ "%c", (m[i]>=' ' && m[i]<=127) ? m[i] : '.');
+ }
+
+ dolog();
+ }
+}
+
+#else
+ /******* Schnelle Version des Speichermanagers ******/
+
+
+void *mem_alloc(int length)
+{
+ if (length==0) return NULL;
+
+ memoryusage += length;
+ if (memoryusage > maxmemusage) maxmemusage = memoryusage;
+
+ return checked_alloc (length);
+}
+
+
+void *lit_mem_alloc(int length)
+{
+ if (length==0) return NULL;
+
+ memoryusage += length;
+ if (memoryusage > maxmemusage) maxmemusage = memoryusage;
+
+ return lit_checked_alloc (length);
+}
+
+
+void mem_free(void *m, int length)
+{
+ if (!m) {
+ if (length==0) return;
+ panic ("returned memoryblock with address NULL, length != 0");
+ }
+
+ memoryusage -= length;
+
+ free (m);
+}
+
+
+void lit_mem_free(void *m, int length)
+{
+ if (!m) {
+ if (length==0) return;
+ panic ("returned memoryblock with address NULL, length != 0");
+ }
+
+ memoryusage -= length;
+
+#ifdef TRACECALLARGS
+#else
+ free (m);
+#endif
+}
+
+
+void *mem_realloc (void *m1, int len1, int len2)
+{
+ void *m2;
+
+ if (!m1) {
+ if (len1!=0)
+ panic ("reallocating memoryblock with address NULL, length != 0");
+ }
+
+ memoryusage = (memoryusage - len1) + len2;
+
+ m2 = realloc (m1, len2);
+ if (!m2) panic ("Out of memory");
+ return m2;
+}
+
+
+#endif
+
+ /******* allgemeine Teile des Speichermanagers ******/
+
+
+
+long int mem_usage()
+{
+ return memoryusage;
+}
+
+
+
+
+
+void *dump_alloc(int length)
+{
+ void *m;
+
+ if (length==0) return NULL;
+
+ length = ALIGN (length, ALIGNSIZE);
+
+ assert (length <= DUMPBLOCKSIZE);
+ assert (length > 0);
+
+ if (dumpsize + length > dumpspace) {
+ dumplist *newdumpblock = checked_alloc (sizeof(dumplist));
+
+ newdumpblock -> prev = topdumpblock;
+ topdumpblock = newdumpblock;
+
+ newdumpblock -> dumpmem = checked_alloc (DUMPBLOCKSIZE);
+
+ dumpsize = dumpspace;
+ dumpspace += DUMPBLOCKSIZE;
+ }
+
+ m = topdumpblock -> dumpmem + DUMPBLOCKSIZE - (dumpspace - dumpsize);
+ dumpsize += length;
+
+ if (dumpsize > maxdumpsize) {
+ maxdumpsize = dumpsize;
+ }
+
+ return m;
+}
+
+
+void *dump_realloc(void *ptr, int len1, int len2)
+{
+ void *p2 = dump_alloc (len2);
+ memcpy (p2, ptr, len1);
+ return p2;
+}
+
+
+long int dump_size()
+{
+ return dumpsize;
+}
+
+
+void dump_release(long int size)
+{
+ assert (size >= 0 && size <= dumpsize);
+
+ dumpsize = size;
+
+ while (dumpspace > dumpsize + DUMPBLOCKSIZE) {
+ dumplist *oldtop = topdumpblock;
+
+ topdumpblock = oldtop -> prev;
+ dumpspace -= DUMPBLOCKSIZE;
+
+#ifdef TRACECALLARGS
+#else
+ free (oldtop -> dumpmem);
+ free (oldtop);
+#endif
+ }
+}
+
+
+
+
+void mem_usagelog (int givewarnings)
+{
+ if ((memoryusage!=0) && givewarnings) {
+ sprintf (logtext, "Allocated memory not returned: %d",
+ (int)memoryusage);
+ dolog();
+
+#ifdef DEBUG
+ {
+ memblock *mb = firstmemblock;
+ while (mb) {
+ sprintf (logtext, " Memory block size: %d",
+ (int)(mb->length) );
+ dolog();
+ mem_characterlog ( ((unsigned char*)mb) + BLOCKOFFSET, mb->length);
+ mb = mb->next;
+ }
+ }
+#endif
+
+ }
+
+ if ((dumpsize!=0) && givewarnings) {
+ sprintf (logtext, "Dump memory not returned: %d",(int)dumpsize);
+ dolog();
+ }
+
+
+ sprintf (logtext, "Random/Dump - memory usage: %dK/%dK",
+ (int)((maxmemusage+1023)/1024),
+ (int)((maxdumpsize+1023)/1024) );
+ dolog();
+
+}
+
--- /dev/null
+/************************* toolbox/memory.h ************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Headerfiles und Makros f"ur die Speicherverwaltung.
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1996/10/03
+
+*******************************************************************************/
+
+#define CODEMMAP
+
+#define ALIGN(pos,size) ( ( ((pos)+(size)-1) / (size))*(size) )
+#define PADDING(pos,size) ( ALIGN((pos),(size)) - (pos) )
+#define OFFSET(s,el) ( (int) &( ((s*)0) -> el ) )
+
+
+#define NEW(type) ((type*) mem_alloc ( sizeof(type) ))
+#define FREE(ptr,type) mem_free (ptr, sizeof(type) )
+
+#define LNEW(type) ((type*) lit_mem_alloc ( sizeof(type) ))
+#define LFREE(ptr,type) lit_mem_free (ptr, sizeof(type) )
+
+#define MNEW(type,num) ((type*) mem_alloc ( sizeof(type) * (num) ))
+#define MFREE(ptr,type,num) mem_free (ptr, sizeof(type) * (num) )
+#define MREALLOC(ptr,type,num1,num2) mem_realloc (ptr, sizeof(type) * (num1), \
+ sizeof(type) * (num2) )
+
+#define DNEW(type) ((type*) dump_alloc ( sizeof(type) ))
+#define DMNEW(type,num) ((type*) dump_alloc ( sizeof(type) * (num) ))
+#define DMREALLOC(ptr,type,num1,num2) dump_realloc (ptr, sizeof(type)*(num1),\
+ sizeof(type) * (num2) )
+
+#define MCOPY(dest,src,type,num) memcpy (dest,src, sizeof(type)* (num) )
+
+#ifdef CODEMMAP
+#define CNEW(type,num) ((type*) mem_mmap ( sizeof(type) * (num) ))
+#define CFREE(ptr,num)
+#else
+#define CNEW(type,num) ((type*) mem_alloc ( sizeof(type) * (num) ))
+#define CFREE(ptr,num) mem_free (ptr, num)
+#endif
+
+void *mem_alloc(int length);
+void *mem_mmap(int length);
+void *lit_mem_alloc(int length);
+void mem_free(void *m, int length);
+void lit_mem_free(void *m, int length);
+void *mem_realloc(void *m, int len1, int len2);
+long int mem_usage();
+
+void *dump_alloc(int length);
+void *dump_realloc(void *m, int len1, int len2);
+long int dump_size();
+void dump_release(long int size);
+
+void mem_usagelog(int givewarnings);
+
+
+
+/*
+---------------------------- Schnittstellenbeschreibung -----------------------
+
+Der Speicherverwalter hat zwei m"ogliche Arten Speicher zu reservieren
+und freizugeben:
+
+ 1. explizites Anfordern / Freigeben
+
+ mem_alloc ..... Anfordern eines Speicherblocks
+ mem_free ...... Freigeben eines Speicherblocks
+ mem_realloc ... Vergr"o"sern eines Speicherblocks (wobei
+ der Inhalt eventuell an eine neue Position kommt)
+ mem_usage ..... Menge des bereits belegten Speichers
+
+
+ 2. explizites Anfordern und automatisches Freigeben
+
+ dump_alloc .... Anfordern eines Speicherblocks vom
+ (wie ich es nenne) DUMP-Speicher
+ dump_realloc .. Vergr"o"sern eines Speicherblocks
+ dump_size ..... Merkt sich eine Freigabemarke am Dump
+ dump_release .. Gibt allen Speicher, der nach der Marke angelegt
+ worden ist, wieder frei.
+
+
+Es gibt f"ur diese Funktionen ein paar praktische Makros:
+
+ NEW (type) ....... legt Speicher f"ur ein Element des Typs `type` an.
+ FREE (ptr,type) .. gibt Speicher zur"uck
+
+ MNEW (type,num) .. legt Speicher f"ur ein ganzes Array an
+ MFREE (ptr,type,num) .. gibt den Speicher wieder her
+
+ MREALLOC (ptr,type,num1,num2) .. vergr"o"sert den Speicher f"ur das Array
+ auf die Gr"o"se num2
+
+Die meisten der Makros gibt es auch f"ur den DUMP-Speicher, na"mlich mit
+gleichem Namen, nur mit vorangestelltem 'D', also:
+
+ DNEW, DMNEW, DMREALLOC (DFREE gibt es nat"urlich keines)
+
+
+-------------------------------------------------------------------------------
+
+Die restlichen Makros:
+
+ ALIGN (pos, size) ... Rundet den Wert von 'pos' auf die n"achste durch
+ 'size' teilbare Zahl auf.
+
+
+ OFFSET (s,el) ....... Berechnet den Offset (in Bytes) des Elementes 'el'
+ in der Struktur 's'.
+
+ MCOPY (dest,src,type,num) ... Kopiert 'num' Elemente vom Typ 'type'.
+
+
+*/
--- /dev/null
+/************************** toolbox/tree.c *************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Not documented, see tree.h.
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1996/10/03
+
+*******************************************************************************/
+
+#include <stdio.h>
+#include <assert.h>
+
+#include "memory.h"
+#include "tree.h"
+
+
+tree *tree_new (treeelementcomperator comperator)
+{
+ tree *t = NEW (tree);
+
+ t -> usedump = 0;
+ t -> comperator = comperator;
+ t -> top = NULL;
+ t -> active = NULL;
+
+ return t;
+}
+
+tree *tree_dnew (treeelementcomperator comperator)
+{
+ tree *t = DNEW (tree);
+
+ t -> usedump = 1;
+ t -> comperator = comperator;
+ t -> top = NULL;
+ t -> active = NULL;
+
+ return t;
+}
+
+
+static void tree_nodefree (treenode *tn)
+{
+ if (!tn) return;
+ tree_nodefree (tn -> left);
+ tree_nodefree (tn -> right);
+ FREE (tn, treenode);
+}
+
+void tree_free (tree *t)
+{
+ assert (! t -> usedump);
+
+ tree_nodefree ( t -> top );
+ FREE (t, tree);
+}
+
+
+static treenode *tree_nodeadd
+ (tree *t, treenode *par, treenode *n, void *element, void *key)
+{
+ if (!n) {
+ if ( t-> usedump ) n = DNEW (treenode);
+ else n = NEW (treenode);
+
+ n -> left = NULL;
+ n -> right = NULL;
+ n -> parent = par;
+ n -> element = element;
+ }
+ else {
+ if ( t->comperator (key, n -> element) < 0 ) {
+ n -> left = tree_nodeadd (t, n, n -> left, element, key);
+ }
+ else {
+ n -> right = tree_nodeadd (t, n, n -> right, element, key);
+ }
+ }
+
+ return n;
+}
+
+void tree_add (tree *t, void *element, void *key)
+{
+ t -> top = tree_nodeadd (t, NULL, t -> top, element, key);
+ t -> active = t -> top;
+}
+
+
+static treenode *tree_nodefind (tree *t, treenode *n, void *key)
+{
+ int way;
+
+ if (!n) return NULL;
+
+ way = t -> comperator (key, n->element);
+ if (way==0) return n;
+ if (way<0) return tree_nodefind (t, n -> left, key);
+ else return tree_nodefind (t, n -> right, key);
+}
+
+
+void *tree_find (tree *t, void *key)
+{
+ treenode *tn = tree_nodefind (t, t -> top, key);
+ if (!tn) return NULL;
+
+ t -> active = tn;
+ return tn -> element;
+}
+
+
+
+void *tree_this (tree *t)
+{
+ if (! t->active) return NULL;
+ return t->active->element;
+}
+
+
+static treenode *leftmostnode(treenode *t)
+{
+ while (t->left) t=t->left;
+ return t;
+}
+
+void *tree_first (tree *t)
+{
+ treenode *a = t->top;
+ if (!a) return NULL;
+
+ a = leftmostnode (a);
+ t->active = a;
+ return a->element;
+}
+
+void *tree_next (tree *t)
+{
+ treenode *a = t->active;
+ treenode *comefrom = NULL;
+
+ while (a) {
+ if (!a) return NULL;
+
+ if (a->left && (a->left == comefrom)) {
+ t -> active = a;
+ return a->element;
+ }
+
+ if (a->right && (a->right != comefrom) ) {
+ a = leftmostnode(a->right);
+ t -> active = a;
+ return a->element;
+ }
+
+ comefrom=a;
+ a=a->parent;
+ }
+ t->active = NULL;
+ return NULL;
+}
--- /dev/null
+/************************* toolbox/tree.h **************************************
+
+ Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+ See file COPYRIGHT for information on usage and disclaimer of warranties
+
+ Verwaltung bin"arer B"aume
+
+ Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
+
+ Last Change: 1996/10/03
+
+*******************************************************************************/
+
+typedef int (*treeelementcomperator) (void *key, void * element);
+
+
+typedef struct treenode {
+ struct treenode *left,*right;
+ struct treenode *parent;
+
+ void *element;
+ } treenode;
+
+typedef struct {
+ int usedump;
+ treeelementcomperator comperator;
+
+ treenode *top;
+ treenode *active;
+ } tree;
+
+
+
+tree *tree_new (treeelementcomperator comperator);
+tree *tree_dnew (treeelementcomperator comperator);
+void tree_free (tree *t);
+
+void tree_add (tree *t, void *element, void *key);
+void *tree_find (tree *t, void *key);
+
+void *tree_this (tree *t);
+void *tree_first (tree *t);
+void *tree_next (tree *t);
+