001/* 002 * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.hotspot.stubs; 024 025import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; 026import static com.oracle.graal.hotspot.replacements.NewObjectSnippets.*; 027import static com.oracle.graal.hotspot.stubs.NewInstanceStub.*; 028import static com.oracle.graal.hotspot.stubs.StubUtil.*; 029import static jdk.internal.jvmci.hotspot.HotSpotMetaAccessProvider.*; 030import jdk.internal.jvmci.code.*; 031import jdk.internal.jvmci.hotspot.*; 032import com.oracle.graal.api.replacements.*; 033import com.oracle.graal.compiler.common.spi.*; 034import com.oracle.graal.graph.Node.ConstantNodeParameter; 035import com.oracle.graal.graph.Node.NodeIntrinsic; 036import com.oracle.graal.hotspot.*; 037import com.oracle.graal.hotspot.meta.*; 038import com.oracle.graal.hotspot.nodes.*; 039import com.oracle.graal.hotspot.replacements.*; 040import com.oracle.graal.hotspot.word.*; 041import com.oracle.graal.nodes.*; 042import com.oracle.graal.replacements.*; 043import com.oracle.graal.replacements.Snippet.ConstantParameter; 044import com.oracle.graal.word.*; 045 046/** 047 * Stub implementing the fast path for TLAB refill during instance class allocation. This stub is 048 * called from the {@linkplain NewObjectSnippets inline} allocation code when TLAB allocation fails. 049 * If this stub fails to refill the TLAB or allocate the object, it calls out to the HotSpot C++ 050 * runtime to complete the allocation. 051 */ 052public class NewArrayStub extends SnippetStub { 053 054 public NewArrayStub(HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { 055 super("newArray", providers, linkage); 056 } 057 058 @Override 059 protected Object[] makeConstArgs() { 060 HotSpotResolvedObjectType intArrayType = (HotSpotResolvedObjectType) providers.getMetaAccess().lookupJavaType(int[].class); 061 int count = method.getSignature().getParameterCount(false); 062 Object[] args = new Object[count]; 063 assert checkConstArg(2, "intArrayHub"); 064 assert checkConstArg(3, "threadRegister"); 065 args[2] = ConstantNode.forConstant(providers.getStampProvider().createHubStamp(true), intArrayType.klass(), null); 066 args[3] = providers.getRegisters().getThreadRegister(); 067 return args; 068 } 069 070 @Fold 071 private static boolean logging() { 072 return Boolean.getBoolean("graal.logNewArrayStub"); 073 } 074 075 /** 076 * Re-attempts allocation after an initial TLAB allocation failed or was skipped (e.g., due to 077 * -XX:-UseTLAB). 078 * 079 * @param hub the hub of the object to be allocated 080 * @param length the length of the array 081 * @param intArrayHub the hub for {@code int[].class} 082 */ 083 @Snippet 084 private static Object newArray(KlassPointer hub, int length, @ConstantParameter KlassPointer intArrayHub, @ConstantParameter Register threadRegister) { 085 int layoutHelper = loadKlassLayoutHelperIntrinsic(hub); 086 int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift()) & layoutHelperLog2ElementSizeMask(); 087 int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift()) & layoutHelperHeaderSizeMask(); 088 int elementKind = (layoutHelper >> layoutHelperElementTypeShift()) & layoutHelperElementTypeMask(); 089 int sizeInBytes = computeArrayAllocationSize(length, wordSize(), headerSize, log2ElementSize); 090 if (logging()) { 091 printf("newArray: element kind %d\n", elementKind); 092 printf("newArray: array length %d\n", length); 093 printf("newArray: array size %d\n", sizeInBytes); 094 printf("newArray: hub=%p\n", hub.asWord().rawValue()); 095 } 096 097 // check that array length is small enough for fast path. 098 Word thread = registerAsWord(threadRegister); 099 if (length >= 0 && length <= MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH) { 100 Word memory = refillAllocate(thread, intArrayHub, sizeInBytes, logging()); 101 if (memory.notEqual(0)) { 102 if (logging()) { 103 printf("newArray: allocated new array at %p\n", memory.rawValue()); 104 } 105 return verifyObject(formatArray(hub, sizeInBytes, length, headerSize, memory, Word.unsigned(arrayPrototypeMarkWord()), true, false, false)); 106 } 107 } 108 if (logging()) { 109 printf("newArray: calling new_array_c\n"); 110 } 111 112 newArrayC(NEW_ARRAY_C, thread, hub, length); 113 handlePendingException(thread, true); 114 return verifyObject(getAndClearObjectResult(thread)); 115 } 116 117 public static final ForeignCallDescriptor NEW_ARRAY_C = newDescriptor(NewArrayStub.class, "newArrayC", void.class, Word.class, KlassPointer.class, int.class); 118 119 @NodeIntrinsic(StubForeignCallNode.class) 120 public static native void newArrayC(@ConstantNodeParameter ForeignCallDescriptor newArrayC, Word thread, KlassPointer hub, int length); 121}