<commit_before>// Copyright (c) Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Reflection;
using System.Reflection.Emit;
using System.Threading;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Scripting.Emit;
using Roslyn.Utilities;

namespace Microsoft.CodeAnalysis.Scripting
{
    /// <summary>
    /// Represents a runtime execution context for C# scripts.
    /// </summary>
    internal class ScriptBuilder
    {
        /// <summary>
        /// Unique prefix for generated uncollectible assemblies.
        /// </summary>
        /// <remarks>
        /// The full names of uncollectible assemblies generated by this context must be unique,
        /// so that we can resolve references among them. Note that CLR can load two different assemblies of the very 
        /// identity into the same load context.
        /// 
        /// We are using a certain naming scheme for the generated assemblies (a fixed name prefix followed by a number). 
        /// If we allowed the compiled code to add references that match this exact pattern it migth happen that 
        /// the user supplied reference identity conflicts with the identity we use for our generated assemblies and 
        /// the AppDomain assembly resolve event won't be able to correctly identify the target assembly.
        /// 
        /// To avoid this problem we use a prefix for assemblies we generate that is unlikely to conflict with user specified references.
        /// We also check that no user provided references are allowed to be used in the compiled code and report an error ("reserved assembly name").
        /// </remarks>
        private static readonly string s_globalAssemblyNamePrefix;
        private static int s_engineIdDispenser;
        private int _submissionIdDispenser = -1;
        private readonly string _assemblyNamePrefix;

        // dynamic code storage
        //
        // TODO (tomat): Dynamic assembly allocation strategy. A dynamic assembly is a unit of
        // collection. We need to find a balance between creating a new assembly per execution
        // (potentially shorter code lifetime) and reusing a single assembly for all executions
        // (less overhead per execution).

        private readonly UncollectibleCodeManager _uncollectibleCodeManager;
        private readonly CollectibleCodeManager _collectibleCodeManager;

        /// <summary>
        /// Lockable object only instance is knowledgeable about.
        /// <summary>
        private readonly object _gate = new object();

        #region Testing and Debugging

        private const string CollectibleModuleFileName = "CollectibleModule.dll";
        private const string UncollectibleModuleFileName = "UncollectibleModule.dll";

        // Setting this flag will add DebuggableAttribute on the emitted code that disables JIT optimizations.
        // With optimizations disabled JIT will verify the method before it compiles it so we can easily 
        // discover incorrect code.
        internal static bool DisableJitOptimizations;

#if DEBUG<commit_msg>Fix malformed XML doc comment causing build warning<commit_after>// Copyright (c) Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Reflection;
using System.Reflection.Emit;
using System.Threading;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Scripting.Emit;
using Roslyn.Utilities;

namespace Microsoft.CodeAnalysis.Scripting
{
    /// <summary>
    /// Represents a runtime execution context for C# scripts.
    /// </summary>
    internal class ScriptBuilder
    {
        /// <summary>
        /// Unique prefix for generated uncollectible assemblies.
        /// </summary>
        /// <remarks>
        /// The full names of uncollectible assemblies generated by this context must be unique,
        /// so that we can resolve references among them. Note that CLR can load two different assemblies of the very 
        /// identity into the same load context.
        /// 
        /// We are using a certain naming scheme for the generated assemblies (a fixed name prefix followed by a number). 
        /// If we allowed the compiled code to add references that match this exact pattern it migth happen that 
        /// the user supplied reference identity conflicts with the identity we use for our generated assemblies and 
        /// the AppDomain assembly resolve event won't be able to correctly identify the target assembly.
        /// 
        /// To avoid this problem we use a prefix for assemblies we generate that is unlikely to conflict with user specified references.
        /// We also check that no user provided references are allowed to be used in the compiled code and report an error ("reserved assembly name").
        /// </remarks>
        private static readonly string s_globalAssemblyNamePrefix;
        private static int s_engineIdDispenser;
        private int _submissionIdDispenser = -1;
        private readonly string _assemblyNamePrefix;

        // dynamic code storage
        //
        // TODO (tomat): Dynamic assembly allocation strategy. A dynamic assembly is a unit of
        // collection. We need to find a balance between creating a new assembly per execution
        // (potentially shorter code lifetime) and reusing a single assembly for all executions
        // (less overhead per execution).

        private readonly UncollectibleCodeManager _uncollectibleCodeManager;
        private readonly CollectibleCodeManager _collectibleCodeManager;

        /// <summary>
        /// Lockable object only instance is knowledgeable about.
        /// </summary>
        private readonly object _gate = new object();

        #region Testing and Debugging

        private const string CollectibleModuleFileName = "CollectibleModule.dll";
        private const string UncollectibleModuleFileName = "UncollectibleModule.dll";

        // Setting this flag will add DebuggableAttribute on the emitted code that disables JIT optimizations.
        // With optimizations disabled JIT will verify the method before it compiles it so we can easily 
        // discover incorrect code.
        internal static bool DisableJitOptimizations;

#if DEBUG
{'fraction_non_alphanumeric': 0.0605831696630911, 'fraction_numerical': 0.0009064813415923856, 'mean_word_length': 2.776383342840844, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7040800', 'n_tokens_mistral': 1495, 'n_tokens_neox': 1442, 'n_words': 720}