protected bool IsCopyAlwaysUnnecessaryForAssignmentTarget(JSExpression target) { target = JSReferenceExpression.Strip(target); var targetDot = target as JSDotExpressionBase; // The assignment is performing a write into an element proxy, so a copy is unnecessary // because the element proxy immediately unpacks the value into the array. if ((targetDot != null) && PackedArrayUtil.IsElementProxy(targetDot.Target)) { return(true); } return(false); }
public void VisitNode(JSNewBoxedVariable nbv) { GenericParameter relevantParameter; var initialValue = nbv.InitialValue; var initialValueDerefed = initialValue; initialValueDerefed = JSReferenceExpression.Strip(initialValueDerefed); var initialValueType = initialValueDerefed.GetActualType(TypeSystem); if (!nbv.SuppressClone && IsCopyNeeded(nbv.InitialValue, out relevantParameter) && // We don't need to make a copy if the source value is a reference (like T& this) !((initialValueType) != null && initialValueType.IsByReference) ) { nbv.ReplaceChild(nbv.InitialValue, new JSStructCopyExpression(nbv.InitialValue)); } VisitChildren(nbv); }
protected bool IsCopyNeededForAssignmentTarget(JSExpression target) { target = JSReferenceExpression.Strip(target); if (!OptimizeCopies) { return(true); } if (IsImmutable(target)) { return(false); } var variable = target as JSVariable; if (variable != null) { return(SecondPass.IsVariableModified(variable.Name)); } return(true); }
protected bool IsImmutable(JSExpression target) { target = JSReferenceExpression.Strip(target); var fieldAccess = target as JSFieldAccess; if (fieldAccess != null) { return(fieldAccess.Field.Field.Metadata.HasAttribute("JSIL.Meta.JSImmutable")); } var dot = target as JSDotExpressionBase; if (dot != null) { if (IsImmutable(dot.Target)) { return(true); } else if (IsImmutable(dot.Member)) { return(true); } } var indexer = target as JSIndexerExpression; if (indexer != null) { if (IsImmutable(indexer.Target)) { return(true); } } return(false); }
protected bool IsCopyNeeded( JSExpression value, out GenericParameter relevantParameter, bool allowImmutabilityOptimizations = true ) { relevantParameter = null; if ((value == null) || (value.IsNull)) { return(false); } value = JSReferenceExpression.Strip(value); var sce = value as JSStructCopyExpression; if (sce != null) { return(false); } var valueType = value.GetActualType(TypeSystem); var valueTypeDerefed = TypeUtil.DereferenceType(valueType) ?? valueType; var cte = value as JSChangeTypeExpression; var cast = value as JSCastExpression; TypeReference originalType; int temp; if (cte != null) { originalType = cte.Expression.GetActualType(TypeSystem); } else if (cast != null) { originalType = cast.Expression.GetActualType(TypeSystem); } else { originalType = null; } if (originalType != null) { originalType = TypeUtil.FullyDereferenceType(originalType, out temp); if (!IsStructOrGenericParameter(valueTypeDerefed) && !IsStructOrGenericParameter(originalType)) { return(false); } relevantParameter = (originalType as GenericParameter) ?? (valueTypeDerefed as GenericParameter); } else { if (!IsStructOrGenericParameter(valueTypeDerefed)) { return(false); } relevantParameter = (valueTypeDerefed as GenericParameter); } if (value is JSValueOfNullableExpression) { return(true); } if (IsTypeExcludedFromCopies(valueType)) { return(false); } if ( (value is JSLiteral) || (value is JSNewExpression) || (value is JSPassByReferenceExpression) || (value is JSNewBoxedVariable) || (value is JSDefaultValueLiteral) || (value is JSFieldOfExpression) ) { return(false); } if (!OptimizeCopies) { return(true); } if (IsImmutable(value) && allowImmutabilityOptimizations) { return(false); } var valueDot = value as JSDotExpressionBase; // The value is being read out of an element proxy, so no copy is necessary - the read unpacks the value // on demand from the packed array. if ( (valueDot != null) && PackedArrayUtil.IsElementProxy(valueDot.Target) ) { // return false; } var valueTypeInfo = TypeInfo.GetExisting(valueType); if ((valueTypeInfo != null) && valueTypeInfo.IsImmutable && allowImmutabilityOptimizations) { return(false); } // If the expression is a parameter that is only used once and isn't aliased, // we don't need to copy it. var rightVar = value as JSVariable; if (rightVar != null) { int referenceCount; if ( ReferenceCounts.TryGetValue(rightVar.Identifier, out referenceCount) && (referenceCount == 1) && !rightVar.IsReference && rightVar.IsParameter && !SecondPass.VariableAliases.ContainsKey(rightVar.Identifier) ) { if (TraceElidedCopies) { Console.WriteLine(String.Format("Returning false from IsCopyNeeded for parameter {0} because reference count is 1 and it has no aliases", value)); } return(false); } } return(true); }