@Override public long getMemorySize(Constant constant) { if (constant.getKind() == Kind.Object) { HotSpotResolvedObjectType lookupJavaType = (HotSpotResolvedObjectType) this.lookupJavaType(constant); if (lookupJavaType == null) { return 0; } else { if (lookupJavaType.isArray()) { // TODO(tw): Add compressed pointer support. int length = Array.getLength(HotSpotObjectConstant.asObject(constant)); ResolvedJavaType elementType = lookupJavaType.getComponentType(); Kind elementKind = elementType.getKind(); final int headerSize = HotSpotGraalRuntime.getArrayBaseOffset(elementKind); int sizeOfElement = HotSpotGraalRuntime.runtime().getTarget().getSizeInBytes(elementKind); int alignment = HotSpotGraalRuntime.runtime().getTarget().wordSize; int log2ElementSize = CodeUtil.log2(sizeOfElement); return NewObjectSnippets.computeArrayAllocationSize( length, alignment, headerSize, log2ElementSize); } return lookupJavaType.instanceSize(); } } else { return constant.getKind().getByteCount(); } }
/** * For one or more `invoke` arguments, flow-sensitive information may suggest their narrowing or * simplification. In those cases, a new {@link com.oracle.graal.nodes.java.MethodCallTargetNode * MethodCallTargetNode} is prepared just for this callsite, consuming reduced arguments. * * <p>Specializing the {@link com.oracle.graal.nodes.java.MethodCallTargetNode * MethodCallTargetNode} as described above may enable two optimizations: * * <ul> * <li>devirtualization of an {@link com.oracle.graal.nodes.CallTargetNode.InvokeKind#Interface} * or {@link com.oracle.graal.nodes.CallTargetNode.InvokeKind#Virtual} callsite * (devirtualization made possible after narrowing the type of the receiver) * <li>(future work) actual-argument-aware inlining, ie, to specialize callees on the types of * arguments other than the receiver (examples: multi-methods, the inlining problem, lambdas * as arguments). * </ul> * * <p>Precondition: inputs haven't been deverbosified yet. */ private void visitInvoke(Invoke invoke) { if (invoke.asNode().stamp() instanceof IllegalStamp) { return; // just to be safe } boolean isMethodCallTarget = invoke.callTarget() instanceof MethodCallTargetNode; if (!isMethodCallTarget) { return; } FlowUtil.replaceInPlace( invoke.asNode(), invoke.callTarget(), deverbosifyInputsCopyOnWrite((MethodCallTargetNode) invoke.callTarget())); MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget(); if (callTarget.invokeKind() != CallTargetNode.InvokeKind.Interface && callTarget.invokeKind() != CallTargetNode.InvokeKind.Virtual) { return; } ValueNode receiver = callTarget.receiver(); if (receiver == null) { return; } if (!FlowUtil.hasLegalObjectStamp(receiver)) { return; } Witness w = state.typeInfo(receiver); ResolvedJavaType type; ResolvedJavaType stampType = StampTool.typeOrNull(receiver); if (w == null || w.cluelessAboutType()) { // can't improve on stamp but wil try to devirtualize anyway type = stampType; } else { type = FlowUtil.tighten(w.type(), stampType); } if (type == null) { return; } ResolvedJavaMethod method = type.resolveMethod(callTarget.targetMethod(), invoke.getContextType()); if (method == null) { return; } if (method.canBeStaticallyBound() || Modifier.isFinal(type.getModifiers())) { metricMethodResolved.increment(); callTarget.setInvokeKind(CallTargetNode.InvokeKind.Special); callTarget.setTargetMethod(method); } }