Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_langtools
提交
85661013
D
dragonwell8_langtools
项目概览
openanolis
/
dragonwell8_langtools
通知
0
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell8_langtools
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
85661013
编写于
1月 20, 2015
作者:
V
vromero
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
8064857: javac generates LVT entry with length 0 for local variable
Reviewed-by: mcimadamore, jjg
上级
29e40c9c
变更
11
隐藏空白更改
内联
并排
Showing
11 changed file
with
65 addition
and
536 deletion
+65
-536
src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java
src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java
+2
-2
src/share/classes/com/sun/tools/javac/jvm/Code.java
src/share/classes/com/sun/tools/javac/jvm/Code.java
+8
-29
src/share/classes/com/sun/tools/javac/jvm/Gen.java
src/share/classes/com/sun/tools/javac/jvm/Gen.java
+2
-364
src/share/classes/com/sun/tools/javac/jvm/LVTRanges.java
src/share/classes/com/sun/tools/javac/jvm/LVTRanges.java
+0
-129
test/tools/javac/flow/LVTHarness.java
test/tools/javac/flow/LVTHarness.java
+6
-5
test/tools/javac/flow/tests/TestCaseFor.java
test/tools/javac/flow/tests/TestCaseFor.java
+2
-2
test/tools/javac/flow/tests/TestCaseForEach.java
test/tools/javac/flow/tests/TestCaseForEach.java
+1
-1
test/tools/javac/flow/tests/TestCaseIfElse.java
test/tools/javac/flow/tests/TestCaseIfElse.java
+15
-0
test/tools/javac/flow/tests/TestCaseSwitch.java
test/tools/javac/flow/tests/TestCaseSwitch.java
+22
-0
test/tools/javac/flow/tests/TestCaseTry.java
test/tools/javac/flow/tests/TestCaseTry.java
+6
-3
test/tools/javac/flow/tests/TestCaseWhile.java
test/tools/javac/flow/tests/TestCaseWhile.java
+1
-1
未找到文件。
src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java
浏览文件 @
85661013
/*
* Copyright (c) 1999, 201
3
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 201
5
, 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
...
...
@@ -1186,7 +1186,7 @@ public class ClassWriter extends ClassFile {
Assert
.
check
(
r
.
start_pc
>=
0
&&
r
.
start_pc
<=
code
.
cp
);
databuf
.
appendChar
(
r
.
start_pc
);
Assert
.
check
(
r
.
length
>
=
0
Assert
.
check
(
r
.
length
>
0
&&
(
r
.
start_pc
+
r
.
length
)
<=
code
.
cp
);
databuf
.
appendChar
(
r
.
length
);
VarSymbol
sym
=
var
.
sym
;
...
...
src/share/classes/com/sun/tools/javac/jvm/Code.java
浏览文件 @
85661013
/*
* Copyright (c) 1999, 201
4
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 201
5
, 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
...
...
@@ -182,8 +182,6 @@ public class Code {
final
MethodSymbol
meth
;
final
LVTRanges
lvtRanges
;
/** Construct a code object, given the settings of the fatcode,
* debugging info switches and the CharacterRangeTable.
*/
...
...
@@ -196,8 +194,7 @@ public class Code {
CRTable
crt
,
Symtab
syms
,
Types
types
,
Pool
pool
,
LVTRanges
lvtRanges
)
{
Pool
pool
)
{
this
.
meth
=
meth
;
this
.
fatcode
=
fatcode
;
this
.
lineMap
=
lineMap
;
...
...
@@ -219,7 +216,6 @@ public class Code {
state
=
new
State
();
lvar
=
new
LocalVar
[
20
];
this
.
pool
=
pool
;
this
.
lvtRanges
=
lvtRanges
;
}
...
...
@@ -1193,7 +1189,9 @@ public class Code {
public
int
entryPoint
(
State
state
)
{
int
pc
=
curCP
();
alive
=
true
;
this
.
state
=
state
.
dup
();
State
newState
=
state
.
dup
();
setDefined
(
newState
.
defined
);
this
.
state
=
newState
;
Assert
.
check
(
state
.
stacksize
<=
max_stack
);
if
(
debugCode
)
System
.
err
.
println
(
"entry point "
+
state
);
pendingStackMap
=
needStackMap
;
...
...
@@ -1206,7 +1204,9 @@ public class Code {
public
int
entryPoint
(
State
state
,
Type
pushed
)
{
int
pc
=
curCP
();
alive
=
true
;
this
.
state
=
state
.
dup
();
State
newState
=
state
.
dup
();
setDefined
(
newState
.
defined
);
this
.
state
=
newState
;
Assert
.
check
(
state
.
stacksize
<=
max_stack
);
this
.
state
.
push
(
pushed
);
if
(
debugCode
)
System
.
err
.
println
(
"entry point "
+
state
);
...
...
@@ -2008,27 +2008,6 @@ public class Code {
state
.
defined
.
excl
(
adr
);
}
public
void
closeAliveRanges
(
JCTree
tree
)
{
closeAliveRanges
(
tree
,
cp
);
}
public
void
closeAliveRanges
(
JCTree
tree
,
int
closingCP
)
{
List
<
VarSymbol
>
locals
=
lvtRanges
.
getVars
(
meth
,
tree
);
for
(
LocalVar
localVar:
lvar
)
{
for
(
VarSymbol
aliveLocal
:
locals
)
{
if
(
localVar
!=
null
)
{
if
(
localVar
.
sym
==
aliveLocal
&&
localVar
.
lastRange
()
!=
null
)
{
char
length
=
(
char
)(
closingCP
-
localVar
.
lastRange
().
start_pc
);
if
(
length
<
Character
.
MAX_VALUE
)
{
localVar
.
closeRange
(
length
);
}
}
}
}
}
}
void
adjustAliveRanges
(
int
oldCP
,
int
delta
)
{
for
(
LocalVar
localVar:
lvar
)
{
if
(
localVar
!=
null
)
{
...
...
src/share/classes/com/sun/tools/javac/jvm/Gen.java
浏览文件 @
85661013
/*
* Copyright (c) 1999, 201
4
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 201
5
, 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
...
...
@@ -101,10 +101,6 @@ public class Gen extends JCTree.Visitor {
*/
private
Pool
pool
;
/** LVTRanges info.
*/
private
LVTRanges
lvtRanges
;
private
final
boolean
typeAnnoAsserts
;
protected
Gen
(
Context
context
)
{
...
...
@@ -137,9 +133,6 @@ public class Gen extends JCTree.Visitor {
options
.
isUnset
(
G_CUSTOM
)
?
options
.
isSet
(
G
)
:
options
.
isSet
(
G_CUSTOM
,
"vars"
);
if
(
varDebugInfo
)
{
lvtRanges
=
LVTRanges
.
instance
(
context
);
}
genCrt
=
options
.
isSet
(
XJCOV
);
debugCode
=
options
.
isSet
(
"debugcode"
);
allowInvokedynamic
=
target
.
hasInvokedynamic
()
||
options
.
isSet
(
"invokedynamic"
);
...
...
@@ -1103,8 +1096,7 @@ public class Gen extends JCTree.Visitor {
:
null
,
syms
,
types
,
pool
,
varDebugInfo
?
lvtRanges
:
null
);
pool
);
items
=
new
Items
(
pool
,
code
,
syms
,
types
);
if
(
code
.
debugCode
)
{
System
.
err
.
println
(
meth
+
" for body "
+
tree
);
...
...
@@ -1207,30 +1199,14 @@ public class Gen extends JCTree.Visitor {
Chain
loopDone
=
c
.
jumpFalse
();
code
.
resolve
(
c
.
trueJumps
);
genStat
(
body
,
loopEnv
,
CRT_STATEMENT
|
CRT_FLOW_TARGET
);
if
(
varDebugInfo
)
{
checkLoopLocalVarRangeEnding
(
loop
,
body
,
LoopLocalVarRangeEndingPoint
.
BEFORE_STEPS
);
}
code
.
resolve
(
loopEnv
.
info
.
cont
);
genStats
(
step
,
loopEnv
);
if
(
varDebugInfo
)
{
checkLoopLocalVarRangeEnding
(
loop
,
body
,
LoopLocalVarRangeEndingPoint
.
AFTER_STEPS
);
}
code
.
resolve
(
code
.
branch
(
goto_
),
startpc
);
code
.
resolve
(
loopDone
);
}
else
{
genStat
(
body
,
loopEnv
,
CRT_STATEMENT
|
CRT_FLOW_TARGET
);
if
(
varDebugInfo
)
{
checkLoopLocalVarRangeEnding
(
loop
,
body
,
LoopLocalVarRangeEndingPoint
.
BEFORE_STEPS
);
}
code
.
resolve
(
loopEnv
.
info
.
cont
);
genStats
(
step
,
loopEnv
);
if
(
varDebugInfo
)
{
checkLoopLocalVarRangeEnding
(
loop
,
body
,
LoopLocalVarRangeEndingPoint
.
AFTER_STEPS
);
}
CondItem
c
;
if
(
cond
!=
null
)
{
code
.
statBegin
(
cond
.
pos
);
...
...
@@ -1247,44 +1223,6 @@ public class Gen extends JCTree.Visitor {
}
}
private
enum
LoopLocalVarRangeEndingPoint
{
BEFORE_STEPS
,
AFTER_STEPS
,
}
/**
* Checks whether we have reached an alive range ending point for local
* variables after a loop.
*
* Local variables alive range ending point for loops varies depending
* on the loop type. The range can be closed before or after the code
* for the steps sentences has been generated.
*
* - While loops has no steps so in that case the range is closed just
* after the body of the loop.
*
* - For-like loops may have steps so as long as the steps sentences
* can possibly contain non-synthetic local variables, the alive range
* for local variables must be closed after the steps in this case.
*/
private
void
checkLoopLocalVarRangeEnding
(
JCTree
loop
,
JCTree
body
,
LoopLocalVarRangeEndingPoint
endingPoint
)
{
if
(
varDebugInfo
&&
lvtRanges
.
containsKey
(
code
.
meth
,
body
))
{
switch
(
endingPoint
)
{
case
BEFORE_STEPS:
if
(!
loop
.
hasTag
(
FORLOOP
))
{
code
.
closeAliveRanges
(
body
);
}
break
;
case
AFTER_STEPS:
if
(
loop
.
hasTag
(
FORLOOP
))
{
code
.
closeAliveRanges
(
body
);
}
break
;
}
}
}
public
void
visitForeachLoop
(
JCEnhancedForLoop
tree
)
{
throw
new
AssertionError
();
// should have been removed by Lower.
}
...
...
@@ -1398,9 +1336,6 @@ public class Gen extends JCTree.Visitor {
// Generate code for the statements in this case.
genStats
(
c
.
stats
,
switchEnv
,
CRT_FLOW_TARGET
);
if
(
varDebugInfo
&&
lvtRanges
.
containsKey
(
code
.
meth
,
c
.
stats
.
last
()))
{
code
.
closeAliveRanges
(
c
.
stats
.
last
());
}
}
// Resolve all breaks.
...
...
@@ -1557,9 +1492,6 @@ public class Gen extends JCTree.Visitor {
genFinalizer
(
env
);
code
.
statBegin
(
TreeInfo
.
endPos
(
env
.
tree
));
Chain
exitChain
=
code
.
branch
(
goto_
);
if
(
varDebugInfo
&&
lvtRanges
.
containsKey
(
code
.
meth
,
body
))
{
code
.
closeAliveRanges
(
body
);
}
endFinalizerGap
(
env
);
if
(
startpc
!=
endpc
)
for
(
List
<
JCCatch
>
l
=
catchers
;
l
.
nonEmpty
();
l
=
l
.
tail
)
{
// start off with exception on stack
...
...
@@ -1815,17 +1747,11 @@ public class Gen extends JCTree.Visitor {
code
.
resolve
(
c
.
trueJumps
);
genStat
(
tree
.
thenpart
,
env
,
CRT_STATEMENT
|
CRT_FLOW_TARGET
);
thenExit
=
code
.
branch
(
goto_
);
if
(
varDebugInfo
&&
lvtRanges
.
containsKey
(
code
.
meth
,
tree
.
thenpart
))
{
code
.
closeAliveRanges
(
tree
.
thenpart
,
code
.
cp
);
}
}
if
(
elseChain
!=
null
)
{
code
.
resolve
(
elseChain
);
if
(
tree
.
elsepart
!=
null
)
{
genStat
(
tree
.
elsepart
,
env
,
CRT_STATEMENT
|
CRT_FLOW_TARGET
);
if
(
varDebugInfo
&&
lvtRanges
.
containsKey
(
code
.
meth
,
tree
.
elsepart
))
{
code
.
closeAliveRanges
(
tree
.
elsepart
);
}
}
}
code
.
resolve
(
thenExit
);
...
...
@@ -2514,16 +2440,6 @@ public class Gen extends JCTree.Visitor {
localEnv
.
toplevel
=
env
.
toplevel
;
localEnv
.
enclClass
=
cdef
;
/* We must not analyze synthetic methods
*/
if
(
varDebugInfo
&&
(
cdef
.
sym
.
flags
()
&
SYNTHETIC
)
==
0
)
{
try
{
new
LVTAssignAnalyzer
().
analyzeTree
(
localEnv
);
}
catch
(
Throwable
e
)
{
throw
e
;
}
}
for
(
List
<
JCTree
>
l
=
cdef
.
defs
;
l
.
nonEmpty
();
l
=
l
.
tail
)
{
genDef
(
l
.
head
,
localEnv
);
}
...
...
@@ -2609,282 +2525,4 @@ public class Gen extends JCTree.Visitor {
}
}
class
LVTAssignAnalyzer
extends
Flow
.
AbstractAssignAnalyzer
<
LVTAssignAnalyzer
.
LVTAssignPendingExit
>
{
final
LVTBits
lvtInits
;
/* This class is anchored to a context dependent tree. The tree can
* vary inside the same instruction for example in the switch instruction
* the same FlowBits instance can be anchored to the whole tree, or
* to a given case. The aim is to always anchor the bits to the tree
* capable of closing a DA range.
*/
class
LVTBits
extends
Bits
{
JCTree
currentTree
;
private
int
[]
oldBits
=
null
;
BitsState
stateBeforeOp
;
@Override
public
void
clear
()
{
generalOp
(
null
,
-
1
,
BitsOpKind
.
CLEAR
);
}
@Override
protected
void
internalReset
()
{
super
.
internalReset
();
oldBits
=
null
;
}
@Override
public
Bits
assign
(
Bits
someBits
)
{
// bits can be null
oldBits
=
bits
;
stateBeforeOp
=
currentState
;
super
.
assign
(
someBits
);
changed
();
return
this
;
}
@Override
public
void
excludeFrom
(
int
start
)
{
generalOp
(
null
,
start
,
BitsOpKind
.
EXCL_RANGE
);
}
@Override
public
void
excl
(
int
x
)
{
Assert
.
check
(
x
>=
0
);
generalOp
(
null
,
x
,
BitsOpKind
.
EXCL_BIT
);
}
@Override
public
Bits
andSet
(
Bits
xs
)
{
return
generalOp
(
xs
,
-
1
,
BitsOpKind
.
AND_SET
);
}
@Override
public
Bits
orSet
(
Bits
xs
)
{
return
generalOp
(
xs
,
-
1
,
BitsOpKind
.
OR_SET
);
}
@Override
public
Bits
diffSet
(
Bits
xs
)
{
return
generalOp
(
xs
,
-
1
,
BitsOpKind
.
DIFF_SET
);
}
@Override
public
Bits
xorSet
(
Bits
xs
)
{
return
generalOp
(
xs
,
-
1
,
BitsOpKind
.
XOR_SET
);
}
private
Bits
generalOp
(
Bits
xs
,
int
i
,
BitsOpKind
opKind
)
{
Assert
.
check
(
currentState
!=
BitsState
.
UNKNOWN
);
oldBits
=
dupBits
();
stateBeforeOp
=
currentState
;
switch
(
opKind
)
{
case
AND_SET:
super
.
andSet
(
xs
);
break
;
case
OR_SET:
super
.
orSet
(
xs
);
break
;
case
XOR_SET:
super
.
xorSet
(
xs
);
break
;
case
DIFF_SET:
super
.
diffSet
(
xs
);
break
;
case
CLEAR:
super
.
clear
();
break
;
case
EXCL_BIT:
super
.
excl
(
i
);
break
;
case
EXCL_RANGE:
super
.
excludeFrom
(
i
);
break
;
}
changed
();
return
this
;
}
/* The tree we need to anchor the bits instance to.
*/
LVTBits
at
(
JCTree
tree
)
{
this
.
currentTree
=
tree
;
return
this
;
}
/* If the instance should be changed but the tree is not a closing
* tree then a reset is needed or the former tree can mistakingly be
* used.
*/
LVTBits
resetTree
()
{
this
.
currentTree
=
null
;
return
this
;
}
/** This method will be called after any operation that causes a change to
* the bits. Subclasses can thus override it in order to extract information
* from the changes produced to the bits by the given operation.
*/
public
void
changed
()
{
if
(
currentTree
!=
null
&&
stateBeforeOp
!=
BitsState
.
UNKNOWN
&&
trackTree
(
currentTree
))
{
List
<
VarSymbol
>
locals
=
lvtRanges
.
getVars
(
currentMethod
,
currentTree
);
locals
=
locals
!=
null
?
locals
:
List
.<
VarSymbol
>
nil
();
for
(
JCVariableDecl
vardecl
:
vardecls
)
{
//once the first is null, the rest will be so.
if
(
vardecl
==
null
)
{
break
;
}
if
(
trackVar
(
vardecl
.
sym
)
&&
bitChanged
(
vardecl
.
sym
.
adr
))
{
locals
=
locals
.
prepend
(
vardecl
.
sym
);
}
}
if
(!
locals
.
isEmpty
())
{
lvtRanges
.
setEntry
(
currentMethod
,
currentTree
,
locals
);
}
}
}
boolean
bitChanged
(
int
x
)
{
boolean
isMemberOfBits
=
isMember
(
x
);
int
[]
tmp
=
bits
;
bits
=
oldBits
;
boolean
isMemberOfOldBits
=
isMember
(
x
);
bits
=
tmp
;
return
(!
isMemberOfBits
&&
isMemberOfOldBits
);
}
boolean
trackVar
(
VarSymbol
var
)
{
return
(
var
.
owner
.
kind
==
MTH
&&
(
var
.
flags
()
&
PARAMETER
)
==
0
&&
trackable
(
var
));
}
boolean
trackTree
(
JCTree
tree
)
{
switch
(
tree
.
getTag
())
{
// of course a method closes the alive range of a local variable.
case
METHODDEF:
// for while loops we want only the body
case
WHILELOOP:
return
false
;
}
return
true
;
}
}
public
class
LVTAssignPendingExit
extends
Flow
.
AbstractAssignAnalyzer
<
LVTAssignPendingExit
>.
AbstractAssignPendingExit
{
LVTAssignPendingExit
(
JCTree
tree
,
final
Bits
inits
,
final
Bits
uninits
)
{
super
(
tree
,
inits
,
uninits
);
}
@Override
public
void
resolveJump
(
JCTree
tree
)
{
lvtInits
.
at
(
tree
);
super
.
resolveJump
(
tree
);
}
}
private
LVTAssignAnalyzer
()
{
flow
.
super
();
lvtInits
=
new
LVTBits
();
inits
=
lvtInits
;
}
@Override
protected
void
markDead
(
JCTree
tree
)
{
lvtInits
.
at
(
tree
).
inclRange
(
returnadr
,
nextadr
);
super
.
markDead
(
tree
);
}
@Override
protected
void
merge
(
JCTree
tree
)
{
lvtInits
.
at
(
tree
);
super
.
merge
(
tree
);
}
boolean
isSyntheticOrMandated
(
Symbol
sym
)
{
return
(
sym
.
flags
()
&
(
SYNTHETIC
|
MANDATED
))
!=
0
;
}
@Override
protected
boolean
trackable
(
VarSymbol
sym
)
{
if
(
isSyntheticOrMandated
(
sym
))
{
//fast check to avoid tracking synthetic or mandated variables
return
false
;
}
return
super
.
trackable
(
sym
);
}
@Override
protected
void
initParam
(
JCVariableDecl
def
)
{
if
(!
isSyntheticOrMandated
(
def
.
sym
))
{
super
.
initParam
(
def
);
}
}
@Override
protected
void
assignToInits
(
JCTree
tree
,
Bits
bits
)
{
lvtInits
.
at
(
tree
);
lvtInits
.
assign
(
bits
);
}
@Override
protected
void
andSetInits
(
JCTree
tree
,
Bits
bits
)
{
lvtInits
.
at
(
tree
);
lvtInits
.
andSet
(
bits
);
}
@Override
protected
void
orSetInits
(
JCTree
tree
,
Bits
bits
)
{
lvtInits
.
at
(
tree
);
lvtInits
.
orSet
(
bits
);
}
@Override
protected
void
exclVarFromInits
(
JCTree
tree
,
int
adr
)
{
lvtInits
.
at
(
tree
);
lvtInits
.
excl
(
adr
);
}
@Override
protected
LVTAssignPendingExit
createNewPendingExit
(
JCTree
tree
,
Bits
inits
,
Bits
uninits
)
{
return
new
LVTAssignPendingExit
(
tree
,
inits
,
uninits
);
}
MethodSymbol
currentMethod
;
@Override
public
void
visitMethodDef
(
JCMethodDecl
tree
)
{
if
((
tree
.
sym
.
flags
()
&
(
SYNTHETIC
|
GENERATEDCONSTR
))
!=
0
&&
(
tree
.
sym
.
flags
()
&
LAMBDA_METHOD
)
==
0
)
{
return
;
}
if
(
tree
.
name
.
equals
(
names
.
clinit
))
{
return
;
}
boolean
enumClass
=
(
tree
.
sym
.
owner
.
flags
()
&
ENUM
)
!=
0
;
if
(
enumClass
&&
(
tree
.
name
.
equals
(
names
.
valueOf
)
||
tree
.
name
.
equals
(
names
.
values
)
||
tree
.
name
.
equals
(
names
.
init
)))
{
return
;
}
currentMethod
=
tree
.
sym
;
super
.
visitMethodDef
(
tree
);
}
}
}
src/share/classes/com/sun/tools/javac/jvm/LVTRanges.java
已删除
100644 → 0
浏览文件 @
29e40c9c
/*
* Copyright (c) 2013, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.tools.javac.jvm
;
import
java.util.Map
;
import
java.util.Map.Entry
;
import
java.util.WeakHashMap
;
import
com.sun.tools.javac.code.Symbol.MethodSymbol
;
import
com.sun.tools.javac.code.Symbol.VarSymbol
;
import
com.sun.tools.javac.tree.JCTree
;
import
com.sun.tools.javac.util.Context
;
import
com.sun.tools.javac.util.List
;
/** This class contains a one to many relation between a tree and a set of variables.
* The relation implies that the given tree closes the DA (definite assignment)
* range for the set of variables.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public
class
LVTRanges
{
/** The context key for the LVT ranges. */
protected
static
final
Context
.
Key
<
LVTRanges
>
lvtRangesKey
=
new
Context
.
Key
<>();
/** Get the LVTRanges instance for this context. */
public
static
LVTRanges
instance
(
Context
context
)
{
LVTRanges
instance
=
context
.
get
(
lvtRangesKey
);
if
(
instance
==
null
)
{
instance
=
new
LVTRanges
(
context
);
}
return
instance
;
}
private
static
final
long
serialVersionUID
=
1812267524140424433L
;
protected
Context
context
;
protected
Map
<
MethodSymbol
,
Map
<
JCTree
,
List
<
VarSymbol
>>>
aliveRangeClosingTrees
=
new
WeakHashMap
<>();
public
LVTRanges
(
Context
context
)
{
this
.
context
=
context
;
context
.
put
(
lvtRangesKey
,
this
);
}
public
List
<
VarSymbol
>
getVars
(
MethodSymbol
method
,
JCTree
tree
)
{
Map
<
JCTree
,
List
<
VarSymbol
>>
varMap
=
aliveRangeClosingTrees
.
get
(
method
);
return
(
varMap
!=
null
)
?
varMap
.
get
(
tree
)
:
null
;
}
public
boolean
containsKey
(
MethodSymbol
method
,
JCTree
tree
)
{
Map
<
JCTree
,
List
<
VarSymbol
>>
varMap
=
aliveRangeClosingTrees
.
get
(
method
);
if
(
varMap
==
null
)
{
return
false
;
}
return
varMap
.
containsKey
(
tree
);
}
public
void
setEntry
(
MethodSymbol
method
,
JCTree
tree
,
List
<
VarSymbol
>
vars
)
{
Map
<
JCTree
,
List
<
VarSymbol
>>
varMap
=
aliveRangeClosingTrees
.
get
(
method
);
if
(
varMap
!=
null
)
{
varMap
.
put
(
tree
,
vars
);
}
else
{
varMap
=
new
WeakHashMap
<>();
varMap
.
put
(
tree
,
vars
);
aliveRangeClosingTrees
.
put
(
method
,
varMap
);
}
}
public
List
<
VarSymbol
>
removeEntry
(
MethodSymbol
method
,
JCTree
tree
)
{
Map
<
JCTree
,
List
<
VarSymbol
>>
varMap
=
aliveRangeClosingTrees
.
get
(
method
);
if
(
varMap
!=
null
)
{
List
<
VarSymbol
>
result
=
varMap
.
remove
(
tree
);
if
(
varMap
.
isEmpty
())
{
aliveRangeClosingTrees
.
remove
(
method
);
}
return
result
;
}
return
null
;
}
/* This method should be used for debugging LVT related issues.
*/
@Override
public
String
toString
()
{
String
result
=
""
;
for
(
Entry
<
MethodSymbol
,
Map
<
JCTree
,
List
<
VarSymbol
>>>
mainEntry:
aliveRangeClosingTrees
.
entrySet
())
{
result
+=
"Method: \n"
+
mainEntry
.
getKey
().
flatName
()
+
"\n"
;
int
i
=
1
;
for
(
Entry
<
JCTree
,
List
<
VarSymbol
>>
treeEntry:
mainEntry
.
getValue
().
entrySet
())
{
result
+=
" Tree "
+
i
+
": \n"
+
treeEntry
.
getKey
().
toString
()
+
"\n"
;
result
+=
" Variables closed:\n"
;
for
(
VarSymbol
var
:
treeEntry
.
getValue
())
{
result
+=
" "
+
var
.
toString
();
}
result
+=
"\n"
;
i
++;
}
}
return
result
;
}
}
test/tools/javac/flow/LVTHarness.java
浏览文件 @
85661013
/*
* Copyright (c) 2013, 201
4
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 201
5
, 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
...
...
@@ -23,7 +23,7 @@
/*
* @test
* @bug 7047734 8027660 8037937 8047719 8058708
* @bug 7047734 8027660 8037937 8047719 8058708
8064857
* @summary The LVT is not generated correctly during some try/catch scenarios
* javac crash while creating LVT entry for a local variable defined in
* an inner block
...
...
@@ -144,7 +144,7 @@ public class LVTHarness {
}
void
checkMethod
(
ConstantPool
constantPool
,
Method
method
,
AliveRanges
ranges
)
throws
InvalidIndex
,
UnexpectedEntry
{
throws
InvalidIndex
,
UnexpectedEntry
,
ConstantPoolException
{
Code_attribute
code
=
(
Code_attribute
)
method
.
attributes
.
get
(
Attribute
.
Code
);
LocalVariableTable_attribute
lvt
=
(
LocalVariableTable_attribute
)
(
code
.
attributes
.
get
(
Attribute
.
LocalVariableTable
));
...
...
@@ -166,7 +166,7 @@ public class LVTHarness {
}
if
(
i
<
infoFromRanges
.
size
())
{
error
(
infoFromLVT
,
infoFromRanges
);
error
(
infoFromLVT
,
infoFromRanges
,
method
.
getName
(
constantPool
).
toString
()
);
}
}
...
...
@@ -202,9 +202,10 @@ public class LVTHarness {
return
sb
.
toString
();
}
protected
void
error
(
List
<
String
>
infoFromLVT
,
List
<
String
>
infoFromRanges
)
{
protected
void
error
(
List
<
String
>
infoFromLVT
,
List
<
String
>
infoFromRanges
,
String
methodName
)
{
nerrors
++;
System
.
err
.
printf
(
"Error occurred while checking file: %s\n"
,
jfo
.
getName
());
System
.
err
.
printf
(
"at method: %s\n"
,
methodName
);
System
.
err
.
println
(
"The range info from the annotations is"
);
printStringListToErrOutput
(
infoFromRanges
);
System
.
err
.
println
();
...
...
test/tools/javac/flow/tests/TestCaseFor.java
浏览文件 @
85661013
...
...
@@ -2,7 +2,7 @@
public
class
TestCaseFor
{
@AliveRange
(
varName
=
"o"
,
bytecodeStart
=
10
,
bytecodeLength
=
8
)
@AliveRange
(
varName
=
"o"
,
bytecodeStart
=
10
,
bytecodeLength
=
11
)
@AliveRange
(
varName
=
"o"
,
bytecodeStart
=
24
,
bytecodeLength
=
1
)
void
m1
(
String
[]
args
)
{
Object
o
;
...
...
@@ -13,7 +13,7 @@ public class TestCaseFor {
o
=
""
;
}
@AliveRange
(
varName
=
"o"
,
bytecodeStart
=
10
,
bytecodeLength
=
8
)
@AliveRange
(
varName
=
"o"
,
bytecodeStart
=
10
,
bytecodeLength
=
11
)
@AliveRange
(
varName
=
"o"
,
bytecodeStart
=
24
,
bytecodeLength
=
1
)
void
m2
(
String
[]
args
)
{
Object
o
;
...
...
test/tools/javac/flow/tests/TestCaseForEach.java
浏览文件 @
85661013
...
...
@@ -2,7 +2,7 @@
public
class
TestCaseForEach
{
@AliveRange
(
varName
=
"o"
,
bytecodeStart
=
25
,
bytecodeLength
=
8
)
@AliveRange
(
varName
=
"o"
,
bytecodeStart
=
25
,
bytecodeLength
=
11
)
@AliveRange
(
varName
=
"o"
,
bytecodeStart
=
39
,
bytecodeLength
=
1
)
void
m
(
String
[]
args
)
{
Object
o
;
...
...
test/tools/javac/flow/tests/TestCaseIfElse.java
浏览文件 @
85661013
...
...
@@ -60,4 +60,19 @@ public class TestCaseIfElse {
}
return
null
;
}
@AliveRange
(
varName
=
"i"
,
bytecodeStart
=
6
,
bytecodeLength
=
2
)
int
m4
(
boolean
flag
)
{
int
i
;
label:
{
if
(
flag
)
{
i
=
1
;
}
else
{
break
label
;
}
return
i
;
}
return
-
1
;
}
}
test/tools/javac/flow/tests/TestCaseSwitch.java
浏览文件 @
85661013
...
...
@@ -81,4 +81,26 @@ public class TestCaseSwitch {
o
=
"finish"
;
}
@AliveRange
(
varName
=
"oCache"
,
bytecodeStart
=
30
,
bytecodeLength
=
6
)
@AliveRange
(
varName
=
"cache"
,
bytecodeStart
=
41
,
bytecodeLength
=
3
)
@AliveRange
(
varName
=
"cache"
,
bytecodeStart
=
54
,
bytecodeLength
=
2
)
@AliveRange
(
varName
=
"service"
,
bytecodeStart
=
39
,
bytecodeLength
=
5
)
Object
m4
(
int
i
)
{
Object
cache
;
switch
(
i
)
{
case
0
:
Object
oCache
=
null
;
if
(
oCache
!=
null
)
{
return
oCache
;
}
case
1
:
Object
service
=
null
;
cache
=
null
;
break
;
default
:
throw
new
AssertionError
(
""
);
}
return
cache
;
}
}
test/tools/javac/flow/tests/TestCaseTry.java
浏览文件 @
85661013
...
...
@@ -17,7 +17,8 @@ public class TestCaseTry {
}
@AliveRange
(
varName
=
"o"
,
bytecodeStart
=
3
,
bytecodeLength
=
16
)
@AliveRange
(
varName
=
"o"
,
bytecodeStart
=
23
,
bytecodeLength
=
23
)
@AliveRange
(
varName
=
"o"
,
bytecodeStart
=
23
,
bytecodeLength
=
8
)
@AliveRange
(
varName
=
"o"
,
bytecodeStart
=
35
,
bytecodeLength
=
11
)
void
m1
()
{
Object
o
;
try
{
...
...
@@ -33,7 +34,8 @@ public class TestCaseTry {
}
@AliveRange
(
varName
=
"o"
,
bytecodeStart
=
3
,
bytecodeLength
=
16
)
@AliveRange
(
varName
=
"o"
,
bytecodeStart
=
23
,
bytecodeLength
=
31
)
@AliveRange
(
varName
=
"o"
,
bytecodeStart
=
23
,
bytecodeLength
=
16
)
@AliveRange
(
varName
=
"o"
,
bytecodeStart
=
43
,
bytecodeLength
=
11
)
void
m2
()
{
Object
o
;
try
{
...
...
@@ -51,7 +53,8 @@ public class TestCaseTry {
}
@AliveRange
(
varName
=
"o"
,
bytecodeStart
=
22
,
bytecodeLength
=
38
)
@AliveRange
(
varName
=
"o"
,
bytecodeStart
=
103
,
bytecodeLength
=
8
)
@AliveRange
(
varName
=
"o"
,
bytecodeStart
=
103
,
bytecodeLength
=
3
)
@AliveRange
(
varName
=
"o"
,
bytecodeStart
=
110
,
bytecodeLength
=
1
)
void
m3
()
{
Object
o
;
try
(
BufferedReader
br
=
...
...
test/tools/javac/flow/tests/TestCaseWhile.java
浏览文件 @
85661013
...
...
@@ -2,7 +2,7 @@
public
class
TestCaseWhile
{
@AliveRange
(
varName
=
"o"
,
bytecodeStart
=
9
,
bytecodeLength
=
5
)
@AliveRange
(
varName
=
"o"
,
bytecodeStart
=
9
,
bytecodeLength
=
8
)
@AliveRange
(
varName
=
"o"
,
bytecodeStart
=
20
,
bytecodeLength
=
1
)
void
m
(
String
[]
args
)
{
Object
o
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录