Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_langtools
提交
cce529ce
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看板
提交
cce529ce
编写于
10月 18, 2013
作者:
J
jjg
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
8026749: Missing LV table in lambda bodies
Reviewed-by: vromero, jlahoda
上级
be5910ac
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
248 addition
and
8 deletion
+248
-8
src/share/classes/com/sun/tools/javac/code/Flags.java
src/share/classes/com/sun/tools/javac/code/Flags.java
+7
-1
src/share/classes/com/sun/tools/javac/comp/Flow.java
src/share/classes/com/sun/tools/javac/comp/Flow.java
+3
-3
src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java
...hare/classes/com/sun/tools/javac/comp/LambdaToMethod.java
+15
-3
src/share/classes/com/sun/tools/javac/jvm/Gen.java
src/share/classes/com/sun/tools/javac/jvm/Gen.java
+3
-1
test/tools/javac/lambda/LocalVariableTable.java
test/tools/javac/lambda/LocalVariableTable.java
+220
-0
未找到文件。
src/share/classes/com/sun/tools/javac/code/Flags.java
浏览文件 @
cce529ce
...
...
@@ -270,6 +270,11 @@ public class Flags {
*/
public
static
final
long
POTENTIALLY_AMBIGUOUS
=
1L
<<
48
;
/**
* Flag that marks a synthetic method body for a lambda expression
*/
public
static
final
long
LAMBDA_METHOD
=
1L
<<
49
;
/** Modifier masks.
*/
public
static
final
int
...
...
@@ -378,7 +383,8 @@ public class Flags {
NOT_IN_PROFILE
(
Flags
.
NOT_IN_PROFILE
),
BAD_OVERRIDE
(
Flags
.
BAD_OVERRIDE
),
SIGNATURE_POLYMORPHIC
(
Flags
.
SIGNATURE_POLYMORPHIC
),
THROWS
(
Flags
.
THROWS
);
THROWS
(
Flags
.
THROWS
),
LAMBDA_METHOD
(
Flags
.
LAMBDA_METHOD
);
Flag
(
long
flag
)
{
this
.
value
=
flag
;
...
...
src/share/classes/com/sun/tools/javac/comp/Flow.java
浏览文件 @
cce529ce
...
...
@@ -1718,9 +1718,9 @@ public class Flow {
if
(
tree
.
body
==
null
)
{
return
;
}
/*
MemberEnter can generate synthetic methods, ignore them
/*
Ignore synthetic methods, except for translated lambda methods.
*/
if
((
tree
.
sym
.
flags
()
&
SYNTHETIC
)
!=
0
)
{
if
((
tree
.
sym
.
flags
()
&
(
SYNTHETIC
|
LAMBDA_METHOD
))
==
SYNTHETIC
)
{
return
;
}
...
...
@@ -1795,7 +1795,7 @@ public class Flow {
protected
void
initParam
(
JCVariableDecl
def
)
{
inits
.
incl
(
def
.
sym
.
adr
);
uninits
.
excl
(
def
.
sym
.
adr
);
}
}
public
void
visitVarDef
(
JCVariableDecl
tree
)
{
boolean
track
=
trackable
(
tree
.
sym
);
...
...
src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java
浏览文件 @
cce529ce
...
...
@@ -30,6 +30,7 @@ import com.sun.tools.javac.tree.JCTree.JCMemberReference.ReferenceKind;
import
com.sun.tools.javac.tree.TreeMaker
;
import
com.sun.tools.javac.tree.TreeTranslator
;
import
com.sun.tools.javac.code.Attribute
;
import
com.sun.tools.javac.code.Flags
;
import
com.sun.tools.javac.code.Kinds
;
import
com.sun.tools.javac.code.Scope
;
import
com.sun.tools.javac.code.Symbol
;
...
...
@@ -1315,7 +1316,9 @@ public class LambdaToMethod extends TreeTranslator {
ListBuffer
<
JCVariableDecl
>
paramBuff
=
new
ListBuffer
<
JCVariableDecl
>();
int
i
=
0
;
for
(
List
<
Type
>
l
=
ptypes
;
l
.
nonEmpty
();
l
=
l
.
tail
)
{
paramBuff
.
append
(
make
.
Param
(
make
.
paramName
(
i
++),
l
.
head
,
owner
));
JCVariableDecl
param
=
make
.
Param
(
make
.
paramName
(
i
++),
l
.
head
,
owner
);
param
.
sym
.
pos
=
tree
.
pos
;
paramBuff
.
append
(
param
);
}
List
<
JCVariableDecl
>
params
=
paramBuff
.
toList
();
...
...
@@ -1755,7 +1758,7 @@ public class LambdaToMethod extends TreeTranslator {
((
VarSymbol
)
ret
).
pos
=
((
VarSymbol
)
sym
).
pos
;
break
;
case
CAPTURED_VAR:
ret
=
new
VarSymbol
(
SYNTHETIC
|
FINAL
,
name
,
types
.
erasure
(
sym
.
type
),
translatedSym
)
{
ret
=
new
VarSymbol
(
SYNTHETIC
|
FINAL
|
PARAMETER
,
name
,
types
.
erasure
(
sym
.
type
),
translatedSym
)
{
@Override
public
Symbol
baseSymbol
()
{
//keep mapping with original captured symbol
...
...
@@ -1763,8 +1766,17 @@ public class LambdaToMethod extends TreeTranslator {
}
};
break
;
case
LOCAL_VAR:
ret
=
new
VarSymbol
(
FINAL
,
name
,
types
.
erasure
(
sym
.
type
),
translatedSym
);
((
VarSymbol
)
ret
).
pos
=
((
VarSymbol
)
sym
).
pos
;
break
;
case
PARAM:
ret
=
new
VarSymbol
(
FINAL
|
PARAMETER
,
name
,
types
.
erasure
(
sym
.
type
),
translatedSym
);
((
VarSymbol
)
ret
).
pos
=
((
VarSymbol
)
sym
).
pos
;
break
;
default
:
ret
=
makeSyntheticVar
(
FINAL
,
name
,
types
.
erasure
(
sym
.
type
),
translatedSym
);
((
VarSymbol
)
ret
).
pos
=
((
VarSymbol
)
sym
).
pos
;
}
if
(
ret
!=
sym
)
{
ret
.
setDeclarationAttributes
(
sym
.
getRawAttributes
());
...
...
@@ -1845,7 +1857,7 @@ public class LambdaToMethod extends TreeTranslator {
// If instance access isn't needed, make it static.
// Interface instance methods must be default methods.
// Lambda methods are private synthetic.
translatedSym
.
flags_field
=
SYNTHETIC
|
translatedSym
.
flags_field
=
SYNTHETIC
|
LAMBDA_METHOD
|
PRIVATE
|
(
thisReferenced
?
(
inInterface
?
DEFAULT
:
0
)
:
STATIC
);
...
...
src/share/classes/com/sun/tools/javac/jvm/Gen.java
浏览文件 @
cce529ce
...
...
@@ -2892,7 +2892,8 @@ public class Gen extends JCTree.Visitor {
@Override
public
void
visitMethodDef
(
JCMethodDecl
tree
)
{
if
((
tree
.
sym
.
flags
()
&
(
SYNTHETIC
|
GENERATEDCONSTR
))
!=
0
)
{
if
((
tree
.
sym
.
flags
()
&
(
SYNTHETIC
|
GENERATEDCONSTR
))
!=
0
&&
(
tree
.
sym
.
flags
()
&
LAMBDA_METHOD
)
==
0
)
{
return
;
}
if
(
tree
.
name
.
equals
(
names
.
clinit
))
{
...
...
@@ -2906,6 +2907,7 @@ public class Gen extends JCTree.Visitor {
return
;
}
currentMethod
=
tree
.
sym
;
super
.
visitMethodDef
(
tree
);
}
...
...
test/tools/javac/lambda/LocalVariableTable.java
0 → 100644
浏览文件 @
cce529ce
/*
* 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.
*
* 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.
*/
/*
* @test
* @bug 8025998 8026749
* @summary Missing LV table in lambda bodies
* @compile -g LocalVariableTable.java
* @run main LocalVariableTable
*/
import
java.io.*
;
import
java.lang.annotation.*
;
import
java.util.*
;
import
com.sun.tools.classfile.*
;
/*
* The test checks that a LocalVariableTable attribute is generated for the
* method bodies representing lambda expressions, and checks that the expected
* set of entries is found in the attribute.
*
* Since the bug was about missing entries in the LVT, not malformed entries,
* the test is not intended to be a detailed test of the contents of each
* LocalVariableTable entry: it is assumed that if a entry is present, it
* will have the correct contents.
*
* The test looks for test cases represented by nested classes whose
* name begins with "Lambda". Each such class contains a lambda expression
* that will mapped into a lambda method, and because the test is compiled
* with -g, these methods should have a LocalVariableTable. The set of
* expected names in the LVT is provided in an annotation on the class for
* the test case.
*/
public
class
LocalVariableTable
{
public
static
void
main
(
String
...
args
)
throws
Exception
{
new
LocalVariableTable
().
run
();
}
void
run
()
throws
Exception
{
// the declared classes are returned in an unspecified order,
// so for neatness, sort them by name before processing them
Class
<?>[]
classes
=
getClass
().
getDeclaredClasses
();
Arrays
.
sort
(
classes
,
(
c1
,
c2
)
->
c1
.
getName
().
compareTo
(
c2
.
getName
()));
for
(
Class
<?>
c
:
classes
)
{
if
(
c
.
getSimpleName
().
startsWith
(
"Lambda"
))
check
(
c
);
}
if
(
errors
>
0
)
throw
new
Exception
(
errors
+
" errors found"
);
}
/** Check an individual test case. */
void
check
(
Class
<?>
c
)
throws
Exception
{
System
.
err
.
println
(
"Checking "
+
c
.
getSimpleName
());
Expect
expect
=
c
.
getAnnotation
(
Expect
.
class
);
if
(
expect
==
null
)
{
error
(
"@Expect not found for class "
+
c
.
getSimpleName
());
return
;
}
ClassFile
cf
=
ClassFile
.
read
(
getClass
().
getResource
(
c
.
getName
()
+
".class"
).
openStream
());
Method
m
=
getLambdaMethod
(
cf
);
if
(
m
==
null
)
{
error
(
"lambda method not found"
);
return
;
}
Code_attribute
code
=
(
Code_attribute
)
m
.
attributes
.
get
(
Attribute
.
Code
);
if
(
code
==
null
)
{
error
(
"Code attribute not found"
);
return
;
}
LocalVariableTable_attribute
lvt
=
(
LocalVariableTable_attribute
)
code
.
attributes
.
get
(
Attribute
.
LocalVariableTable
);
if
(
lvt
==
null
)
{
error
(
"LocalVariableTable attribute not found"
);
return
;
}
Set
<
String
>
foundNames
=
new
LinkedHashSet
<>();
for
(
LocalVariableTable_attribute
.
Entry
e:
lvt
.
local_variable_table
)
{
foundNames
.
add
(
cf
.
constant_pool
.
getUTF8Value
(
e
.
name_index
));
}
Set
<
String
>
expectNames
=
new
LinkedHashSet
<>(
Arrays
.
asList
(
expect
.
value
()));
if
(!
foundNames
.
equals
(
expectNames
))
{
Set
<
String
>
foundOnly
=
new
LinkedHashSet
<>(
foundNames
);
foundOnly
.
removeAll
(
expectNames
);
for
(
String
s:
foundOnly
)
error
(
"Unexpected name found: "
+
s
);
Set
<
String
>
expectOnly
=
new
LinkedHashSet
<>(
expectNames
);
expectOnly
.
removeAll
(
foundNames
);
for
(
String
s:
expectOnly
)
error
(
"Expected name not found: "
+
s
);
}
}
/** Get a method whose name begins "lambda$...". */
Method
getLambdaMethod
(
ClassFile
cf
)
throws
ConstantPoolException
{
for
(
Method
m:
cf
.
methods
)
{
if
(
m
.
getName
(
cf
.
constant_pool
).
startsWith
(
"lambda$"
))
return
m
;
}
return
null
;
}
/** Report an error. */
void
error
(
String
msg
)
{
System
.
err
.
println
(
"Error: "
+
msg
);
errors
++;
}
int
errors
;
/**
* Annotation used to provide the set of names expected in the LVT attribute.
*/
@Retention
(
RetentionPolicy
.
RUNTIME
)
@interface
Expect
{
String
[]
value
();
}
/** Functional interface with nullary method. */
interface
Run0
{
public
void
run
();
}
/** Functional interface with 1-ary method. */
interface
Run1
{
public
void
run
(
int
a0
);
}
/** Functional interface with 2-ary method. */
interface
Run2
{
public
void
run
(
int
a0
,
int
a1
);
}
/*
* ---------- Test cases ---------------------------------------------------
*/
@Expect
({
"x"
})
static
class
Lambda_Args0_Local1
{
Run0
r
=
()
->
{
int
x
=
0
;
};
}
@Expect
({
"x"
,
"this"
})
static
class
Lambda_Args0_Local1_this
{
int
v
;
Run0
r
=
()
->
{
int
x
=
v
;
};
}
@Expect
({
"a"
})
static
class
Lambda_Args1_Local0
{
Run1
r
=
(
a
)
->
{
};
}
@Expect
({
"a"
,
"x"
})
static
class
Lambda_Args1_Local1
{
Run1
r
=
(
a
)
->
{
int
x
=
a
;
};
}
@Expect
({
"a"
,
"x"
})
static
class
Lambda_Args1_Local1_Captured1
{
void
m
()
{
int
v
=
0
;
Run1
r
=
(
a
)
->
{
int
x
=
a
+
v
;
};
}
}
@Expect
({
"a1"
,
"a2"
,
"x1"
,
"x2"
,
"this"
})
static
class
Lambda_Args2_Local2_Captured2_this
{
int
v
;
void
m
()
{
int
v1
=
0
;
int
v2
=
0
;
Run2
r
=
(
a1
,
a2
)
->
{
int
x1
=
a1
+
v1
+
v
;
int
x2
=
a2
+
v2
+
v
;
};
}
}
@Expect
({
"e"
})
static
class
Lambda_Try_Catch
{
private
static
Runnable
asUncheckedRunnable
(
Closeable
c
)
{
return
()
->
{
try
{
c
.
close
();
}
catch
(
IOException
e
)
{
throw
new
UncheckedIOException
(
e
);
}
};
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录