/// <summary> /// Emits the catch-block. /// </summary> /// <param name="codeGenerator">A code generator.</param> /// <param name="exceptionLocal">A local variable containing an instance of <see cref="Library.SPL.Exception"/>.</param> /// <param name="endLabel">A label in IL stream where the processing of the try-catch blocks ends.</param> /// <param name="nextCatchLabel">A label in IL stream where the next catch block processing begins.</param> internal void Emit(CodeGenerator /*!*/ codeGenerator, LocalBuilder /*!*/ exceptionLocal, Label endLabel, Label nextCatchLabel) { ILEmitter il = codeGenerator.IL; codeGenerator.MarkSequencePoint( variable.Position.FirstLine, variable.Position.FirstColumn, variable.Position.LastLine, variable.Position.LastColumn + 1 ); // IF !InstanceOf(<class name>) GOTO next_catch; il.Ldloc(exceptionLocal); resolvedType.EmitInstanceOf(codeGenerator, null); il.Emit(OpCodes.Brfalse, nextCatchLabel); // variable = exception; variable.Emit(codeGenerator); il.Ldloc(exceptionLocal); variable.EmitAssign(codeGenerator); foreach (Statement statement in statements) { statement.Emit(codeGenerator); } // LEAVE end; il.Emit(OpCodes.Leave, endLabel); }
internal void Emit(CodeGenerator codeGenerator) { ILEmitter il = codeGenerator.IL; string id = codeGenerator.GetLocationId(); if (id == null) { // we are in global code -> just assign the iniVal to the variable variable.Emit(codeGenerator); if (initializer != null) { codeGenerator.EmitBoxing(initializer.Emit(codeGenerator)); il.Emit(OpCodes.Newobj, Constructors.PhpReference_Object); } else { il.Emit(OpCodes.Newobj, Constructors.PhpReference_Void); } variable.EmitAssign(codeGenerator); } else { // (J): cache the integer index of static local variable to access its value fast from within the array // unique static local variable string ID id = String.Format("{0}${1}${2}${3}", id, variable.VarName, position.FirstLine, position.FirstColumn); // create static field for static local index: private static int <id>; var type = codeGenerator.IL.TypeBuilder; Debug.Assert(type != null, "The method does not have declaring type! (global code in pure mode?)"); var field_id = type.DefineField(id, Types.Int[0], System.Reflection.FieldAttributes.Private | System.Reflection.FieldAttributes.Static); // we are in a function or method -> try to retrieve the local value from ScriptContext variable.Emit(codeGenerator); // <context>.GetStaticLocal( <field> ) codeGenerator.EmitLoadScriptContext(); // <context> il.Emit(OpCodes.Ldsfld, field_id); // <field> il.Emit(OpCodes.Callvirt, Methods.ScriptContext.GetStaticLocal); // GetStaticLocal il.Emit(OpCodes.Dup); // ?? <context>.AddStaticLocal( <field> != 0 ? <field> : ( <field> = ScriptContext.GetStaticLocalId(<id>) ), <initializer> ) if (true) { // if (GetStaticLocal(<field>) == null) Label local_initialized = il.DefineLabel(); il.Emit(OpCodes.Brtrue /*not .S, initializer can emit really long code*/, local_initialized); il.Emit(OpCodes.Pop); // <field> != 0 ? <field> : ( <field> = ScriptContext.GetStaticLocalId(<id>) ) il.Emit(OpCodes.Ldsfld, field_id); // <field> if (true) { // if (<field> == 0) Label id_initialized = il.DefineLabel(); il.Emit(OpCodes.Brtrue_S, id_initialized); // <field> = GetStaticLocalId( <id> ) il.Emit(OpCodes.Ldstr, id); il.Emit(OpCodes.Call, Methods.ScriptContext.GetStaticLocalId); il.Emit(OpCodes.Stsfld, field_id); il.MarkLabel(id_initialized); } // <context>.AddStaticLocal(<field>,<initialize>) codeGenerator.EmitLoadScriptContext(); // <context> il.Emit(OpCodes.Ldsfld, field_id); // <field> if (initializer != null) { codeGenerator.EmitBoxing(initializer.Emit(codeGenerator)); // <initializer> } else { il.Emit(OpCodes.Ldnull); } il.Emit(OpCodes.Callvirt, Methods.ScriptContext.AddStaticLocal); // AddStaticLocal // il.MarkLabel(local_initialized); } // (J) Following code used Dictionary. It was replaced by the code above. /* * codeGenerator.EmitLoadScriptContext(); * il.Emit(OpCodes.Ldstr, id); * il.Emit(OpCodes.Call, Methods.ScriptContext.GetStaticLocal); * * Label reference_gotten = codeGenerator.IL.DefineLabel(); * il.Emit(OpCodes.Dup); * il.Emit(OpCodes.Brtrue, reference_gotten); * il.Emit(OpCodes.Pop); * * // this is the first time execution reach the statement for current request -> initialize the local * codeGenerator.EmitLoadScriptContext(); * il.Emit(OpCodes.Ldstr, id); * * if (initializer != null) * codeGenerator.EmitBoxing(initializer.Emit(codeGenerator)); * else * il.Emit(OpCodes.Ldnull); * * il.Emit(OpCodes.Call, Methods.ScriptContext.AddStaticLocal); * * // assign the resulting PhpReference into the variable * il.MarkLabel(reference_gotten, true); */ variable.EmitAssign(codeGenerator); } }