001/*
002 * Copyright (c) 2009, 2015, 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;
024
025import static jdk.internal.jvmci.code.ValueUtil.*;
026
027import java.util.*;
028
029import com.oracle.graal.lir.*;
030import com.oracle.graal.lir.framemap.*;
031
032import jdk.internal.jvmci.code.*;
033import jdk.internal.jvmci.common.*;
034import jdk.internal.jvmci.hotspot.*;
035import jdk.internal.jvmci.meta.*;
036
037public final class HotSpotReferenceMapBuilder extends ReferenceMapBuilder {
038
039    private int maxRegisterSize;
040
041    private final ArrayList<Value> objectValues;
042    private int objectCount;
043
044    private final TargetDescription target;
045    private final int totalFrameSize;
046
047    public HotSpotReferenceMapBuilder(TargetDescription target, int totalFrameSize) {
048        this.objectValues = new ArrayList<>();
049        this.objectCount = 0;
050
051        this.target = target;
052        this.totalFrameSize = totalFrameSize;
053    }
054
055    @Override
056    public void addLiveValue(Value v) {
057        if (isConstant(v)) {
058            return;
059        }
060        LIRKind lirKind = v.getLIRKind();
061        if (!lirKind.isValue()) {
062            objectValues.add(v);
063            if (lirKind.isUnknownReference()) {
064                objectCount++;
065            } else {
066                objectCount += lirKind.getReferenceCount();
067            }
068        }
069        if (isRegister(v)) {
070            int size = target.getSizeInBytes(lirKind.getPlatformKind());
071            if (size > maxRegisterSize) {
072                maxRegisterSize = size;
073            }
074        }
075    }
076
077    @Override
078    public ReferenceMap finish(LIRFrameState state) {
079        Location[] objects = new Location[objectCount];
080        Location[] derivedBase = new Location[objectCount];
081        int[] sizeInBytes = new int[objectCount];
082
083        int idx = 0;
084        for (Value obj : objectValues) {
085            LIRKind kind = obj.getLIRKind();
086            int bytes = bytesPerElement(kind);
087            if (kind.isUnknownReference()) {
088                throw JVMCIError.unimplemented("derived references not yet implemented");
089            } else {
090                Location base = null;
091                if (kind.isDerivedReference()) {
092                    Variable baseVariable = (Variable) kind.getDerivedReferenceBase();
093                    Value baseValue = state.getLiveBasePointers().get(baseVariable.index);
094                    assert baseValue.getPlatformKind().getVectorLength() == 1 && baseValue.getLIRKind().isReference(0) && !baseValue.getLIRKind().isDerivedReference();
095                    base = toLocation(baseValue, 0);
096                }
097
098                for (int i = 0; i < kind.getPlatformKind().getVectorLength(); i++) {
099                    if (kind.isReference(i)) {
100                        objects[idx] = toLocation(obj, i * bytes);
101                        derivedBase[idx] = base;
102                        sizeInBytes[idx] = bytes;
103                        idx++;
104                    }
105                }
106            }
107        }
108
109        return new HotSpotReferenceMap(objects, derivedBase, sizeInBytes, maxRegisterSize);
110    }
111
112    private int bytesPerElement(LIRKind kind) {
113        PlatformKind platformKind = kind.getPlatformKind();
114        return target.getSizeInBytes(platformKind) / platformKind.getVectorLength();
115    }
116
117    private Location toLocation(Value v, int offset) {
118        if (isRegister(v)) {
119            return Location.subregister(asRegister(v), offset);
120        } else {
121            StackSlot s = asStackSlot(v);
122            return Location.stack(s.getOffset(totalFrameSize) + offset);
123        }
124    }
125}