/*
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.max.vm.reference.hosted;
import static com.sun.max.vm.VMConfiguration.*;
import java.lang.reflect.*;
import com.sun.max.*;
import com.sun.max.program.*;
import com.sun.max.unsafe.*;
import com.sun.max.vm.actor.holder.*;
import com.sun.max.vm.actor.member.*;
import com.sun.max.vm.layout.SpecificLayout.ObjectMirror;
import com.sun.max.vm.object.*;
import com.sun.max.vm.type.*;
import com.sun.max.vm.value.*;
/**
*/
public class HostedObjectMirror implements ObjectMirror {
private final Object object;
private final ClassActor classActor;
public HostedObjectMirror(final Object object) {
this.object = object;
classActor = ClassActor.fromJava(object.getClass());
}
public boolean isArray() {
return classActor.isArrayClass();
}
public ClassActor classActor() {
return classActor;
}
public Value readHub() {
return ReferenceValue.from(classActor.dynamicHub());
}
public Value readElement(Kind kind, int index) {
if (object instanceof Hybrid) {
final Hybrid hybrid = (Hybrid) object;
switch (kind.asEnum) {
case INT:
return IntValue.from(hybrid.getInt(index));
case WORD:
return new WordValue(hybrid.getWord(index));
default:
throw ProgramError.unknownCase();
}
}
final Object javaValue = Array.get(object, index);
final ArrayClassActor arrayClassActor = (ArrayClassActor) classActor;
ProgramError.check(arrayClassActor.componentClassActor().kind.stackKind == kind.stackKind);
return arrayClassActor.componentClassActor().kind.asValue(javaValue);
}
public Value readField(int offset) {
final FieldActor fieldActor = classActor.findInstanceFieldActor(offset);
final Field field = fieldActor.toJava();
field.setAccessible(true);
try {
return fieldActor.kind.asValue(field.get(object));
} catch (Throwable throwable) {
throw ProgramError.unexpected("could not read field: " + field, throwable);
}
}
public Value readMisc() {
return new WordValue(vmConfig().monitorScheme().createMisc(object));
}
public int readArrayLength() {
return ArrayAccess.readArrayLength(object);
}
public void writeArrayLength(Value value) {
assert value.asInt() == ArrayAccess.readArrayLength(object);
}
public void writeHub(Value value) {
assert value == ReferenceValue.from(classActor);
}
public void writeElement(Kind kind, int index, Value value) {
if (object instanceof Hybrid) {
final Hybrid hybrid = (Hybrid) object;
switch (kind.asEnum) {
case INT:
hybrid.setInt(index, value.asInt());
break;
case WORD:
hybrid.setWord(index, value.asWord());
break;
default:
throw ProgramError.unknownCase();
}
} else {
final ArrayClassActor arrayClassActor = (ArrayClassActor) classActor;
final ClassActor componentClassActor = arrayClassActor.componentClassActor();
if (componentClassActor.kind.stackKind != kind.stackKind) {
throw new ArrayStoreException("cannot store a '" + kind + "' into an array of '" + componentClassActor.kind + "'");
}
if (object instanceof Object[]) {
final Object[] objectArray = (Object[]) object;
objectArray[index] = value.asObject();
} else {
final Object javaBoxedValue = componentClassActor.kind.convert(value).asBoxedJavaValue();
Array.set(object, index, javaBoxedValue);
}
}
}
public void writeField(int offset, Value value) {
final TupleClassActor tupleClassActor = (TupleClassActor) classActor;
final FieldActor fieldActor = tupleClassActor.findInstanceFieldActor(offset);
final Field field = fieldActor.toJava();
field.setAccessible(true);
final TypeDescriptor fieldDescriptor = fieldActor.descriptor();
try {
if (fieldDescriptor.toKind().isWord) {
final Class<Class<? extends Word>> type = null;
final Word word = value.toWord().as(Utils.cast(type, field.getType()));
field.set(object, word);
} else {
field.set(object, fieldActor.kind.convert(value).asBoxedJavaValue());
}
} catch (IllegalArgumentException e) {
throw ProgramError.unexpected(e);
} catch (IllegalAccessException e) {
throw ProgramError.unexpected(e);
}
}
public void writeMisc(Value value) {
assert value.asWord().equals(vmConfig().monitorScheme().createMisc(object));
}
public int firstWordIndex() {
if (classActor.isHybridClass()) {
final Hybrid hybrid = (Hybrid) object;
return hybrid.firstWordIndex();
}
return Integer.MAX_VALUE;
}
public int firstIntIndex() {
if (classActor.isHybridClass()) {
final Hybrid hybrid = (Hybrid) object;
return hybrid.firstIntIndex();
}
return Integer.MAX_VALUE;
}
}