224 Compile* C = _stringopts->C;
225 CallStaticJavaNode* call = new (C) CallStaticJavaNode(call_type, call_addr, "uncommon_trap",
226 jvms->bci(), no_memory_effects);
227 for (int e = 0; e < TypeFunc::Parms; e++) {
228 call->init_req(e, uct->in(e));
229 }
230 // Set the trap request to record intrinsic failure if this trap
231 // is taken too many times. Ideally we would handle then traps by
232 // doing the original bookkeeping in the MDO so that if it caused
233 // the code to be thrown out we could still recompile and use the
234 // optimization. Failing the uncommon traps doesn't really mean
235 // that the optimization is a bad idea but there's no other way to
236 // do the MDO updates currently.
237 int trap_request = Deoptimization::make_trap_request(Deoptimization::Reason_intrinsic,
238 Deoptimization::Action_make_not_entrant);
239 call->init_req(TypeFunc::Parms, __ intcon(trap_request));
240 kit.add_safepoint_edges(call);
241
242 _stringopts->gvn()->transform(call);
243 C->gvn_replace_by(uct, call);
244 uct->disconnect_inputs(NULL);
245 }
246 }
247
248 void cleanup() {
249 // disconnect the hook node
250 _arguments->disconnect_inputs(NULL);
251 }
252 };
253
254
255 void StringConcat::eliminate_unneeded_control() {
256 for (uint i = 0; i < _control.size(); i++) {
257 Node* n = _control.at(i);
258 if (n->is_Allocate()) {
259 eliminate_initialize(n->as_Allocate()->initialization());
260 }
261 if (n->is_Call()) {
262 if (n != _end) {
263 eliminate_call(n->as_Call());
264 }
265 } else if (n->is_IfTrue()) {
266 Compile* C = _stringopts->C;
267 C->gvn_replace_by(n, n->in(0)->in(0));
268 C->gvn_replace_by(n->in(0), C->top());
269 }
270 }
341 }
342 C->gvn_replace_by(call, C->top());
343 }
344
345 void StringConcat::eliminate_initialize(InitializeNode* init) {
346 Compile* C = _stringopts->C;
347
348 // Eliminate Initialize node.
349 assert(init->outcnt() <= 2, "only a control and memory projection expected");
350 assert(init->req() <= InitializeNode::RawStores, "no pending inits");
351 Node *ctrl_proj = init->proj_out(TypeFunc::Control);
352 if (ctrl_proj != NULL) {
353 C->gvn_replace_by(ctrl_proj, init->in(TypeFunc::Control));
354 }
355 Node *mem_proj = init->proj_out(TypeFunc::Memory);
356 if (mem_proj != NULL) {
357 Node *mem = init->in(TypeFunc::Memory);
358 C->gvn_replace_by(mem_proj, mem);
359 }
360 C->gvn_replace_by(init, C->top());
361 init->disconnect_inputs(NULL);
362 }
363
364 Node_List PhaseStringOpts::collect_toString_calls() {
365 Node_List string_calls;
366 Node_List worklist;
367
368 _visited.Clear();
369
370 // Prime the worklist
371 for (uint i = 1; i < C->root()->len(); i++) {
372 Node* n = C->root()->in(i);
373 if (n != NULL && !_visited.test_set(n->_idx)) {
374 worklist.push(n);
375 }
376 }
377
378 while (worklist.size() > 0) {
379 Node* ctrl = worklist.pop();
380 if (StringConcat::is_SB_toString(ctrl)) {
381 CallStaticJavaNode* csj = ctrl->as_CallStaticJava();
1460 if (result == NULL) {
1461 PreserveReexecuteState preexecs(&kit);
1462 // The original jvms is for an allocation of either a String or
1463 // StringBuffer so no stack adjustment is necessary for proper
1464 // reexecution.
1465 kit.jvms()->set_should_reexecute(true);
1466 result = kit.new_instance(__ makecon(TypeKlassPtr::make(C->env()->String_klass())));
1467 }
1468
1469 // Intialize the string
1470 if (java_lang_String::has_offset_field()) {
1471 kit.store_String_offset(kit.control(), result, __ intcon(0));
1472 kit.store_String_length(kit.control(), result, length);
1473 }
1474 kit.store_String_value(kit.control(), result, char_array);
1475
1476 // hook up the outgoing control and result
1477 kit.replace_call(sc->end(), result);
1478
1479 // Unhook any hook nodes
1480 string_sizes->disconnect_inputs(NULL);
1481 sc->cleanup();
1482 }
|
224 Compile* C = _stringopts->C;
225 CallStaticJavaNode* call = new (C) CallStaticJavaNode(call_type, call_addr, "uncommon_trap",
226 jvms->bci(), no_memory_effects);
227 for (int e = 0; e < TypeFunc::Parms; e++) {
228 call->init_req(e, uct->in(e));
229 }
230 // Set the trap request to record intrinsic failure if this trap
231 // is taken too many times. Ideally we would handle then traps by
232 // doing the original bookkeeping in the MDO so that if it caused
233 // the code to be thrown out we could still recompile and use the
234 // optimization. Failing the uncommon traps doesn't really mean
235 // that the optimization is a bad idea but there's no other way to
236 // do the MDO updates currently.
237 int trap_request = Deoptimization::make_trap_request(Deoptimization::Reason_intrinsic,
238 Deoptimization::Action_make_not_entrant);
239 call->init_req(TypeFunc::Parms, __ intcon(trap_request));
240 kit.add_safepoint_edges(call);
241
242 _stringopts->gvn()->transform(call);
243 C->gvn_replace_by(uct, call);
244 uct->disconnect_inputs(NULL, C);
245 }
246 }
247
248 void cleanup() {
249 // disconnect the hook node
250 _arguments->disconnect_inputs(NULL, _stringopts->C);
251 }
252 };
253
254
255 void StringConcat::eliminate_unneeded_control() {
256 for (uint i = 0; i < _control.size(); i++) {
257 Node* n = _control.at(i);
258 if (n->is_Allocate()) {
259 eliminate_initialize(n->as_Allocate()->initialization());
260 }
261 if (n->is_Call()) {
262 if (n != _end) {
263 eliminate_call(n->as_Call());
264 }
265 } else if (n->is_IfTrue()) {
266 Compile* C = _stringopts->C;
267 C->gvn_replace_by(n, n->in(0)->in(0));
268 C->gvn_replace_by(n->in(0), C->top());
269 }
270 }
341 }
342 C->gvn_replace_by(call, C->top());
343 }
344
345 void StringConcat::eliminate_initialize(InitializeNode* init) {
346 Compile* C = _stringopts->C;
347
348 // Eliminate Initialize node.
349 assert(init->outcnt() <= 2, "only a control and memory projection expected");
350 assert(init->req() <= InitializeNode::RawStores, "no pending inits");
351 Node *ctrl_proj = init->proj_out(TypeFunc::Control);
352 if (ctrl_proj != NULL) {
353 C->gvn_replace_by(ctrl_proj, init->in(TypeFunc::Control));
354 }
355 Node *mem_proj = init->proj_out(TypeFunc::Memory);
356 if (mem_proj != NULL) {
357 Node *mem = init->in(TypeFunc::Memory);
358 C->gvn_replace_by(mem_proj, mem);
359 }
360 C->gvn_replace_by(init, C->top());
361 init->disconnect_inputs(NULL, C);
362 }
363
364 Node_List PhaseStringOpts::collect_toString_calls() {
365 Node_List string_calls;
366 Node_List worklist;
367
368 _visited.Clear();
369
370 // Prime the worklist
371 for (uint i = 1; i < C->root()->len(); i++) {
372 Node* n = C->root()->in(i);
373 if (n != NULL && !_visited.test_set(n->_idx)) {
374 worklist.push(n);
375 }
376 }
377
378 while (worklist.size() > 0) {
379 Node* ctrl = worklist.pop();
380 if (StringConcat::is_SB_toString(ctrl)) {
381 CallStaticJavaNode* csj = ctrl->as_CallStaticJava();
1460 if (result == NULL) {
1461 PreserveReexecuteState preexecs(&kit);
1462 // The original jvms is for an allocation of either a String or
1463 // StringBuffer so no stack adjustment is necessary for proper
1464 // reexecution.
1465 kit.jvms()->set_should_reexecute(true);
1466 result = kit.new_instance(__ makecon(TypeKlassPtr::make(C->env()->String_klass())));
1467 }
1468
1469 // Intialize the string
1470 if (java_lang_String::has_offset_field()) {
1471 kit.store_String_offset(kit.control(), result, __ intcon(0));
1472 kit.store_String_length(kit.control(), result, length);
1473 }
1474 kit.store_String_value(kit.control(), result, char_array);
1475
1476 // hook up the outgoing control and result
1477 kit.replace_call(sc->end(), result);
1478
1479 // Unhook any hook nodes
1480 string_sizes->disconnect_inputs(NULL, C);
1481 sc->cleanup();
1482 }
|