[phc-internals] [phc commit] r1194 - in trunk/src: . codegen

codesite-noreply at google.com codesite-noreply at google.com
Fri Apr 25 04:48:08 IST 2008


Author: paul.biggar
Date: Thu Apr 24 20:47:48 2008
New Revision: 1194

Modified:
   trunk/src/codegen/Clarify.cpp
   trunk/src/codegen/Lift_functions_and_classes.h
   trunk/src/codegen/Prune_symbol_table.cpp
   trunk/src/codegen/Prune_symbol_table.h
   trunk/src/phc.cpp

Log:
This adds superglobals other than GLOBALS. It also adds an optimization 
to remove those globals.

We look through the variables used in a method, and if there is no reflection
or run-time code generation, then the globals can be removed if they are
unused.

Additionally, we make Lift_functions_and_classes non-optional.

Overall, this results in a 4% speed increase, but this is really about 
15% increase in each of the recursive functions, which benefit from 
having GLOBALS removed.

Note that this breaks a number of tests, specifically anything with 
nested functions. Rather than fix this, I'm going to replace nested 
functions with MIR intrinsics, which we talked about a long time ago. 
I'm committing this now since I need the results.


Modified: trunk/src/codegen/Clarify.cpp
==============================================================================
--- trunk/src/codegen/Clarify.cpp	(original)
+++ trunk/src/codegen/Clarify.cpp	Thu Apr 24 20:47:48 2008
@@ -6,6 +6,7 @@
  */

 #include "Clarify.h"
+#include "process_ir/General.h"

 using namespace MIR;

@@ -25,13 +26,28 @@

 void Clarify::post_method (MIR::Method* in)
 {
-	MIR::Global* global =
-		new MIR::Global (
-			new MIR::VARIABLE_NAME (
-				new String ("GLOBALS")));
+	if (in->statements == NULL)
+		return;

-	if (in->statements)
-		in->statements->push_front (global);
-	else
-		in->statements = new List<MIR::Statement*> (global);
+	List<String*>* var_names = new List<String*>;
+	var_names->push_back (s("GLOBALS"));
+	var_names->push_back (s("_ENV"));
+	var_names->push_back (s("HTTP_ENV_VARS"));
+	var_names->push_back (s("_POST"));
+	var_names->push_back (s("HTTP_POST_VARS"));
+	var_names->push_back (s("_GET"));
+	var_names->push_back (s("HTTP_GET_VARS"));
+	var_names->push_back (s("_COOKIE"));
+	var_names->push_back (s("HTTP_COOKIE_VARS"));
+	var_names->push_back (s("_FILES"));
+	var_names->push_back (s("HTTP_FILES_VARS"));
+	var_names->push_back (s("_REQUEST"));
+	var_names->push_back (s("HTTP_REQUEST_VARS"));
+	for_lci(var_names,String,i)
+	{
+		in->statements->push_front (
+			new MIR::Global (
+				new MIR::VARIABLE_NAME (
+					*i)));
+	}
 }

Modified: trunk/src/codegen/Lift_functions_and_classes.h
==============================================================================
--- trunk/src/codegen/Lift_functions_and_classes.h	(original)
+++ trunk/src/codegen/Lift_functions_and_classes.h	Thu Apr 24 20:47:48 2008
@@ -9,27 +9,9 @@
 #define PHC_LIFT_FUNCTIONS_AND_CLASSES_H

 #include "MIR_transform.h"
-#include "pass_manager/Pass_manager.h"

-class Lift_functions_and_classes : public MIR::Transform, public Pass
+class Lift_functions_and_classes : public MIR::Transform
 {
-public:
-
-	Lift_functions_and_classes ()
-	{
-		this->name = new String ("lfc");
-		this->description = new String ("Move statements from global scope 
into __MAIN__ method");
-	}
-
-	// TODO this should be done on HIR, I think
-	void run (IR::PHP_script* in, Pass_manager* pm)
-	{
-		if (pm->args_info->generate_c_flag
-			or pm->args_info->compile_flag)
-		{
-			in->transform_children(this);
-		}
-	}
 	void children_php_script(MIR::PHP_script* in);
 };


Modified: trunk/src/codegen/Prune_symbol_table.cpp
==============================================================================
--- trunk/src/codegen/Prune_symbol_table.cpp	(original)
+++ trunk/src/codegen/Prune_symbol_table.cpp	Thu Apr 24 20:47:48 2008
@@ -21,14 +21,22 @@
  *
  *		means we need a symbol table entry, but that is true of
  *		anything which uses reflection.
+ *
+ * Pruning globals:
+ *		We add global declarations of all the superglobals --- GLOBALS,
+ *		HTTP_POST_VARS etc --- in Clarify. Here we check if they are used. 
If a
+ *		global is not used, we remove them. Since we use 
post_variable_name to do
+ *		this, we must avoid going into the VARIABLE_NAME belonging to 
global $X -
+ *		that would defeat the purpose.
  */

 #include "Prune_symbol_table.h"
+#include "MIR_transform.h"

 using namespace MIR;

 Prune_symbol_table::Prune_symbol_table ()
-:  prune (true)
+:  prune (false)
 {

 }
@@ -41,6 +49,9 @@
 {
 	// reset
 	prune = true;
+	var_reflection_present = false;;
+	record_globals = true;
+	vars.clear();

 	if (*in->signature->method_name->value == "__MAIN__")
 	{
@@ -57,8 +68,6 @@

 void Prune_symbol_table::pre_method_invocation (Method_invocation* in)
 {
-	/* To be able to support includes with return statements, without
-	 * dataflow, we dont shred their string arguments */
 	METHOD_NAME* name = dynamic_cast<METHOD_NAME*>(in->method_name);
 	if (name && (
 				*name->value == "eval"
@@ -76,13 +85,63 @@
 	}
 }

+void Prune_symbol_table::pre_global (Global* in)
+{
+	// Don't mark children variable names
+	record_globals = false;
+}
+
+void Prune_symbol_table::post_global (Global* in)
+{
+	record_globals = true;
+}
+

 void Prune_symbol_table::post_variable_name (VARIABLE_NAME* in)
 {
 	if (prune)
+	{
 		in->attrs->set_true ("phc.codegen.st_entry_not_required");
+
+		// record variable names for removing globals in post_method
+		if (record_globals)
+			vars[*in->value] = true;
+	}
 }

+
+void Prune_symbol_table::post_variable_name (Variable_name* in)
+{
+	// reflection means we cant remove any globals
+	if (in->classid () == Reflection::ID)
+		var_reflection_present = true;
+}
+
+class Remove_globals : public Transform
+{
+private:
+	map<string, bool> var_names;
+
+public:
+	Remove_globals (map<string, bool> *var_names)
+	: var_names (*var_names)
+	{
+	}
+
+	void pre_global (Global* in, List<Statement*>* out)
+	{
+		VARIABLE_NAME* var_name = dynamic_cast<VARIABLE_NAME*> (in->variable_name);
+		assert (var_name); // if there were any reflection, we wouldnt be here
+
+		// if the key is there, we need the global
+		if (var_names.find (*var_name->value) != var_names.end ())
+			out->push_back (in);
+		else
+			; // we dont need the global
+	}
+};
+
+
 /* Also mark the function. */
 void Prune_symbol_table::post_method (Method* in)
 {
@@ -90,5 +149,12 @@
 	{
 		assert (*in->signature->method_name->value != "__MAIN__");
 		in->signature->method_name->attrs->set_true ("phc.codegen.st_entry_not_required");
+
+		// Go through the globals and check if they're used
+		if (!var_reflection_present)
+			in->transform_children (new Remove_globals (&vars));
 	}
 }
+
+
+

Modified: trunk/src/codegen/Prune_symbol_table.h
==============================================================================
--- trunk/src/codegen/Prune_symbol_table.h	(original)
+++ trunk/src/codegen/Prune_symbol_table.h	Thu Apr 24 20:47:48 2008
@@ -13,18 +13,32 @@

 class Prune_symbol_table : public MIR::Visitor
 {
+private:
+	// We can only prune in functions other than __MAIN__
 	bool prune;

+	// is there reflection
+	bool var_reflection_present;
+
+	// We only record globals if they are not in a gloal statement
+	bool record_globals;
+
+	// variables which are present anywhere in the method
+	map<string, bool> vars;
+
 public:
 	Prune_symbol_table ();
 	// do the analysis
 	void pre_method (MIR::Method* in);
 	void pre_reflection (MIR::Reflection* in);
 	void pre_method_invocation (MIR::Method_invocation* in);
+	void pre_global (MIR::Global* in);
+	void post_global (MIR::Global* in);

 	// mark methods and variable_names
 	void post_method (MIR::Method* in);
 	void post_variable_name (MIR::VARIABLE_NAME* in);
+	void post_variable_name (MIR::Variable_name* in);
 };

 #endif  // _PRUNE_SYMBOL_TABLE_H_

Modified: trunk/src/phc.cpp
==============================================================================
--- trunk/src/phc.cpp	(original)
+++ trunk/src/phc.cpp	Thu Apr 24 20:47:48 2008
@@ -163,7 +163,7 @@
 	// Use ss to pass generated code between Generate_C and Compile_C
  	pm->add_mir_pass (new Fake_pass (s("mir"), s("Medium-level Internal 
Representation - simple code with high-level constructs lowered to 
straight-line code.")));
 //	pm->add_mir_pass (new Process_includes (true, new String ("mir"), pm, "incl2"));
-	pm->add_mir_pass (new Lift_functions_and_classes ());
+	pm->add_mir_transform (new Lift_functions_and_classes (), s("lfc"), 
s("Move statements from global scope into __MAIN__ method"));
  	pm->add_mir_visitor (new Clarify (), s("clar"), s("Clarify - Make 
implicit defintions explicit"));
  	pm->add_mir_visitor (new Prune_symbol_table (), s("pst"), s("Prune 
Symbol Table - Note whether a symbol table is required in generated code"));
 	stringstream ss;


More information about the phc-internals mailing list