示例#1
0
        private static void SwitchNumber <T>(this ILGenerator ilGen,
                                             Action <ILGenerator> emitLoadValue,
                                             Action <ILGenerator, T> emitLoadItem,
                                             CaseInfo <T>[] cases,
                                             Label defaultLabel,
                                             int begin,
                                             int index,
                                             int end)
        {
            if (begin > end)
            {
                ilGen.Branch(defaultLabel);

                return;
            }

            if (begin + 1 == end)
            {
                emitLoadValue(ilGen);
                emitLoadItem(ilGen, cases[begin].Value);
                ilGen.BranchIfEqual(cases[begin].Label);

                emitLoadValue(ilGen);
                emitLoadItem(ilGen, cases[end].Value);
                ilGen.BranchIfEqual(cases[end].Label);

                ilGen.Branch(defaultLabel);

                return;
            }

            if (begin == end)
            {
                emitLoadValue(ilGen);
                emitLoadItem(ilGen, cases[begin].Value);
                ilGen.BranchIfEqual(cases[begin].Label);

                ilGen.Branch(defaultLabel);

                return;
            }

            var greaterLabel = ilGen.DefineLabel();

            emitLoadValue(ilGen);
            emitLoadItem(ilGen, cases[index].Value);
            ilGen.BranchIfGreater(greaterLabel);

            SwitchNumber(ilGen, emitLoadValue, emitLoadItem, cases, defaultLabel, begin, (begin + index) / 2, index);

            ilGen.MarkLabel(greaterLabel);

            SwitchNumber(ilGen, emitLoadValue, emitLoadItem, cases, defaultLabel, index + 1, (index + 1 + end) / 2, end);
        }
示例#2
0
        /// <summary>
        /// Pushes the value of the reference onto the stack.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        /// <param name="throwIfUnresolvable"> <c>true</c> to throw a ReferenceError exception if
        /// the name is unresolvable; <c>false</c> to output <c>null</c> instead. </param>
        public void GenerateGet(ILGenerator generator, OptimizationInfo optimizationInfo, bool throwIfUnresolvable)
        {
            string propertyName = null;
            bool   isArrayIndex = false;

            // Right-hand-side can be a property name (a.b)
            if (this.OperatorType == OperatorType.MemberAccess)
            {
                var rhs = this.GetOperand(1) as NameExpression;
                if (rhs == null)
                {
                    throw new JavaScriptException(optimizationInfo.Engine, "SyntaxError", "Invalid member access", optimizationInfo.SourceSpan.StartLine, optimizationInfo.Source.Path, optimizationInfo.FunctionName);
                }
                propertyName = rhs.Name;
            }

            // Or a constant indexer (a['b'])
            if (this.OperatorType == OperatorType.Index)
            {
                var rhs = this.GetOperand(1) as LiteralExpression;
                if (rhs != null && (PrimitiveTypeUtilities.IsNumeric(rhs.ResultType) || rhs.ResultType == PrimitiveType.String))
                {
                    propertyName = TypeConverter.ToString(rhs.Value);

                    // Or a array index (a[0])
                    if (rhs.ResultType == PrimitiveType.Int32 || (propertyName != null && Library.ArrayInstance.ParseArrayIndex(propertyName) != uint.MaxValue))
                    {
                        isArrayIndex = true;
                    }
                }
            }

            if (isArrayIndex)
            {
                // Array indexer
                // -------------
                // xxx = object[index]

                // Load the left-hand side and convert to an object instance.
                var lhs = this.GetOperand(0);
                lhs.GenerateCode(generator, optimizationInfo);
                EmitConversion.ToObject(generator, lhs.ResultType, optimizationInfo);

                // Load the right-hand side and convert to a uint32.
                var rhs = this.GetOperand(1);
                rhs.GenerateCode(generator, optimizationInfo);
                EmitConversion.ToUInt32(generator, rhs.ResultType);

                // Call the indexer.
                generator.Call(ReflectionHelpers.ObjectInstance_GetPropertyValue_Int.Value);
            }
            else if (propertyName != null)
            {
                //// Load the left-hand side and convert to an object instance.
                //var lhs = this.GetOperand(0);
                //lhs.GenerateCode(generator, optimizationInfo);
                //EmitConversion.ToObject(generator, lhs.ResultType);

                //// Call Get(string)
                //generator.LoadString(propertyName);
                //generator.Call(ReflectionHelpers.ObjectInstance_GetPropertyValue_String);



                // Named property access (e.g. x = y.property)
                // -------------------------------------------
                // __object_cacheKey = null;
                // __object_property_cachedIndex = 0;
                // ...
                // if (__object_cacheKey != object.InlineCacheKey)
                //     xxx = object.InlineGetPropertyValue("property", out __object_property_cachedIndex, out __object_cacheKey)
                // else
                //     xxx = object.InlinePropertyValues[__object_property_cachedIndex];

                // Load the left-hand side and convert to an object instance.
                var lhs = this.GetOperand(0);
                lhs.GenerateCode(generator, optimizationInfo);
                EmitConversion.ToObject(generator, lhs.ResultType, optimizationInfo);

                // TODO: share these variables somehow.
                var cacheKey    = generator.DeclareVariable(typeof(object), null);
                var cachedIndex = generator.DeclareVariable(typeof(int), null);

                // Store the object into a temp variable.
                var objectInstance = generator.DeclareVariable(PrimitiveType.Object, null);
                generator.StoreVariable(objectInstance);

                // if (__object_cacheKey != object.InlineCacheKey)
                generator.LoadVariable(cacheKey);
                generator.LoadVariable(objectInstance);
                generator.Call(ReflectionHelpers.ObjectInstance_InlineCacheKey.Value);
                var elseClause = generator.CreateLabel();
                generator.BranchIfEqual(elseClause);

                // value = object.InlineGetProperty("property", out __object_property_cachedIndex, out __object_cacheKey)
                generator.LoadVariable(objectInstance);
                generator.LoadString(propertyName);
                generator.LoadAddressOfVariable(cachedIndex);
                generator.LoadAddressOfVariable(cacheKey);
                generator.Call(ReflectionHelpers.ObjectInstance_InlineGetPropertyValue.Value);

                var endOfIf = generator.CreateLabel();
                generator.Branch(endOfIf);

                // else
                generator.DefineLabelPosition(elseClause);

                // value = object.InlinePropertyValues[__object_property_cachedIndex];
                generator.LoadVariable(objectInstance);
                generator.Call(ReflectionHelpers.ObjectInstance_InlinePropertyValues.Value);
                generator.LoadVariable(cachedIndex);
                generator.LoadArrayElement(typeof(object));

                // End of the if statement
                generator.DefineLabelPosition(endOfIf);
            }
            else
            {
                // Dynamic property access
                // -----------------------
                // xxx = object.Get(x)

                // Load the left-hand side and convert to an object instance.
                var lhs = this.GetOperand(0);
                lhs.GenerateCode(generator, optimizationInfo);
                EmitConversion.ToObject(generator, lhs.ResultType, optimizationInfo);

                // Load the property name and convert to a string.
                var rhs = this.GetOperand(1);
                rhs.GenerateCode(generator, optimizationInfo);
                EmitConversion.ToString(generator, rhs.ResultType);

                // Call Get(string)
                generator.Call(ReflectionHelpers.ObjectInstance_GetPropertyValue_String.Value);
            }
        }