Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2024, 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
Expand Down Expand Up @@ -632,7 +632,7 @@ public LocalVariableTable getLocalVariableTable() {

for (int i = 0; i < localVariableTableLength; i++) {
final int startBci = UNSAFE.getChar(localVariableTableElement + config.localVariableTableElementStartBciOffset);
final int endBci = startBci + UNSAFE.getChar(localVariableTableElement + config.localVariableTableElementLengthOffset);
final int endBci = startBci + UNSAFE.getChar(localVariableTableElement + config.localVariableTableElementLengthOffset) - 1;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a question: Can the length of a local variable be 0?

If the code length is 0, the endBci here may be less than startBci.

Copy link
Member

@dougxc dougxc Mar 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see anything in JVMS 4.7.13 that says it cannot be 0. It basically means the LVT entry is useless (denotes a local that is never alive) but is otherwise harmless.
Maybe add this to the javadoc for getEndBci() to make the API user aware of this corner case:

If the value returned is less than {@link #getStartBCI}, this object denotes a local that is never live.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason, which causes this problem, is that the Local::endBci includes itself instead of excluding it. But now, we can only fix the javadoc just as you suggested.

If the value returned is less than {@link #getStartBCI}, this object denotes a local that is never live.

a local variable may be better to a local above.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had checked the specs on that and came to the same conclusion.
I also think the current state is fine in that regards in terms of code since it just means that there is no bci where this local would be valid when checking both start and end bci.
Adding a note about that to the javadoc is a good idea. I'll do that.

final int nameCpIndex = UNSAFE.getChar(localVariableTableElement + config.localVariableTableElementNameCpIndexOffset);
final int typeCpIndex = UNSAFE.getChar(localVariableTableElement + config.localVariableTableElementDescriptorCpIndexOffset);
final int slot = UNSAFE.getChar(localVariableTableElement + config.localVariableTableElementSlotOffset);
Expand Down
11 changes: 10 additions & 1 deletion src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/Local.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2024, 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
Expand Down Expand Up @@ -41,10 +41,19 @@ public Local(String name, JavaType type, int startBci, int endBci, int slot) {
this.type = type;
}

/**
* Returns the first BCI at which this local has a value (inclusive).
*/
public int getStartBCI() {
return startBci;
}


/**
* Returns the last BCI at which this local has a value (inclusive).
* If the value returned is less than {@link #getStartBCI}, this object denotes a local
* variable that is never live.
*/
public int getEndBCI() {
return endBci;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@

import jdk.vm.ci.meta.ConstantPool;
import jdk.vm.ci.meta.ExceptionHandler;
import jdk.vm.ci.meta.Local;
import jdk.vm.ci.meta.LocalVariableTable;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.ResolvedJavaMethod.Parameter;
import jdk.vm.ci.meta.ResolvedJavaType;
Expand Down Expand Up @@ -734,6 +736,24 @@ public void getOopMapAtTest() throws Exception {
Assert.assertTrue(processedMethodWithManyArgs[0]);
}

@Test
public void getLocalVariableTableTest() {
for (ResolvedJavaMethod m : methods.values()) {
LocalVariableTable table = m.getLocalVariableTable();
if (table == null) {
continue;
}
for (Local l : table.getLocals()) {
if (l.getStartBCI() < 0) {
throw new AssertionError(m.format("%H.%n(%p)") + " local " + l.getName() + " starts at " + l.getStartBCI());
}
if (l.getEndBCI() >= m.getCodeSize()) {
throw new AssertionError(m.format("%H.%n(%p)") + " (" + m.getCodeSize() + "bytes) local " + l.getName() + " ends at " + l.getEndBCI());
}
}
}
}

private Method findTestMethod(Method apiMethod) {
String testName = apiMethod.getName() + "Test";
for (Method m : getClass().getDeclaredMethods()) {
Expand All @@ -756,7 +776,6 @@ private Method findTestMethod(Method apiMethod) {
"canBeInlined",
"shouldBeInlined",
"getLineNumberTable",
"getLocalVariableTable",
"isInVirtualMethodTable",
"toParameterTypes",
"getParameterAnnotation",
Expand Down