Should .class output be identical from Water and VS (same Elements & source)?

Compiling a project to .jar file (Oxygene, Elements 10.0.0.2331) with Water and VS2015. In .jars all except 2 of the .class files are identical. These 2 are identical byte size, but have a few differences.

Is it expected that these should be identical?

They should be, yes, if you’re building with the same set of settings. What’s the difference? Note that I’m not familiar with the .class byte format in detail, it might well be that it has semi-random bites that are affected by things such as the time stamp…

Nevermind…I rebuilt in Water and it now matches the build from VS. Not sure what happened as I didn’t change anything…just clear and rebuild. I’ll pay a bit of attention going forward…

1 Like

I fooled myself into thinking there was no difference. There is…repeatably.

Here’s what’s happening: testing for inclusion in a set is resulting in boolean tests 'or’d in a different order. The logic is equivalent, but why is it different, but apparently a different parser is in use in water vs VS.

Does that make sense?

Below are the two sections that differed when build in Water vs VS. Shown are the Oxygene source, and the decompiled .class from the .jars built by Water and VS

(I set code fragments as ‘preformatted text’ but the result is inconsistent…)


source:

  TLcorner : Char = #$DA;
  TRcorner : Char = #$BF;
  BLcorner : Char = #$C0;
  BRcorner : Char = #$D9;
  HorzLine : Char = #$C4;
  VertLine : Char = #$B3;
  Up_T     : Char = #$C2;
  Down_T   : Char = #$C1;
  Right_T  : Char = #$B4;
  Left_T   : Char = #$C3;
  Cross    : Char = #$C5;


method tDataEntryForm.hideLineDrawChar(ch:Char):Boolean;
begin
  if myTerm.fpMsgMode then begin
    result :=  (ch in [#254,TLcorner,TRcorner,BLcorner,BRcorner,VertLine,
                      HorzLine,Down_T,Up_T,Right_T,Left_T,Cross]);
  end else begin
    result := (ch > #175) and (myTerm.LineDrawSetString.indexOf(ch) > -1);
  end;
end;
  • compiled in Water:
    public boolean hideLineDrawChar(char var1) {
    boolean var2 = false;
    if (this.myTerm.fpMsgMode) {
    var2 = var1 == 254 || var1 == 194 || var1 == 193 || var1 == 180 || var1 == 197 || var1 == 195 || var1 == 196 || var1 == 191 || var1 == 218 || var1 == 192 || var1 == 179 || var1 == 217;
    } else {
    var2 = var1 <= 175 ? false : this.myTerm.LineDrawSetString.indexOf(Character.toString(var1)) > -1;
    }

      return var2;
    

    }

  • compiled in VS:
    public boolean hideLineDrawChar(char var1) {
    boolean var2 = false;
    if (this.myTerm.fpMsgMode) {
    var2 = var1 == 254 || var1 == 218 || var1 == 191 || var1 == 192 || var1 == 217 || var1 == 179 || var1 == 196 || var1 == 193 || var1 == 194 || var1 == 180 || var1 == 195 || var1 == 197;
    } else {
    var2 = var1 <= 175 ? false : this.myTerm.LineDrawSetString.indexOf(Character.toString(var1)) > -1;
    }

      return var2;
    

    }


source:
for i := 1 to fpBtns[ndx].numKeystrokes do begin
//don’t include non-char keys in s, save for exitKey field of field leave msg
//assumes only 1 such non-char key and it’s the last one
if (fpBtns[ndx].keystrokes[i] in [13,33…47,58,59,91…255]) then begin
lastKey := fpBtns[ndx].keystrokes[i];
end else begin
s := s + Char(fpBtns[ndx].keystrokes[i]);
end;
if not (fpBtns[ndx].keystrokes[i] in [13,32…126,128…255]) then begin
keyBrdBtn := false;
break;
end;
end;

compiled in Water:
int var8 = this.fpBtns[var1].numKeystrokes & ‘\uffff’ & ‘\uffff’;
int var12 = 1;
if (var12 <= var8) {
++var8;

        do {
            int var9 = this.fpBtns[var1].keystrokes[var12] & '\uffff';
            if (var9 == 13 || var9 == 58 || var9 == 59 || var9 >= 91 & var9 <= 255 || var9 >= 33 & var9 <= 47) {
                var14 = this.fpBtns[var1].keystrokes[var12] & '\uffff';
            } else {
                String var11 = Character.toString((char)(this.fpBtns[var1].keystrokes[var12] & '\uffff'));
                var5 = var5 == null ? var11 : (var11 == null ? var5 : var5.concat(var11));
            }

            var9 = this.fpBtns[var1].keystrokes[var12] & '\uffff';
            if (var9 != 13 && !(var9 >= 128 & var9 <= 255) && !(var9 >= 32 & var9 <= 126)) {
                var2 = false;
                break;
            }

            ++var12;
        } while(var12 != var8);
    }

compiled in VS:
int var8 = this.fpBtns[var1].numKeystrokes & ‘\uffff’ & ‘\uffff’;
int var12 = 1;
if (var12 <= var8) {
++var8;

        do {
            int var9 = this.fpBtns[var1].keystrokes[var12] & '\uffff';
            if (var9 == 13 || var9 == 58 || var9 == 59 || var9 >= 33 & var9 <= 47 || var9 >= 91 & var9 <= 255) {
                var14 = this.fpBtns[var1].keystrokes[var12] & '\uffff';
            } else {
                String var11 = Character.toString((char)(this.fpBtns[var1].keystrokes[var12] & '\uffff'));
                var5 = var5 == null ? var11 : (var11 == null ? var5 : var5.concat(var11));
            }

            var9 = this.fpBtns[var1].keystrokes[var12] & '\uffff';
            if (var9 != 13 && !(var9 >= 32 & var9 <= 126) && !(var9 >= 128 & var9 <= 255)) {
                var2 = false;
                break;
            }

            ++var12;
        } while(var12 != var8);
    }

hmm. that makes no sense. @ck, any idea?

richard, can you post the full diagnostic build log? i want to make sure both builds are using the same compiler version, although i cant imagine how they would not.

I’ll try to reproduce and fetch the logs today. I’m suspicious that it’s not compiler, but a slight difference in the oxygene to java translation.

How do I get the actual build log from VS? The displayed build output is only the messages, no info about compiler.

Water build log info (minus messages):
“C:\Program Files (x86)\RemObjects Software\Elements\Bin\EBuild.exe” C:\oxygene\classes\com.mirvsoftware\com.mirvsoftware.sln --logger:fire --configuration:Debug --verbosity:normal --xml:C:\oxygene\classes\com.mirvsoftware\obj\com.mirvsoftware.water.xml --rebuild --setting:TreatFixableErrorsAsWarnings=True
RemObjects EBuild. An open source build engine for Elements and beyond.
Copyright RemObjects Software 2016-2018. All Rights Reserved. Created by marc hoffman.
Version 10.0.0.2331 (develop) built on talax, 20180928-142533. Commit 8e4eb02.

   Project: <RemObjects.EBuild.Elements.EBuildElementsProject: com.mirvsoftware>
   Solution 'com.mirvsoftware' cleaned successfully.
   Reference 'log4j-api-2.8.2' was resolved to 'C:\java_libs\apache-log4j-2.8.2-bin\log4j-api-2.8.2.jar' via absolute path for target 'Cooper'.
   Reference 'log4j-core-2.8.2' was resolved to 'C:\java_libs\apache-log4j-2.8.2-bin\log4j-core-2.8.2.jar' via absolute path for target 'Cooper'.
   Reference 'cooper' was resolved to 'C:\Program Files (x86)\RemObjects Software\Elements\Cooper\Reference Archives\cooper.jar' via XML for target 'Cooper'.
   Reference 'jce' was resolved to 'C:\Program Files\Java\jdk1.8.0_162\jre\lib\jce.jar' for target 'Cooper'.
   Reference 'MIRVsoft' was resolved to 'c:\MIRVsoft\out\artifacts\MIRVsoft.jar' via absolute path for target 'Cooper'.
   Reference 'regex' was resolved to 'C:\oxygene\MIRVsoft\regex.jar' via 'HintPath' for target 'Cooper'.
   Reference 'ssi_webfast' was resolved to 'C:\oxygene\MIRVsoft\ssi_webfast.jar' via 'HintPath' for target 'Cooper'.
   Reference 'RemObjects.Elements.EUnit' was resolved to 'C:\Program Files (x86)\RemObjects Software\Elements\Cooper\Reference Archives\Plain\RemObjects.Elements.EUnit.jar' via XML for target 'Cooper'.
   Reference 'rt' was resolved to 'C:\Program Files\Java\jdk1.8.0_162\jre\lib\rt.jar' for target 'Cooper'.
   RemObjects Elements (Oxygene, C#, Swift and Java) Compiler for .NET, Cocoa, Java and Island.
   Version 10.0.0.2331 (develop) built on talax, 20180928-142533. Commit 8e4eb02.
   Copyright 2003-2018 RemObjects Software, LLC. All rights reserved.

VS info:

VS diagnostic build log:

		         Compiling target 'Cooper'
		         -> Target Cooper started compiling.
		            Starting compile for com.mirvsoftware Cooper 
		            RemObjects Elements (Oxygene, C#, Swift and Java) Compiler for .NET, Cocoa, Java and Island.
		            Version 10.0.0.2331 (develop) built on talax, 20180928-142533. Commit 8e4eb02.
		            Copyright 2003-2018 RemObjects Software, LLC. All rights reserved.

VS2015-build-log.txt (72.5 KB)

ok, so thats the exact same compiler binary, yeah. i do assume youre building the same configurattion (debug vs release) in both, right?

Both built as debug

Thanks, logged as bugs://81322

There’s sorting logic in the compiler to optimize the order of elements (left to right) but it doesn’t seem to work right for indirect constants vs inline constants. And different .NET versions act different on this. Will fix.

1 Like

bugs://81322 got closed with status fixed.

Does this mean that even though the compiler version was identical, the behavior differed in VS and Water due to using differing .NET versions? That’s a bit scary…

sort of. Array.Sort isn’t “stable” in it’s sort order (it’s not in most languages);what we did by accident is make it look like they compared all equal. With a different pivot (which changes between versions) it would end up differently.

Understood, and thanks for the details.