Strange, elusive bug in boolean return values with latest fetch from cvs

Andrew Haley aph@redhat.com
Wed Jun 9 19:14:00 GMT 2004


Okay, so I can duplicate your test case!
Here's a partial patch. Its result is:
.globl BugJune3.seeIfItsTrue() .globl BugJune3.seeIfItsTrue()
 .type BugJune3.seeIfItsTrue(), @function .type BugJune3.seeIfItsTrue(), @function
BugJune3.seeIfItsTrue(): BugJune3.seeIfItsTrue():
.LFB3: .LFB3:
 pushq %rbp pushq %rbp
.LCFI5: .LCFI5:
 movq 8(%rdi), %rdi movq 8(%rdi), %rdi
 > xorl %eax, %eax
 movq %rsp, %rbp movq %rsp, %rbp
.LCFI6: .LCFI6:
 testq %rdi, %rdi testq %rdi, %rdi
 je .L3 | je .L5
.L4: | .L3:
 movq (%rdi), %rax movq (%rdi), %rax
 call *56(%rax) call *56(%rax)
.L3: | movzbl %al, %eax
 > .L5:
 leave leave
 xorl %eax, %eax <
 ret ret
.LFE3: .LFE3:
 .size BugJune3.seeIfItsTrue(), .-_ZN8BugJune31 .size BugJune3.seeIfItsTrue(), .-_ZN8BugJune31
The problem seems to be due to the fact that the type system of the
Java Virtual Machine is subtly different from the type system of the
Java Programming Language. In particular, booleans and ints are
incompatible in the source language but are both treated as integer
types in the VM. So, treating these as distinct types when compiling
bytecode is incorrect.
What we do at the moment is basically wrong, in that if we have two
sources and one destination, and one source is int and the other
boolean, then they are treated as distinct variables.
Look at this fragment:
 7: iconst_0
 8: goto 18
 11: aload_0
 12: getfield #4=<Field BugJune3.littleThing BugJune3$LittleThing>
 15: invokevirtual #5=<Method BugJune3$LittleThing.isTrue ()boolean>
 18: ireturn
insn 7 pushes an int, and insn 15 pushes a boolean. insn 18 returns
something, and the compiler doesn't believe that these types are
compatible. So, when the compiler wants a temporary to hold the
result of insn 15, it generates a new one instead of using the same
one that was generated for insn 7. And, of course, that value is
lost.
So, when we create a temporary for an item on the evaluation stack, we
need to create an int, even if the insn that created it returned a
boolean.
This patch forces all pushes of booleans onto the operand stack to be
converted to ints. I don't think it is totally correct, but it's
better.
I have't tested it at all: see how you get on.
Andrew.
2004年06月09日 Andrew Haley <aph@redhat.com>
	* expr.c (flush_quick_stack): Perform type conversion when
	building our MODIFY_EXPR.
	(push_type_0): Treat booleans pushed onto the stack as ints.
	(push_value): Likewise.
Index: expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/expr.c,v
retrieving revision 1.192
diff -p -2 -c -w -r1.192 expr.c
*** expr.c	8 Jun 2004 13:27:38 -0000	1.192
--- expr.c	9 Jun 2004 19:04:32 -0000
*************** flush_quick_stack (void)
*** 240,244 ****
--- 240,248 ----
 decl = find_stack_slot (stack_index, type);
 if (decl != node)
+ 	{
+ 	 if (TREE_TYPE (node) != TREE_TYPE (decl))
+ 	 decl = convert (TREE_TYPE (node), decl);
 	 java_add_stmt (build (MODIFY_EXPR, TREE_TYPE (node), decl, node));
+ 	}
 stack_index += 1 + TYPE_IS_WIDE (type);
 }
*************** push_type_0 (tree type)
*** 253,256 ****
--- 257,264 ----
 int n_words;
 type = promote_type (type);
+ /* Although Java local variables may be of boolean type, the Java VM
+ treats them as though they're integers. */
+ if (type == promoted_boolean_type_node)
+ type = int_type_node;
 n_words = 1 + TYPE_IS_WIDE (type);
 if (stack_pointer + n_words > DECL_MAX_STACK (current_function_decl))
*************** push_value (tree value)
*** 277,280 ****
--- 285,292 ----
 {
 type = promote_type (type);
+ /* Although Java local variables may be of boolean type, the Java VM
+ 	 treats them as though they're integers. */
+ if (type == promoted_boolean_type_node)
+ 	type = int_type_node;
 value = convert (type, value);
 }


More information about the Java mailing list

AltStyle によって変換されたページ (->オリジナル) /