Author: [email protected]
Date: Thu Jan  8 01:42:14 2009
New Revision: 1043

Modified:
    branches/experimental/toiger/src/codegen-ia32.cc
    branches/experimental/toiger/src/codegen-ia32.h

Log:
Experimental: fix a bug where we could have returns from a function
but never generate the return sequence.
Review URL: http://codereview.chromium.org/16579

Modified: branches/experimental/toiger/src/codegen-ia32.cc
==============================================================================
--- branches/experimental/toiger/src/codegen-ia32.cc    (original)
+++ branches/experimental/toiger/src/codegen-ia32.cc    Thu Jan  8 01:42:14  
2009
@@ -286,14 +286,29 @@
  #endif
        VisitStatements(body);

-      // Generate a return statement if necessary.  A NULL frame indicates
-      // that control flow leaves the body on all paths and cannot fall
-      // through.
+      // Handle the return from the function.
        if (has_valid_frame()) {
+        // If there is a valid frame, control flow can fall off the end of
+        // the body.  In that case there is an implicit return statement.
+        // Compiling a return statement will jump to the return sequence if
+        // it is already generated or generate it if not.
+        ASSERT(!function_return_is_shadowed_);
          Literal undefined(Factory::undefined_value());
          ReturnStatement statement(&undefined);
          statement.set_statement_pos(fun->end_position());
          VisitReturnStatement(&statement);
+      } else if (function_return_.is_linked()) {
+        // If the return target has dangling jumps to it, then we have not
+        // yet generated the return sequence.  This can happen when (a)
+        // control does not flow off the end of the body so we did not
+        // compile an artificial return statement just above, and (b) there
+        // are return statements in the body but (c) they are all shadowed.
+        //
+        // There is no valid frame here but it is safe (also necessary) to
+        // load the return value into eax.
+        __ mov(eax, Immediate(Factory::undefined_value()));
+        function_return_.Bind();
+        GenerateReturnSequence();
        }
      }
    }
@@ -1648,27 +1663,37 @@
        function_return_.Jump();
      } else {
        function_return_.Bind();
-      if (FLAG_trace) {
-        frame_->Push(eax);  // Materialize result on the stack.
-        frame_->CallRuntime(Runtime::kTraceExit, 1);
-      }
-
-      // Add a label for checking the size of the code used for returning.
-      Label check_exit_codesize;
-      __ bind(&check_exit_codesize);
-
-      // Leave the frame and return popping the arguments and the
-      // receiver.
-      frame_->Exit();
-      __ ret((scope_->num_parameters() + 1) * kPointerSize);
-      DeleteFrame();
-
-      // Check that the size of the code used for returning matches what is
-      // expected by the debugger.
-      ASSERT_EQ(Debug::kIa32JSReturnSequenceLength,
-                __ SizeOfCodeGeneratedSince(&check_exit_codesize));
+      GenerateReturnSequence();
      }
    }
+}
+
+
+void CodeGenerator::GenerateReturnSequence() {
+  // The return value is a live (but not currently reference counted)
+  // reference to eax.  This is safe because the current frame does not
+  // contain a reference to eax (it is prepared for the return by spilling
+  // all registers).
+  ASSERT(has_valid_frame());
+  if (FLAG_trace) {
+    frame_->Push(eax);  // Materialize result on the stack.
+    frame_->CallRuntime(Runtime::kTraceExit, 1);
+  }
+
+  // Add a label for checking the size of the code used for returning.
+  Label check_exit_codesize;
+  __ bind(&check_exit_codesize);
+
+  // Leave the frame and return popping the arguments and the
+  // receiver.
+  frame_->Exit();
+  __ ret((scope_->num_parameters() + 1) * kPointerSize);
+  DeleteFrame();
+
+  // Check that the size of the code used for returning matches what is
+  // expected by the debugger.
+  ASSERT_EQ(Debug::kIa32JSReturnSequenceLength,
+            __ SizeOfCodeGeneratedSince(&check_exit_codesize));
  }



Modified: branches/experimental/toiger/src/codegen-ia32.h
==============================================================================
--- branches/experimental/toiger/src/codegen-ia32.h     (original)
+++ branches/experimental/toiger/src/codegen-ia32.h     Thu Jan  8 01:42:14 2009
@@ -264,6 +264,12 @@
    // Main code generation function
    void GenCode(FunctionLiteral* fun);

+  // Generate the return sequence code.  Should be called no more than once
+  // per compiled function (it binds the return target, which can not be
+  // done more than once).  The return value is assumed to be in eax by the
+  // code generated.
+  void GenerateReturnSequence();
+
    // The following are used by class Reference.
    void LoadReference(Reference* ref);
    void UnloadReference(Reference* ref);

--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---

Reply via email to