public void lower(ArrayCopyUnrollNode arraycopy, LoweringTool tool) {
   StructuredGraph graph = arraycopy.graph();
   if (!graph.getGuardsStage().areFrameStatesAtDeopts()) {
     // Can't be lowered yet
     return;
   }
   SnippetInfo snippetInfo = arraycopyUnrolledWorkSnippet;
   Arguments args = new Arguments(snippetInfo, graph.getGuardsStage(), tool.getLoweringStage());
   args.add("nonNullSrc", arraycopy.getSource());
   args.add("srcPos", arraycopy.getSourcePosition());
   args.add("nonNullDest", arraycopy.getDestination());
   args.add("destPos", arraycopy.getDestinationPosition());
   args.addConst("length", arraycopy.getUnrollLength());
   args.addConst("elementKind", arraycopy.getElementKind());
   template(args)
       .instantiate(
           providers.getMetaAccess(), arraycopy, SnippetTemplate.DEFAULT_REPLACER, args);
 }
 public void lower(ArrayCopySlowPathNode arraycopy, LoweringTool tool) {
   StructuredGraph graph = arraycopy.graph();
   if (!graph.getGuardsStage().areFrameStatesAtDeopts()) {
     // Can't be lowered yet
     return;
   }
   SnippetInfo snippetInfo = arraycopy.getSnippet();
   Arguments args = new Arguments(snippetInfo, graph.getGuardsStage(), tool.getLoweringStage());
   args.add("nonNullSrc", arraycopy.getSource());
   args.add("srcPos", arraycopy.getSourcePosition());
   args.add("nonNullDest", arraycopy.getDestination());
   args.add("destPos", arraycopy.getDestinationPosition());
   if (snippetInfo == arraycopyUnrolledWorkSnippet) {
     args.addConst("length", ((Integer) arraycopy.getArgument()).intValue());
     args.addConst("elementKind", arraycopy.getElementKind());
   } else {
     args.add("length", arraycopy.getLength());
   }
   if (snippetInfo == arraycopyPredictedObjectWorkSnippet) {
     HotSpotResolvedObjectType arrayKlass =
         (HotSpotResolvedObjectType) tool.getMetaAccess().lookupJavaType(Object[].class);
     ValueNode objectArrayKlass =
         ConstantNode.forConstant(
             KlassPointerStamp.klassNonNull(),
             arrayKlass.klass(),
             tool.getMetaAccess(),
             arraycopy.graph());
     args.add("objectArrayKlass", objectArrayKlass);
     args.addConst("counter", arraycopyCallCounters.get(JavaKind.Object));
     args.addConst("copiedCounter", arraycopyCallCopiedCounters.get(JavaKind.Object));
   }
   instantiate(args, arraycopy);
 }
    public void lower(ArrayCopyNode arraycopy, LoweringTool tool) {
      JavaKind componentKind = selectComponentKind(arraycopy);
      SnippetInfo snippetInfo = null;
      SnippetInfo slowPathSnippetInfo = null;
      Object slowPathArgument = null;

      if (arraycopy.getLength().isConstant()
          && arraycopy.getLength().asJavaConstant().asLong() == 0) {
        snippetInfo = arraycopyZeroLengthIntrinsicSnippet;
      } else if (arraycopy.isExact()) {
        snippetInfo = arraycopyExactIntrinsicSnippet;
        if (shouldUnroll(arraycopy.getLength())) {
          snippetInfo = arraycopyUnrolledIntrinsicSnippet;
        }
      } else {
        if (componentKind == JavaKind.Object) {
          ResolvedJavaType srcType = StampTool.typeOrNull(arraycopy.getSource().stamp());
          ResolvedJavaType destType = StampTool.typeOrNull(arraycopy.getDestination().stamp());
          ResolvedJavaType srcComponentType = srcType == null ? null : srcType.getComponentType();
          ResolvedJavaType destComponentType =
              destType == null ? null : destType.getComponentType();
          if (srcComponentType != null
              && destComponentType != null
              && !srcComponentType.isPrimitive()
              && !destComponentType.isPrimitive()) {
            snippetInfo = arraycopySlowPathIntrinsicSnippet;
            slowPathSnippetInfo = checkcastArraycopyWorkSnippet;
            slowPathArgument = LocationIdentity.any();
            /*
             * Because this snippet has to use Sysytem.arraycopy as a slow path, we must
             * pretend to kill any() so clear the componentKind.
             */
            componentKind = null;
          }
        }
        if (componentKind == null && snippetInfo == null) {
          JavaKind predictedKind = selectComponentKind(arraycopy, false);
          if (predictedKind != null) {
            /*
             * At least one array is of a known type requiring no store checks, so
             * assume the other is of the same type. Generally this is working around
             * deficiencies in our propagation of type information.
             */
            componentKind = predictedKind;
            if (predictedKind == JavaKind.Object) {
              snippetInfo = arraycopySlowPathIntrinsicSnippet;
              slowPathSnippetInfo = arraycopyPredictedObjectWorkSnippet;
              slowPathArgument = predictedKind;
              componentKind = null;
            } else {
              snippetInfo = arraycopyPredictedExactIntrinsicSnippet;
            }
          }
        }
        if (snippetInfo == null) {
          snippetInfo = arraycopyGenericSnippet;
        }
      }
      Arguments args =
          new Arguments(snippetInfo, arraycopy.graph().getGuardsStage(), tool.getLoweringStage());
      args.add("src", arraycopy.getSource());
      args.add("srcPos", arraycopy.getSourcePosition());
      args.add("dest", arraycopy.getDestination());
      args.add("destPos", arraycopy.getDestinationPosition());
      args.add("length", arraycopy.getLength());
      if (snippetInfo == arraycopyUnrolledIntrinsicSnippet) {
        args.addConst("unrolledLength", arraycopy.getLength().asJavaConstant().asInt());
        args.addConst("elementKind", componentKind != null ? componentKind : JavaKind.Illegal);
      } else if (snippetInfo == arraycopySlowPathIntrinsicSnippet) {
        args.addConst("elementKind", componentKind != null ? componentKind : JavaKind.Illegal);
        args.addConst("slowPath", slowPathSnippetInfo);
        assert slowPathArgument != null;
        args.addConst("slowPathArgument", slowPathArgument);
      } else if (snippetInfo == arraycopyExactIntrinsicSnippet
          || snippetInfo == arraycopyPredictedExactIntrinsicSnippet) {
        assert componentKind != null;
        args.addConst("elementKind", componentKind);
        args.addConst("counter", arraycopyCallCounters.get(componentKind));
        args.addConst("copiedCounter", arraycopyCallCopiedCounters.get(componentKind));
      }
      instantiate(args, arraycopy);
    }