Skip to content

Commit

Permalink
Defined __PACKED pragma to align struct representing Java classes. C6…
Browse files Browse the repository at this point in the history
…4 platform fixed.
  • Loading branch information
mzattera committed Nov 9, 2020
1 parent 108b4f2 commit ed684de
Show file tree
Hide file tree
Showing 19 changed files with 1,232 additions and 1,115 deletions.
2 changes: 1 addition & 1 deletion dev/test/Sprite.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ private Sprite (int idx) {

// Factory method.
public static synchronized Sprite getSprite (int idx) {
if (_sprites[idx] == NULL)
if (_sprites[idx] == null)
_sprites[idx] = new Sprite(idx);
return _sprites[idx];
}
Expand Down
15 changes: 14 additions & 1 deletion dev/test/Sting.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,15 @@ public class Sting {
*/
public static void main(String[] args) {
String a1 = "AAA";

String a2 = "AAA";
String b = "BBB";
String c1 = C0;
String c2 = C0;


// System.out.println ("a1 offset: " + a1._TVM_constantOffset);
// System.out.println ("a2 offset: " + a2._TVM_constantOffset);

System.out.println ("a1 == a1 " + (a1==a1));
System.out.println ("a1 == a2 " + (a1==a2));
System.out.println ("a1 eq a1 " + a1.equals(a1));
Expand All @@ -38,5 +42,14 @@ public static void main(String[] args) {
System.out.println ("c1 == c2 " + (c1==c2));
System.out.println ("c1 eq c1 " + c1.equals(c1));
System.out.println ("c1 eq c2 " + c1.equals(c2));

/*
System.out.println ("a1 next: " + (a1._TVM_next==null?"null":a1._TVM_next));
System.out.println ("a2 next: " + (a2._TVM_next==null?"null":a2._TVM_next));
System.out.println ("b next: " + (b._TVM_next==null?"null":b._TVM_next));
System.out.println ("C0 next: " + (C0._TVM_next==null?"null":C0._TVM_next));
System.out.println ("c1 next: " + (c1._TVM_next==null?"null":c1._TVM_next));
System.out.println ("c2 next: " + (c2._TVM_next==null?"null":c2._TVM_next));
*/
}
}
6 changes: 1 addition & 5 deletions distr/bin/makeJVM.bat
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,11 @@ if ERRORLEVEL 1 goto end
if ERRORLEVEL 1 goto end
%CC_CLI% javavm\memory.c
if ERRORLEVEL 1 goto end
%CC_CLI% javavm\debug.c
if ERRORLEVEL 1 goto end
%CC_CLI% javavm\nativeemul.c
if ERRORLEVEL 1 goto end
%CC_CLI% javavm\tvmemul.c
if ERRORLEVEL 1 goto end

%CC_CLI% platform\c64\load.c
if ERRORLEVEL 1 goto end
%CC_CLI% platform\c64\platform_native.c
if ERRORLEVEL 1 goto end
%CC_CLI% platform\c64\main.c
Expand All @@ -78,7 +74,7 @@ set "CL_PARAMS="
set "CL_CLI=%CL% %CL_PARAMS%"

@echo Linking btfJ.prg
%CL_CLI% -t c64 -o b2fJ.prg exceptions.o interpreter.o language.o load.o main.o memory.o debug.o nativeemul.o platform_native.o threads.o tvmemul.o c64.lib
%CL_CLI% -t c64 -o b2fJ.prg exceptions.o interpreter.o language.o main.o memory.o nativeemul.o platform_native.o threads.o tvmemul.o c64.lib
@if not exist b2fJ.prg (
echo Some compilation error happened.
goto end
Expand Down
Binary file modified distr/lib/classes.jar
Binary file not shown.
Binary file modified distr/lib/jtools.jar
Binary file not shown.
1 change: 1 addition & 0 deletions distr/src/java/classes/java/lang/String.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public final class String implements CharSequence, Comparable<String> {
// Their sizes and location can only be changed
// if classes.h is changed accordingly. Needless
// to say, they are read-only (and useless from Java).
// THESE ARE ONLY STORAGE AND THEIR VALUE IS NOT PROPERLY SET FOR USE IN JAVA
@SuppressWarnings("unused")
private String _TVM_next;
@SuppressWarnings("unused")
Expand Down
231 changes: 115 additions & 116 deletions distr/src/javavm/classes.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,150 +35,149 @@
#define get_monitor_count(OBJ_) ((OBJ_)->monitorCount)
#define is_gc(OBJ_) ((OBJ_)->flags.objects.mark)

/**
* Object class native structure
*/
typedef struct S_Object
/**
* Object class native structure
*/
typedef __PACKED(struct S_Object
{
/**
* Object/block flags.
* Free block:
* -- bits 0-14: Size of free block in words.
* -- bit 15 : Zero (not allocated).
* Objects:
* -- bits 0-7 : Class index.
* -- bits 8-12: Unused.
* -- bit 13 : Garbage collection mark.
* -- bit 14 : Zero (not an array).
* -- bit 15 : One (allocated).
* Arrays:
* -- bits 0-8 : Array length (0-511).
* -- bits 9-12: Element type.
* -- bit 13 : Garbage collection mark.
* -- bit 14 : One (is an array).
* -- bit 15 : One (allocated).
*/
union _flags
{
TWOBYTES all;
struct _freeBlock
{
__TWOBYTE_BITFIELD size:15;
__TWOBYTE_BITFIELD isAllocated:1;
} freeBlock;
struct _objects
{
__TWOBYTE_BITFIELD class:9;
// __TWOBYTE_BITFIELD padding : 5;
// Maxi: The above looks incorrect counting the bits, and it causes the JVM to crash.
__TWOBYTE_BITFIELD padding : 4;
__TWOBYTE_BITFIELD mark:1;
__TWOBYTE_BITFIELD isArray:1;
__TWOBYTE_BITFIELD isAllocated:1;
} objects;
struct _arrays
{
__TWOBYTE_BITFIELD length:9;
__TWOBYTE_BITFIELD type:4;
__TWOBYTE_BITFIELD mark:1;
__TWOBYTE_BITFIELD isArray:1;
__TWOBYTE_BITFIELD isAllocated:1;
} arrays;
} flags;

/**
* Synchronization state.
*/
byte monitorCount;
byte threadId;

} Object;
/**
* Object/block flags.
* Free block:
* -- bits 0-14: Size of free block in words.
* -- bit 15 : Zero (not allocated).
* Objects:
* -- bits 0-7 : Class index.
* -- bits 8-12: Unused.
* -- bit 13 : Garbage collection mark.
* -- bit 14 : Zero (not an array).
* -- bit 15 : One (allocated).
* Arrays:
* -- bits 0-8 : Array length (0-511).
* -- bits 9-12: Element type.
* -- bit 13 : Garbage collection mark.
* -- bit 14 : One (is an array).
* -- bit 15 : One (allocated).
*/
union _flags
{
TWOBYTES all;
struct _freeBlock
{
__TWOBYTE_BITFIELD size : 15;
__TWOBYTE_BITFIELD isAllocated : 1;
} freeBlock;
struct _objects
{
__TWOBYTE_BITFIELD class :9;
__TWOBYTE_BITFIELD padding : 4;
__TWOBYTE_BITFIELD mark : 1;
__TWOBYTE_BITFIELD isArray : 1;
__TWOBYTE_BITFIELD isAllocated : 1;
} objects;
struct _arrays
{
__TWOBYTE_BITFIELD length : 9;
__TWOBYTE_BITFIELD type : 4;
__TWOBYTE_BITFIELD mark : 1;
__TWOBYTE_BITFIELD isArray : 1;
__TWOBYTE_BITFIELD isAllocated : 1;
} arrays;
} flags;

/**
* Synchronization state.
*/
byte monitorCount;
byte threadId;

}) Object;

/**
* Thread class native structure
*/
typedef struct S_Thread
typedef __PACKED(struct S_Thread
{
Object _super; // Superclass object storage

REFERENCE nextThread; // Intrinsic circular list of threads
JINT waitingOn; // Object who's monitor we want
JINT sleepUntil; // Time to wake up
JINT stackFrameArray; // Array of stack frames
JINT stackArray; // The stack itself
JBYTE stackFrameArraySize; // Number of stack frames in use.
JBYTE monitorCount; // Saved monitor depth for context switches
JBYTE threadId; // Unique thread ID
JBYTE state; // RUNNING, DEAD, etc.
JBYTE priority; // The priority
JBYTE interruptState; // INTERRUPT_CLEARED, INTERRUPT_REQUESTED, ...
JBYTE daemon; // true == daemon thread
} Thread;
Object _super; // Superclass object storage

REFERENCE nextThread; // Intrinsic circular list of threads
JINT waitingOn; // Object who's monitor we want
JINT sleepUntil; // Time to wake up
JINT stackFrameArray; // Array of stack frames
JINT stackArray; // The stack itself
JBYTE stackFrameArraySize; // Number of stack frames in use.
JBYTE monitorCount; // Saved monitor depth for context switches
JBYTE threadId; // Unique thread ID
JBYTE state; // RUNNING, DEAD, etc.
JBYTE priority; // The priority
JBYTE interruptState; // INTERRUPT_CLEARED, INTERRUPT_REQUESTED, ...
JBYTE daemon; // true == daemon thread
}) Thread;

/**
* Runtime class native structure. Doesn't actually contain
* any instance data. Maybe it ought to? Like ALL of the leJOS
* specific runtime instance data?
*/
typedef struct S_Runtime
typedef __PACKED(struct S_Runtime
{
Object _super;
} Runtime;
Object _super;
}) Runtime;

/**
* String class native structure
*/
typedef struct S_String
typedef __PACKED(struct S_String
{
Object _super;

REFERENCE characters;

/*
Maxi: Original leJos code creates a new String each time a String constant is used (ldc bytecode).
So, for example, a loop that prints always the same string will generate an OutOfMemoryException.
To avoid this, we link allocated Java Strings in a list and we store a pointer to constants from which they were created.
When we need to create a new String, we check in the list first, if a String for given constant is already allocated and re-use it.
BTW this aligns b2fJ with Java behavior.
*/
REFERENCE next;
JSHORT constantOffset;
} String;

Object _super;

REFERENCE characters;

/*
Maxi: Original leJos code creates a new String each time a String constant is used (ldc bytecode).
So, for example, a loop that prints always the same string will generate an OutOfMemoryException.
To avoid this, we link allocated Java Strings in a list and we store a pointer to constants from which they were created.
When we need to create a new String, we check in the list first, if a String for given constant is already allocated and re-use it.
BTW this aligns b2fJ with Java behavior.
*/
/* !!! NOTE !!! To have these values accessible form Java we should use get_word() and set_word() */
/* !!! NOTE !!! We don't do this for performance, as these values are useless from Java */
REFERENCE next;
JSHORT constantOffset;
}) String;

#if WIMPY_MATH

static __INLINED TWOBYTES get_array_length (Object *obj)
static __INLINED TWOBYTES get_array_length(Object *obj)
{
TWOBYTES aux;
aux = obj->flags.all & ARRAY_LENGTH_MASK;
#if (ARRAY_LENGTH_SHIFT == 0)
return aux;
#else
return (aux >> ARRAY_LENGTH_SHIFT);
#endif
TWOBYTES aux;
aux = obj->flags.all & ARRAY_LENGTH_MASK;
#if (ARRAY_LENGTH_SHIFT == 0)
return aux;
#else
return (aux >> ARRAY_LENGTH_SHIFT);
#endif
}

static __INLINED TWOBYTES get_element_type (Object *obj)
static __INLINED TWOBYTES get_element_type(Object *obj)
{
TWOBYTES aux;
aux = obj->flags.all & ELEM_TYPE_MASK;
#if (ELEM_TYPE_SHIFT == 0)
return aux;
#else
return (aux >> ELEM_TYPE_SHIFT);
#endif
TWOBYTES aux;
aux = obj->flags.all & ELEM_TYPE_MASK;
#if (ELEM_TYPE_SHIFT == 0)
return aux;
#else
return (aux >> ELEM_TYPE_SHIFT);
#endif
}

static __INLINED TWOBYTES get_na_class_index (Object *obj)
static __INLINED TWOBYTES get_na_class_index(Object *obj)
{
TWOBYTES aux;
aux = obj->flags.all & CLASS_MASK;
#if (CLASS_SHIFT == 0)
return aux;
#else
return (aux >> CLASS_SHIFT);
#endif
TWOBYTES aux;
aux = obj->flags.all & CLASS_MASK;
#if (CLASS_SHIFT == 0)
return aux;
#else
return (aux >> CLASS_SHIFT);
#endif
}

#else
Expand Down
6 changes: 2 additions & 4 deletions distr/src/javavm/interpreter.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ static __INLINED Object *create_string(ConstantRecord *constantRecord,
TWOBYTES i;

/* Maxi: We chcek first if there is already a String for this constant */
/* !!! NOTE !!! To have these values accessible form Java we should use get_word() and set_word() */
/* !!! NOTE !!! We don't do this for performance, as these values are useless from Java */
String *sp = stringList;
while (sp != JNULL) {
if (sp->constantOffset == constantRecord->offset) return (Object*)sp;
Expand All @@ -109,15 +111,11 @@ static __INLINED Object *create_string(ConstantRecord *constantRecord,
return JNULL;
}

// printf ("char array at %d\n", (int) arr);

store_word((byte *) &(((String *)ref)->characters), 4, obj2word(arr));

for (i = 0; i < constantRecord->constantSize; i++)
{
jchar_array(arr)[i] = (JCHAR)get_constant_ptr(constantRecord)[i];

// printf ("char %lx %d: %c\n", jchar_array(arr), i, (char) (jchar_array(arr)[i]));
}

sp = (String *)ref;
Expand Down
Loading

0 comments on commit ed684de

Please sign in to comment.