提交 b55e5313 编写于 作者: K kvn

7129284: +DoEscapeAnalysis regression w/ early build of 7u4 (HotSpot 23) on Linux

Summary: Removed code which tried to create edges from fields of destination objects of arraycopy to fields of source objects. Added 30 sec time limit for EA graph construction.
Reviewed-by: never
上级 0f222ff2
/*
* Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2012, 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
......@@ -1687,12 +1687,23 @@ bool ConnectionGraph::compute_escape() {
// Observed 8 passes in jvm2008 compiler.compiler.
// Set limit to 20 to catch situation when something
// did go wrong and recompile the method without EA.
// Also limit build time to 30 sec (60 in debug VM).
#define CG_BUILD_ITER_LIMIT 20
#ifdef ASSERT
#define CG_BUILD_TIME_LIMIT 60.0
#else
#define CG_BUILD_TIME_LIMIT 30.0
#endif
uint length = worklist.length();
int iterations = 0;
while(_progress && (iterations++ < CG_BUILD_ITER_LIMIT)) {
elapsedTimer time;
while(_progress &&
(iterations++ < CG_BUILD_ITER_LIMIT) &&
(time.seconds() < CG_BUILD_TIME_LIMIT)) {
time.start();
_progress = false;
for( uint next = 0; next < length; ++next ) {
int ni = worklist.at(next);
......@@ -1701,18 +1712,19 @@ bool ConnectionGraph::compute_escape() {
assert(n != NULL, "should be known node");
build_connection_graph(n, igvn);
}
time.stop();
}
if (iterations >= CG_BUILD_ITER_LIMIT) {
assert(iterations < CG_BUILD_ITER_LIMIT,
err_msg("infinite EA connection graph build with %d nodes and worklist size %d",
nodes_size(), length));
if ((iterations >= CG_BUILD_ITER_LIMIT) ||
(time.seconds() >= CG_BUILD_TIME_LIMIT)) {
assert(false, err_msg("infinite EA connection graph build (%f sec, %d iterations) with %d nodes and worklist size %d",
time.seconds(), iterations, nodes_size(), length));
// Possible infinite build_connection_graph loop,
// retry compilation without escape analysis.
C->record_failure(C2Compiler::retry_no_escape_analysis());
// bailout (no changes to ideal graph were made).
_collecting = false;
return false;
}
#undef CG_BUILD_ITER_LIMIT
#undef CG_BUILD_TIME_LIMIT
// 5. Propagate escaped states.
worklist.clear();
......@@ -2292,26 +2304,9 @@ void ConnectionGraph::process_call_arguments(CallNode *call, PhaseTransform *pha
PointsToNode::EscapeState arg_esc = ptnode_adr(arg->_idx)->escape_state();
if (!arg->is_top() && at->isa_ptr() && aat->isa_ptr() &&
(is_arraycopy || arg_esc < PointsToNode::ArgEscape)) {
#ifdef ASSERT
assert(aat == Type::TOP || aat == TypePtr::NULL_PTR ||
aat->isa_ptr() != NULL, "expecting an Ptr");
bool arg_has_oops = aat->isa_oopptr() &&
(aat->isa_oopptr()->klass() == NULL || aat->isa_instptr() ||
(aat->isa_aryptr() && aat->isa_aryptr()->klass()->is_obj_array_klass()));
if (i == TypeFunc::Parms) {
src_has_oops = arg_has_oops;
}
//
// src or dst could be j.l.Object when other is basic type array:
//
// arraycopy(char[],0,Object*,0,size);
// arraycopy(Object*,0,char[],0,size);
//
// Don't add edges from dst's fields in such cases.
//
bool arg_is_arraycopy_dest = src_has_oops && is_arraycopy &&
arg_has_oops && (i > TypeFunc::Parms);
#ifdef ASSERT
if (!(is_arraycopy ||
call->as_CallLeaf()->_name != NULL &&
(strcmp(call->as_CallLeaf()->_name, "g1_wb_pre") == 0 ||
......@@ -2321,13 +2316,7 @@ void ConnectionGraph::process_call_arguments(CallNode *call, PhaseTransform *pha
assert(false, "EA: unexpected CallLeaf");
}
#endif
// Always process arraycopy's destination object since
// we need to add all possible edges to references in
// source object.
if (arg_esc >= PointsToNode::ArgEscape &&
!arg_is_arraycopy_dest) {
continue;
}
if (arg_esc < PointsToNode::ArgEscape) {
set_escape_state(arg->_idx, PointsToNode::ArgEscape);
Node* arg_base = arg;
if (arg->is_AddP()) {
......@@ -2340,52 +2329,49 @@ void ConnectionGraph::process_call_arguments(CallNode *call, PhaseTransform *pha
// pointer to the base (with offset) is passed as argument.
//
arg_base = get_addp_base(arg);
set_escape_state(arg_base->_idx, PointsToNode::ArgEscape);
}
}
VectorSet argset = *PointsTo(arg_base); // Clone set
for( VectorSetI j(&argset); j.test(); ++j ) {
uint pd = j.elem; // Destination object
set_escape_state(pd, PointsToNode::ArgEscape);
if (arg_is_arraycopy_dest) {
PointsToNode* ptd = ptnode_adr(pd);
// Conservatively reference an unknown object since
// not all source's fields/elements may be known.
add_edge_from_fields(pd, _phantom_object, Type::OffsetBot);
Node *src = call->in(TypeFunc::Parms)->uncast();
bool arg_has_oops = aat->isa_oopptr() &&
(aat->isa_oopptr()->klass() == NULL || aat->isa_instptr() ||
(aat->isa_aryptr() && aat->isa_aryptr()->klass()->is_obj_array_klass()));
if (i == TypeFunc::Parms) {
src_has_oops = arg_has_oops;
}
//
// src or dst could be j.l.Object when other is basic type array:
//
// arraycopy(char[],0,Object*,0,size);
// arraycopy(Object*,0,char[],0,size);
//
// Do nothing special in such cases.
//
if (is_arraycopy && (i > TypeFunc::Parms) &&
src_has_oops && arg_has_oops) {
// Destination object's fields reference an unknown object.
Node* arg_base = arg;
if (arg->is_AddP()) {
arg_base = get_addp_base(arg);
}
for (VectorSetI s(PointsTo(arg_base)); s.test(); ++s) {
uint ps = s.elem;
set_escape_state(ps, PointsToNode::ArgEscape);
add_edge_from_fields(ps, _phantom_object, Type::OffsetBot);
}
// Conservatively all values in source object fields globally escape
// since we don't know if values in destination object fields
// escape (it could be traced but it is too expensive).
Node* src = call->in(TypeFunc::Parms)->uncast();
Node* src_base = src;
if (src->is_AddP()) {
src_base = get_addp_base(src);
}
// Create edges from destination's fields to
// everything known source's fields could point to.
for( VectorSetI s(PointsTo(src_base)); s.test(); ++s ) {
for (VectorSetI s(PointsTo(src_base)); s.test(); ++s) {
uint ps = s.elem;
bool has_bottom_offset = false;
for (uint fd = 0; fd < ptd->edge_count(); fd++) {
assert(ptd->edge_type(fd) == PointsToNode::FieldEdge, "expecting a field edge");
int fdi = ptd->edge_target(fd);
PointsToNode* pfd = ptnode_adr(fdi);
int offset = pfd->offset();
if (offset == Type::OffsetBot)
has_bottom_offset = true;
assert(offset != -1, "offset should be set");
add_deferred_edge_to_fields(fdi, ps, offset);
}
// Destination object may not have access (no field edge)
// to fields which are accessed in source object.
// As result no edges will be created to those source's
// fields and escape state of destination object will
// not be propagated to those fields.
//
// Mark source object as global escape except in
// the case with Type::OffsetBot field (which is
// common case for array elements access) when
// edges are created to all source's fields.
if (!has_bottom_offset) {
set_escape_state(ps, PointsToNode::GlobalEscape);
}
}
set_escape_state(ps, PointsToNode::ArgEscape);
// Use OffsetTop to indicate fields global escape.
add_edge_from_fields(ps, _phantom_object, Type::OffsetTop);
}
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册