Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix number to boolean conversion #138

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

goto1134
Copy link
Contributor

also fixes #123

@goto1134
Copy link
Contributor Author

goto1134 commented Aug 25, 2017

@headius how can I see what's wrong with the test? Works for me.

@goto1134
Copy link
Contributor Author

There is a problem with x86asm.

@goto1134
Copy link
Contributor Author

goto1134 commented Aug 27, 2017

The two assembler stub compulers (for x32 and x64) declare that native method returns boolean, but it actually returns the original number value. If the native value is long long, the first 32 bits of the number are ignored.

I feel pain looking at the assebler instructions and don't understand the code yet, so I need help!

@goto1134
Copy link
Contributor Author

x64 problem part

if (saveErrno) {
// Save the return on the stack
switch (resultType.getNativeType()) {
case VOID:
// No need to save/reload return value registers
break;
case FLOAT:
a.movss(dword_ptr(rsp, 0), xmm0);
break;
case DOUBLE:
a.movsd(qword_ptr(rsp, 0), xmm0);
break;
default:
a.mov(qword_ptr(rsp, 0), rax);
}
// Save the errno in a thread-local variable
a.call(imm(errnoFunctionAddress));
// Retrieve return value and put it back in the appropriate return register
switch (resultType.getNativeType()) {
case VOID:
// No need to save/reload return value registers
break;
case SCHAR:
a.movsx(rax, byte_ptr(rsp, 0));
break;
case UCHAR:
a.movzx(rax, byte_ptr(rsp, 0));
break;
case SSHORT:
a.movsx(rax, word_ptr(rsp, 0));
break;
case USHORT:
a.movzx(rax, word_ptr(rsp, 0));
break;
case SINT:
a.movsxd(rax, dword_ptr(rsp, 0));
break;
case UINT:
// storing a value in eax zeroes out the upper 32 bits of rax
a.mov(eax, dword_ptr(rsp, 0));
break;
case FLOAT:
a.movss(xmm0, dword_ptr(rsp, 0));
break;
case DOUBLE:
a.movsd(xmm0, qword_ptr(rsp, 0));
break;
default:
a.mov(rax, qword_ptr(rsp, 0));
break;
}
} else {
// sign/zero extend the result
switch (resultType.getNativeType()) {
case SCHAR:
a.movsx(rax, al);
break;
case UCHAR:
a.movzx(rax, al);
break;
case SSHORT:
a.movsx(rax, ax);
break;
case USHORT:
a.movzx(rax, ax);
break;
case SINT:
if (long.class == resultClass) a.movsxd(rax, eax);
break;
case UINT:
if (long.class == resultClass) a.mov(eax, eax);
break;
}
}
// Restore rsp to original position
a.add(rsp, imm(space));
a.ret();
stubs.add(new Stub(name, sig(resultClass, parameterClasses), a));

@goto1134
Copy link
Contributor Author

x32 problem part

if (saveErrno) {
int save = 0;
switch (resultType.getNativeType()) {
case FLOAT:
a.fstp(dword_ptr(esp, save));
break;
case DOUBLE:
a.fstp(qword_ptr(esp, save));
break;
case SLONGLONG:
case ULONGLONG:
a.mov(dword_ptr(esp, save), eax);
a.mov(dword_ptr(esp, save + 4), edx);
break;
case VOID:
// No need to save for void values
break;
default:
a.mov(dword_ptr(esp, save), eax);
}
// Save the errno in a thread-local variable
a.call(imm(errnoFunctionAddress & 0xffffffffL));
// Retrieve return value and put it back in the appropriate return register
switch (resultType.getNativeType()) {
case FLOAT:
a.fld(dword_ptr(esp, save));
break;
case DOUBLE:
a.fld(qword_ptr(esp, save));
break;
case SCHAR:
a.movsx(eax, byte_ptr(esp, save));
break;
case UCHAR:
a.movzx(eax, byte_ptr(esp, save));
break;
case SSHORT:
a.movsx(eax, word_ptr(esp, save));
break;
case USHORT:
a.movzx(eax, word_ptr(esp, save));
break;
case SLONGLONG:
case ULONGLONG:
a.mov(eax, dword_ptr(esp, save));
a.mov(edx, dword_ptr(esp, save + 4));
break;
case VOID:
// No need to save for void values
break;
default:
a.mov(eax, dword_ptr(esp, save));
}
} else {
switch (resultType.getNativeType()) {
case SCHAR:
a.movsx(eax, al);
break;
case UCHAR:
a.movzx(eax, al);
break;
case SSHORT:
a.movsx(eax, ax);
break;
case USHORT:
a.movzx(eax, ax);
break;
}
}
if (long.class == resultClass) {
// sign or zero extend the result to 64 bits
switch (resultType.getNativeType()) {
case SCHAR:
case SSHORT:
case SINT:
case SLONG:
// sign extend eax to edx:eax
a.mov(edx, eax);
a.sar(edx, imm(31));
break;
case UCHAR:
case USHORT:
case UINT:
case ULONG:
case ADDRESS:
a.mov(edx, imm(0));
break;
}
}
// Restore esp to the original position and return
a.add(esp, imm(stackadj));
a.ret();
stubs.add(new Stub(name, sig(resultClass, parameterClasses), a));

@zhanhb
Copy link
Contributor

zhanhb commented Oct 24, 2017

What should these conversions be?

public final class Boolean extends AbstractBoolean {
public Boolean() {
super(NativeType.SCHAR);
}
public final boolean get() {
return (getMemory().getByte(offset()) & 0x1) != 0;
}
public final void set(boolean value) {
getMemory().putByte(offset(), (byte) (value ? 1 : 0));
}
}

public final class WBOOL extends AbstractBoolean {
public WBOOL() {
super(NativeType.SINT);
}
public final boolean get() {
return (getMemory().getInt(offset()) & 0x1) != 0;
}
public final void set(boolean value) {
getMemory().putInt(offset(), value ? 1 : 0);
}
}

public final class BOOL16 extends AbstractBoolean {
public BOOL16() {
super(NativeType.SSHORT);
}
public final boolean get() {
return (getMemory().getShort(offset()) & 0x1) != 0;
}
public final void set(boolean value) {
getMemory().putShort(offset(), (short) (value ? 1 : 0));
}
}

IMO, boolean is evaluated to false only if its integer value is zero.

@goto1134
Copy link
Contributor Author

Yes, you are right. Regular boolean parameters are converted the way you mentioned. I think, this should be changed.

@zhanhb
Copy link
Contributor

zhanhb commented Oct 25, 2017

parameterTypes[i].equals(boolean.class)

} else if (parameterTypes[i].equals(char.class)) {
mv.iload(slot);
mv.i2b();
mv.invokestatic(Boolean.class, "valueOf", Boolean.class, boolean.class);
} else {

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

C int to java Boolean convertion for >1 values
2 participants