# HG changeset patch # User Doug Simon # Date 1353448167 -3600 # Node ID eec373d34caf7377fc47805fb1a68c512e697f17 # Parent edb2d7ed9a01b65610fa7bcdbd480c56912aecbd added support for annotated Constants and used it to track Klass* values in Graal and register them in the metadata section of a nmethod during code installation diff -r edb2d7ed9a01 -r eec373d34caf graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java Tue Nov 20 22:35:20 2012 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java Tue Nov 20 22:49:27 2012 +0100 @@ -22,6 +22,7 @@ */ package com.oracle.graal.api.code; +import com.oracle.graal.api.code.CompilationResult.DataPatch; import com.oracle.graal.api.code.RuntimeCall.Descriptor; import com.oracle.graal.api.meta.*; @@ -93,4 +94,11 @@ * @return the encoded value as an integer */ int encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason); + + /** + * Determines if a {@link DataPatch} should be created for a given {@linkplain Constant#getPrimitiveAnnotation() annotated} + * primitive constant that part of a {@link CompilationResult}. A data patch is always + * created for an object constant. + */ + boolean needsDataPatch(Constant constant); } diff -r edb2d7ed9a01 -r eec373d34caf graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java Tue Nov 20 22:35:20 2012 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java Tue Nov 20 22:49:27 2012 +0100 @@ -136,10 +136,16 @@ public final Constant constant; public final int alignment; - DataPatch(int pcOffset, Constant data, int alignment) { + /** + * Determines if the data is encoded inline or is loaded from a separate data area. + */ + public final boolean inlined; + + DataPatch(int pcOffset, Constant data, int alignment, boolean inlined) { super(pcOffset); this.constant = data; this.alignment = alignment; + this.inlined = inlined; } @Override @@ -387,10 +393,11 @@ * @param codePos the position in the code where the data reference occurs * @param data the data that is referenced * @param alignment the alignment requirement of the data or 0 if there is no alignment requirement + * @param inlined specifies if the data is encoded inline or is loaded from a separate data area */ - public void recordDataReference(int codePos, Constant data, int alignment) { + public void recordDataReference(int codePos, Constant data, int alignment, boolean inlined) { assert codePos >= 0 && data != null; - getDataReferences().add(new DataPatch(codePos, data, alignment)); + getDataReferences().add(new DataPatch(codePos, data, alignment, inlined)); } /** diff -r edb2d7ed9a01 -r eec373d34caf graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java Tue Nov 20 22:35:20 2012 +0100 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java Tue Nov 20 22:49:27 2012 +0100 @@ -63,7 +63,8 @@ } /** - * The boxed object value. This is ignored iff {@code !kind.isObject()}. + * The boxed object value if {@code !kind.isObject()} otherwise the (possibly null) + * {@link #getPrimitiveAnnotation() annotation} for a primitive value. */ private final Object object; @@ -75,7 +76,7 @@ private final long primitive; /** - * Create a new constant represented by the specified object reference. + * Creates a constant represented by the specified object reference. * @param object the value of this constant */ private Constant(Object object) { @@ -85,18 +86,36 @@ } /** - * Create a new constant represented by the specified primitive. + * Creates a constant represented by the specified primitive. * * @param kind the type of this constant * @param primitive the value of this constant */ public Constant(Kind kind, long primitive) { super(kind); + assert !kind.isObject(); this.object = null; this.primitive = primitive; } /** + * Creates an annotated primitive constant. An annotation enables a {@linkplain MetaAccessProvider provider} to + * associate some extra semantic or debugging information with a primitive. An annotated primitive constant + * is never {@linkplain #equals(Object) equal} to a non-annotated constant. + * + * @param kind the type of this constant + * @param primitive the value of this constant + * @param annotation an arbitrary non-null object + */ + public Constant(Kind kind, long primitive, Object annotation) { + super(kind); + assert !kind.isObject(); + assert annotation != null; + this.object = annotation; + this.primitive = primitive; + } + + /** * Checks whether this constant is non-null. * * @return {@code true} if this constant is a primitive, or an object constant that is not null @@ -125,7 +144,11 @@ @Override public String toString() { - return getKind().getJavaName() + "[" + getKind().format(asBoxedValue()) + (getKind() != Kind.Object ? "|0x" + Long.toHexString(primitive) : "") + "]"; + String annotationSuffix = ""; + if (!getKind().isObject() && getPrimitiveAnnotation() != null) { + annotationSuffix = "{" + getPrimitiveAnnotation() + "}"; + } + return getKind().getJavaName() + "[" + getKind().format(asBoxedValue()) + (getKind() != Kind.Object ? "|0x" + Long.toHexString(primitive) : "") + "]" + annotationSuffix; } /** @@ -140,15 +163,15 @@ case Boolean: return asInt() == 0 ? Boolean.FALSE : Boolean.TRUE; case Short: - return (short) asInt(); + return (short) primitive; case Char: - return (char) asInt(); + return (char) primitive; case Jsr: return (int) primitive; case Int: - return asInt(); + return (int) primitive; case Long: - return asLong(); + return primitive; case Float: return asFloat(); case Double: @@ -167,7 +190,7 @@ if (getKind().isObject()) { return object == other.object; } - return primitive == other.primitive; + return primitive == other.primitive && getPrimitiveAnnotation() == other.getPrimitiveAnnotation(); } /** @@ -276,6 +299,15 @@ } /** + * Gets the annotation (if any) associated with this constant. + * + * @return null if this constant is not primitive or has no annotation + */ + public Object getPrimitiveAnnotation() { + return getKind().isObject() ? null : object; + } + + /** * Computes the hashcode of this constant. * * @return a suitable hashcode for this constant @@ -289,8 +321,8 @@ } /** - * Checks whether this constant equals another object. This is only true if the other object is a constant and has - * the same value. + * Checks whether this constant equals another object. This is only true if the other object is a constant that has + * the same {@linkplain #getKind() kind}, value and {@link #getPrimitiveAnnotation() annotation}. * * @param o the object to compare equality * @return {@code true} if this constant is equivalent to the specified object diff -r edb2d7ed9a01 -r eec373d34caf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaType.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaType.java Tue Nov 20 22:35:20 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaType.java Tue Nov 20 22:49:27 2012 +0100 @@ -403,8 +403,7 @@ @Override public Constant klass() { - Kind wordKind = HotSpotGraalRuntime.getInstance().getTarget().wordKind; - return wordKind.isLong() ? Constant.forLong(metaspaceKlass) : Constant.forInt((int) metaspaceKlass); + return new Constant(HotSpotGraalRuntime.getInstance().getTarget().wordKind, metaspaceKlass, this); } public boolean isPrimaryType() { @@ -419,12 +418,4 @@ public long prototypeMarkWord() { return HotSpotGraalRuntime.getInstance().getCompilerToVM().getPrototypeMarkWord(this); } - - public long address() { - return metaspaceKlass; - } - - public String symbol() { - return javaMirror.getName(); - } } diff -r edb2d7ed9a01 -r eec373d34caf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Tue Nov 20 22:35:20 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Tue Nov 20 22:49:27 2012 +0100 @@ -733,4 +733,8 @@ default: throw GraalInternalError.shouldNotReachHere(); } } + + public boolean needsDataPatch(Constant constant) { + return constant.getPrimitiveAnnotation() instanceof HotSpotResolvedJavaType; + } } diff -r edb2d7ed9a01 -r eec373d34caf graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java Tue Nov 20 22:35:20 2012 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java Tue Nov 20 22:49:27 2012 +0100 @@ -155,7 +155,12 @@ if (key.getKind() == Kind.Int) { Register intKey = asIntReg(key); for (int i = 0; i < keyConstants.length; i++) { - masm.cmpl(intKey, tasm.asIntConst(keyConstants[i])); + if (tasm.runtime.needsDataPatch(keyConstants[i])) { + tasm.recordDataReferenceInCode(keyConstants[i], 0, true); + } + long lc = keyConstants[i].asLong(); + assert NumUtil.isInt(lc); + masm.cmpl(intKey, (int) lc); masm.jcc(ConditionFlag.equal, keyTargets[i].label()); } } else if (key.getKind() == Kind.Long) { diff -r edb2d7ed9a01 -r eec373d34caf graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java Tue Nov 20 22:35:20 2012 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java Tue Nov 20 22:49:27 2012 +0100 @@ -296,12 +296,19 @@ switch (input.getKind().getStackKind()) { case Jsr: case Int: + if (tasm.runtime.needsDataPatch(input)) { + tasm.recordDataReferenceInCode(input, 0, true); + } // Do not optimize with an XOR as this instruction may be between // a CMP and a Jcc in which case the XOR will modify the condition // flags and interfere with the Jcc. - masm.movl(asRegister(result), tasm.asIntConst(input)); + masm.movl(asRegister(result), input.asInt()); + break; case Long: + if (tasm.runtime.needsDataPatch(input)) { + tasm.recordDataReferenceInCode(input, 0, true); + } // Do not optimize with an XOR as this instruction may be between // a CMP and a Jcc in which case the XOR will modify the condition // flags and interfere with the Jcc. @@ -310,6 +317,7 @@ case Float: // This is *not* the same as 'constant == 0.0f' in the case where constant is -0.0f if (Float.floatToRawIntBits(input.asFloat()) == Float.floatToRawIntBits(0.0f)) { + assert !tasm.runtime.needsDataPatch(input); masm.xorps(asFloatReg(result), asFloatReg(result)); } else { masm.movflt(asFloatReg(result), tasm.asFloatConstRef(input)); @@ -318,6 +326,7 @@ case Double: // This is *not* the same as 'constant == 0.0d' in the case where constant is -0.0d if (Double.doubleToRawLongBits(input.asDouble()) == Double.doubleToRawLongBits(0.0d)) { + assert !tasm.runtime.needsDataPatch(input); masm.xorpd(asDoubleReg(result), asDoubleReg(result)); } else { masm.movdbl(asDoubleReg(result), tasm.asDoubleConstRef(input)); @@ -330,10 +339,10 @@ if (input.isNull()) { masm.movq(asRegister(result), 0x0L); } else if (tasm.target.inlineObjects) { - tasm.recordDataReferenceInCode(input, 0); + tasm.recordDataReferenceInCode(input, 0, true); masm.movq(asRegister(result), 0xDEADDEADDEADDEADL); } else { - masm.movq(asRegister(result), tasm.recordDataReferenceInCode(input, 0)); + masm.movq(asRegister(result), tasm.recordDataReferenceInCode(input, 0, false)); } break; default: @@ -342,6 +351,7 @@ } private static void const2stack(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Value result, Constant input) { + assert !tasm.runtime.needsDataPatch(input); switch (input.getKind().getStackKind()) { case Jsr: case Int: masm.movl(tasm.asAddress(result), input.asInt()); break; diff -r edb2d7ed9a01 -r eec373d34caf graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java Tue Nov 20 22:35:20 2012 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java Tue Nov 20 22:49:27 2012 +0100 @@ -163,11 +163,11 @@ targetMethod.recordSafepoint(pos, debugInfo); } - public Address recordDataReferenceInCode(Constant data, int alignment) { + public Address recordDataReferenceInCode(Constant data, int alignment, boolean inlined) { assert data != null; int pos = asm.codeBuffer.position(); Debug.log("Data reference in code: pos = %d, data = %s", pos, data.toString()); - targetMethod.recordDataReference(pos, data, alignment); + targetMethod.recordDataReference(pos, data, alignment, inlined); return Address.Placeholder; } @@ -175,15 +175,16 @@ return lastSafepointPos; } - /** - * Returns the integer value of any constants that can be represented by a 32-bit integer value, + * Returns the integer value of any constant that can be represented by a 32-bit integer value, * including long constants that fit into the 32-bit range. */ public int asIntConst(Value value) { assert (value.getKind().getStackKind() == Kind.Int || value.getKind() == Kind.Jsr || value.getKind() == Kind.Long) && isConstant(value); - long c = ((Constant) value).asLong(); - if (!(NumUtil.isInt(c))) { + Constant constant = (Constant) value; + assert !runtime.needsDataPatch(constant) : constant + " should be in a DataPatch"; + long c = constant.asLong(); + if (!NumUtil.isInt(c)) { throw GraalInternalError.shouldNotReachHere(); } return (int) c; @@ -198,7 +199,7 @@ public Address asFloatConstRef(Value value, int alignment) { assert value.getKind() == Kind.Float && isConstant(value); - return recordDataReferenceInCode((Constant) value, alignment); + return recordDataReferenceInCode((Constant) value, alignment, false); } /** @@ -210,7 +211,7 @@ public Address asDoubleConstRef(Value value, int alignment) { assert value.getKind() == Kind.Double && isConstant(value); - return recordDataReferenceInCode((Constant) value, alignment); + return recordDataReferenceInCode((Constant) value, alignment, false); } /** @@ -218,7 +219,7 @@ */ public Address asLongConstRef(Value value) { assert value.getKind() == Kind.Long && isConstant(value); - return recordDataReferenceInCode((Constant) value, 8); + return recordDataReferenceInCode((Constant) value, 8, false); } public Address asIntAddr(Value value) { diff -r edb2d7ed9a01 -r eec373d34caf src/share/vm/graal/graalCodeInstaller.cpp --- a/src/share/vm/graal/graalCodeInstaller.cpp Tue Nov 20 22:35:20 2012 +0100 +++ b/src/share/vm/graal/graalCodeInstaller.cpp Tue Nov 20 22:49:27 2012 +0100 @@ -102,7 +102,28 @@ return map; } -static ScopeValue* get_hotspot_value(oop value, int total_frame_size, GrowableArray* objects, ScopeValue* &second) { +// Records any Metadata values embedded in a Constant (e.g., the value returned by HotSpotResolvedJavaType.klass()). +static void record_metadata_in_constant(oop constant, OopRecorder* oop_recorder) { + char kind = Kind::typeChar(Constant::kind(constant)); + char wordKind = 'j'; + if (kind == wordKind) { + oop obj = Constant::object(constant); + jlong prim = Constant::primitive(constant); + if (obj != NULL) { + if (obj->is_a(HotSpotResolvedJavaType::klass())) { + Klass* klass = (Klass*) (address) HotSpotResolvedJavaType::metaspaceKlass(obj); + assert((Klass*) prim == klass, err_msg("%s @ %p != %p", klass->name()->as_C_string(), klass, prim)); + int index = oop_recorder->find_index(klass); + TRACE_graal_3("metadata[%d of %d] = %s", index, oop_recorder->metadata_count(), klass->name()->as_C_string()); + } else { + assert(java_lang_String::is_instance(obj), + err_msg("unexpected annotation type (%s) for constant %ld (%p) of kind %c", obj->klass()->name()->as_C_string(), prim, prim, kind)); + } + } + } +} + +static ScopeValue* get_hotspot_value(oop value, int total_frame_size, GrowableArray* objects, ScopeValue* &second, OopRecorder* oop_recorder) { second = NULL; if (value == Value::ILLEGAL()) { return new LocationValue(Location::new_stk_loc(Location::invalid, 0)); @@ -157,7 +178,7 @@ } return value; } else if (value->is_a(Constant::klass())){ - oop obj = Constant::object(value); + record_metadata_in_constant(value, oop_recorder); jlong prim = Constant::primitive(value); if (type == T_INT || type == T_FLOAT || type == T_SHORT || type == T_CHAR || type == T_BOOLEAN || type == T_BYTE) { return new ConstantIntValue(*(jint*)&prim); @@ -195,7 +216,7 @@ arrayOop values = (arrayOop) VirtualObject::values(value); for (jint i = 0; i < values->length(); i++) { ScopeValue* cur_second = NULL; - ScopeValue* value = get_hotspot_value(((oop*) values->base(T_OBJECT))[i], total_frame_size, objects, cur_second); + ScopeValue* value = get_hotspot_value(((oop*) values->base(T_OBJECT))[i], total_frame_size, objects, cur_second, oop_recorder); if (isLongArray && cur_second == NULL) { // we're trying to put ints into a long array... this isn't really valid, but it's used for some optimizations. @@ -222,14 +243,14 @@ return NULL; } -static MonitorValue* get_monitor_value(oop value, int total_frame_size, GrowableArray* objects) { +static MonitorValue* get_monitor_value(oop value, int total_frame_size, GrowableArray* objects, OopRecorder* oop_recorder) { guarantee(value->is_a(code_MonitorValue::klass()), "Monitors must be of type MonitorValue"); ScopeValue* second = NULL; - ScopeValue* owner_value = get_hotspot_value(code_MonitorValue::owner(value), total_frame_size, objects, second); + ScopeValue* owner_value = get_hotspot_value(code_MonitorValue::owner(value), total_frame_size, objects, second, oop_recorder); assert(second == NULL, "monitor cannot occupy two stack slots"); - ScopeValue* lock_data_value = get_hotspot_value(code_MonitorValue::lockData(value), total_frame_size, objects, second); + ScopeValue* lock_data_value = get_hotspot_value(code_MonitorValue::lockData(value), total_frame_size, objects, second, oop_recorder); assert(second == lock_data_value, "monitor is LONG value that occupies two stack slots"); assert(lock_data_value->is_location(), "invalid monitor location"); Location lock_data_loc = ((LocationValue*)lock_data_value)->location(); @@ -482,19 +503,19 @@ oop value = ((oop*) values->base(T_OBJECT))[i]; if (i < local_count) { - ScopeValue* first = get_hotspot_value(value, _total_frame_size, objects, second); + ScopeValue* first = get_hotspot_value(value, _total_frame_size, objects, second, _oop_recorder); if (second != NULL) { locals->append(second); } locals->append(first); } else if (i < local_count + expression_count) { - ScopeValue* first = get_hotspot_value(value, _total_frame_size, objects, second); + ScopeValue* first = get_hotspot_value(value, _total_frame_size, objects, second, _oop_recorder); if (second != NULL) { expressions->append(second); } expressions->append(first); } else { - monitors->append(get_monitor_value(value, _total_frame_size, objects)); + monitors->append(get_monitor_value(value, _total_frame_size, objects, _oop_recorder)); } if (second != NULL) { i++; @@ -601,7 +622,7 @@ jump->set_jump_destination(VmIds::getStub(global_stub)); _instructions->relocate((address)inst, runtime_call_Relocation::spec(), Assembler::call32_operand); } - TRACE_graal_3("relocating (stub) at %016x", inst); + TRACE_graal_3("relocating (stub) at %p", inst); } else { // method != NULL assert(hotspot_method != NULL, "unexpected JavaMethod"); assert(debug_info != NULL, "debug info expected"); @@ -659,6 +680,7 @@ void CodeInstaller::site_DataPatch(CodeBuffer& buffer, jint pc_offset, oop site) { oop constant = CompilationResult_DataPatch::constant(site); int alignment = CompilationResult_DataPatch::alignment(site); + bool inlined = CompilationResult_DataPatch::inlined(site); oop kind = Constant::kind(constant); address instruction = _instructions->start() + pc_offset; @@ -675,24 +697,30 @@ case 'f': case 'j': case 'd': { - address operand = Assembler::locate_operand(instruction, Assembler::disp32_operand); - address next_instruction = Assembler::locate_next_instruction(instruction); - int size = _constants->size(); - if (alignment > 0) { - guarantee(alignment <= _constants->alignment(), "Alignment inside constants section is restricted by alignment of section begin"); - size = align_size_up(size, alignment); + record_metadata_in_constant(constant, _oop_recorder); + if (inlined) { + address operand = Assembler::locate_operand(instruction, Assembler::imm_operand); + *((jlong*) operand) = Constant::primitive(constant); + } else { + address operand = Assembler::locate_operand(instruction, Assembler::disp32_operand); + address next_instruction = Assembler::locate_next_instruction(instruction); + int size = _constants->size(); + if (alignment > 0) { + guarantee(alignment <= _constants->alignment(), "Alignment inside constants section is restricted by alignment of section begin"); + size = align_size_up(size, alignment); + } + // we don't care if this is a long/double/etc., the primitive field contains the right bits + address dest = _constants->start() + size; + _constants->set_end(dest + BytesPerLong); + *(jlong*) dest = Constant::primitive(constant); + + long disp = dest - next_instruction; + assert(disp == (jint) disp, "disp doesn't fit in 32 bits"); + *((jint*) operand) = (jint) disp; + + _instructions->relocate(instruction, section_word_Relocation::spec((address) dest, CodeBuffer::SECT_CONSTS), Assembler::disp32_operand); + TRACE_graal_3("relocating (%c) at %p/%p with destination at %p (%d)", typeChar, instruction, operand, dest, size); } - // we don't care if this is a long/double/etc., the primitive field contains the right bits - address dest = _constants->start() + size; - _constants->set_end(dest + BytesPerLong); - *(jlong*) dest = Constant::primitive(constant); - - long disp = dest - next_instruction; - assert(disp == (jint) disp, "disp doesn't fit in 32 bits"); - *((jint*) operand) = (jint) disp; - - _instructions->relocate(instruction, section_word_Relocation::spec((address) dest, CodeBuffer::SECT_CONSTS), Assembler::disp32_operand); - TRACE_graal_3("relocating (%c) at %016x/%016x with destination at %016x (%d)", typeChar, instruction, operand, dest, size); break; } case 'a': { @@ -702,11 +730,11 @@ jobject value = JNIHandles::make_local(obj()); *((jobject*) operand) = value; _instructions->relocate(instruction, oop_Relocation::spec_for_immediate(), Assembler::imm_operand); - TRACE_graal_3("relocating (oop constant) at %016x/%016x", instruction, operand); + TRACE_graal_3("relocating (oop constant) at %p/%p", instruction, operand); break; } default: - fatal("unexpected Kind in DataPatch"); + fatal(err_msg("unexpected Kind (%d) in DataPatch", typeChar)); break; } } diff -r edb2d7ed9a01 -r eec373d34caf src/share/vm/graal/graalJavaAccess.hpp --- a/src/share/vm/graal/graalJavaAccess.hpp Tue Nov 20 22:35:20 2012 +0100 +++ b/src/share/vm/graal/graalJavaAccess.hpp Tue Nov 20 22:49:27 2012 +0100 @@ -127,6 +127,7 @@ start_class(CompilationResult_DataPatch) \ oop_field(CompilationResult_DataPatch, constant, "Lcom/oracle/graal/api/meta/Constant;") \ int_field(CompilationResult_DataPatch, alignment) \ + boolean_field(CompilationResult_DataPatch, inlined) \ end_class \ start_class(CompilationResult_Safepoint) \ oop_field(CompilationResult_Safepoint, debugInfo, "Lcom/oracle/graal/api/code/DebugInfo;") \