Browse Source

* do not create full copies of objects when object checking is on, resolves #36863

git-svn-id: trunk@44598 -
florian 5 years ago
parent
commit
0f06a7205b
3 changed files with 47 additions and 7 deletions
  1. 1 0
      .gitattributes
  2. 16 7
      compiler/nutils.pas
  3. 30 0
      tests/webtbs/tw36863.pp

+ 1 - 0
.gitattributes

@@ -18136,6 +18136,7 @@ tests/webtbs/tw36738.pp svneol=native#text/pascal
 tests/webtbs/tw3676.pp svneol=native#text/plain
 tests/webtbs/tw3681.pp svneol=native#text/plain
 tests/webtbs/tw3683.pp svneol=native#text/plain
+tests/webtbs/tw36863.pp svneol=native#text/pascal
 tests/webtbs/tw3687.pp svneol=native#text/plain
 tests/webtbs/tw3691.pp svneol=native#text/plain
 tests/webtbs/tw3694.pp svneol=native#text/plain

+ 16 - 7
compiler/nutils.pas

@@ -649,13 +649,21 @@ implementation
 
         block:=nil;
         stat:=nil;
+        self_temp:=nil;
         if docheck then
           begin
             { check for nil self-pointer }
             block:=internalstatements(stat);
-            self_temp:=ctempcreatenode.create_value(
-              self_resultdef,self_resultdef.size,tt_persistent,true,
-              self_node);
+            if is_object(self_resultdef) then
+              begin
+                self_temp:=ctempcreatenode.create_value(
+                  cpointerdef.getreusable(self_resultdef),cpointerdef.getreusable(self_resultdef).size,tt_persistent,true,
+                  caddrnode.create(self_node));
+              end
+            else
+              self_temp:=ctempcreatenode.create_value(
+                self_resultdef,self_resultdef.size,tt_persistent,true,
+                self_node);
             addstatement(stat,self_temp);
 
             { in case of an object, self can only be nil if it's a dereferenced
@@ -665,8 +673,6 @@ implementation
                (actualtargetnode(@self_node)^.nodetype=derefn) then
               begin
                 check_self:=ctemprefnode.create(self_temp);
-                if is_object(self_resultdef) then
-                  check_self:=caddrnode.create(check_self);
                 addstatement(stat,cifnode.create(
                   caddnode.create(equaln,
                     ctypeconvnode.create_explicit(
@@ -678,8 +684,10 @@ implementation
                   nil)
                 );
               end;
-            addstatement(stat,ctempdeletenode.create_normal_temp(self_temp));
-            self_node:=ctemprefnode.create(self_temp);
+            if is_object(self_resultdef) then
+              self_node:=cderefnode.create(ctemprefnode.create(self_temp))
+            else
+              self_node:=ctemprefnode.create(self_temp)
           end;
         { in case of a classref, the "instance" is a pointer
           to pointer to a VMT and there is no vmt field }
@@ -729,6 +737,7 @@ implementation
                 )
               );
             addstatement(stat,ctempdeletenode.create_normal_temp(vmt_temp));
+            addstatement(stat,ctempdeletenode.create(self_temp));
             addstatement(stat,ctemprefnode.create(vmt_temp));
             result:=block;
           end

+ 30 - 0
tests/webtbs/tw36863.pp

@@ -0,0 +1,30 @@
+{ %OPT=-Ct -CR }
+{$M 65536,65536}
+
+type
+  TObj = object
+    v: array [0..$2000] of Byte;
+    procedure Proc(depth: Integer);
+    procedure VProc; virtual;
+  end;
+
+  procedure TObj.VProc;
+  begin
+  end;
+
+  procedure TObj.Proc(depth: Integer);
+  begin
+    {stack is eaten here on the function entry}
+    if (depth < 64) then
+      Proc(depth+1);
+    {do not actually call the method since the obj is not initialized, just for minimal demonstration}
+    if (depth < 0) then
+    VProc;
+  end;
+
+var
+  Obj: TObj;
+begin
+  Obj.Proc(0);
+  writeln('Completed');
+end.