Re: [rvm-research] Approach for fixing the RVM-1017(Implicit unlock in synchronized method relies on local variable 0 )
Pushparaj Motamari <[email protected]>
| Newsgroups | gmane.comp.java.jikes.rvm.devel |
|---|---|
| Message-ID | <CAKO14CXFf=9WQUvapRW4zcTRtvKr-O3JdqHwVuM2e7DZN8caKA@mail.gmail.com> |
Hi, When I build the Jikes after chanigng the GenerationContext.java as you suggested, the precommit run successful,but when I try to run a testcase which modifies the localvariable 0. It is failing. I am attaching the patch and the testcase with the mail. Thank You Pushparaj On Tue, Apr 30, 2013 at 3:48 AM, David P Grove <[email protected]> wrote: > Pushparaj Motamari <[email protected]> wrote on 04/29/2013 04:32:44 > PM: > > > > > I am working on the fix for RVM-1017(Implicit unlock in synchronized > > method relies on local variable 0 ). I tried by reserving one extra > > localword in NormalMethod.java, now it adds extra word to every > > method, but it can be changed by putting "if(method.isSynchronized > > ())". I am attaching the patch with the mail. When I do precommit > > with this patch for development configuration (dacapo), some > > testcases are failing ..like eclipse. But with prototype > > onfiguration i.e (basic and opttests) it is successful. I would like > > to know other approaches to fixing this. > > > > Hi, > > I'd think about it from the perspective of what parts of the system need > to know how to get to the this pointer. In addition to the obvious need of > the compilers to generate code in the prologue/epilogue of a synchronized > instance method to lock/unlock this, we also need to be able to unlock when > unwinding the stack frame due to an exception being processed. The GC will > also need to know about it in order to make sure it is recognized as a root > during GC and processed. > > I'd also go simple first, then try to optimize it after it was working. > > I think the fix to the opt compiler is actually much simpler than the > baseline compilers. For the opt compiler, I would just add a new temporary > "cachedThis" in the GenerationContext and use it instead of localO in > getLockObject. In the prologue, add an assignment to cachedThis from > local0. Since the opt compiler (in GenerationContext) wraps the real body > of the synchronized method in a generated try/catch that uses getLockObject > to unlock this and then rethrow the exception when we need to unwind the > method, just tweaking GenerationContext to stash away the original value of > this should fix everything. The fix for the opt compiler should be > confined entirely to GenerationContext. > > In the baseline compiler, things are much more annoying. You really need > an entry in the stackframe to hold the this pointer. You'll need to store > it there in the prologue, make sure the GC maps know about it, and use it > to unlock in the method epilogue and the exception delivery code > (unwindStackFrame in BaselineExceptionDeliverer). > > You're trying to get yourself a stackslot in the baseline compiler by > modifying NormalMethod to add an extra local word. I think I would not > approach it this way, because you will have to track down all the places in > the system that do some computation based on getLocalWords() and adjust > them. Not pretty. And you only need an explicit extra word in the > stackframe for the baseline compiler. So, I'd probably go after it by > unconditionally making the baseline compiler's stackframe header have an > extra word (next to the CMID), stashing the this pointer there in the > prologue of a synchronized instance method (before the yieldpoint), > teaching the GC mapping code to include this word for a synchronized > instance method, and using this word to unlock in the exception handler and > method epilogue. After this is working robustly, then you could try to > move it out of the fixed header and treat it as if there was an extra local > for synchronized instance methods to avoid adding a word to the stackframe > for all methods. I doubt this is actually worth the complexity of doing, > but it probably could be done. > > --dave > > > > > ------------------------------------------------------------------------------ > Try New Relic Now & We'll Send You this Cool Shirt > New Relic is the only SaaS-based application performance monitoring service > that delivers powerful full stack analytics. Optimize and monitor your > browser, app, & servers with just a few lines of code. Try New Relic > and get this awesome Nerd Life shirt! http://p.sf.net/sfu/newrelic_d2d_apr > _______________________________________________ > Jikesrvm-researchers mailing list > [email protected] > https://lists.sourceforge.net/lists/listinfo/jikesrvm-researchers > > ------------------------------------------------------------------------------ Try New Relic Now & We'll Send You this Cool Shirt New Relic is the only SaaS-based application performance monitoring service that delivers powerful full stack analytics. Optimize and monitor your browser, app, & servers with just a few lines of code. Try New Relic and get this awesome Nerd Life shirt! http://p.sf.net/sfu/newrelic_d2d_apr _______________________________________________ Jikesrvm-researchers mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/jikesrvm-researchers
newDiff.patch
(application/octet-stream, 6.5 KB)
diff -urB ./rvm/src/org/jikesrvm/compilers/opt/bc2ir/GenerationContext.java ../New_UnMd/rvm/src/org/jikesrvm/compilers/opt/bc2ir/GenerationContext.java
--- ./rvm/src/org/jikesrvm/compilers/opt/bc2ir/GenerationContext.java 2013-03-14 15:01:46.000000000 -0700
+++ ../New_UnMd/rvm/src/org/jikesrvm/compilers/opt/bc2ir/GenerationContext.java 2013-04-29 16:35:09.261783204 -0700
@@ -83,6 +83,7 @@
*/
CompiledMethod original_cm;
+ public int numberOfArgs;
/**
* The method to be generated
*/
@@ -156,7 +156,7 @@
* synchronized methods.
*/
BasicBlock unlockAndRethrow;
-
+ public TypeReference thisTypeRef;
/**
* The Register to which BC2IR should assign the return value(s)
* of the method. It will be null when the method has a void return.
@@ -192,7 +192,8 @@
* Did BC2IR encounter a magic that requires us to allocate a stack frame?
*/
public boolean allocFrame;
-
+ public RegisterOperand cachedThis;
+ public Register thisReg;
/**
* Used to communicate the meet of the return values back to the caller
* Mainly useful when BC2IR is doing inlining....allows the caller
@@ -249,6 +250,7 @@
int numParams = params.length;
int argIdx = 0;
int localNum = 0;
+ //arguments = new Operand[method.isStatic() ? numParams : numParams + 1];
arguments = new Operand[method.isStatic() ? numParams : numParams + 1];
// Insert IR_PROLOGUE instruction. Loop below will fill in its operands
Instruction prologueInstr = Prologue.create(IR_PROLOGUE, arguments.length);
@@ -257,7 +259,10 @@
if (!method.isStatic()) {
TypeReference thisType = meth.getDeclaringClass().getTypeRef();
RegisterOperand thisOp = makeLocal(localNum, thisType);
- // The this param of a virtual method is by definition non null
+ //makeLocal(method.getLocalWords()-1, thisType);
+ thisTypeRef = thisType;
+ numberOfArgs = numParams+1;
+ // The this param of a virtual method is by definition non null
RegisterOperand guard = makeNullCheckGuard(thisOp.getRegister());
BC2IR.setGuard(thisOp, guard);
appendInstruction(prologue, Move.create(GUARD_MOVE, guard.copyRO(), new TrueGuardOperand()), PROLOGUE_BCI);
@@ -268,6 +273,11 @@
}
arguments[0] = thisOp;
Prologue.setFormal(prologueInstr, 0, thisOp.copyU2D());
+ /* simulating aload0 , astore_method.getLocalWords-1*/
+ thisReg = temps.getReg(thisType);
+ //thisReg.setLocal();
+ cachedThis = new RegisterOperand(thisReg,thisType);
+ appendInstruction(prologue, Move.create(IRTools.getMoveOp(thisType),cachedThis, thisOp), PROLOGUE_BCI);
argIdx++;
localNum++;
}
@@ -330,11 +338,15 @@
// Now inherit state based on callSite
child.inlineSequence = new InlineSequence(child.method, callSite.position, callSite);
child.enclosingHandlers = ebag;
- child.arguments = new Operand[Call.getNumberOfParams(callSite)];
+ child.numberOfArgs = Call.getNumberOfParams(callSite);
+ // child.arguments = new Operand[Call.getNumberOfParams(callSite)];
+ child.arguments = new Operand[child.numberOfArgs];
+ // for (int i = 0; i < child.arguments.length; i++) {
for (int i = 0; i < child.arguments.length; i++) {
child.arguments[i] = Call.getParam(callSite, i).copy(); // copy instead
// of clearing in case inlining aborts.
}
+ //child.arguments[child.numberOfArgs-1]=Call.getParam(callSite, 0).copy();
if (Call.hasResult(callSite)) {
child.resultReg = Call.getResult(callSite).copyD2D().getRegister();
child.resultReg.setSpansBasicBlock(); // it will...
@@ -369,9 +379,23 @@
objPtr.setDeclaredType();
objPtr.setType(child.method.getDeclaringClass().getTypeRef());
}
+ RegisterOperand myOp = objPtr.copyRO();
local = child.makeLocal(localNum, objPtr);
localNum++;
- child.arguments[0] = local; // Avoid confusion in BC2IR of callee
+ child.arguments[0] = local;
+ //child.makeLocal(child.method.getLocalWords()-1, myOp);
+ /*receiver = child.arguments[0];
+ objPtr = receiver.asRegister();
+ if (ClassLoaderProxy.includesType(child.method.getDeclaringClass().getTypeRef(), objPtr.getType()) != YES) {
+ // narrow type of actual to match formal static type implied by method
+ objPtr.clearPreciseType(); // Can be precise but not assignable if enough classes aren't loaded
+ objPtr.setDeclaredType();
+ objPtr.setType(child.method.getDeclaringClass().getTypeRef());
+ }
+ child.arguments[child.numberOfArgs-1]=child.makeLocal(child.method.getLocalWords(), objPtr);
+ */
+ //child.thisTypeRef =child.makeLocal(child.method.getLocalWords(), objPtr).type;
+ //child.arguments[child.numberOfArgs-1] = child.makeLocal(child.method.getLocalWords(),objPtr );// Avoid confusion in BC2IR of callee
// when objPtr is a local in the caller.
} else if (receiver.isConstant()) {
local = child.makeLocal(localNum, receiver.getType());
@@ -384,11 +408,20 @@
} else {
OptimizingCompilerException.UNREACHABLE("Unexpected receiver operand");
}
- Instruction s = Move.create(REF_MOVE, local, receiver);
+
+ if(local!=null){
+child.thisReg = child.temps.getReg(local.getType());
+ //child.thisReg.setLocal();
+ child.cachedThis = new RegisterOperand(child.thisReg,local.getType());
+ Instruction n = Move.create(IRTools.getMoveOp(local.getType()),child.cachedThis, local);
+ //s.bcIndex = PROLOGUE_BCI;
+ child.prologue.appendInstruction(n);
+ }
+ Instruction s = Move.create(REF_MOVE, local, receiver);
s.bcIndex = PROLOGUE_BCI;
s.position = callSite.position;
child.prologue.appendInstruction(s);
- }
+ }
for (int paramIdx = 0; paramIdx < numParams; paramIdx++, argIdx++) {
TypeReference argType = params[paramIdx];
RegisterOperand formal;
@@ -774,8 +806,10 @@
Offset offs = Offset.fromIntSignExtend(Statics.findOrCreateObjectLiteral(klass));
return new ClassConstantOperand(klass, offs);
} else {
- return makeLocal(0, arguments[0].getType());
- }
+ return new RegisterOperand(cachedThis.getRegister(), method.getDeclaringClass().getTypeRef());
+ //return new RegisterOperand(addressLocals[method.getLocalWords()],arguments[arguments.length-1].getType());
+ //new RegisterOperand(, type);
+ }
}
private void appendInstruction(BasicBlock b, Instruction s, int bcIndex) {
Only in ../New_UnMd/rvm/src/org/jikesrvm/compilers/opt/bc2ir: GenerationContext.java~
a_lk.class
(application/octet-stream, 358 B) - not displayed