private ReadIndexerExpression MakeReadIndexerExpression(Expression container, Expression index) { StringLiteral constIndex = index as StringLiteral; int integerIndex; ReadIndexerExpression n; //We need to make sure that the string is not an integer, because in the case of Arrays integer strings are equivalent to integers!! if (constIndex != null && !int.TryParse(constIndex.Value, out integerIndex)) { n = new ReadPropertyExpression(MakeToObject((Expression)container), constIndex); } else { n = new ReadIndexerExpression(MakeToObject((Expression)container), (Expression)index); } return(n); }
protected override void PerformLookup(ReadIndexerExpression node, LocalBuilder obj, mdr.ValueTypes objType, mdr.ValueTypes indexType, LocalBuilder value) { if (objType == mdr.ValueTypes.Array && indexType == mdr.ValueTypes.Int32) base.PerformLookup(node, obj, objType, indexType, value); else { _ilGen.Callvirt(Types.DObject.GetPropertyDescriptor.Get(_result.ValueType)); //_ilGen.Callvirt(Types.DObject.GetField(_result.ValueType)); int profIndex = _currFuncMetadata.GetProfileIndex(node); _ilGen.Ldloc(_profiler); _ilGen.Ldc_I4(profIndex); _ilGen.Ldloc(obj); _ilGen.Call(Types.DObject.GetMap); _ilGen.Call(Types.Operations.Internals.UpdateMapProfile); _ilGen.Ldloc(obj); _ilGen.Ldloca(value); _ilGen.Callvirt(Types.PropertyDescriptor.Get_DObject_DValueRef); } }
protected virtual void PerformLookup(ReadIndexerExpression node, LocalBuilder obj, mdr.ValueTypes objType, mdr.ValueTypes indexType, LocalBuilder value) { if (objType == mdr.ValueTypes.Array && indexType == mdr.ValueTypes.Int32) { var index = _localVars.PushTemporary(indexType); _ilGen.Stloc(index); var slowPath = _ilGen.DefineLabel(); var exitPath = _ilGen.DefineLabel(); _ilGen.Pop(); _ilGen.Ldloc(index); _ilGen.Ldc_I4_0(); _ilGen.Blt(slowPath); _ilGen.Ldloc(index); _ilGen.Ldloc(obj); _ilGen.Ldfld(Types.DArray.ElementsLength); _ilGen.Bge(slowPath); _ilGen.Ldloc(obj); _ilGen.Ldfld(Types.DArray.Elements); _ilGen.Ldloc(index); _ilGen.Ldelema(Types.DValue.TypeOf); _ilGen.Ldobj(Types.DValue.TypeOf); _ilGen.Stloc(value); _ilGen.Br(exitPath); _localVars.PopTemporary(index); _ilGen.MarkLabel(slowPath); _ilGen.Ldloc(obj); _ilGen.Ldloc(index); _ilGen.Callvirt(Types.DObject.GetPropertyDescriptor.Get(_result.ValueType)); _ilGen.Ldloc(obj); _ilGen.Ldloca(value); _ilGen.Callvirt(Types.PropertyDescriptor.Get_DObject_DValueRef); _ilGen.MarkLabel(exitPath); } else { _ilGen.Callvirt(Types.DObject.GetPropertyDescriptor.Get(_result.ValueType)); //_ilGen.Callvirt(Types.DObject.GetField(_result.ValueType)); _ilGen.Ldloc(obj); _ilGen.Ldloca(value); _ilGen.Callvirt(Types.PropertyDescriptor.Get_DObject_DValueRef); } }
public override void Visit(ReadIndexerExpression node) { PushLocation(node); //TODO: how should we add typed array acces to this? // If we know the actual type is DArray with some type data, we can potentially use that. But that should be done at run time // So, we should generate code to do that. Or is it more complicated than that? ///Any read or write in this situation must consider that the results might a Prototype, and so getter/setter should be called as well ///In the case of Usages.ReadWrite: ///We should execute the read side then the write side. If object itself does not have field, it will ///use its prototype chain for read. If we do the reverse order, the field is first added to the object. ///Also, /// if the object does have the field, the result ref for read and write will be point to two different objects /// if the object has the filed, both refs will point to the same thing. So, we should be ok in terms of dangling refs ///Note: ////GetField... does not have any side effects, so we don't need to call it! ///SetField... or GetOrAddField... may have side effects, so we should call it as well no matter what, but if we are in Write or ReadWrite mode, the User cannot be null //We push this first since we don't want to pop it later, before pushing/poping more var value = _localVars.PushTemporary(Types.DValue.TypeOf); var stackState = _localVars.GetTemporaryStackState(); VisitNode(node.Container); AsDObject(); var objType = _result.ValueType; var obj = _localVars.PushTemporary(objType); _ilGen.Stloc(obj); _ilGen.Ldloc(obj); //TODO: we need to insert the inline cache here VisitNode(node.Index); var indexType = _result.ValueType; PerformLookup(node, obj, objType, indexType, value); _localVars.PopTemporariesAfter(stackState); _ilGen.Ldloca(value); _result.ValueType = mdr.ValueTypes.DValueRef; PopLocation(); }
public override void Visit(ReadIndexerExpression node) { Visit((Indexer)node); }
public override void Visit(ReadIndexerExpression node) { base.Visit(node); node.ValueType = GetType(node); }
internal static mdr.ValueTypes GetType(ReadIndexerExpression expression) { return mdr.ValueTypes.DValueRef; }
public override void Visit(ReadIndexerExpression node) { /*var nodeProfile = _currProfiler.GetNodeProfile(node); if (_currFuncMetadata.EnableInlineCache && nodeProfile != null && nodeProfile.Map != null && nodeProfile.PD == JSRuntime.Instance.GetArrayItemAccessor()) { PushLocation(node); var value = _localVars.PushTemporary(Types.DValue.TypeOf); var stackState = _localVars.GetTemporaryStackState(); VisitNode(node.Container); AsDObject(); var objType = _result.ValueType; var obj = _localVars.PushTemporary(objType); _ilGen.Stloc(obj); _ilGen.Ldloc(obj); //TODO: we need to insert the inline cache here VisitNode(node.Index); var indexType = _result.ValueType; if (indexType != mdr.ValueTypes.Int32) { AsInt32(); } PerformLookup(node, obj, mdr.ValueTypes.Array, mdr.ValueTypes.Int32, value); _localVars.PopTemporariesAfter(stackState); _ilGen.Ldloca(value); _result.ValueType = mdr.ValueTypes.DValueRef; PopLocation(); } else*/ base.Visit(node); }
public override void Visit(ReadIndexerExpression node) { PushLocation(node); VisitNode(node.Container); VisitNode(node.Index); _stackModel.Pop(2); BeginICMethod(node); _ilGen.Ldarg_CallFrame(); _ilGen.Ldc_I4(_stackModel.StackPointer); _ilGen.Call(Types.Operations.ICMethods.ReadIndexer); EndICMethod(); _stackModel.Push(1); PopLocation(); }
private ReadIndexerExpression MakeReadIndexerExpression(Expression container, Expression index) { StringLiteral constIndex = index as StringLiteral; int integerIndex; ReadIndexerExpression n; //We need to make sure that the string is not an integer, because in the case of Arrays integer strings are equivalent to integers!! if (constIndex != null && !int.TryParse(constIndex.Value, out integerIndex)) n = new ReadPropertyExpression(MakeToObject((Expression)container), constIndex); else n = new ReadIndexerExpression(MakeToObject((Expression)container), (Expression)index); return n; }
public abstract void Visit(ReadIndexerExpression node);
public override void Visit(ReadIndexerExpression node) { PushLocation(node); //TODO: how should we add typed array acces to this? // If we know the actual type is DArray with some type data, we can potentially use that. But that should be done at run time // So, we should generate code to do that. Or is it more complicated than that? ///Any read or write in this situation must consider that the results might a Prototype, and so getter/setter should be called as well ///In the case of Usages.ReadWrite: ///We should execute the read side then the write side. If object itself does not have field, it will ///use its prototype chain for read. If we do the reverse order, the field is first added to the object. ///Also, /// if the object does have the field, the result ref for read and write will be point to two different objects /// if the object has the filed, both refs will point to the same thing. So, we should be ok in terms of dangling refs ///Note: ////GetField... does not have any side effects, so we don't need to call it! ///SetField... or GetOrAddField... may have side effects, so we should call it as well no matter what, but if we are in Write or ReadWrite mode, the User cannot be null VisitNode(node.Container); VisitNode(node.Index); // TODO: Commented since canPopOperand is unused. /*var canPopOperand = true;// !expression.UserIsFunction;*/ var popOperandCount = 2;// expression.UserIsFunction ? 1 : 2; //remove index, but leave object for This if user is function _ilGen.Ldc_I4(popOperandCount); Call(Types.Operations.Stack.LoadField, popOperandCount, 1); PopLocation(); }
internal void PopLocation(ReadIndexerExpression node, mdr.DObject obj, mdr.PropertyDescriptor pd) { if (_currProfiler != null) { if (mdr.Runtime.Instance.Configuration.ProfileStats) { mdr.Runtime.Instance.Counters.GetCounter("Prop lookup").Count++; if (pd.IsDataDescriptor && !pd.IsInherited) { mdr.Runtime.Instance.Counters.GetCounter("Prop lookup owndata").Count++; } if (pd.IsDataDescriptor && pd.IsInherited) { mdr.Runtime.Instance.Counters.GetCounter("Prop lookup inherited").Count++; } MapNodeProfile mapProfile = _currProfiler.GetOrAddNodeProfile(node); if (mapProfile != null) { if (mapProfile.Map == obj.Map) { mdr.Runtime.Instance.Counters.GetCounter("Prop lookup map hit").Count++; if (mapProfile.PD == pd) { mdr.Runtime.Instance.Counters.GetCounter("Prop lookup map/pd hit").Count++; if (pd.HasAttributes(mdr.PropertyDescriptor.Attributes.Data) && !pd.HasAttributes(mdr.PropertyDescriptor.Attributes.Inherited)) { mdr.Runtime.Instance.Counters.GetCounter("Prop lookup map/pd owndata hit").Count++; } if (pd.HasAttributes(mdr.PropertyDescriptor.Attributes.Inherited)) { mdr.Runtime.Instance.Counters.GetCounter("Prop lookup map/pd inherited hit").Count++; } } } } } _currProfiler.GetOrAddNodeProfile(node).UpdateNodeProfile(obj.Map, pd); //NodeProfile nProfile = _currProfiler.GetNodeProfile(node); //if (nProfile != null) //{ // (nProfile as MapNodeProfile).UpdateNodeProfile(obj.Map, pd); //} //else //{ // _currProfiler.CreateNewProfile(node, obj.Map, pd); //} } }
public override void Visit(ReadIndexerExpression node) { throw new NotImplementedException(); }
public override void Visit(ReadIndexerExpression node) { AssignToImplicitReturn(node); }