Mercurial > hg > truffle
annotate src/share/vm/c1/c1_LIRGenerator.cpp @ 20543:e7d0505c8a30
8059758: Footprint regressions with JDK-8038423
Summary: Changes in JDK-8038423 always initialize (zero out) virtual memory used for auxiliary data structures. This causes a footprint regression for G1 in startup benchmarks. This is because they do not touch that memory at all, so the operating system does not actually commit these pages. The fix is to, if the initialization value of the data structures matches the default value of just committed memory (=0), do not do anything.
Reviewed-by: jwilhelm, brutisso
author | tschatzl |
---|---|
date | Fri, 10 Oct 2014 15:51:58 +0200 |
parents | b29261b17343 |
children | 7848fc12602b |
rev | line source |
---|---|
0 | 1 /* |
10105
aeaca88565e6
8010862: The Method counter fields used for profiling can be allocated lazily.
jiangli
parents:
8869
diff
changeset
|
2 * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1378
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1378
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1378
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "c1/c1_Compilation.hpp" | |
27 #include "c1/c1_FrameMap.hpp" | |
28 #include "c1/c1_Instruction.hpp" | |
29 #include "c1/c1_LIRAssembler.hpp" | |
30 #include "c1/c1_LIRGenerator.hpp" | |
31 #include "c1/c1_ValueStack.hpp" | |
32 #include "ci/ciArrayKlass.hpp" | |
33 #include "ci/ciInstance.hpp" | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6616
diff
changeset
|
34 #include "ci/ciObjArray.hpp" |
1972 | 35 #include "runtime/sharedRuntime.hpp" |
36 #include "runtime/stubRoutines.hpp" | |
37 #include "utilities/bitMap.inline.hpp" | |
8001
db9981fd3124
8005915: Unify SERIALGC and INCLUDE_ALTERNATE_GCS
jprovino
parents:
7425
diff
changeset
|
38 #include "utilities/macros.hpp" |
db9981fd3124
8005915: Unify SERIALGC and INCLUDE_ALTERNATE_GCS
jprovino
parents:
7425
diff
changeset
|
39 #if INCLUDE_ALL_GCS |
1972 | 40 #include "gc_implementation/g1/heapRegion.hpp" |
8001
db9981fd3124
8005915: Unify SERIALGC and INCLUDE_ALTERNATE_GCS
jprovino
parents:
7425
diff
changeset
|
41 #endif // INCLUDE_ALL_GCS |
0 | 42 |
43 #ifdef ASSERT | |
44 #define __ gen()->lir(__FILE__, __LINE__)-> | |
45 #else | |
46 #define __ gen()->lir()-> | |
47 #endif | |
48 | |
1681
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
49 // TODO: ARM - Use some recognizable constant which still fits architectural constraints |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
50 #ifdef ARM |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
51 #define PATCHED_ADDR (204) |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
52 #else |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
53 #define PATCHED_ADDR (max_jint) |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
54 #endif |
0 | 55 |
56 void PhiResolverState::reset(int max_vregs) { | |
57 // Initialize array sizes | |
58 _virtual_operands.at_put_grow(max_vregs - 1, NULL, NULL); | |
59 _virtual_operands.trunc_to(0); | |
60 _other_operands.at_put_grow(max_vregs - 1, NULL, NULL); | |
61 _other_operands.trunc_to(0); | |
62 _vreg_table.at_put_grow(max_vregs - 1, NULL, NULL); | |
63 _vreg_table.trunc_to(0); | |
64 } | |
65 | |
66 | |
67 | |
68 //-------------------------------------------------------------- | |
69 // PhiResolver | |
70 | |
71 // Resolves cycles: | |
72 // | |
73 // r1 := r2 becomes temp := r1 | |
74 // r2 := r1 r1 := r2 | |
75 // r2 := temp | |
76 // and orders moves: | |
77 // | |
78 // r2 := r3 becomes r1 := r2 | |
79 // r1 := r2 r2 := r3 | |
80 | |
81 PhiResolver::PhiResolver(LIRGenerator* gen, int max_vregs) | |
82 : _gen(gen) | |
83 , _state(gen->resolver_state()) | |
84 , _temp(LIR_OprFact::illegalOpr) | |
85 { | |
86 // reinitialize the shared state arrays | |
87 _state.reset(max_vregs); | |
88 } | |
89 | |
90 | |
91 void PhiResolver::emit_move(LIR_Opr src, LIR_Opr dest) { | |
92 assert(src->is_valid(), ""); | |
93 assert(dest->is_valid(), ""); | |
94 __ move(src, dest); | |
95 } | |
96 | |
97 | |
98 void PhiResolver::move_temp_to(LIR_Opr dest) { | |
99 assert(_temp->is_valid(), ""); | |
100 emit_move(_temp, dest); | |
101 NOT_PRODUCT(_temp = LIR_OprFact::illegalOpr); | |
102 } | |
103 | |
104 | |
105 void PhiResolver::move_to_temp(LIR_Opr src) { | |
106 assert(_temp->is_illegal(), ""); | |
107 _temp = _gen->new_register(src->type()); | |
108 emit_move(src, _temp); | |
109 } | |
110 | |
111 | |
112 // Traverse assignment graph in depth first order and generate moves in post order | |
113 // ie. two assignments: b := c, a := b start with node c: | |
114 // Call graph: move(NULL, c) -> move(c, b) -> move(b, a) | |
115 // Generates moves in this order: move b to a and move c to b | |
116 // ie. cycle a := b, b := a start with node a | |
117 // Call graph: move(NULL, a) -> move(a, b) -> move(b, a) | |
118 // Generates moves in this order: move b to temp, move a to b, move temp to a | |
119 void PhiResolver::move(ResolveNode* src, ResolveNode* dest) { | |
120 if (!dest->visited()) { | |
121 dest->set_visited(); | |
122 for (int i = dest->no_of_destinations()-1; i >= 0; i --) { | |
123 move(dest, dest->destination_at(i)); | |
124 } | |
125 } else if (!dest->start_node()) { | |
126 // cylce in graph detected | |
127 assert(_loop == NULL, "only one loop valid!"); | |
128 _loop = dest; | |
129 move_to_temp(src->operand()); | |
130 return; | |
131 } // else dest is a start node | |
132 | |
133 if (!dest->assigned()) { | |
134 if (_loop == dest) { | |
135 move_temp_to(dest->operand()); | |
136 dest->set_assigned(); | |
137 } else if (src != NULL) { | |
138 emit_move(src->operand(), dest->operand()); | |
139 dest->set_assigned(); | |
140 } | |
141 } | |
142 } | |
143 | |
144 | |
145 PhiResolver::~PhiResolver() { | |
146 int i; | |
147 // resolve any cycles in moves from and to virtual registers | |
148 for (i = virtual_operands().length() - 1; i >= 0; i --) { | |
149 ResolveNode* node = virtual_operands()[i]; | |
150 if (!node->visited()) { | |
151 _loop = NULL; | |
152 move(NULL, node); | |
153 node->set_start_node(); | |
154 assert(_temp->is_illegal(), "move_temp_to() call missing"); | |
155 } | |
156 } | |
157 | |
158 // generate move for move from non virtual register to abitrary destination | |
159 for (i = other_operands().length() - 1; i >= 0; i --) { | |
160 ResolveNode* node = other_operands()[i]; | |
161 for (int j = node->no_of_destinations() - 1; j >= 0; j --) { | |
162 emit_move(node->operand(), node->destination_at(j)->operand()); | |
163 } | |
164 } | |
165 } | |
166 | |
167 | |
168 ResolveNode* PhiResolver::create_node(LIR_Opr opr, bool source) { | |
169 ResolveNode* node; | |
170 if (opr->is_virtual()) { | |
171 int vreg_num = opr->vreg_number(); | |
172 node = vreg_table().at_grow(vreg_num, NULL); | |
173 assert(node == NULL || node->operand() == opr, ""); | |
174 if (node == NULL) { | |
175 node = new ResolveNode(opr); | |
176 vreg_table()[vreg_num] = node; | |
177 } | |
178 // Make sure that all virtual operands show up in the list when | |
179 // they are used as the source of a move. | |
180 if (source && !virtual_operands().contains(node)) { | |
181 virtual_operands().append(node); | |
182 } | |
183 } else { | |
184 assert(source, ""); | |
185 node = new ResolveNode(opr); | |
186 other_operands().append(node); | |
187 } | |
188 return node; | |
189 } | |
190 | |
191 | |
192 void PhiResolver::move(LIR_Opr src, LIR_Opr dest) { | |
193 assert(dest->is_virtual(), ""); | |
194 // tty->print("move "); src->print(); tty->print(" to "); dest->print(); tty->cr(); | |
195 assert(src->is_valid(), ""); | |
196 assert(dest->is_valid(), ""); | |
197 ResolveNode* source = source_node(src); | |
198 source->append(destination_node(dest)); | |
199 } | |
200 | |
201 | |
202 //-------------------------------------------------------------- | |
203 // LIRItem | |
204 | |
205 void LIRItem::set_result(LIR_Opr opr) { | |
206 assert(value()->operand()->is_illegal() || value()->operand()->is_constant(), "operand should never change"); | |
207 value()->set_operand(opr); | |
208 | |
209 if (opr->is_virtual()) { | |
210 _gen->_instruction_for_operand.at_put_grow(opr->vreg_number(), value(), NULL); | |
211 } | |
212 | |
213 _result = opr; | |
214 } | |
215 | |
216 void LIRItem::load_item() { | |
217 if (result()->is_illegal()) { | |
218 // update the items result | |
219 _result = value()->operand(); | |
220 } | |
221 if (!result()->is_register()) { | |
222 LIR_Opr reg = _gen->new_register(value()->type()); | |
223 __ move(result(), reg); | |
224 if (result()->is_constant()) { | |
225 _result = reg; | |
226 } else { | |
227 set_result(reg); | |
228 } | |
229 } | |
230 } | |
231 | |
232 | |
233 void LIRItem::load_for_store(BasicType type) { | |
234 if (_gen->can_store_as_constant(value(), type)) { | |
235 _result = value()->operand(); | |
236 if (!_result->is_constant()) { | |
237 _result = LIR_OprFact::value_type(value()->type()); | |
238 } | |
239 } else if (type == T_BYTE || type == T_BOOLEAN) { | |
240 load_byte_item(); | |
241 } else { | |
242 load_item(); | |
243 } | |
244 } | |
245 | |
246 void LIRItem::load_item_force(LIR_Opr reg) { | |
247 LIR_Opr r = result(); | |
248 if (r != reg) { | |
1681
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
249 #if !defined(ARM) && !defined(E500V2) |
0 | 250 if (r->type() != reg->type()) { |
251 // moves between different types need an intervening spill slot | |
1681
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
252 r = _gen->force_to_spill(r, reg->type()); |
0 | 253 } |
1681
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
254 #endif |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
255 __ move(r, reg); |
0 | 256 _result = reg; |
257 } | |
258 } | |
259 | |
260 ciObject* LIRItem::get_jobject_constant() const { | |
261 ObjectType* oc = type()->as_ObjectType(); | |
262 if (oc) { | |
263 return oc->constant_value(); | |
264 } | |
265 return NULL; | |
266 } | |
267 | |
268 | |
269 jint LIRItem::get_jint_constant() const { | |
270 assert(is_constant() && value() != NULL, ""); | |
271 assert(type()->as_IntConstant() != NULL, "type check"); | |
272 return type()->as_IntConstant()->value(); | |
273 } | |
274 | |
275 | |
276 jint LIRItem::get_address_constant() const { | |
277 assert(is_constant() && value() != NULL, ""); | |
278 assert(type()->as_AddressConstant() != NULL, "type check"); | |
279 return type()->as_AddressConstant()->value(); | |
280 } | |
281 | |
282 | |
283 jfloat LIRItem::get_jfloat_constant() const { | |
284 assert(is_constant() && value() != NULL, ""); | |
285 assert(type()->as_FloatConstant() != NULL, "type check"); | |
286 return type()->as_FloatConstant()->value(); | |
287 } | |
288 | |
289 | |
290 jdouble LIRItem::get_jdouble_constant() const { | |
291 assert(is_constant() && value() != NULL, ""); | |
292 assert(type()->as_DoubleConstant() != NULL, "type check"); | |
293 return type()->as_DoubleConstant()->value(); | |
294 } | |
295 | |
296 | |
297 jlong LIRItem::get_jlong_constant() const { | |
298 assert(is_constant() && value() != NULL, ""); | |
299 assert(type()->as_LongConstant() != NULL, "type check"); | |
300 return type()->as_LongConstant()->value(); | |
301 } | |
302 | |
303 | |
304 | |
305 //-------------------------------------------------------------- | |
306 | |
307 | |
308 void LIRGenerator::init() { | |
342 | 309 _bs = Universe::heap()->barrier_set(); |
0 | 310 } |
311 | |
312 | |
313 void LIRGenerator::block_do_prolog(BlockBegin* block) { | |
314 #ifndef PRODUCT | |
315 if (PrintIRWithLIR) { | |
316 block->print(); | |
317 } | |
318 #endif | |
319 | |
320 // set up the list of LIR instructions | |
321 assert(block->lir() == NULL, "LIR list already computed for this block"); | |
322 _lir = new LIR_List(compilation(), block); | |
323 block->set_lir(_lir); | |
324 | |
325 __ branch_destination(block->label()); | |
326 | |
327 if (LIRTraceExecution && | |
1584 | 328 Compilation::current()->hir()->start()->block_id() != block->block_id() && |
0 | 329 !block->is_set(BlockBegin::exception_entry_flag)) { |
330 assert(block->lir()->instructions_list()->length() == 1, "should come right after br_dst"); | |
331 trace_block_entry(block); | |
332 } | |
333 } | |
334 | |
335 | |
336 void LIRGenerator::block_do_epilog(BlockBegin* block) { | |
337 #ifndef PRODUCT | |
338 if (PrintIRWithLIR) { | |
339 tty->cr(); | |
340 } | |
341 #endif | |
342 | |
343 // LIR_Opr for unpinned constants shouldn't be referenced by other | |
344 // blocks so clear them out after processing the block. | |
345 for (int i = 0; i < _unpinned_constants.length(); i++) { | |
346 _unpinned_constants.at(i)->clear_operand(); | |
347 } | |
348 _unpinned_constants.trunc_to(0); | |
349 | |
350 // clear our any registers for other local constants | |
351 _constants.trunc_to(0); | |
352 _reg_for_constants.trunc_to(0); | |
353 } | |
354 | |
355 | |
356 void LIRGenerator::block_do(BlockBegin* block) { | |
357 CHECK_BAILOUT(); | |
358 | |
359 block_do_prolog(block); | |
360 set_block(block); | |
361 | |
362 for (Instruction* instr = block; instr != NULL; instr = instr->next()) { | |
363 if (instr->is_pinned()) do_root(instr); | |
364 } | |
365 | |
366 set_block(NULL); | |
367 block_do_epilog(block); | |
368 } | |
369 | |
370 | |
371 //-------------------------LIRGenerator----------------------------- | |
372 | |
373 // This is where the tree-walk starts; instr must be root; | |
374 void LIRGenerator::do_root(Value instr) { | |
375 CHECK_BAILOUT(); | |
376 | |
377 InstructionMark im(compilation(), instr); | |
378 | |
379 assert(instr->is_pinned(), "use only with roots"); | |
380 assert(instr->subst() == instr, "shouldn't have missed substitution"); | |
381 | |
382 instr->visit(this); | |
383 | |
384 assert(!instr->has_uses() || instr->operand()->is_valid() || | |
385 instr->as_Constant() != NULL || bailed_out(), "invalid item set"); | |
386 } | |
387 | |
388 | |
389 // This is called for each node in tree; the walk stops if a root is reached | |
390 void LIRGenerator::walk(Value instr) { | |
391 InstructionMark im(compilation(), instr); | |
392 //stop walk when encounter a root | |
393 if (instr->is_pinned() && instr->as_Phi() == NULL || instr->operand()->is_valid()) { | |
394 assert(instr->operand() != LIR_OprFact::illegalOpr || instr->as_Constant() != NULL, "this root has not yet been visited"); | |
395 } else { | |
396 assert(instr->subst() == instr, "shouldn't have missed substitution"); | |
397 instr->visit(this); | |
398 // assert(instr->use_count() > 0 || instr->as_Phi() != NULL, "leaf instruction must have a use"); | |
399 } | |
400 } | |
401 | |
402 | |
403 CodeEmitInfo* LIRGenerator::state_for(Instruction* x, ValueStack* state, bool ignore_xhandler) { | |
1819 | 404 assert(state != NULL, "state must be defined"); |
405 | |
8860 | 406 #ifndef PRODUCT |
407 state->verify(); | |
408 #endif | |
409 | |
1819 | 410 ValueStack* s = state; |
411 for_each_state(s) { | |
412 if (s->kind() == ValueStack::EmptyExceptionState) { | |
413 assert(s->stack_size() == 0 && s->locals_size() == 0 && (s->locks_size() == 0 || s->locks_size() == 1), "state must be empty"); | |
414 continue; | |
0 | 415 } |
1819 | 416 |
417 int index; | |
418 Value value; | |
419 for_each_stack_value(s, index, value) { | |
420 assert(value->subst() == value, "missed substitution"); | |
421 if (!value->is_pinned() && value->as_Constant() == NULL && value->as_Local() == NULL) { | |
422 walk(value); | |
423 assert(value->operand()->is_valid(), "must be evaluated now"); | |
424 } | |
425 } | |
426 | |
427 int bci = s->bci(); | |
0 | 428 IRScope* scope = s->scope(); |
429 ciMethod* method = scope->method(); | |
430 | |
431 MethodLivenessResult liveness = method->liveness_at_bci(bci); | |
432 if (bci == SynchronizationEntryBCI) { | |
433 if (x->as_ExceptionObject() || x->as_Throw()) { | |
434 // all locals are dead on exit from the synthetic unlocker | |
435 liveness.clear(); | |
436 } else { | |
4116
973293defacd
7112085: assert(fr.interpreter_frame_expression_stack_size()==0) failed: only handle empty stacks
iveresov
parents:
3997
diff
changeset
|
437 assert(x->as_MonitorEnter() || x->as_ProfileInvoke(), "only other cases are MonitorEnter and ProfileInvoke"); |
0 | 438 } |
439 } | |
440 if (!liveness.is_valid()) { | |
441 // Degenerate or breakpointed method. | |
442 bailout("Degenerate or breakpointed method"); | |
443 } else { | |
444 assert((int)liveness.size() == s->locals_size(), "error in use of liveness"); | |
445 for_each_local_value(s, index, value) { | |
446 assert(value->subst() == value, "missed substition"); | |
447 if (liveness.at(index) && !value->type()->is_illegal()) { | |
448 if (!value->is_pinned() && value->as_Constant() == NULL && value->as_Local() == NULL) { | |
449 walk(value); | |
450 assert(value->operand()->is_valid(), "must be evaluated now"); | |
451 } | |
452 } else { | |
453 // NULL out this local so that linear scan can assume that all non-NULL values are live. | |
454 s->invalidate_local(index); | |
455 } | |
456 } | |
457 } | |
458 } | |
459 | |
8860 | 460 return new CodeEmitInfo(state, ignore_xhandler ? NULL : x->exception_handlers(), x->check_flag(Instruction::DeoptimizeOnException)); |
0 | 461 } |
462 | |
463 | |
464 CodeEmitInfo* LIRGenerator::state_for(Instruction* x) { | |
1819 | 465 return state_for(x, x->exception_state()); |
0 | 466 } |
467 | |
468 | |
20344
2fd0fd493045
8031994: java/lang/Character/CheckProp test times out
rbackman
parents:
17925
diff
changeset
|
469 void LIRGenerator::klass2reg_with_patching(LIR_Opr r, ciMetadata* obj, CodeEmitInfo* info, bool need_resolve) { |
2fd0fd493045
8031994: java/lang/Character/CheckProp test times out
rbackman
parents:
17925
diff
changeset
|
470 /* C2 relies on constant pool entries being resolved (ciTypeFlow), so if TieredCompilation |
2fd0fd493045
8031994: java/lang/Character/CheckProp test times out
rbackman
parents:
17925
diff
changeset
|
471 * is active and the class hasn't yet been resolved we need to emit a patch that resolves |
2fd0fd493045
8031994: java/lang/Character/CheckProp test times out
rbackman
parents:
17925
diff
changeset
|
472 * the class. */ |
2fd0fd493045
8031994: java/lang/Character/CheckProp test times out
rbackman
parents:
17925
diff
changeset
|
473 if ((TieredCompilation && need_resolve) || !obj->is_loaded() || PatchALot) { |
0 | 474 assert(info != NULL, "info must be set if class is not loaded"); |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6616
diff
changeset
|
475 __ klass2reg_patch(NULL, r, info); |
0 | 476 } else { |
477 // no patching needed | |
6739
8a02ca5e5576
7195816: NPG: Crash in c1_ValueType - ShouldNotReachHere
roland
parents:
6731
diff
changeset
|
478 __ metadata2reg(obj->constant_encoding(), r); |
0 | 479 } |
480 } | |
481 | |
482 | |
483 void LIRGenerator::array_range_check(LIR_Opr array, LIR_Opr index, | |
484 CodeEmitInfo* null_check_info, CodeEmitInfo* range_check_info) { | |
485 CodeStub* stub = new RangeCheckStub(range_check_info, index); | |
486 if (index->is_constant()) { | |
487 cmp_mem_int(lir_cond_belowEqual, array, arrayOopDesc::length_offset_in_bytes(), | |
488 index->as_jint(), null_check_info); | |
489 __ branch(lir_cond_belowEqual, T_INT, stub); // forward branch | |
490 } else { | |
491 cmp_reg_mem(lir_cond_aboveEqual, index, array, | |
492 arrayOopDesc::length_offset_in_bytes(), T_INT, null_check_info); | |
493 __ branch(lir_cond_aboveEqual, T_INT, stub); // forward branch | |
494 } | |
495 } | |
496 | |
497 | |
498 void LIRGenerator::nio_range_check(LIR_Opr buffer, LIR_Opr index, LIR_Opr result, CodeEmitInfo* info) { | |
499 CodeStub* stub = new RangeCheckStub(info, index, true); | |
500 if (index->is_constant()) { | |
501 cmp_mem_int(lir_cond_belowEqual, buffer, java_nio_Buffer::limit_offset(), index->as_jint(), info); | |
502 __ branch(lir_cond_belowEqual, T_INT, stub); // forward branch | |
503 } else { | |
504 cmp_reg_mem(lir_cond_aboveEqual, index, buffer, | |
505 java_nio_Buffer::limit_offset(), T_INT, info); | |
506 __ branch(lir_cond_aboveEqual, T_INT, stub); // forward branch | |
507 } | |
508 __ move(index, result); | |
509 } | |
510 | |
511 | |
512 | |
513 void LIRGenerator::arithmetic_op(Bytecodes::Code code, LIR_Opr result, LIR_Opr left, LIR_Opr right, bool is_strictfp, LIR_Opr tmp_op, CodeEmitInfo* info) { | |
514 LIR_Opr result_op = result; | |
515 LIR_Opr left_op = left; | |
516 LIR_Opr right_op = right; | |
517 | |
518 if (TwoOperandLIRForm && left_op != result_op) { | |
519 assert(right_op != result_op, "malformed"); | |
520 __ move(left_op, result_op); | |
521 left_op = result_op; | |
522 } | |
523 | |
524 switch(code) { | |
525 case Bytecodes::_dadd: | |
526 case Bytecodes::_fadd: | |
527 case Bytecodes::_ladd: | |
528 case Bytecodes::_iadd: __ add(left_op, right_op, result_op); break; | |
529 case Bytecodes::_fmul: | |
530 case Bytecodes::_lmul: __ mul(left_op, right_op, result_op); break; | |
531 | |
532 case Bytecodes::_dmul: | |
533 { | |
534 if (is_strictfp) { | |
535 __ mul_strictfp(left_op, right_op, result_op, tmp_op); break; | |
536 } else { | |
537 __ mul(left_op, right_op, result_op); break; | |
538 } | |
539 } | |
540 break; | |
541 | |
542 case Bytecodes::_imul: | |
543 { | |
544 bool did_strength_reduce = false; | |
545 | |
546 if (right->is_constant()) { | |
547 int c = right->as_jint(); | |
548 if (is_power_of_2(c)) { | |
549 // do not need tmp here | |
550 __ shift_left(left_op, exact_log2(c), result_op); | |
551 did_strength_reduce = true; | |
552 } else { | |
553 did_strength_reduce = strength_reduce_multiply(left_op, c, result_op, tmp_op); | |
554 } | |
555 } | |
556 // we couldn't strength reduce so just emit the multiply | |
557 if (!did_strength_reduce) { | |
558 __ mul(left_op, right_op, result_op); | |
559 } | |
560 } | |
561 break; | |
562 | |
563 case Bytecodes::_dsub: | |
564 case Bytecodes::_fsub: | |
565 case Bytecodes::_lsub: | |
566 case Bytecodes::_isub: __ sub(left_op, right_op, result_op); break; | |
567 | |
568 case Bytecodes::_fdiv: __ div (left_op, right_op, result_op); break; | |
569 // ldiv and lrem are implemented with a direct runtime call | |
570 | |
571 case Bytecodes::_ddiv: | |
572 { | |
573 if (is_strictfp) { | |
574 __ div_strictfp (left_op, right_op, result_op, tmp_op); break; | |
575 } else { | |
576 __ div (left_op, right_op, result_op); break; | |
577 } | |
578 } | |
579 break; | |
580 | |
581 case Bytecodes::_drem: | |
582 case Bytecodes::_frem: __ rem (left_op, right_op, result_op); break; | |
583 | |
584 default: ShouldNotReachHere(); | |
585 } | |
586 } | |
587 | |
588 | |
589 void LIRGenerator::arithmetic_op_int(Bytecodes::Code code, LIR_Opr result, LIR_Opr left, LIR_Opr right, LIR_Opr tmp) { | |
590 arithmetic_op(code, result, left, right, false, tmp); | |
591 } | |
592 | |
593 | |
594 void LIRGenerator::arithmetic_op_long(Bytecodes::Code code, LIR_Opr result, LIR_Opr left, LIR_Opr right, CodeEmitInfo* info) { | |
595 arithmetic_op(code, result, left, right, false, LIR_OprFact::illegalOpr, info); | |
596 } | |
597 | |
598 | |
599 void LIRGenerator::arithmetic_op_fpu(Bytecodes::Code code, LIR_Opr result, LIR_Opr left, LIR_Opr right, bool is_strictfp, LIR_Opr tmp) { | |
600 arithmetic_op(code, result, left, right, is_strictfp, tmp); | |
601 } | |
602 | |
603 | |
604 void LIRGenerator::shift_op(Bytecodes::Code code, LIR_Opr result_op, LIR_Opr value, LIR_Opr count, LIR_Opr tmp) { | |
605 if (TwoOperandLIRForm && value != result_op) { | |
606 assert(count != result_op, "malformed"); | |
607 __ move(value, result_op); | |
608 value = result_op; | |
609 } | |
610 | |
611 assert(count->is_constant() || count->is_register(), "must be"); | |
612 switch(code) { | |
613 case Bytecodes::_ishl: | |
614 case Bytecodes::_lshl: __ shift_left(value, count, result_op, tmp); break; | |
615 case Bytecodes::_ishr: | |
616 case Bytecodes::_lshr: __ shift_right(value, count, result_op, tmp); break; | |
617 case Bytecodes::_iushr: | |
618 case Bytecodes::_lushr: __ unsigned_shift_right(value, count, result_op, tmp); break; | |
619 default: ShouldNotReachHere(); | |
620 } | |
621 } | |
622 | |
623 | |
624 void LIRGenerator::logic_op (Bytecodes::Code code, LIR_Opr result_op, LIR_Opr left_op, LIR_Opr right_op) { | |
625 if (TwoOperandLIRForm && left_op != result_op) { | |
626 assert(right_op != result_op, "malformed"); | |
627 __ move(left_op, result_op); | |
628 left_op = result_op; | |
629 } | |
630 | |
631 switch(code) { | |
632 case Bytecodes::_iand: | |
633 case Bytecodes::_land: __ logical_and(left_op, right_op, result_op); break; | |
634 | |
635 case Bytecodes::_ior: | |
636 case Bytecodes::_lor: __ logical_or(left_op, right_op, result_op); break; | |
637 | |
638 case Bytecodes::_ixor: | |
639 case Bytecodes::_lxor: __ logical_xor(left_op, right_op, result_op); break; | |
640 | |
641 default: ShouldNotReachHere(); | |
642 } | |
643 } | |
644 | |
645 | |
646 void LIRGenerator::monitor_enter(LIR_Opr object, LIR_Opr lock, LIR_Opr hdr, LIR_Opr scratch, int monitor_no, CodeEmitInfo* info_for_exception, CodeEmitInfo* info) { | |
647 if (!GenerateSynchronizationCode) return; | |
648 // for slow path, use debug info for state after successful locking | |
649 CodeStub* slow_path = new MonitorEnterStub(object, lock, info); | |
650 __ load_stack_address_monitor(monitor_no, lock); | |
651 // for handling NullPointerException, use debug info representing just the lock stack before this monitorenter | |
652 __ lock_object(hdr, object, lock, scratch, slow_path, info_for_exception); | |
653 } | |
654 | |
655 | |
1681
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
656 void LIRGenerator::monitor_exit(LIR_Opr object, LIR_Opr lock, LIR_Opr new_hdr, LIR_Opr scratch, int monitor_no) { |
0 | 657 if (!GenerateSynchronizationCode) return; |
658 // setup registers | |
659 LIR_Opr hdr = lock; | |
660 lock = new_hdr; | |
661 CodeStub* slow_path = new MonitorExitStub(lock, UseFastLocking, monitor_no); | |
662 __ load_stack_address_monitor(monitor_no, lock); | |
1681
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
663 __ unlock_object(hdr, object, lock, scratch, slow_path); |
0 | 664 } |
665 | |
20344
2fd0fd493045
8031994: java/lang/Character/CheckProp test times out
rbackman
parents:
17925
diff
changeset
|
666 #ifndef PRODUCT |
2fd0fd493045
8031994: java/lang/Character/CheckProp test times out
rbackman
parents:
17925
diff
changeset
|
667 void LIRGenerator::print_if_not_loaded(const NewInstance* new_instance) { |
2fd0fd493045
8031994: java/lang/Character/CheckProp test times out
rbackman
parents:
17925
diff
changeset
|
668 if (PrintNotLoaded && !new_instance->klass()->is_loaded()) { |
2fd0fd493045
8031994: java/lang/Character/CheckProp test times out
rbackman
parents:
17925
diff
changeset
|
669 tty->print_cr(" ###class not loaded at new bci %d", new_instance->printable_bci()); |
2fd0fd493045
8031994: java/lang/Character/CheckProp test times out
rbackman
parents:
17925
diff
changeset
|
670 } else if (PrintNotLoaded && (TieredCompilation && new_instance->is_unresolved())) { |
2fd0fd493045
8031994: java/lang/Character/CheckProp test times out
rbackman
parents:
17925
diff
changeset
|
671 tty->print_cr(" ###class not resolved at new bci %d", new_instance->printable_bci()); |
2fd0fd493045
8031994: java/lang/Character/CheckProp test times out
rbackman
parents:
17925
diff
changeset
|
672 } |
2fd0fd493045
8031994: java/lang/Character/CheckProp test times out
rbackman
parents:
17925
diff
changeset
|
673 } |
2fd0fd493045
8031994: java/lang/Character/CheckProp test times out
rbackman
parents:
17925
diff
changeset
|
674 #endif |
2fd0fd493045
8031994: java/lang/Character/CheckProp test times out
rbackman
parents:
17925
diff
changeset
|
675 |
2fd0fd493045
8031994: java/lang/Character/CheckProp test times out
rbackman
parents:
17925
diff
changeset
|
676 void LIRGenerator::new_instance(LIR_Opr dst, ciInstanceKlass* klass, bool is_unresolved, LIR_Opr scratch1, LIR_Opr scratch2, LIR_Opr scratch3, LIR_Opr scratch4, LIR_Opr klass_reg, CodeEmitInfo* info) { |
2fd0fd493045
8031994: java/lang/Character/CheckProp test times out
rbackman
parents:
17925
diff
changeset
|
677 klass2reg_with_patching(klass_reg, klass, info, is_unresolved); |
0 | 678 // If klass is not loaded we do not know if the klass has finalizers: |
679 if (UseFastNewInstance && klass->is_loaded() | |
680 && !Klass::layout_helper_needs_slow_path(klass->layout_helper())) { | |
681 | |
682 Runtime1::StubID stub_id = klass->is_initialized() ? Runtime1::fast_new_instance_id : Runtime1::fast_new_instance_init_check_id; | |
683 | |
684 CodeStub* slow_path = new NewInstanceStub(klass_reg, dst, klass, info, stub_id); | |
685 | |
686 assert(klass->is_loaded(), "must be loaded"); | |
687 // allocate space for instance | |
688 assert(klass->size_helper() >= 0, "illegal instance size"); | |
689 const int instance_size = align_object_size(klass->size_helper()); | |
690 __ allocate_object(dst, scratch1, scratch2, scratch3, scratch4, | |
691 oopDesc::header_size(), instance_size, klass_reg, !klass->is_initialized(), slow_path); | |
692 } else { | |
693 CodeStub* slow_path = new NewInstanceStub(klass_reg, dst, klass, info, Runtime1::new_instance_id); | |
694 __ branch(lir_cond_always, T_ILLEGAL, slow_path); | |
695 __ branch_destination(slow_path->continuation()); | |
696 } | |
697 } | |
698 | |
699 | |
700 static bool is_constant_zero(Instruction* inst) { | |
701 IntConstant* c = inst->type()->as_IntConstant(); | |
702 if (c) { | |
703 return (c->value() == 0); | |
704 } | |
705 return false; | |
706 } | |
707 | |
708 | |
709 static bool positive_constant(Instruction* inst) { | |
710 IntConstant* c = inst->type()->as_IntConstant(); | |
711 if (c) { | |
712 return (c->value() >= 0); | |
713 } | |
714 return false; | |
715 } | |
716 | |
717 | |
718 static ciArrayKlass* as_array_klass(ciType* type) { | |
719 if (type != NULL && type->is_array_klass() && type->is_loaded()) { | |
720 return (ciArrayKlass*)type; | |
721 } else { | |
722 return NULL; | |
723 } | |
724 } | |
725 | |
2446 | 726 static ciType* phi_declared_type(Phi* phi) { |
727 ciType* t = phi->operand_at(0)->declared_type(); | |
728 if (t == NULL) { | |
729 return NULL; | |
730 } | |
731 for(int i = 1; i < phi->operand_count(); i++) { | |
732 if (t != phi->operand_at(i)->declared_type()) { | |
733 return NULL; | |
734 } | |
735 } | |
736 return t; | |
737 } | |
738 | |
0 | 739 void LIRGenerator::arraycopy_helper(Intrinsic* x, int* flagsp, ciArrayKlass** expected_typep) { |
740 Instruction* src = x->argument_at(0); | |
741 Instruction* src_pos = x->argument_at(1); | |
742 Instruction* dst = x->argument_at(2); | |
743 Instruction* dst_pos = x->argument_at(3); | |
744 Instruction* length = x->argument_at(4); | |
745 | |
746 // first try to identify the likely type of the arrays involved | |
747 ciArrayKlass* expected_type = NULL; | |
2446 | 748 bool is_exact = false, src_objarray = false, dst_objarray = false; |
0 | 749 { |
750 ciArrayKlass* src_exact_type = as_array_klass(src->exact_type()); | |
751 ciArrayKlass* src_declared_type = as_array_klass(src->declared_type()); | |
2446 | 752 Phi* phi; |
753 if (src_declared_type == NULL && (phi = src->as_Phi()) != NULL) { | |
754 src_declared_type = as_array_klass(phi_declared_type(phi)); | |
755 } | |
0 | 756 ciArrayKlass* dst_exact_type = as_array_klass(dst->exact_type()); |
757 ciArrayKlass* dst_declared_type = as_array_klass(dst->declared_type()); | |
2446 | 758 if (dst_declared_type == NULL && (phi = dst->as_Phi()) != NULL) { |
759 dst_declared_type = as_array_klass(phi_declared_type(phi)); | |
760 } | |
761 | |
0 | 762 if (src_exact_type != NULL && src_exact_type == dst_exact_type) { |
763 // the types exactly match so the type is fully known | |
764 is_exact = true; | |
765 expected_type = src_exact_type; | |
766 } else if (dst_exact_type != NULL && dst_exact_type->is_obj_array_klass()) { | |
767 ciArrayKlass* dst_type = (ciArrayKlass*) dst_exact_type; | |
768 ciArrayKlass* src_type = NULL; | |
769 if (src_exact_type != NULL && src_exact_type->is_obj_array_klass()) { | |
770 src_type = (ciArrayKlass*) src_exact_type; | |
771 } else if (src_declared_type != NULL && src_declared_type->is_obj_array_klass()) { | |
772 src_type = (ciArrayKlass*) src_declared_type; | |
773 } | |
774 if (src_type != NULL) { | |
775 if (src_type->element_type()->is_subtype_of(dst_type->element_type())) { | |
776 is_exact = true; | |
777 expected_type = dst_type; | |
778 } | |
779 } | |
780 } | |
781 // at least pass along a good guess | |
782 if (expected_type == NULL) expected_type = dst_exact_type; | |
783 if (expected_type == NULL) expected_type = src_declared_type; | |
784 if (expected_type == NULL) expected_type = dst_declared_type; | |
2446 | 785 |
786 src_objarray = (src_exact_type && src_exact_type->is_obj_array_klass()) || (src_declared_type && src_declared_type->is_obj_array_klass()); | |
787 dst_objarray = (dst_exact_type && dst_exact_type->is_obj_array_klass()) || (dst_declared_type && dst_declared_type->is_obj_array_klass()); | |
0 | 788 } |
789 | |
790 // if a probable array type has been identified, figure out if any | |
791 // of the required checks for a fast case can be elided. | |
792 int flags = LIR_OpArrayCopy::all_flags; | |
2446 | 793 |
794 if (!src_objarray) | |
795 flags &= ~LIR_OpArrayCopy::src_objarray; | |
796 if (!dst_objarray) | |
797 flags &= ~LIR_OpArrayCopy::dst_objarray; | |
798 | |
799 if (!x->arg_needs_null_check(0)) | |
800 flags &= ~LIR_OpArrayCopy::src_null_check; | |
801 if (!x->arg_needs_null_check(2)) | |
802 flags &= ~LIR_OpArrayCopy::dst_null_check; | |
803 | |
804 | |
0 | 805 if (expected_type != NULL) { |
2446 | 806 Value length_limit = NULL; |
807 | |
808 IfOp* ifop = length->as_IfOp(); | |
809 if (ifop != NULL) { | |
810 // look for expressions like min(v, a.length) which ends up as | |
811 // x > y ? y : x or x >= y ? y : x | |
812 if ((ifop->cond() == If::gtr || ifop->cond() == If::geq) && | |
813 ifop->x() == ifop->fval() && | |
814 ifop->y() == ifop->tval()) { | |
815 length_limit = ifop->y(); | |
816 } | |
817 } | |
818 | |
819 // try to skip null checks and range checks | |
820 NewArray* src_array = src->as_NewArray(); | |
821 if (src_array != NULL) { | |
0 | 822 flags &= ~LIR_OpArrayCopy::src_null_check; |
2446 | 823 if (length_limit != NULL && |
824 src_array->length() == length_limit && | |
825 is_constant_zero(src_pos)) { | |
826 flags &= ~LIR_OpArrayCopy::src_range_check; | |
827 } | |
828 } | |
829 | |
830 NewArray* dst_array = dst->as_NewArray(); | |
831 if (dst_array != NULL) { | |
0 | 832 flags &= ~LIR_OpArrayCopy::dst_null_check; |
2446 | 833 if (length_limit != NULL && |
834 dst_array->length() == length_limit && | |
835 is_constant_zero(dst_pos)) { | |
836 flags &= ~LIR_OpArrayCopy::dst_range_check; | |
837 } | |
838 } | |
0 | 839 |
840 // check from incoming constant values | |
841 if (positive_constant(src_pos)) | |
842 flags &= ~LIR_OpArrayCopy::src_pos_positive_check; | |
843 if (positive_constant(dst_pos)) | |
844 flags &= ~LIR_OpArrayCopy::dst_pos_positive_check; | |
845 if (positive_constant(length)) | |
846 flags &= ~LIR_OpArrayCopy::length_positive_check; | |
847 | |
848 // see if the range check can be elided, which might also imply | |
849 // that src or dst is non-null. | |
850 ArrayLength* al = length->as_ArrayLength(); | |
851 if (al != NULL) { | |
852 if (al->array() == src) { | |
853 // it's the length of the source array | |
854 flags &= ~LIR_OpArrayCopy::length_positive_check; | |
855 flags &= ~LIR_OpArrayCopy::src_null_check; | |
856 if (is_constant_zero(src_pos)) | |
857 flags &= ~LIR_OpArrayCopy::src_range_check; | |
858 } | |
859 if (al->array() == dst) { | |
860 // it's the length of the destination array | |
861 flags &= ~LIR_OpArrayCopy::length_positive_check; | |
862 flags &= ~LIR_OpArrayCopy::dst_null_check; | |
863 if (is_constant_zero(dst_pos)) | |
864 flags &= ~LIR_OpArrayCopy::dst_range_check; | |
865 } | |
866 } | |
867 if (is_exact) { | |
868 flags &= ~LIR_OpArrayCopy::type_check; | |
869 } | |
870 } | |
871 | |
2446 | 872 IntConstant* src_int = src_pos->type()->as_IntConstant(); |
873 IntConstant* dst_int = dst_pos->type()->as_IntConstant(); | |
874 if (src_int && dst_int) { | |
875 int s_offs = src_int->value(); | |
876 int d_offs = dst_int->value(); | |
877 if (src_int->value() >= dst_int->value()) { | |
878 flags &= ~LIR_OpArrayCopy::overlapping; | |
879 } | |
880 if (expected_type != NULL) { | |
881 BasicType t = expected_type->element_type()->basic_type(); | |
882 int element_size = type2aelembytes(t); | |
883 if (((arrayOopDesc::base_offset_in_bytes(t) + s_offs * element_size) % HeapWordSize == 0) && | |
884 ((arrayOopDesc::base_offset_in_bytes(t) + d_offs * element_size) % HeapWordSize == 0)) { | |
885 flags &= ~LIR_OpArrayCopy::unaligned; | |
886 } | |
887 } | |
888 } else if (src_pos == dst_pos || is_constant_zero(dst_pos)) { | |
889 // src and dest positions are the same, or dst is zero so assume | |
890 // nonoverlapping copy. | |
891 flags &= ~LIR_OpArrayCopy::overlapping; | |
892 } | |
893 | |
0 | 894 if (src == dst) { |
895 // moving within a single array so no type checks are needed | |
896 if (flags & LIR_OpArrayCopy::type_check) { | |
897 flags &= ~LIR_OpArrayCopy::type_check; | |
898 } | |
899 } | |
900 *flagsp = flags; | |
901 *expected_typep = (ciArrayKlass*)expected_type; | |
902 } | |
903 | |
904 | |
905 LIR_Opr LIRGenerator::round_item(LIR_Opr opr) { | |
906 assert(opr->is_register(), "why spill if item is not register?"); | |
907 | |
908 if (RoundFPResults && UseSSE < 1 && opr->is_single_fpu()) { | |
909 LIR_Opr result = new_register(T_FLOAT); | |
910 set_vreg_flag(result, must_start_in_memory); | |
911 assert(opr->is_register(), "only a register can be spilled"); | |
912 assert(opr->value_type()->is_float(), "rounding only for floats available"); | |
913 __ roundfp(opr, LIR_OprFact::illegalOpr, result); | |
914 return result; | |
915 } | |
916 return opr; | |
917 } | |
918 | |
919 | |
920 LIR_Opr LIRGenerator::force_to_spill(LIR_Opr value, BasicType t) { | |
6616
7a302948f5a4
7192167: JSR 292: C1 has old broken code which needs to be removed
twisti
parents:
6615
diff
changeset
|
921 assert(type2size[t] == type2size[value->type()], |
7a302948f5a4
7192167: JSR 292: C1 has old broken code which needs to be removed
twisti
parents:
6615
diff
changeset
|
922 err_msg_res("size mismatch: t=%s, value->type()=%s", type2name(t), type2name(value->type()))); |
0 | 923 if (!value->is_register()) { |
924 // force into a register | |
925 LIR_Opr r = new_register(value->type()); | |
926 __ move(value, r); | |
927 value = r; | |
928 } | |
929 | |
930 // create a spill location | |
931 LIR_Opr tmp = new_register(t); | |
932 set_vreg_flag(tmp, LIRGenerator::must_start_in_memory); | |
933 | |
934 // move from register to spill | |
935 __ move(value, tmp); | |
936 return tmp; | |
937 } | |
938 | |
939 void LIRGenerator::profile_branch(If* if_instr, If::Condition cond) { | |
940 if (if_instr->should_profile()) { | |
941 ciMethod* method = if_instr->profiled_method(); | |
942 assert(method != NULL, "method should be set if branch is profiled"); | |
2007
5ddfcf4b079e
7003554: (tiered) assert(is_null_object() || handle() != NULL) failed: cannot embed null pointer
iveresov
parents:
2002
diff
changeset
|
943 ciMethodData* md = method->method_data_or_null(); |
5ddfcf4b079e
7003554: (tiered) assert(is_null_object() || handle() != NULL) failed: cannot embed null pointer
iveresov
parents:
2002
diff
changeset
|
944 assert(md != NULL, "Sanity"); |
0 | 945 ciProfileData* data = md->bci_to_data(if_instr->profiled_bci()); |
946 assert(data != NULL, "must have profiling data"); | |
947 assert(data->is_BranchData(), "need BranchData for two-way branches"); | |
948 int taken_count_offset = md->byte_offset_of_slot(data, BranchData::taken_offset()); | |
949 int not_taken_count_offset = md->byte_offset_of_slot(data, BranchData::not_taken_offset()); | |
1783 | 950 if (if_instr->is_swapped()) { |
951 int t = taken_count_offset; | |
952 taken_count_offset = not_taken_count_offset; | |
953 not_taken_count_offset = t; | |
954 } | |
955 | |
6739
8a02ca5e5576
7195816: NPG: Crash in c1_ValueType - ShouldNotReachHere
roland
parents:
6731
diff
changeset
|
956 LIR_Opr md_reg = new_register(T_METADATA); |
8a02ca5e5576
7195816: NPG: Crash in c1_ValueType - ShouldNotReachHere
roland
parents:
6731
diff
changeset
|
957 __ metadata2reg(md->constant_encoding(), md_reg); |
1783 | 958 |
959 LIR_Opr data_offset_reg = new_pointer_register(); | |
0 | 960 __ cmove(lir_cond(cond), |
1783 | 961 LIR_OprFact::intptrConst(taken_count_offset), |
962 LIR_OprFact::intptrConst(not_taken_count_offset), | |
2089
037c727f35fb
7009231: C1: Incorrect CAS code for longs on SPARC 32bit
iveresov
parents:
2007
diff
changeset
|
963 data_offset_reg, as_BasicType(if_instr->x()->type())); |
1783 | 964 |
965 // MDO cells are intptr_t, so the data_reg width is arch-dependent. | |
966 LIR_Opr data_reg = new_pointer_register(); | |
967 LIR_Address* data_addr = new LIR_Address(md_reg, data_offset_reg, data_reg->type()); | |
2002 | 968 __ move(data_addr, data_reg); |
1783 | 969 // Use leal instead of add to avoid destroying condition codes on x86 |
0 | 970 LIR_Address* fake_incr_value = new LIR_Address(data_reg, DataLayout::counter_increment, T_INT); |
971 __ leal(LIR_OprFact::address(fake_incr_value), data_reg); | |
2002 | 972 __ move(data_reg, data_addr); |
0 | 973 } |
974 } | |
975 | |
976 // Phi technique: | |
977 // This is about passing live values from one basic block to the other. | |
978 // In code generated with Java it is rather rare that more than one | |
979 // value is on the stack from one basic block to the other. | |
980 // We optimize our technique for efficient passing of one value | |
981 // (of type long, int, double..) but it can be extended. | |
982 // When entering or leaving a basic block, all registers and all spill | |
983 // slots are release and empty. We use the released registers | |
984 // and spill slots to pass the live values from one block | |
985 // to the other. The topmost value, i.e., the value on TOS of expression | |
986 // stack is passed in registers. All other values are stored in spilling | |
987 // area. Every Phi has an index which designates its spill slot | |
988 // At exit of a basic block, we fill the register(s) and spill slots. | |
989 // At entry of a basic block, the block_prolog sets up the content of phi nodes | |
990 // and locks necessary registers and spilling slots. | |
991 | |
992 | |
993 // move current value to referenced phi function | |
994 void LIRGenerator::move_to_phi(PhiResolver* resolver, Value cur_val, Value sux_val) { | |
995 Phi* phi = sux_val->as_Phi(); | |
996 // cur_val can be null without phi being null in conjunction with inlining | |
997 if (phi != NULL && cur_val != NULL && cur_val != phi && !phi->is_illegal()) { | |
998 LIR_Opr operand = cur_val->operand(); | |
999 if (cur_val->operand()->is_illegal()) { | |
1000 assert(cur_val->as_Constant() != NULL || cur_val->as_Local() != NULL, | |
1001 "these can be produced lazily"); | |
1002 operand = operand_for_instruction(cur_val); | |
1003 } | |
1004 resolver->move(operand, operand_for_instruction(phi)); | |
1005 } | |
1006 } | |
1007 | |
1008 | |
1009 // Moves all stack values into their PHI position | |
1010 void LIRGenerator::move_to_phi(ValueStack* cur_state) { | |
1011 BlockBegin* bb = block(); | |
1012 if (bb->number_of_sux() == 1) { | |
1013 BlockBegin* sux = bb->sux_at(0); | |
1014 assert(sux->number_of_preds() > 0, "invalid CFG"); | |
1015 | |
1016 // a block with only one predecessor never has phi functions | |
1017 if (sux->number_of_preds() > 1) { | |
1018 int max_phis = cur_state->stack_size() + cur_state->locals_size(); | |
1019 PhiResolver resolver(this, _virtual_register_number + max_phis * 2); | |
1020 | |
1021 ValueStack* sux_state = sux->state(); | |
1022 Value sux_value; | |
1023 int index; | |
1024 | |
1819 | 1025 assert(cur_state->scope() == sux_state->scope(), "not matching"); |
1026 assert(cur_state->locals_size() == sux_state->locals_size(), "not matching"); | |
1027 assert(cur_state->stack_size() == sux_state->stack_size(), "not matching"); | |
1028 | |
0 | 1029 for_each_stack_value(sux_state, index, sux_value) { |
1030 move_to_phi(&resolver, cur_state->stack_at(index), sux_value); | |
1031 } | |
1032 | |
1033 for_each_local_value(sux_state, index, sux_value) { | |
1034 move_to_phi(&resolver, cur_state->local_at(index), sux_value); | |
1035 } | |
1036 | |
1037 assert(cur_state->caller_state() == sux_state->caller_state(), "caller states must be equal"); | |
1038 } | |
1039 } | |
1040 } | |
1041 | |
1042 | |
1043 LIR_Opr LIRGenerator::new_register(BasicType type) { | |
1044 int vreg = _virtual_register_number; | |
1045 // add a little fudge factor for the bailout, since the bailout is | |
1046 // only checked periodically. This gives a few extra registers to | |
1047 // hand out before we really run out, which helps us keep from | |
1048 // tripping over assertions. | |
1049 if (vreg + 20 >= LIR_OprDesc::vreg_max) { | |
1050 bailout("out of virtual registers"); | |
1051 if (vreg + 2 >= LIR_OprDesc::vreg_max) { | |
1052 // wrap it around | |
1053 _virtual_register_number = LIR_OprDesc::vreg_base; | |
1054 } | |
1055 } | |
1056 _virtual_register_number += 1; | |
1057 return LIR_OprFact::virtual_register(vreg, type); | |
1058 } | |
1059 | |
1060 | |
1061 // Try to lock using register in hint | |
1062 LIR_Opr LIRGenerator::rlock(Value instr) { | |
1063 return new_register(instr->type()); | |
1064 } | |
1065 | |
1066 | |
1067 // does an rlock and sets result | |
1068 LIR_Opr LIRGenerator::rlock_result(Value x) { | |
1069 LIR_Opr reg = rlock(x); | |
1070 set_result(x, reg); | |
1071 return reg; | |
1072 } | |
1073 | |
1074 | |
1075 // does an rlock and sets result | |
1076 LIR_Opr LIRGenerator::rlock_result(Value x, BasicType type) { | |
1077 LIR_Opr reg; | |
1078 switch (type) { | |
1079 case T_BYTE: | |
1080 case T_BOOLEAN: | |
1081 reg = rlock_byte(type); | |
1082 break; | |
1083 default: | |
1084 reg = rlock(x); | |
1085 break; | |
1086 } | |
1087 | |
1088 set_result(x, reg); | |
1089 return reg; | |
1090 } | |
1091 | |
1092 | |
1093 //--------------------------------------------------------------------- | |
1094 ciObject* LIRGenerator::get_jobject_constant(Value value) { | |
1095 ObjectType* oc = value->type()->as_ObjectType(); | |
1096 if (oc) { | |
1097 return oc->constant_value(); | |
1098 } | |
1099 return NULL; | |
1100 } | |
1101 | |
1102 | |
1103 void LIRGenerator::do_ExceptionObject(ExceptionObject* x) { | |
1104 assert(block()->is_set(BlockBegin::exception_entry_flag), "ExceptionObject only allowed in exception handler block"); | |
1105 assert(block()->next() == x, "ExceptionObject must be first instruction of block"); | |
1106 | |
1107 // no moves are created for phi functions at the begin of exception | |
1108 // handlers, so assign operands manually here | |
1109 for_each_phi_fun(block(), phi, | |
1110 operand_for_instruction(phi)); | |
1111 | |
1112 LIR_Opr thread_reg = getThreadPointer(); | |
2002 | 1113 __ move_wide(new LIR_Address(thread_reg, in_bytes(JavaThread::exception_oop_offset()), T_OBJECT), |
1114 exceptionOopOpr()); | |
1115 __ move_wide(LIR_OprFact::oopConst(NULL), | |
1116 new LIR_Address(thread_reg, in_bytes(JavaThread::exception_oop_offset()), T_OBJECT)); | |
1117 __ move_wide(LIR_OprFact::oopConst(NULL), | |
1118 new LIR_Address(thread_reg, in_bytes(JavaThread::exception_pc_offset()), T_OBJECT)); | |
0 | 1119 |
1120 LIR_Opr result = new_register(T_OBJECT); | |
1121 __ move(exceptionOopOpr(), result); | |
1122 set_result(x, result); | |
1123 } | |
1124 | |
1125 | |
1126 //---------------------------------------------------------------------- | |
1127 //---------------------------------------------------------------------- | |
1128 //---------------------------------------------------------------------- | |
1129 //---------------------------------------------------------------------- | |
1130 // visitor functions | |
1131 //---------------------------------------------------------------------- | |
1132 //---------------------------------------------------------------------- | |
1133 //---------------------------------------------------------------------- | |
1134 //---------------------------------------------------------------------- | |
1135 | |
1136 void LIRGenerator::do_Phi(Phi* x) { | |
1137 // phi functions are never visited directly | |
1138 ShouldNotReachHere(); | |
1139 } | |
1140 | |
1141 | |
1142 // Code for a constant is generated lazily unless the constant is frequently used and can't be inlined. | |
1143 void LIRGenerator::do_Constant(Constant* x) { | |
1819 | 1144 if (x->state_before() != NULL) { |
0 | 1145 // Any constant with a ValueStack requires patching so emit the patch here |
1146 LIR_Opr reg = rlock_result(x); | |
1819 | 1147 CodeEmitInfo* info = state_for(x, x->state_before()); |
0 | 1148 __ oop2reg_patch(NULL, reg, info); |
1149 } else if (x->use_count() > 1 && !can_inline_as_constant(x)) { | |
1150 if (!x->is_pinned()) { | |
1151 // unpinned constants are handled specially so that they can be | |
1152 // put into registers when they are used multiple times within a | |
1153 // block. After the block completes their operand will be | |
1154 // cleared so that other blocks can't refer to that register. | |
1155 set_result(x, load_constant(x)); | |
1156 } else { | |
1157 LIR_Opr res = x->operand(); | |
1158 if (!res->is_valid()) { | |
1159 res = LIR_OprFact::value_type(x->type()); | |
1160 } | |
1161 if (res->is_constant()) { | |
1162 LIR_Opr reg = rlock_result(x); | |
1163 __ move(res, reg); | |
1164 } else { | |
1165 set_result(x, res); | |
1166 } | |
1167 } | |
1168 } else { | |
1169 set_result(x, LIR_OprFact::value_type(x->type())); | |
1170 } | |
1171 } | |
1172 | |
1173 | |
1174 void LIRGenerator::do_Local(Local* x) { | |
1175 // operand_for_instruction has the side effect of setting the result | |
1176 // so there's no need to do it here. | |
1177 operand_for_instruction(x); | |
1178 } | |
1179 | |
1180 | |
1181 void LIRGenerator::do_IfInstanceOf(IfInstanceOf* x) { | |
1182 Unimplemented(); | |
1183 } | |
1184 | |
1185 | |
1186 void LIRGenerator::do_Return(Return* x) { | |
780
c96bf21b756f
6788527: Server vm intermittently fails with assertion "live value must not be garbage" with fastdebug bits
kvn
parents:
579
diff
changeset
|
1187 if (compilation()->env()->dtrace_method_probes()) { |
0 | 1188 BasicTypeList signature; |
2002 | 1189 signature.append(LP64_ONLY(T_LONG) NOT_LP64(T_INT)); // thread |
12969
9acbfe04b5c3
8026495: JVM Crashes when started with -XX:+DTraceMethodProbes on Solaris x86_64
iveresov
parents:
12962
diff
changeset
|
1190 signature.append(T_METADATA); // Method* |
0 | 1191 LIR_OprList* args = new LIR_OprList(); |
1192 args->append(getThreadPointer()); | |
6739
8a02ca5e5576
7195816: NPG: Crash in c1_ValueType - ShouldNotReachHere
roland
parents:
6731
diff
changeset
|
1193 LIR_Opr meth = new_register(T_METADATA); |
8a02ca5e5576
7195816: NPG: Crash in c1_ValueType - ShouldNotReachHere
roland
parents:
6731
diff
changeset
|
1194 __ metadata2reg(method()->constant_encoding(), meth); |
0 | 1195 args->append(meth); |
1196 call_runtime(&signature, args, CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit), voidType, NULL); | |
1197 } | |
1198 | |
1199 if (x->type()->is_void()) { | |
1200 __ return_op(LIR_OprFact::illegalOpr); | |
1201 } else { | |
1202 LIR_Opr reg = result_register_for(x->type(), /*callee=*/true); | |
1203 LIRItem result(x->result(), this); | |
1204 | |
1205 result.load_item_force(reg); | |
1206 __ return_op(result.result()); | |
1207 } | |
1208 set_no_result(x); | |
1209 } | |
1210 | |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1211 // Examble: ref.get() |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1212 // Combination of LoadField and g1 pre-write barrier |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1213 void LIRGenerator::do_Reference_get(Intrinsic* x) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1214 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1215 const int referent_offset = java_lang_ref_Reference::referent_offset; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1216 guarantee(referent_offset > 0, "referent offset not initialized"); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1217 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1218 assert(x->number_of_arguments() == 1, "wrong type"); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1219 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1220 LIRItem reference(x->argument_at(0), this); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1221 reference.load_item(); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1222 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1223 // need to perform the null check on the reference objecy |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1224 CodeEmitInfo* info = NULL; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1225 if (x->needs_null_check()) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1226 info = state_for(x); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1227 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1228 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1229 LIR_Address* referent_field_adr = |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1230 new LIR_Address(reference.result(), referent_offset, T_OBJECT); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1231 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1232 LIR_Opr result = rlock_result(x); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1233 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1234 __ load(referent_field_adr, result, info); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1235 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1236 // Register the value in the referent field with the pre-barrier |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1237 pre_barrier(LIR_OprFact::illegalOpr /* addr_opr */, |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1238 result /* pre_val */, |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1239 false /* do_load */, |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1240 false /* patch */, |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1241 NULL /* info */); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1242 } |
0 | 1243 |
6135 | 1244 // Example: clazz.isInstance(object) |
1245 void LIRGenerator::do_isInstance(Intrinsic* x) { | |
1246 assert(x->number_of_arguments() == 2, "wrong type"); | |
1247 | |
1248 // TODO could try to substitute this node with an equivalent InstanceOf | |
1249 // if clazz is known to be a constant Class. This will pick up newly found | |
1250 // constants after HIR construction. I'll leave this to a future change. | |
1251 | |
1252 // as a first cut, make a simple leaf call to runtime to stay platform independent. | |
1253 // could follow the aastore example in a future change. | |
1254 | |
1255 LIRItem clazz(x->argument_at(0), this); | |
1256 LIRItem object(x->argument_at(1), this); | |
1257 clazz.load_item(); | |
1258 object.load_item(); | |
1259 LIR_Opr result = rlock_result(x); | |
1260 | |
1261 // need to perform null check on clazz | |
1262 if (x->needs_null_check()) { | |
1263 CodeEmitInfo* info = state_for(x); | |
1264 __ null_check(clazz.result(), info); | |
1265 } | |
1266 | |
1267 LIR_Opr call_result = call_runtime(clazz.value(), object.value(), | |
1268 CAST_FROM_FN_PTR(address, Runtime1::is_instance_of), | |
1269 x->type(), | |
1270 NULL); // NULL CodeEmitInfo results in a leaf call | |
1271 __ move(call_result, result); | |
1272 } | |
1273 | |
0 | 1274 // Example: object.getClass () |
1275 void LIRGenerator::do_getClass(Intrinsic* x) { | |
1276 assert(x->number_of_arguments() == 1, "wrong type"); | |
1277 | |
1278 LIRItem rcvr(x->argument_at(0), this); | |
1279 rcvr.load_item(); | |
12955 | 1280 LIR_Opr temp = new_register(T_METADATA); |
0 | 1281 LIR_Opr result = rlock_result(x); |
1282 | |
1283 // need to perform the null check on the rcvr | |
1284 CodeEmitInfo* info = NULL; | |
1285 if (x->needs_null_check()) { | |
1819 | 1286 info = state_for(x); |
0 | 1287 } |
12955 | 1288 |
1289 // FIXME T_ADDRESS should actually be T_METADATA but it can't because the | |
1290 // meaning of these two is mixed up (see JDK-8026837). | |
1291 __ move(new LIR_Address(rcvr.result(), oopDesc::klass_offset_in_bytes(), T_ADDRESS), temp, info); | |
1292 __ move_wide(new LIR_Address(temp, in_bytes(Klass::java_mirror_offset()), T_OBJECT), result); | |
0 | 1293 } |
1294 | |
1295 | |
1296 // Example: Thread.currentThread() | |
1297 void LIRGenerator::do_currentThread(Intrinsic* x) { | |
1298 assert(x->number_of_arguments() == 0, "wrong type"); | |
1299 LIR_Opr reg = rlock_result(x); | |
2002 | 1300 __ move_wide(new LIR_Address(getThreadPointer(), in_bytes(JavaThread::threadObj_offset()), T_OBJECT), reg); |
0 | 1301 } |
1302 | |
1303 | |
1304 void LIRGenerator::do_RegisterFinalizer(Intrinsic* x) { | |
1305 assert(x->number_of_arguments() == 1, "wrong type"); | |
1306 LIRItem receiver(x->argument_at(0), this); | |
1307 | |
1308 receiver.load_item(); | |
1309 BasicTypeList signature; | |
1310 signature.append(T_OBJECT); // receiver | |
1311 LIR_OprList* args = new LIR_OprList(); | |
1312 args->append(receiver.result()); | |
1313 CodeEmitInfo* info = state_for(x, x->state()); | |
1314 call_runtime(&signature, args, | |
1315 CAST_FROM_FN_PTR(address, Runtime1::entry_for(Runtime1::register_finalizer_id)), | |
1316 voidType, info); | |
1317 | |
1318 set_no_result(x); | |
1319 } | |
1320 | |
1321 | |
1322 //------------------------local access-------------------------------------- | |
1323 | |
1324 LIR_Opr LIRGenerator::operand_for_instruction(Instruction* x) { | |
1325 if (x->operand()->is_illegal()) { | |
1326 Constant* c = x->as_Constant(); | |
1327 if (c != NULL) { | |
1328 x->set_operand(LIR_OprFact::value_type(c->type())); | |
1329 } else { | |
1330 assert(x->as_Phi() || x->as_Local() != NULL, "only for Phi and Local"); | |
1331 // allocate a virtual register for this local or phi | |
1332 x->set_operand(rlock(x)); | |
1333 _instruction_for_operand.at_put_grow(x->operand()->vreg_number(), x, NULL); | |
1334 } | |
1335 } | |
1336 return x->operand(); | |
1337 } | |
1338 | |
1339 | |
1340 Instruction* LIRGenerator::instruction_for_opr(LIR_Opr opr) { | |
1341 if (opr->is_virtual()) { | |
1342 return instruction_for_vreg(opr->vreg_number()); | |
1343 } | |
1344 return NULL; | |
1345 } | |
1346 | |
1347 | |
1348 Instruction* LIRGenerator::instruction_for_vreg(int reg_num) { | |
1349 if (reg_num < _instruction_for_operand.length()) { | |
1350 return _instruction_for_operand.at(reg_num); | |
1351 } | |
1352 return NULL; | |
1353 } | |
1354 | |
1355 | |
1356 void LIRGenerator::set_vreg_flag(int vreg_num, VregFlag f) { | |
1357 if (_vreg_flags.size_in_bits() == 0) { | |
1358 BitMap2D temp(100, num_vreg_flags); | |
1359 temp.clear(); | |
1360 _vreg_flags = temp; | |
1361 } | |
1362 _vreg_flags.at_put_grow(vreg_num, f, true); | |
1363 } | |
1364 | |
1365 bool LIRGenerator::is_vreg_flag_set(int vreg_num, VregFlag f) { | |
1366 if (!_vreg_flags.is_valid_index(vreg_num, f)) { | |
1367 return false; | |
1368 } | |
1369 return _vreg_flags.at(vreg_num, f); | |
1370 } | |
1371 | |
1372 | |
1373 // Block local constant handling. This code is useful for keeping | |
1374 // unpinned constants and constants which aren't exposed in the IR in | |
1375 // registers. Unpinned Constant instructions have their operands | |
1376 // cleared when the block is finished so that other blocks can't end | |
1377 // up referring to their registers. | |
1378 | |
1379 LIR_Opr LIRGenerator::load_constant(Constant* x) { | |
1380 assert(!x->is_pinned(), "only for unpinned constants"); | |
1381 _unpinned_constants.append(x); | |
1382 return load_constant(LIR_OprFact::value_type(x->type())->as_constant_ptr()); | |
1383 } | |
1384 | |
1385 | |
1386 LIR_Opr LIRGenerator::load_constant(LIR_Const* c) { | |
1387 BasicType t = c->type(); | |
1388 for (int i = 0; i < _constants.length(); i++) { | |
1389 LIR_Const* other = _constants.at(i); | |
1390 if (t == other->type()) { | |
1391 switch (t) { | |
1392 case T_INT: | |
1393 case T_FLOAT: | |
1394 if (c->as_jint_bits() != other->as_jint_bits()) continue; | |
1395 break; | |
1396 case T_LONG: | |
1397 case T_DOUBLE: | |
486
a738a625039a
6757316: load_constant() produces a wrong long constant, with high a low words swapped
never
parents:
380
diff
changeset
|
1398 if (c->as_jint_hi_bits() != other->as_jint_hi_bits()) continue; |
a738a625039a
6757316: load_constant() produces a wrong long constant, with high a low words swapped
never
parents:
380
diff
changeset
|
1399 if (c->as_jint_lo_bits() != other->as_jint_lo_bits()) continue; |
0 | 1400 break; |
1401 case T_OBJECT: | |
1402 if (c->as_jobject() != other->as_jobject()) continue; | |
1403 break; | |
1404 } | |
1405 return _reg_for_constants.at(i); | |
1406 } | |
1407 } | |
1408 | |
1409 LIR_Opr result = new_register(t); | |
1410 __ move((LIR_Opr)c, result); | |
1411 _constants.append(c); | |
1412 _reg_for_constants.append(result); | |
1413 return result; | |
1414 } | |
1415 | |
1416 // Various barriers | |
1417 | |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1418 void LIRGenerator::pre_barrier(LIR_Opr addr_opr, LIR_Opr pre_val, |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1419 bool do_load, bool patch, CodeEmitInfo* info) { |
342 | 1420 // Do the pre-write barrier, if any. |
1421 switch (_bs->kind()) { | |
8001
db9981fd3124
8005915: Unify SERIALGC and INCLUDE_ALTERNATE_GCS
jprovino
parents:
7425
diff
changeset
|
1422 #if INCLUDE_ALL_GCS |
342 | 1423 case BarrierSet::G1SATBCT: |
1424 case BarrierSet::G1SATBCTLogging: | |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1425 G1SATBCardTableModRef_pre_barrier(addr_opr, pre_val, do_load, patch, info); |
342 | 1426 break; |
8001
db9981fd3124
8005915: Unify SERIALGC and INCLUDE_ALTERNATE_GCS
jprovino
parents:
7425
diff
changeset
|
1427 #endif // INCLUDE_ALL_GCS |
342 | 1428 case BarrierSet::CardTableModRef: |
1429 case BarrierSet::CardTableExtension: | |
1430 // No pre barriers | |
1431 break; | |
1432 case BarrierSet::ModRef: | |
1433 case BarrierSet::Other: | |
1434 // No pre barriers | |
1435 break; | |
1436 default : | |
1437 ShouldNotReachHere(); | |
1438 | |
1439 } | |
1440 } | |
1441 | |
0 | 1442 void LIRGenerator::post_barrier(LIR_OprDesc* addr, LIR_OprDesc* new_val) { |
342 | 1443 switch (_bs->kind()) { |
8001
db9981fd3124
8005915: Unify SERIALGC and INCLUDE_ALTERNATE_GCS
jprovino
parents:
7425
diff
changeset
|
1444 #if INCLUDE_ALL_GCS |
342 | 1445 case BarrierSet::G1SATBCT: |
1446 case BarrierSet::G1SATBCTLogging: | |
1447 G1SATBCardTableModRef_post_barrier(addr, new_val); | |
1448 break; | |
8001
db9981fd3124
8005915: Unify SERIALGC and INCLUDE_ALTERNATE_GCS
jprovino
parents:
7425
diff
changeset
|
1449 #endif // INCLUDE_ALL_GCS |
0 | 1450 case BarrierSet::CardTableModRef: |
1451 case BarrierSet::CardTableExtension: | |
1452 CardTableModRef_post_barrier(addr, new_val); | |
1453 break; | |
1454 case BarrierSet::ModRef: | |
1455 case BarrierSet::Other: | |
1456 // No post barriers | |
1457 break; | |
1458 default : | |
1459 ShouldNotReachHere(); | |
1460 } | |
1461 } | |
1462 | |
342 | 1463 //////////////////////////////////////////////////////////////////////// |
8001
db9981fd3124
8005915: Unify SERIALGC and INCLUDE_ALTERNATE_GCS
jprovino
parents:
7425
diff
changeset
|
1464 #if INCLUDE_ALL_GCS |
342 | 1465 |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1466 void LIRGenerator::G1SATBCardTableModRef_pre_barrier(LIR_Opr addr_opr, LIR_Opr pre_val, |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1467 bool do_load, bool patch, CodeEmitInfo* info) { |
342 | 1468 // First we test whether marking is in progress. |
1469 BasicType flag_type; | |
1470 if (in_bytes(PtrQueue::byte_width_of_active()) == 4) { | |
1471 flag_type = T_INT; | |
1472 } else { | |
1473 guarantee(in_bytes(PtrQueue::byte_width_of_active()) == 1, | |
1474 "Assumption"); | |
1475 flag_type = T_BYTE; | |
1476 } | |
1477 LIR_Opr thrd = getThreadPointer(); | |
1478 LIR_Address* mark_active_flag_addr = | |
1479 new LIR_Address(thrd, | |
1480 in_bytes(JavaThread::satb_mark_queue_offset() + | |
1481 PtrQueue::byte_offset_of_active()), | |
1482 flag_type); | |
1483 // Read the marking-in-progress flag. | |
1484 LIR_Opr flag_val = new_register(T_INT); | |
1485 __ load(mark_active_flag_addr, flag_val); | |
1486 __ cmp(lir_cond_notEqual, flag_val, LIR_OprFact::intConst(0)); | |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1487 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1488 LIR_PatchCode pre_val_patch_code = lir_patch_none; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1489 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1490 CodeStub* slow; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1491 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1492 if (do_load) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1493 assert(pre_val == LIR_OprFact::illegalOpr, "sanity"); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1494 assert(addr_opr != LIR_OprFact::illegalOpr, "sanity"); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1495 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1496 if (patch) |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1497 pre_val_patch_code = lir_patch_normal; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1498 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1499 pre_val = new_register(T_OBJECT); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1500 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1501 if (!addr_opr->is_address()) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1502 assert(addr_opr->is_register(), "must be"); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1503 addr_opr = LIR_OprFact::address(new LIR_Address(addr_opr, T_OBJECT)); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1504 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1505 slow = new G1PreBarrierStub(addr_opr, pre_val, pre_val_patch_code, info); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1506 } else { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1507 assert(addr_opr == LIR_OprFact::illegalOpr, "sanity"); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1508 assert(pre_val->is_register(), "must be"); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1509 assert(pre_val->type() == T_OBJECT, "must be an object"); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1510 assert(info == NULL, "sanity"); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1511 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1512 slow = new G1PreBarrierStub(pre_val); |
342 | 1513 } |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1514 |
342 | 1515 __ branch(lir_cond_notEqual, T_INT, slow); |
1516 __ branch_destination(slow->continuation()); | |
1517 } | |
1518 | |
1519 void LIRGenerator::G1SATBCardTableModRef_post_barrier(LIR_OprDesc* addr, LIR_OprDesc* new_val) { | |
1520 // If the "new_val" is a constant NULL, no barrier is necessary. | |
1521 if (new_val->is_constant() && | |
1522 new_val->as_constant_ptr()->as_jobject() == NULL) return; | |
1523 | |
1524 if (!new_val->is_register()) { | |
1572 | 1525 LIR_Opr new_val_reg = new_register(T_OBJECT); |
342 | 1526 if (new_val->is_constant()) { |
1527 __ move(new_val, new_val_reg); | |
1528 } else { | |
1529 __ leal(new_val, new_val_reg); | |
1530 } | |
1531 new_val = new_val_reg; | |
1532 } | |
1533 assert(new_val->is_register(), "must be a register at this point"); | |
1534 | |
1535 if (addr->is_address()) { | |
1536 LIR_Address* address = addr->as_address_ptr(); | |
2464
d86923d96dca
7034967: C1: assert(false) failed: error (assembler_sparc.cpp:2043)
iveresov
parents:
2446
diff
changeset
|
1537 LIR_Opr ptr = new_pointer_register(); |
342 | 1538 if (!address->index()->is_valid() && address->disp() == 0) { |
1539 __ move(address->base(), ptr); | |
1540 } else { | |
1541 assert(address->disp() != max_jint, "lea doesn't support patched addresses!"); | |
1542 __ leal(addr, ptr); | |
1543 } | |
1544 addr = ptr; | |
1545 } | |
1546 assert(addr->is_register(), "must be a register at this point"); | |
1547 | |
1548 LIR_Opr xor_res = new_pointer_register(); | |
1549 LIR_Opr xor_shift_res = new_pointer_register(); | |
1550 if (TwoOperandLIRForm ) { | |
1551 __ move(addr, xor_res); | |
1552 __ logical_xor(xor_res, new_val, xor_res); | |
1553 __ move(xor_res, xor_shift_res); | |
1554 __ unsigned_shift_right(xor_shift_res, | |
1555 LIR_OprFact::intConst(HeapRegion::LogOfHRGrainBytes), | |
1556 xor_shift_res, | |
1557 LIR_OprDesc::illegalOpr()); | |
1558 } else { | |
1559 __ logical_xor(addr, new_val, xor_res); | |
1560 __ unsigned_shift_right(xor_res, | |
1561 LIR_OprFact::intConst(HeapRegion::LogOfHRGrainBytes), | |
1562 xor_shift_res, | |
1563 LIR_OprDesc::illegalOpr()); | |
1564 } | |
1565 | |
1566 if (!new_val->is_register()) { | |
1572 | 1567 LIR_Opr new_val_reg = new_register(T_OBJECT); |
342 | 1568 __ leal(new_val, new_val_reg); |
1569 new_val = new_val_reg; | |
1570 } | |
1571 assert(new_val->is_register(), "must be a register at this point"); | |
1572 | |
1573 __ cmp(lir_cond_notEqual, xor_shift_res, LIR_OprFact::intptrConst(NULL_WORD)); | |
1574 | |
1575 CodeStub* slow = new G1PostBarrierStub(addr, new_val); | |
1572 | 1576 __ branch(lir_cond_notEqual, LP64_ONLY(T_LONG) NOT_LP64(T_INT), slow); |
342 | 1577 __ branch_destination(slow->continuation()); |
1578 } | |
1579 | |
8001
db9981fd3124
8005915: Unify SERIALGC and INCLUDE_ALTERNATE_GCS
jprovino
parents:
7425
diff
changeset
|
1580 #endif // INCLUDE_ALL_GCS |
342 | 1581 //////////////////////////////////////////////////////////////////////// |
1582 | |
0 | 1583 void LIRGenerator::CardTableModRef_post_barrier(LIR_OprDesc* addr, LIR_OprDesc* new_val) { |
1584 | |
342 | 1585 assert(sizeof(*((CardTableModRefBS*)_bs)->byte_map_base) == sizeof(jbyte), "adjust this code"); |
1586 LIR_Const* card_table_base = new LIR_Const(((CardTableModRefBS*)_bs)->byte_map_base); | |
0 | 1587 if (addr->is_address()) { |
1588 LIR_Address* address = addr->as_address_ptr(); | |
2464
d86923d96dca
7034967: C1: assert(false) failed: error (assembler_sparc.cpp:2043)
iveresov
parents:
2446
diff
changeset
|
1589 // ptr cannot be an object because we use this barrier for array card marks |
d86923d96dca
7034967: C1: assert(false) failed: error (assembler_sparc.cpp:2043)
iveresov
parents:
2446
diff
changeset
|
1590 // and addr can point in the middle of an array. |
d86923d96dca
7034967: C1: assert(false) failed: error (assembler_sparc.cpp:2043)
iveresov
parents:
2446
diff
changeset
|
1591 LIR_Opr ptr = new_pointer_register(); |
0 | 1592 if (!address->index()->is_valid() && address->disp() == 0) { |
1593 __ move(address->base(), ptr); | |
1594 } else { | |
1595 assert(address->disp() != max_jint, "lea doesn't support patched addresses!"); | |
1596 __ leal(addr, ptr); | |
1597 } | |
1598 addr = ptr; | |
1599 } | |
1600 assert(addr->is_register(), "must be a register at this point"); | |
1601 | |
1681
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
1602 #ifdef ARM |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
1603 // TODO: ARM - move to platform-dependent code |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
1604 LIR_Opr tmp = FrameMap::R14_opr; |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
1605 if (VM_Version::supports_movw()) { |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
1606 __ move((LIR_Opr)card_table_base, tmp); |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
1607 } else { |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
1608 __ move(new LIR_Address(FrameMap::Rthread_opr, in_bytes(JavaThread::card_table_base_offset()), T_ADDRESS), tmp); |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
1609 } |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
1610 |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
1611 CardTableModRefBS* ct = (CardTableModRefBS*)_bs; |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
1612 LIR_Address *card_addr = new LIR_Address(tmp, addr, (LIR_Address::Scale) -CardTableModRefBS::card_shift, 0, T_BYTE); |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
1613 if(((int)ct->byte_map_base & 0xff) == 0) { |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
1614 __ move(tmp, card_addr); |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
1615 } else { |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
1616 LIR_Opr tmp_zero = new_register(T_INT); |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
1617 __ move(LIR_OprFact::intConst(0), tmp_zero); |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
1618 __ move(tmp_zero, card_addr); |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
1619 } |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
1620 #else // ARM |
0 | 1621 LIR_Opr tmp = new_pointer_register(); |
1622 if (TwoOperandLIRForm) { | |
1623 __ move(addr, tmp); | |
1624 __ unsigned_shift_right(tmp, CardTableModRefBS::card_shift, tmp); | |
1625 } else { | |
1626 __ unsigned_shift_right(addr, CardTableModRefBS::card_shift, tmp); | |
1627 } | |
1628 if (can_inline_as_constant(card_table_base)) { | |
1629 __ move(LIR_OprFact::intConst(0), | |
1630 new LIR_Address(tmp, card_table_base->as_jint(), T_BYTE)); | |
1631 } else { | |
1632 __ move(LIR_OprFact::intConst(0), | |
1633 new LIR_Address(tmp, load_constant(card_table_base), | |
1634 T_BYTE)); | |
1635 } | |
1681
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
1636 #endif // ARM |
0 | 1637 } |
1638 | |
1639 | |
1640 //------------------------field access-------------------------------------- | |
1641 | |
1642 // Comment copied form templateTable_i486.cpp | |
1643 // ---------------------------------------------------------------------------- | |
1644 // Volatile variables demand their effects be made known to all CPU's in | |
1645 // order. Store buffers on most chips allow reads & writes to reorder; the | |
1646 // JMM's ReadAfterWrite.java test fails in -Xint mode without some kind of | |
1647 // memory barrier (i.e., it's not sufficient that the interpreter does not | |
1648 // reorder volatile references, the hardware also must not reorder them). | |
1649 // | |
1650 // According to the new Java Memory Model (JMM): | |
1651 // (1) All volatiles are serialized wrt to each other. | |
1652 // ALSO reads & writes act as aquire & release, so: | |
1653 // (2) A read cannot let unrelated NON-volatile memory refs that happen after | |
1654 // the read float up to before the read. It's OK for non-volatile memory refs | |
1655 // that happen before the volatile read to float down below it. | |
1656 // (3) Similar a volatile write cannot let unrelated NON-volatile memory refs | |
1657 // that happen BEFORE the write float down to after the write. It's OK for | |
1658 // non-volatile memory refs that happen after the volatile write to float up | |
1659 // before it. | |
1660 // | |
1661 // We only put in barriers around volatile refs (they are expensive), not | |
1662 // _between_ memory refs (that would require us to track the flavor of the | |
1663 // previous memory refs). Requirements (2) and (3) require some barriers | |
1664 // before volatile stores and after volatile loads. These nearly cover | |
1665 // requirement (1) but miss the volatile-store-volatile-load case. This final | |
1666 // case is placed after volatile-stores although it could just as well go | |
1667 // before volatile-loads. | |
1668 | |
1669 | |
1670 void LIRGenerator::do_StoreField(StoreField* x) { | |
1671 bool needs_patching = x->needs_patching(); | |
1672 bool is_volatile = x->field()->is_volatile(); | |
1673 BasicType field_type = x->field_type(); | |
1674 bool is_oop = (field_type == T_ARRAY || field_type == T_OBJECT); | |
1675 | |
1676 CodeEmitInfo* info = NULL; | |
1677 if (needs_patching) { | |
1678 assert(x->explicit_null_check() == NULL, "can't fold null check into patching field access"); | |
1679 info = state_for(x, x->state_before()); | |
1680 } else if (x->needs_null_check()) { | |
1681 NullCheck* nc = x->explicit_null_check(); | |
1682 if (nc == NULL) { | |
1819 | 1683 info = state_for(x); |
0 | 1684 } else { |
1685 info = state_for(nc); | |
1686 } | |
1687 } | |
1688 | |
1689 | |
1690 LIRItem object(x->obj(), this); | |
1691 LIRItem value(x->value(), this); | |
1692 | |
1693 object.load_item(); | |
1694 | |
1695 if (is_volatile || needs_patching) { | |
1696 // load item if field is volatile (fewer special cases for volatiles) | |
1697 // load item if field not initialized | |
1698 // load item if field not constant | |
1699 // because of code patching we cannot inline constants | |
1700 if (field_type == T_BYTE || field_type == T_BOOLEAN) { | |
1701 value.load_byte_item(); | |
1702 } else { | |
1703 value.load_item(); | |
1704 } | |
1705 } else { | |
1706 value.load_for_store(field_type); | |
1707 } | |
1708 | |
1709 set_no_result(x); | |
1710 | |
1819 | 1711 #ifndef PRODUCT |
0 | 1712 if (PrintNotLoaded && needs_patching) { |
1713 tty->print_cr(" ###class not loaded at store_%s bci %d", | |
1819 | 1714 x->is_static() ? "static" : "field", x->printable_bci()); |
0 | 1715 } |
1819 | 1716 #endif |
0 | 1717 |
1718 if (x->needs_null_check() && | |
1719 (needs_patching || | |
1720 MacroAssembler::needs_explicit_null_check(x->offset()))) { | |
1721 // emit an explicit null check because the offset is too large | |
1722 __ null_check(object.result(), new CodeEmitInfo(info)); | |
1723 } | |
1724 | |
1725 LIR_Address* address; | |
1726 if (needs_patching) { | |
1727 // we need to patch the offset in the instruction so don't allow | |
1728 // generate_address to try to be smart about emitting the -1. | |
1729 // Otherwise the patching code won't know how to find the | |
1730 // instruction to patch. | |
1681
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
1731 address = new LIR_Address(object.result(), PATCHED_ADDR, field_type); |
0 | 1732 } else { |
1733 address = generate_address(object.result(), x->offset(), field_type); | |
1734 } | |
1735 | |
1736 if (is_volatile && os::is_MP()) { | |
1737 __ membar_release(); | |
1738 } | |
1739 | |
342 | 1740 if (is_oop) { |
1741 // Do the pre-write barrier, if any. | |
1742 pre_barrier(LIR_OprFact::address(address), | |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1743 LIR_OprFact::illegalOpr /* pre_val */, |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1744 true /* do_load*/, |
342 | 1745 needs_patching, |
1746 (info ? new CodeEmitInfo(info) : NULL)); | |
1747 } | |
1748 | |
2352
425688247f3d
6965570: assert(!needs_patching && x->is_loaded(),"how do we know it's volatile if it's not loaded")
never
parents:
2167
diff
changeset
|
1749 if (is_volatile && !needs_patching) { |
0 | 1750 volatile_field_store(value.result(), address, info); |
1751 } else { | |
1752 LIR_PatchCode patch_code = needs_patching ? lir_patch_normal : lir_patch_none; | |
1753 __ store(value.result(), address, info, patch_code); | |
1754 } | |
1755 | |
1756 if (is_oop) { | |
819
c6386080541b
6849574: VM crash using NonBlockingHashMap (high_scale_lib)
never
parents:
780
diff
changeset
|
1757 // Store to object so mark the card of the header |
0 | 1758 post_barrier(object.result(), value.result()); |
1759 } | |
1760 | |
1761 if (is_volatile && os::is_MP()) { | |
1762 __ membar(); | |
1763 } | |
1764 } | |
1765 | |
1766 | |
1767 void LIRGenerator::do_LoadField(LoadField* x) { | |
1768 bool needs_patching = x->needs_patching(); | |
1769 bool is_volatile = x->field()->is_volatile(); | |
1770 BasicType field_type = x->field_type(); | |
1771 | |
1772 CodeEmitInfo* info = NULL; | |
1773 if (needs_patching) { | |
1774 assert(x->explicit_null_check() == NULL, "can't fold null check into patching field access"); | |
1775 info = state_for(x, x->state_before()); | |
1776 } else if (x->needs_null_check()) { | |
1777 NullCheck* nc = x->explicit_null_check(); | |
1778 if (nc == NULL) { | |
1819 | 1779 info = state_for(x); |
0 | 1780 } else { |
1781 info = state_for(nc); | |
1782 } | |
1783 } | |
1784 | |
1785 LIRItem object(x->obj(), this); | |
1786 | |
1787 object.load_item(); | |
1788 | |
1819 | 1789 #ifndef PRODUCT |
0 | 1790 if (PrintNotLoaded && needs_patching) { |
1791 tty->print_cr(" ###class not loaded at load_%s bci %d", | |
1819 | 1792 x->is_static() ? "static" : "field", x->printable_bci()); |
0 | 1793 } |
1819 | 1794 #endif |
0 | 1795 |
8860 | 1796 bool stress_deopt = StressLoopInvariantCodeMotion && info && info->deoptimize_on_exception(); |
0 | 1797 if (x->needs_null_check() && |
1798 (needs_patching || | |
8860 | 1799 MacroAssembler::needs_explicit_null_check(x->offset()) || |
1800 stress_deopt)) { | |
1801 LIR_Opr obj = object.result(); | |
1802 if (stress_deopt) { | |
1803 obj = new_register(T_OBJECT); | |
1804 __ move(LIR_OprFact::oopConst(NULL), obj); | |
1805 } | |
0 | 1806 // emit an explicit null check because the offset is too large |
8860 | 1807 __ null_check(obj, new CodeEmitInfo(info)); |
0 | 1808 } |
1809 | |
1810 LIR_Opr reg = rlock_result(x, field_type); | |
1811 LIR_Address* address; | |
1812 if (needs_patching) { | |
1813 // we need to patch the offset in the instruction so don't allow | |
1814 // generate_address to try to be smart about emitting the -1. | |
1815 // Otherwise the patching code won't know how to find the | |
1816 // instruction to patch. | |
1681
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
1817 address = new LIR_Address(object.result(), PATCHED_ADDR, field_type); |
0 | 1818 } else { |
1819 address = generate_address(object.result(), x->offset(), field_type); | |
1820 } | |
1821 | |
2352
425688247f3d
6965570: assert(!needs_patching && x->is_loaded(),"how do we know it's volatile if it's not loaded")
never
parents:
2167
diff
changeset
|
1822 if (is_volatile && !needs_patching) { |
0 | 1823 volatile_field_load(address, reg, info); |
1824 } else { | |
1825 LIR_PatchCode patch_code = needs_patching ? lir_patch_normal : lir_patch_none; | |
1826 __ load(address, reg, info, patch_code); | |
1827 } | |
1828 | |
1829 if (is_volatile && os::is_MP()) { | |
1830 __ membar_acquire(); | |
1831 } | |
1832 } | |
1833 | |
1834 | |
1835 //------------------------java.nio.Buffer.checkIndex------------------------ | |
1836 | |
1837 // int java.nio.Buffer.checkIndex(int) | |
1838 void LIRGenerator::do_NIOCheckIndex(Intrinsic* x) { | |
1839 // NOTE: by the time we are in checkIndex() we are guaranteed that | |
1840 // the buffer is non-null (because checkIndex is package-private and | |
1841 // only called from within other methods in the buffer). | |
1842 assert(x->number_of_arguments() == 2, "wrong type"); | |
1843 LIRItem buf (x->argument_at(0), this); | |
1844 LIRItem index(x->argument_at(1), this); | |
1845 buf.load_item(); | |
1846 index.load_item(); | |
1847 | |
1848 LIR_Opr result = rlock_result(x); | |
1849 if (GenerateRangeChecks) { | |
1850 CodeEmitInfo* info = state_for(x); | |
1851 CodeStub* stub = new RangeCheckStub(info, index.result(), true); | |
1852 if (index.result()->is_constant()) { | |
1853 cmp_mem_int(lir_cond_belowEqual, buf.result(), java_nio_Buffer::limit_offset(), index.result()->as_jint(), info); | |
1854 __ branch(lir_cond_belowEqual, T_INT, stub); | |
1855 } else { | |
1856 cmp_reg_mem(lir_cond_aboveEqual, index.result(), buf.result(), | |
1857 java_nio_Buffer::limit_offset(), T_INT, info); | |
1858 __ branch(lir_cond_aboveEqual, T_INT, stub); | |
1859 } | |
1860 __ move(index.result(), result); | |
1861 } else { | |
1862 // Just load the index into the result register | |
1863 __ move(index.result(), result); | |
1864 } | |
1865 } | |
1866 | |
1867 | |
1868 //------------------------array access-------------------------------------- | |
1869 | |
1870 | |
1871 void LIRGenerator::do_ArrayLength(ArrayLength* x) { | |
1872 LIRItem array(x->array(), this); | |
1873 array.load_item(); | |
1874 LIR_Opr reg = rlock_result(x); | |
1875 | |
1876 CodeEmitInfo* info = NULL; | |
1877 if (x->needs_null_check()) { | |
1878 NullCheck* nc = x->explicit_null_check(); | |
1879 if (nc == NULL) { | |
1880 info = state_for(x); | |
1881 } else { | |
1882 info = state_for(nc); | |
1883 } | |
8860 | 1884 if (StressLoopInvariantCodeMotion && info->deoptimize_on_exception()) { |
1885 LIR_Opr obj = new_register(T_OBJECT); | |
1886 __ move(LIR_OprFact::oopConst(NULL), obj); | |
1887 __ null_check(obj, new CodeEmitInfo(info)); | |
1888 } | |
0 | 1889 } |
1890 __ load(new LIR_Address(array.result(), arrayOopDesc::length_offset_in_bytes(), T_INT), reg, info, lir_patch_none); | |
1891 } | |
1892 | |
1893 | |
1894 void LIRGenerator::do_LoadIndexed(LoadIndexed* x) { | |
1895 bool use_length = x->length() != NULL; | |
1896 LIRItem array(x->array(), this); | |
1897 LIRItem index(x->index(), this); | |
1898 LIRItem length(this); | |
8860 | 1899 bool needs_range_check = x->compute_needs_range_check(); |
1900 | |
1901 if (use_length && needs_range_check) { | |
1902 length.set_instruction(x->length()); | |
1903 length.load_item(); | |
0 | 1904 } |
1905 | |
1906 array.load_item(); | |
1907 if (index.is_constant() && can_inline_as_constant(x->index())) { | |
1908 // let it be a constant | |
1909 index.dont_load_item(); | |
1910 } else { | |
1911 index.load_item(); | |
1912 } | |
1913 | |
1914 CodeEmitInfo* range_check_info = state_for(x); | |
1915 CodeEmitInfo* null_check_info = NULL; | |
1916 if (x->needs_null_check()) { | |
1917 NullCheck* nc = x->explicit_null_check(); | |
1918 if (nc != NULL) { | |
1919 null_check_info = state_for(nc); | |
1920 } else { | |
1921 null_check_info = range_check_info; | |
1922 } | |
8860 | 1923 if (StressLoopInvariantCodeMotion && null_check_info->deoptimize_on_exception()) { |
1924 LIR_Opr obj = new_register(T_OBJECT); | |
1925 __ move(LIR_OprFact::oopConst(NULL), obj); | |
1926 __ null_check(obj, new CodeEmitInfo(null_check_info)); | |
1927 } | |
0 | 1928 } |
1929 | |
1930 // emit array address setup early so it schedules better | |
1931 LIR_Address* array_addr = emit_array_address(array.result(), index.result(), x->elt_type(), false); | |
1932 | |
1933 if (GenerateRangeChecks && needs_range_check) { | |
8860 | 1934 if (StressLoopInvariantCodeMotion && range_check_info->deoptimize_on_exception()) { |
1935 __ branch(lir_cond_always, T_ILLEGAL, new RangeCheckStub(range_check_info, index.result())); | |
1936 } else if (use_length) { | |
0 | 1937 // TODO: use a (modified) version of array_range_check that does not require a |
1938 // constant length to be loaded to a register | |
1939 __ cmp(lir_cond_belowEqual, length.result(), index.result()); | |
1940 __ branch(lir_cond_belowEqual, T_INT, new RangeCheckStub(range_check_info, index.result())); | |
1941 } else { | |
1942 array_range_check(array.result(), index.result(), null_check_info, range_check_info); | |
1943 // The range check performs the null check, so clear it out for the load | |
1944 null_check_info = NULL; | |
1945 } | |
1946 } | |
1947 | |
1948 __ move(array_addr, rlock_result(x, x->elt_type()), null_check_info); | |
1949 } | |
1950 | |
1951 | |
1952 void LIRGenerator::do_NullCheck(NullCheck* x) { | |
1953 if (x->can_trap()) { | |
1954 LIRItem value(x->obj(), this); | |
1955 value.load_item(); | |
1956 CodeEmitInfo* info = state_for(x); | |
1957 __ null_check(value.result(), info); | |
1958 } | |
1959 } | |
1960 | |
1961 | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6145
diff
changeset
|
1962 void LIRGenerator::do_TypeCast(TypeCast* x) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6145
diff
changeset
|
1963 LIRItem value(x->obj(), this); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6145
diff
changeset
|
1964 value.load_item(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6145
diff
changeset
|
1965 // the result is the same as from the node we are casting |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6145
diff
changeset
|
1966 set_result(x, value.result()); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6145
diff
changeset
|
1967 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6145
diff
changeset
|
1968 |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6145
diff
changeset
|
1969 |
0 | 1970 void LIRGenerator::do_Throw(Throw* x) { |
1971 LIRItem exception(x->exception(), this); | |
1972 exception.load_item(); | |
1973 set_no_result(x); | |
1974 LIR_Opr exception_opr = exception.result(); | |
1975 CodeEmitInfo* info = state_for(x, x->state()); | |
1976 | |
1977 #ifndef PRODUCT | |
1978 if (PrintC1Statistics) { | |
1783 | 1979 increment_counter(Runtime1::throw_count_address(), T_INT); |
0 | 1980 } |
1981 #endif | |
1982 | |
1983 // check if the instruction has an xhandler in any of the nested scopes | |
1984 bool unwind = false; | |
1985 if (info->exception_handlers()->length() == 0) { | |
1986 // this throw is not inside an xhandler | |
1987 unwind = true; | |
1988 } else { | |
1989 // get some idea of the throw type | |
1990 bool type_is_exact = true; | |
1991 ciType* throw_type = x->exception()->exact_type(); | |
1992 if (throw_type == NULL) { | |
1993 type_is_exact = false; | |
1994 throw_type = x->exception()->declared_type(); | |
1995 } | |
1996 if (throw_type != NULL && throw_type->is_instance_klass()) { | |
1997 ciInstanceKlass* throw_klass = (ciInstanceKlass*)throw_type; | |
1998 unwind = !x->exception_handlers()->could_catch(throw_klass, type_is_exact); | |
1999 } | |
2000 } | |
2001 | |
2002 // do null check before moving exception oop into fixed register | |
2003 // to avoid a fixed interval with an oop during the null check. | |
2004 // Use a copy of the CodeEmitInfo because debug information is | |
2005 // different for null_check and throw. | |
2006 if (GenerateCompilerNullChecks && | |
2007 (x->exception()->as_NewInstance() == NULL && x->exception()->as_ExceptionObject() == NULL)) { | |
2008 // if the exception object wasn't created using new then it might be null. | |
1819 | 2009 __ null_check(exception_opr, new CodeEmitInfo(info, x->state()->copy(ValueStack::ExceptionState, x->state()->bci()))); |
0 | 2010 } |
2011 | |
1378
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1304
diff
changeset
|
2012 if (compilation()->env()->jvmti_can_post_on_exceptions()) { |
0 | 2013 // we need to go through the exception lookup path to get JVMTI |
2014 // notification done | |
2015 unwind = false; | |
2016 } | |
2017 | |
2018 // move exception oop into fixed register | |
2019 __ move(exception_opr, exceptionOopOpr()); | |
2020 | |
2021 if (unwind) { | |
1378
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1304
diff
changeset
|
2022 __ unwind_exception(exceptionOopOpr()); |
0 | 2023 } else { |
2024 __ throw_exception(exceptionPcOpr(), exceptionOopOpr(), info); | |
2025 } | |
2026 } | |
2027 | |
2028 | |
2029 void LIRGenerator::do_RoundFP(RoundFP* x) { | |
2030 LIRItem input(x->input(), this); | |
2031 input.load_item(); | |
2032 LIR_Opr input_opr = input.result(); | |
2033 assert(input_opr->is_register(), "why round if value is not in a register?"); | |
2034 assert(input_opr->is_single_fpu() || input_opr->is_double_fpu(), "input should be floating-point value"); | |
2035 if (input_opr->is_single_fpu()) { | |
2036 set_result(x, round_item(input_opr)); // This code path not currently taken | |
2037 } else { | |
2038 LIR_Opr result = new_register(T_DOUBLE); | |
2039 set_vreg_flag(result, must_start_in_memory); | |
2040 __ roundfp(input_opr, LIR_OprFact::illegalOpr, result); | |
2041 set_result(x, result); | |
2042 } | |
2043 } | |
2044 | |
20491
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2045 // Here UnsafeGetRaw may have x->base() and x->index() be int or long |
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2046 // on both 64 and 32 bits. Expecting x->base() to be always long on 64bit. |
0 | 2047 void LIRGenerator::do_UnsafeGetRaw(UnsafeGetRaw* x) { |
2048 LIRItem base(x->base(), this); | |
2049 LIRItem idx(this); | |
2050 | |
2051 base.load_item(); | |
2052 if (x->has_index()) { | |
2053 idx.set_instruction(x->index()); | |
2054 idx.load_nonconstant(); | |
2055 } | |
2056 | |
2057 LIR_Opr reg = rlock_result(x, x->basic_type()); | |
2058 | |
2059 int log2_scale = 0; | |
2060 if (x->has_index()) { | |
2061 log2_scale = x->log2_scale(); | |
2062 } | |
2063 | |
2064 assert(!x->has_index() || idx.value() == x->index(), "should match"); | |
2065 | |
2066 LIR_Opr base_op = base.result(); | |
20491
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2067 LIR_Opr index_op = idx.result(); |
0 | 2068 #ifndef _LP64 |
20519
b29261b17343
8059621: JVM crashes with "unexpected index type" assert in LIRGenerator::do_UnsafeGetRaw
iveresov
parents:
20491
diff
changeset
|
2069 if (base_op->type() == T_LONG) { |
0 | 2070 base_op = new_register(T_INT); |
2071 __ convert(Bytecodes::_l2i, base.result(), base_op); | |
20491
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2072 } |
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2073 if (x->has_index()) { |
20519
b29261b17343
8059621: JVM crashes with "unexpected index type" assert in LIRGenerator::do_UnsafeGetRaw
iveresov
parents:
20491
diff
changeset
|
2074 if (index_op->type() == T_LONG) { |
20491
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2075 LIR_Opr long_index_op = index_op; |
20519
b29261b17343
8059621: JVM crashes with "unexpected index type" assert in LIRGenerator::do_UnsafeGetRaw
iveresov
parents:
20491
diff
changeset
|
2076 if (index_op->is_constant()) { |
20491
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2077 long_index_op = new_register(T_LONG); |
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2078 __ move(index_op, long_index_op); |
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2079 } |
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2080 index_op = new_register(T_INT); |
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2081 __ convert(Bytecodes::_l2i, long_index_op, index_op); |
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2082 } else { |
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2083 assert(x->index()->type()->tag() == intTag, "must be"); |
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2084 } |
0 | 2085 } |
20491
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2086 // At this point base and index should be all ints. |
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2087 assert(base_op->type() == T_INT && !base_op->is_constant(), "base should be an non-constant int"); |
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2088 assert(!x->has_index() || index_op->type() == T_INT, "index should be an int"); |
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2089 #else |
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2090 if (x->has_index()) { |
20519
b29261b17343
8059621: JVM crashes with "unexpected index type" assert in LIRGenerator::do_UnsafeGetRaw
iveresov
parents:
20491
diff
changeset
|
2091 if (index_op->type() == T_INT) { |
b29261b17343
8059621: JVM crashes with "unexpected index type" assert in LIRGenerator::do_UnsafeGetRaw
iveresov
parents:
20491
diff
changeset
|
2092 if (!index_op->is_constant()) { |
20491
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2093 index_op = new_register(T_LONG); |
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2094 __ convert(Bytecodes::_i2l, idx.result(), index_op); |
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2095 } |
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2096 } else { |
20519
b29261b17343
8059621: JVM crashes with "unexpected index type" assert in LIRGenerator::do_UnsafeGetRaw
iveresov
parents:
20491
diff
changeset
|
2097 assert(index_op->type() == T_LONG, "must be"); |
b29261b17343
8059621: JVM crashes with "unexpected index type" assert in LIRGenerator::do_UnsafeGetRaw
iveresov
parents:
20491
diff
changeset
|
2098 if (index_op->is_constant()) { |
20491
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2099 index_op = new_register(T_LONG); |
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2100 __ move(idx.result(), index_op); |
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2101 } |
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2102 } |
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2103 } |
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2104 // At this point base is a long non-constant |
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2105 // Index is a long register or a int constant. |
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2106 // We allow the constant to stay an int because that would allow us a more compact encoding by |
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2107 // embedding an immediate offset in the address expression. If we have a long constant, we have to |
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2108 // move it into a register first. |
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2109 assert(base_op->type() == T_LONG && !base_op->is_constant(), "base must be a long non-constant"); |
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2110 assert(!x->has_index() || (index_op->type() == T_INT && index_op->is_constant()) || |
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2111 (index_op->type() == T_LONG && !index_op->is_constant()), "unexpected index type"); |
0 | 2112 #endif |
2113 | |
2114 BasicType dst_type = x->basic_type(); | |
2115 | |
2116 LIR_Address* addr; | |
2117 if (index_op->is_constant()) { | |
2118 assert(log2_scale == 0, "must not have a scale"); | |
20491
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2119 assert(index_op->type() == T_INT, "only int constants supported"); |
0 | 2120 addr = new LIR_Address(base_op, index_op->as_jint(), dst_type); |
2121 } else { | |
304 | 2122 #ifdef X86 |
0 | 2123 addr = new LIR_Address(base_op, index_op, LIR_Address::Scale(log2_scale), 0, dst_type); |
1681
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
2124 #elif defined(ARM) |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
2125 addr = generate_address(base_op, index_op, log2_scale, 0, dst_type); |
0 | 2126 #else |
2127 if (index_op->is_illegal() || log2_scale == 0) { | |
2128 addr = new LIR_Address(base_op, index_op, dst_type); | |
2129 } else { | |
1060 | 2130 LIR_Opr tmp = new_pointer_register(); |
0 | 2131 __ shift_left(index_op, log2_scale, tmp); |
2132 addr = new LIR_Address(base_op, tmp, dst_type); | |
2133 } | |
2134 #endif | |
2135 } | |
2136 | |
2137 if (x->may_be_unaligned() && (dst_type == T_LONG || dst_type == T_DOUBLE)) { | |
2138 __ unaligned_move(addr, reg); | |
2139 } else { | |
2002 | 2140 if (dst_type == T_OBJECT && x->is_wide()) { |
2141 __ move_wide(addr, reg); | |
2142 } else { | |
2143 __ move(addr, reg); | |
2144 } | |
0 | 2145 } |
2146 } | |
2147 | |
2148 | |
2149 void LIRGenerator::do_UnsafePutRaw(UnsafePutRaw* x) { | |
2150 int log2_scale = 0; | |
2151 BasicType type = x->basic_type(); | |
2152 | |
2153 if (x->has_index()) { | |
2154 log2_scale = x->log2_scale(); | |
2155 } | |
2156 | |
2157 LIRItem base(x->base(), this); | |
2158 LIRItem value(x->value(), this); | |
2159 LIRItem idx(this); | |
2160 | |
2161 base.load_item(); | |
2162 if (x->has_index()) { | |
2163 idx.set_instruction(x->index()); | |
2164 idx.load_item(); | |
2165 } | |
2166 | |
2167 if (type == T_BYTE || type == T_BOOLEAN) { | |
2168 value.load_byte_item(); | |
2169 } else { | |
2170 value.load_item(); | |
2171 } | |
2172 | |
2173 set_no_result(x); | |
2174 | |
2175 LIR_Opr base_op = base.result(); | |
20491
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2176 LIR_Opr index_op = idx.result(); |
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2177 |
0 | 2178 #ifndef _LP64 |
20519
b29261b17343
8059621: JVM crashes with "unexpected index type" assert in LIRGenerator::do_UnsafeGetRaw
iveresov
parents:
20491
diff
changeset
|
2179 if (base_op->type() == T_LONG) { |
0 | 2180 base_op = new_register(T_INT); |
2181 __ convert(Bytecodes::_l2i, base.result(), base_op); | |
20491
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2182 } |
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2183 if (x->has_index()) { |
20519
b29261b17343
8059621: JVM crashes with "unexpected index type" assert in LIRGenerator::do_UnsafeGetRaw
iveresov
parents:
20491
diff
changeset
|
2184 if (index_op->type() == T_LONG) { |
20491
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2185 index_op = new_register(T_INT); |
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2186 __ convert(Bytecodes::_l2i, idx.result(), index_op); |
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2187 } |
0 | 2188 } |
20491
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2189 // At this point base and index should be all ints and not constants |
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2190 assert(base_op->type() == T_INT && !base_op->is_constant(), "base should be an non-constant int"); |
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2191 assert(!x->has_index() || (index_op->type() == T_INT && !index_op->is_constant()), "index should be an non-constant int"); |
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2192 #else |
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2193 if (x->has_index()) { |
20519
b29261b17343
8059621: JVM crashes with "unexpected index type" assert in LIRGenerator::do_UnsafeGetRaw
iveresov
parents:
20491
diff
changeset
|
2194 if (index_op->type() == T_INT) { |
20491
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2195 index_op = new_register(T_LONG); |
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2196 __ convert(Bytecodes::_i2l, idx.result(), index_op); |
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2197 } |
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2198 } |
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2199 // At this point base and index are long and non-constant |
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2200 assert(base_op->type() == T_LONG && !base_op->is_constant(), "base must be a non-constant long"); |
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2201 assert(!x->has_index() || (index_op->type() == T_LONG && !index_op->is_constant()), "index must be a non-constant long"); |
0 | 2202 #endif |
2203 | |
2204 if (log2_scale != 0) { | |
2205 // temporary fix (platform dependent code without shift on Intel would be better) | |
20491
a60a1309a03a
8058744: Crash in C1 OSRed method w/ Unsafe usage
iveresov
parents:
20344
diff
changeset
|
2206 // TODO: ARM also allows embedded shift in the address |
0 | 2207 __ shift_left(index_op, log2_scale, index_op); |
2208 } | |
2209 | |
2210 LIR_Address* addr = new LIR_Address(base_op, index_op, x->basic_type()); | |
2211 __ move(value.result(), addr); | |
2212 } | |
2213 | |
2214 | |
2215 void LIRGenerator::do_UnsafeGetObject(UnsafeGetObject* x) { | |
2216 BasicType type = x->basic_type(); | |
2217 LIRItem src(x->object(), this); | |
2218 LIRItem off(x->offset(), this); | |
2219 | |
2220 off.load_item(); | |
2221 src.load_item(); | |
2222 | |
6615
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2223 LIR_Opr value = rlock_result(x, x->basic_type()); |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2224 |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2225 get_Object_unsafe(value, src.result(), off.result(), type, x->is_volatile()); |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2226 |
8001
db9981fd3124
8005915: Unify SERIALGC and INCLUDE_ALTERNATE_GCS
jprovino
parents:
7425
diff
changeset
|
2227 #if INCLUDE_ALL_GCS |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2228 // We might be reading the value of the referent field of a |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2229 // Reference object in order to attach it back to the live |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2230 // object graph. If G1 is enabled then we need to record |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2231 // the value that is being returned in an SATB log buffer. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2232 // |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2233 // We need to generate code similar to the following... |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2234 // |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2235 // if (offset == java_lang_ref_Reference::referent_offset) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2236 // if (src != NULL) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2237 // if (klass(src)->reference_type() != REF_NONE) { |
6615
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2238 // pre_barrier(..., value, ...); |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2239 // } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2240 // } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2241 // } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2242 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2243 if (UseG1GC && type == T_OBJECT) { |
6615
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2244 bool gen_pre_barrier = true; // Assume we need to generate pre_barrier. |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2245 bool gen_offset_check = true; // Assume we need to generate the offset guard. |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2246 bool gen_source_check = true; // Assume we need to check the src object for null. |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2247 bool gen_type_check = true; // Assume we need to check the reference_type. |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2248 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2249 if (off.is_constant()) { |
3254
59766fd005ff
7035117: G1: nsk/stress/jni/jnistress002 fails with assertion failure
johnc
parents:
3249
diff
changeset
|
2250 jlong off_con = (off.type()->is_int() ? |
59766fd005ff
7035117: G1: nsk/stress/jni/jnistress002 fails with assertion failure
johnc
parents:
3249
diff
changeset
|
2251 (jlong) off.get_jint_constant() : |
59766fd005ff
7035117: G1: nsk/stress/jni/jnistress002 fails with assertion failure
johnc
parents:
3249
diff
changeset
|
2252 off.get_jlong_constant()); |
59766fd005ff
7035117: G1: nsk/stress/jni/jnistress002 fails with assertion failure
johnc
parents:
3249
diff
changeset
|
2253 |
59766fd005ff
7035117: G1: nsk/stress/jni/jnistress002 fails with assertion failure
johnc
parents:
3249
diff
changeset
|
2254 |
59766fd005ff
7035117: G1: nsk/stress/jni/jnistress002 fails with assertion failure
johnc
parents:
3249
diff
changeset
|
2255 if (off_con != (jlong) java_lang_ref_Reference::referent_offset) { |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2256 // The constant offset is something other than referent_offset. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2257 // We can skip generating/checking the remaining guards and |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2258 // skip generation of the code stub. |
6615
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2259 gen_pre_barrier = false; |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2260 } else { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2261 // The constant offset is the same as referent_offset - |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2262 // we do not need to generate a runtime offset check. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2263 gen_offset_check = false; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2264 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2265 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2266 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2267 // We don't need to generate stub if the source object is an array |
6615
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2268 if (gen_pre_barrier && src.type()->is_array()) { |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2269 gen_pre_barrier = false; |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2270 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2271 |
6615
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2272 if (gen_pre_barrier) { |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2273 // We still need to continue with the checks. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2274 if (src.is_constant()) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2275 ciObject* src_con = src.get_jobject_constant(); |
10397
075ea888b039
8010724: [parfait] Null pointer dereference in hotspot/src/share/vm/c1/c1_LIRGenerator.cpp
morris
parents:
10116
diff
changeset
|
2276 guarantee(src_con != NULL, "no source constant"); |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2277 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2278 if (src_con->is_null_object()) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2279 // The constant src object is null - We can skip |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2280 // generating the code stub. |
6615
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2281 gen_pre_barrier = false; |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2282 } else { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2283 // Non-null constant source object. We still have to generate |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2284 // the slow stub - but we don't need to generate the runtime |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2285 // null object check. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2286 gen_source_check = false; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2287 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2288 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2289 } |
6615
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2290 if (gen_pre_barrier && !PatchALot) { |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2291 // Can the klass of object be statically determined to be |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2292 // a sub-class of Reference? |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2293 ciType* type = src.value()->declared_type(); |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2294 if ((type != NULL) && type->is_loaded()) { |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2295 if (type->is_subtype_of(compilation()->env()->Reference_klass())) { |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2296 gen_type_check = false; |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2297 } else if (type->is_klass() && |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2298 !compilation()->env()->Object_klass()->is_subtype_of(type->as_klass())) { |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2299 // Not Reference and not Object klass. |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2300 gen_pre_barrier = false; |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2301 } |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2302 } |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2303 } |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2304 |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2305 if (gen_pre_barrier) { |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2306 LabelObj* Lcont = new LabelObj(); |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2307 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2308 // We can have generate one runtime check here. Let's start with |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2309 // the offset check. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2310 if (gen_offset_check) { |
6615
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2311 // if (offset != referent_offset) -> continue |
3254
59766fd005ff
7035117: G1: nsk/stress/jni/jnistress002 fails with assertion failure
johnc
parents:
3249
diff
changeset
|
2312 // If offset is an int then we can do the comparison with the |
59766fd005ff
7035117: G1: nsk/stress/jni/jnistress002 fails with assertion failure
johnc
parents:
3249
diff
changeset
|
2313 // referent_offset constant; otherwise we need to move |
59766fd005ff
7035117: G1: nsk/stress/jni/jnistress002 fails with assertion failure
johnc
parents:
3249
diff
changeset
|
2314 // referent_offset into a temporary register and generate |
59766fd005ff
7035117: G1: nsk/stress/jni/jnistress002 fails with assertion failure
johnc
parents:
3249
diff
changeset
|
2315 // a reg-reg compare. |
59766fd005ff
7035117: G1: nsk/stress/jni/jnistress002 fails with assertion failure
johnc
parents:
3249
diff
changeset
|
2316 |
59766fd005ff
7035117: G1: nsk/stress/jni/jnistress002 fails with assertion failure
johnc
parents:
3249
diff
changeset
|
2317 LIR_Opr referent_off; |
59766fd005ff
7035117: G1: nsk/stress/jni/jnistress002 fails with assertion failure
johnc
parents:
3249
diff
changeset
|
2318 |
59766fd005ff
7035117: G1: nsk/stress/jni/jnistress002 fails with assertion failure
johnc
parents:
3249
diff
changeset
|
2319 if (off.type()->is_int()) { |
59766fd005ff
7035117: G1: nsk/stress/jni/jnistress002 fails with assertion failure
johnc
parents:
3249
diff
changeset
|
2320 referent_off = LIR_OprFact::intConst(java_lang_ref_Reference::referent_offset); |
59766fd005ff
7035117: G1: nsk/stress/jni/jnistress002 fails with assertion failure
johnc
parents:
3249
diff
changeset
|
2321 } else { |
59766fd005ff
7035117: G1: nsk/stress/jni/jnistress002 fails with assertion failure
johnc
parents:
3249
diff
changeset
|
2322 assert(off.type()->is_long(), "what else?"); |
59766fd005ff
7035117: G1: nsk/stress/jni/jnistress002 fails with assertion failure
johnc
parents:
3249
diff
changeset
|
2323 referent_off = new_register(T_LONG); |
59766fd005ff
7035117: G1: nsk/stress/jni/jnistress002 fails with assertion failure
johnc
parents:
3249
diff
changeset
|
2324 __ move(LIR_OprFact::longConst(java_lang_ref_Reference::referent_offset), referent_off); |
59766fd005ff
7035117: G1: nsk/stress/jni/jnistress002 fails with assertion failure
johnc
parents:
3249
diff
changeset
|
2325 } |
6615
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2326 __ cmp(lir_cond_notEqual, off.result(), referent_off); |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2327 __ branch(lir_cond_notEqual, as_BasicType(off.type()), Lcont->label()); |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2328 } |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2329 if (gen_source_check) { |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2330 // offset is a const and equals referent offset |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2331 // if (source == null) -> continue |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2332 __ cmp(lir_cond_equal, src.result(), LIR_OprFact::oopConst(NULL)); |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2333 __ branch(lir_cond_equal, T_OBJECT, Lcont->label()); |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2334 } |
6615
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2335 LIR_Opr src_klass = new_register(T_OBJECT); |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2336 if (gen_type_check) { |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2337 // We have determined that offset == referent_offset && src != null. |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2338 // if (src->_klass->_reference_type == REF_NONE) -> continue |
12000
8d77d02828d9
8016474: Crash in sun.reflect.UnsafeObjectFieldAccessorImpl.get
twisti
parents:
11080
diff
changeset
|
2339 __ move(new LIR_Address(src.result(), oopDesc::klass_offset_in_bytes(), T_ADDRESS), src_klass); |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6616
diff
changeset
|
2340 LIR_Address* reference_type_addr = new LIR_Address(src_klass, in_bytes(InstanceKlass::reference_type_offset()), T_BYTE); |
6615
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2341 LIR_Opr reference_type = new_register(T_INT); |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2342 __ move(reference_type_addr, reference_type); |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2343 __ cmp(lir_cond_equal, reference_type, LIR_OprFact::intConst(REF_NONE)); |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2344 __ branch(lir_cond_equal, T_INT, Lcont->label()); |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2345 } |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2346 { |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2347 // We have determined that src->_klass->_reference_type != REF_NONE |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2348 // so register the value in the referent field with the pre-barrier. |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2349 pre_barrier(LIR_OprFact::illegalOpr /* addr_opr */, |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2350 value /* pre_val */, |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2351 false /* do_load */, |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2352 false /* patch */, |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2353 NULL /* info */); |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2354 } |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2355 __ branch_destination(Lcont->label()); |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2356 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2357 } |
8001
db9981fd3124
8005915: Unify SERIALGC and INCLUDE_ALTERNATE_GCS
jprovino
parents:
7425
diff
changeset
|
2358 #endif // INCLUDE_ALL_GCS |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2359 |
0 | 2360 if (x->is_volatile() && os::is_MP()) __ membar_acquire(); |
2361 } | |
2362 | |
2363 | |
2364 void LIRGenerator::do_UnsafePutObject(UnsafePutObject* x) { | |
2365 BasicType type = x->basic_type(); | |
2366 LIRItem src(x->object(), this); | |
2367 LIRItem off(x->offset(), this); | |
2368 LIRItem data(x->value(), this); | |
2369 | |
2370 src.load_item(); | |
2371 if (type == T_BOOLEAN || type == T_BYTE) { | |
2372 data.load_byte_item(); | |
2373 } else { | |
2374 data.load_item(); | |
2375 } | |
2376 off.load_item(); | |
2377 | |
2378 set_no_result(x); | |
2379 | |
2380 if (x->is_volatile() && os::is_MP()) __ membar_release(); | |
2381 put_Object_unsafe(src.result(), off.result(), data.result(), type, x->is_volatile()); | |
2123
df307487d610
7010665: Misplaced membar in C1 implementation of Unsafe.get/putXXX
dholmes
parents:
2007
diff
changeset
|
2382 if (x->is_volatile() && os::is_MP()) __ membar(); |
0 | 2383 } |
2384 | |
2385 | |
2386 void LIRGenerator::do_UnsafePrefetch(UnsafePrefetch* x, bool is_store) { | |
2387 LIRItem src(x->object(), this); | |
2388 LIRItem off(x->offset(), this); | |
2389 | |
2390 src.load_item(); | |
2391 if (off.is_constant() && can_inline_as_constant(x->offset())) { | |
2392 // let it be a constant | |
2393 off.dont_load_item(); | |
2394 } else { | |
2395 off.load_item(); | |
2396 } | |
2397 | |
2398 set_no_result(x); | |
2399 | |
2400 LIR_Address* addr = generate_address(src.result(), off.result(), 0, 0, T_BYTE); | |
2401 __ prefetch(addr, is_store); | |
2402 } | |
2403 | |
2404 | |
2405 void LIRGenerator::do_UnsafePrefetchRead(UnsafePrefetchRead* x) { | |
2406 do_UnsafePrefetch(x, false); | |
2407 } | |
2408 | |
2409 | |
2410 void LIRGenerator::do_UnsafePrefetchWrite(UnsafePrefetchWrite* x) { | |
2411 do_UnsafePrefetch(x, true); | |
2412 } | |
2413 | |
2414 | |
2415 void LIRGenerator::do_SwitchRanges(SwitchRangeArray* x, LIR_Opr value, BlockBegin* default_sux) { | |
2416 int lng = x->length(); | |
2417 | |
2418 for (int i = 0; i < lng; i++) { | |
2419 SwitchRange* one_range = x->at(i); | |
2420 int low_key = one_range->low_key(); | |
2421 int high_key = one_range->high_key(); | |
2422 BlockBegin* dest = one_range->sux(); | |
2423 if (low_key == high_key) { | |
2424 __ cmp(lir_cond_equal, value, low_key); | |
2425 __ branch(lir_cond_equal, T_INT, dest); | |
2426 } else if (high_key - low_key == 1) { | |
2427 __ cmp(lir_cond_equal, value, low_key); | |
2428 __ branch(lir_cond_equal, T_INT, dest); | |
2429 __ cmp(lir_cond_equal, value, high_key); | |
2430 __ branch(lir_cond_equal, T_INT, dest); | |
2431 } else { | |
2432 LabelObj* L = new LabelObj(); | |
2433 __ cmp(lir_cond_less, value, low_key); | |
4816 | 2434 __ branch(lir_cond_less, T_INT, L->label()); |
0 | 2435 __ cmp(lir_cond_lessEqual, value, high_key); |
2436 __ branch(lir_cond_lessEqual, T_INT, dest); | |
2437 __ branch_destination(L->label()); | |
2438 } | |
2439 } | |
2440 __ jump(default_sux); | |
2441 } | |
2442 | |
2443 | |
2444 SwitchRangeArray* LIRGenerator::create_lookup_ranges(TableSwitch* x) { | |
2445 SwitchRangeList* res = new SwitchRangeList(); | |
2446 int len = x->length(); | |
2447 if (len > 0) { | |
2448 BlockBegin* sux = x->sux_at(0); | |
2449 int key = x->lo_key(); | |
2450 BlockBegin* default_sux = x->default_sux(); | |
2451 SwitchRange* range = new SwitchRange(key, sux); | |
2452 for (int i = 0; i < len; i++, key++) { | |
2453 BlockBegin* new_sux = x->sux_at(i); | |
2454 if (sux == new_sux) { | |
2455 // still in same range | |
2456 range->set_high_key(key); | |
2457 } else { | |
2458 // skip tests which explicitly dispatch to the default | |
2459 if (sux != default_sux) { | |
2460 res->append(range); | |
2461 } | |
2462 range = new SwitchRange(key, new_sux); | |
2463 } | |
2464 sux = new_sux; | |
2465 } | |
2466 if (res->length() == 0 || res->last() != range) res->append(range); | |
2467 } | |
2468 return res; | |
2469 } | |
2470 | |
2471 | |
2472 // we expect the keys to be sorted by increasing value | |
2473 SwitchRangeArray* LIRGenerator::create_lookup_ranges(LookupSwitch* x) { | |
2474 SwitchRangeList* res = new SwitchRangeList(); | |
2475 int len = x->length(); | |
2476 if (len > 0) { | |
2477 BlockBegin* default_sux = x->default_sux(); | |
2478 int key = x->key_at(0); | |
2479 BlockBegin* sux = x->sux_at(0); | |
2480 SwitchRange* range = new SwitchRange(key, sux); | |
2481 for (int i = 1; i < len; i++) { | |
2482 int new_key = x->key_at(i); | |
2483 BlockBegin* new_sux = x->sux_at(i); | |
2484 if (key+1 == new_key && sux == new_sux) { | |
2485 // still in same range | |
2486 range->set_high_key(new_key); | |
2487 } else { | |
2488 // skip tests which explicitly dispatch to the default | |
2489 if (range->sux() != default_sux) { | |
2490 res->append(range); | |
2491 } | |
2492 range = new SwitchRange(new_key, new_sux); | |
2493 } | |
2494 key = new_key; | |
2495 sux = new_sux; | |
2496 } | |
2497 if (res->length() == 0 || res->last() != range) res->append(range); | |
2498 } | |
2499 return res; | |
2500 } | |
2501 | |
2502 | |
2503 void LIRGenerator::do_TableSwitch(TableSwitch* x) { | |
2504 LIRItem tag(x->tag(), this); | |
2505 tag.load_item(); | |
2506 set_no_result(x); | |
2507 | |
2508 if (x->is_safepoint()) { | |
2509 __ safepoint(safepoint_poll_register(), state_for(x, x->state_before())); | |
2510 } | |
2511 | |
2512 // move values into phi locations | |
2513 move_to_phi(x->state()); | |
2514 | |
2515 int lo_key = x->lo_key(); | |
2516 int hi_key = x->hi_key(); | |
2517 int len = x->length(); | |
2518 LIR_Opr value = tag.result(); | |
2519 if (UseTableRanges) { | |
2520 do_SwitchRanges(create_lookup_ranges(x), value, x->default_sux()); | |
2521 } else { | |
2522 for (int i = 0; i < len; i++) { | |
2523 __ cmp(lir_cond_equal, value, i + lo_key); | |
2524 __ branch(lir_cond_equal, T_INT, x->sux_at(i)); | |
2525 } | |
2526 __ jump(x->default_sux()); | |
2527 } | |
2528 } | |
2529 | |
2530 | |
2531 void LIRGenerator::do_LookupSwitch(LookupSwitch* x) { | |
2532 LIRItem tag(x->tag(), this); | |
2533 tag.load_item(); | |
2534 set_no_result(x); | |
2535 | |
2536 if (x->is_safepoint()) { | |
2537 __ safepoint(safepoint_poll_register(), state_for(x, x->state_before())); | |
2538 } | |
2539 | |
2540 // move values into phi locations | |
2541 move_to_phi(x->state()); | |
2542 | |
2543 LIR_Opr value = tag.result(); | |
2544 if (UseTableRanges) { | |
2545 do_SwitchRanges(create_lookup_ranges(x), value, x->default_sux()); | |
2546 } else { | |
2547 int len = x->length(); | |
2548 for (int i = 0; i < len; i++) { | |
2549 __ cmp(lir_cond_equal, value, x->key_at(i)); | |
2550 __ branch(lir_cond_equal, T_INT, x->sux_at(i)); | |
2551 } | |
2552 __ jump(x->default_sux()); | |
2553 } | |
2554 } | |
2555 | |
2556 | |
2557 void LIRGenerator::do_Goto(Goto* x) { | |
2558 set_no_result(x); | |
2559 | |
2560 if (block()->next()->as_OsrEntry()) { | |
2561 // need to free up storage used for OSR entry point | |
2562 LIR_Opr osrBuffer = block()->next()->operand(); | |
2563 BasicTypeList signature; | |
2564 signature.append(T_INT); | |
2565 CallingConvention* cc = frame_map()->c_calling_convention(&signature); | |
2566 __ move(osrBuffer, cc->args()->at(0)); | |
2567 __ call_runtime_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::OSR_migration_end), | |
2568 getThreadTemp(), LIR_OprFact::illegalOpr, cc->args()); | |
2569 } | |
2570 | |
2571 if (x->is_safepoint()) { | |
2572 ValueStack* state = x->state_before() ? x->state_before() : x->state(); | |
2573 | |
2574 // increment backedge counter if needed | |
1783 | 2575 CodeEmitInfo* info = state_for(x, state); |
3997
940513efe83a
7097679: Tiered: events with bad bci to Gotos reduced from Ifs
iveresov
parents:
3964
diff
changeset
|
2576 increment_backedge_counter(info, x->profiled_bci()); |
0 | 2577 CodeEmitInfo* safepoint_info = state_for(x, state); |
2578 __ safepoint(safepoint_poll_register(), safepoint_info); | |
2579 } | |
2580 | |
1783 | 2581 // Gotos can be folded Ifs, handle this case. |
2582 if (x->should_profile()) { | |
2583 ciMethod* method = x->profiled_method(); | |
2584 assert(method != NULL, "method should be set if branch is profiled"); | |
2007
5ddfcf4b079e
7003554: (tiered) assert(is_null_object() || handle() != NULL) failed: cannot embed null pointer
iveresov
parents:
2002
diff
changeset
|
2585 ciMethodData* md = method->method_data_or_null(); |
5ddfcf4b079e
7003554: (tiered) assert(is_null_object() || handle() != NULL) failed: cannot embed null pointer
iveresov
parents:
2002
diff
changeset
|
2586 assert(md != NULL, "Sanity"); |
1783 | 2587 ciProfileData* data = md->bci_to_data(x->profiled_bci()); |
2588 assert(data != NULL, "must have profiling data"); | |
2589 int offset; | |
2590 if (x->direction() == Goto::taken) { | |
2591 assert(data->is_BranchData(), "need BranchData for two-way branches"); | |
2592 offset = md->byte_offset_of_slot(data, BranchData::taken_offset()); | |
2593 } else if (x->direction() == Goto::not_taken) { | |
2594 assert(data->is_BranchData(), "need BranchData for two-way branches"); | |
2595 offset = md->byte_offset_of_slot(data, BranchData::not_taken_offset()); | |
2596 } else { | |
2597 assert(data->is_JumpData(), "need JumpData for branches"); | |
2598 offset = md->byte_offset_of_slot(data, JumpData::taken_offset()); | |
2599 } | |
6739
8a02ca5e5576
7195816: NPG: Crash in c1_ValueType - ShouldNotReachHere
roland
parents:
6731
diff
changeset
|
2600 LIR_Opr md_reg = new_register(T_METADATA); |
8a02ca5e5576
7195816: NPG: Crash in c1_ValueType - ShouldNotReachHere
roland
parents:
6731
diff
changeset
|
2601 __ metadata2reg(md->constant_encoding(), md_reg); |
1783 | 2602 |
2603 increment_counter(new LIR_Address(md_reg, offset, | |
2604 NOT_LP64(T_INT) LP64_ONLY(T_LONG)), DataLayout::counter_increment); | |
2605 } | |
2606 | |
0 | 2607 // emit phi-instruction move after safepoint since this simplifies |
2608 // describing the state as the safepoint. | |
2609 move_to_phi(x->state()); | |
2610 | |
2611 __ jump(x->default_sux()); | |
2612 } | |
2613 | |
13078
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
2614 /** |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
2615 * Emit profiling code if needed for arguments, parameters, return value types |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
2616 * |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
2617 * @param md MDO the code will update at runtime |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
2618 * @param md_base_offset common offset in the MDO for this profile and subsequent ones |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
2619 * @param md_offset offset in the MDO (on top of md_base_offset) for this profile |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
2620 * @param profiled_k current profile |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
2621 * @param obj IR node for the object to be profiled |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
2622 * @param mdp register to hold the pointer inside the MDO (md + md_base_offset). |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
2623 * Set once we find an update to make and use for next ones. |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
2624 * @param not_null true if we know obj cannot be null |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
2625 * @param signature_at_call_k signature at call for obj |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
2626 * @param callee_signature_k signature of callee for obj |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
2627 * at call and callee signatures differ at method handle call |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
2628 * @return the only klass we know will ever be seen at this profile point |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
2629 */ |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
2630 ciKlass* LIRGenerator::profile_type(ciMethodData* md, int md_base_offset, int md_offset, intptr_t profiled_k, |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
2631 Value obj, LIR_Opr& mdp, bool not_null, ciKlass* signature_at_call_k, |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
2632 ciKlass* callee_signature_k) { |
12875
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2633 ciKlass* result = NULL; |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2634 bool do_null = !not_null && !TypeEntries::was_null_seen(profiled_k); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2635 bool do_update = !TypeEntries::is_type_unknown(profiled_k); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2636 // known not to be null or null bit already set and already set to |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2637 // unknown: nothing we can do to improve profiling |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2638 if (!do_null && !do_update) { |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2639 return result; |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2640 } |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2641 |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2642 ciKlass* exact_klass = NULL; |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2643 Compilation* comp = Compilation::current(); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2644 if (do_update) { |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2645 // try to find exact type, using CHA if possible, so that loading |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2646 // the klass from the object can be avoided |
13078
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
2647 ciType* type = obj->exact_type(); |
12875
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2648 if (type == NULL) { |
13078
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
2649 type = obj->declared_type(); |
12875
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2650 type = comp->cha_exact_type(type); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2651 } |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2652 assert(type == NULL || type->is_klass(), "type should be class"); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2653 exact_klass = (type != NULL && type->is_loaded()) ? (ciKlass*)type : NULL; |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2654 |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2655 do_update = exact_klass == NULL || ciTypeEntries::valid_ciklass(profiled_k) != exact_klass; |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2656 } |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2657 |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2658 if (!do_null && !do_update) { |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2659 return result; |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2660 } |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2661 |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2662 ciKlass* exact_signature_k = NULL; |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2663 if (do_update) { |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2664 // Is the type from the signature exact (the only one possible)? |
13078
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
2665 exact_signature_k = signature_at_call_k->exact_klass(); |
12875
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2666 if (exact_signature_k == NULL) { |
13078
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
2667 exact_signature_k = comp->cha_exact_type(signature_at_call_k); |
12875
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2668 } else { |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2669 result = exact_signature_k; |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2670 // Known statically. No need to emit any code: prevent |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2671 // LIR_Assembler::emit_profile_type() from emitting useless code |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2672 profiled_k = ciTypeEntries::with_status(result, profiled_k); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2673 } |
17925
45e59fae8f2b
8041481: JVM crashes with collect_args_for_profiling
roland
parents:
17900
diff
changeset
|
2674 // exact_klass and exact_signature_k can be both non NULL but |
45e59fae8f2b
8041481: JVM crashes with collect_args_for_profiling
roland
parents:
17900
diff
changeset
|
2675 // different if exact_klass is loaded after the ciObject for |
45e59fae8f2b
8041481: JVM crashes with collect_args_for_profiling
roland
parents:
17900
diff
changeset
|
2676 // exact_signature_k is created. |
45e59fae8f2b
8041481: JVM crashes with collect_args_for_profiling
roland
parents:
17900
diff
changeset
|
2677 if (exact_klass == NULL && exact_signature_k != NULL && exact_klass != exact_signature_k) { |
12875
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2678 // sometimes the type of the signature is better than the best type |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2679 // the compiler has |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2680 exact_klass = exact_signature_k; |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2681 } |
13078
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
2682 if (callee_signature_k != NULL && |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
2683 callee_signature_k != signature_at_call_k) { |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
2684 ciKlass* improved_klass = callee_signature_k->exact_klass(); |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
2685 if (improved_klass == NULL) { |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
2686 improved_klass = comp->cha_exact_type(callee_signature_k); |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
2687 } |
17925
45e59fae8f2b
8041481: JVM crashes with collect_args_for_profiling
roland
parents:
17900
diff
changeset
|
2688 if (exact_klass == NULL && improved_klass != NULL && exact_klass != improved_klass) { |
13078
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
2689 exact_klass = exact_signature_k; |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
2690 } |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
2691 } |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
2692 do_update = exact_klass == NULL || ciTypeEntries::valid_ciklass(profiled_k) != exact_klass; |
12875
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2693 } |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2694 |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2695 if (!do_null && !do_update) { |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2696 return result; |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2697 } |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2698 |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2699 if (mdp == LIR_OprFact::illegalOpr) { |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2700 mdp = new_register(T_METADATA); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2701 __ metadata2reg(md->constant_encoding(), mdp); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2702 if (md_base_offset != 0) { |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2703 LIR_Address* base_type_address = new LIR_Address(mdp, md_base_offset, T_ADDRESS); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2704 mdp = new_pointer_register(); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2705 __ leal(LIR_OprFact::address(base_type_address), mdp); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2706 } |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2707 } |
13078
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
2708 LIRItem value(obj, this); |
12875
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2709 value.load_item(); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2710 __ profile_type(new LIR_Address(mdp, md_offset, T_METADATA), |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2711 value.result(), exact_klass, profiled_k, new_pointer_register(), not_null, exact_signature_k != NULL); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2712 return result; |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2713 } |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
2714 |
12962
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
2715 // profile parameters on entry to the root of the compilation |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
2716 void LIRGenerator::profile_parameters(Base* x) { |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
2717 if (compilation()->profile_parameters()) { |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
2718 CallingConvention* args = compilation()->frame_map()->incoming_arguments(); |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
2719 ciMethodData* md = scope()->method()->method_data_or_null(); |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
2720 assert(md != NULL, "Sanity"); |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
2721 |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
2722 if (md->parameters_type_data() != NULL) { |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
2723 ciParametersTypeData* parameters_type_data = md->parameters_type_data(); |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
2724 ciTypeStackSlotEntries* parameters = parameters_type_data->parameters(); |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
2725 LIR_Opr mdp = LIR_OprFact::illegalOpr; |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
2726 for (int java_index = 0, i = 0, j = 0; j < parameters_type_data->number_of_parameters(); i++) { |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
2727 LIR_Opr src = args->at(i); |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
2728 assert(!src->is_illegal(), "check"); |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
2729 BasicType t = src->type(); |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
2730 if (t == T_OBJECT || t == T_ARRAY) { |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
2731 intptr_t profiled_k = parameters->type(j); |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
2732 Local* local = x->state()->local_at(java_index)->as_Local(); |
13078
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
2733 ciKlass* exact = profile_type(md, md->byte_offset_of_slot(parameters_type_data, ParametersTypeData::type_offset(0)), |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
2734 in_bytes(ParametersTypeData::type_offset(j)) - in_bytes(ParametersTypeData::type_offset(0)), |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
2735 profiled_k, local, mdp, false, local->declared_type()->as_klass(), NULL); |
12962
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
2736 // If the profile is known statically set it once for all and do not emit any code |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
2737 if (exact != NULL) { |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
2738 md->set_parameter_type(j, exact); |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
2739 } |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
2740 j++; |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
2741 } |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
2742 java_index += type2size[t]; |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
2743 } |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
2744 } |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
2745 } |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
2746 } |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
2747 |
0 | 2748 void LIRGenerator::do_Base(Base* x) { |
2749 __ std_entry(LIR_OprFact::illegalOpr); | |
2750 // Emit moves from physical registers / stack slots to virtual registers | |
2751 CallingConvention* args = compilation()->frame_map()->incoming_arguments(); | |
2752 IRScope* irScope = compilation()->hir()->top_scope(); | |
2753 int java_index = 0; | |
2754 for (int i = 0; i < args->length(); i++) { | |
2755 LIR_Opr src = args->at(i); | |
2756 assert(!src->is_illegal(), "check"); | |
2757 BasicType t = src->type(); | |
2758 | |
2759 // Types which are smaller than int are passed as int, so | |
2760 // correct the type which passed. | |
2761 switch (t) { | |
2762 case T_BYTE: | |
2763 case T_BOOLEAN: | |
2764 case T_SHORT: | |
2765 case T_CHAR: | |
2766 t = T_INT; | |
2767 break; | |
2768 } | |
2769 | |
2770 LIR_Opr dest = new_register(t); | |
2771 __ move(src, dest); | |
2772 | |
2773 // Assign new location to Local instruction for this local | |
2774 Local* local = x->state()->local_at(java_index)->as_Local(); | |
2775 assert(local != NULL, "Locals for incoming arguments must have been created"); | |
1681
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
2776 #ifndef __SOFTFP__ |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
2777 // The java calling convention passes double as long and float as int. |
0 | 2778 assert(as_ValueType(t)->tag() == local->type()->tag(), "check"); |
1681
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
2779 #endif // __SOFTFP__ |
0 | 2780 local->set_operand(dest); |
2781 _instruction_for_operand.at_put_grow(dest->vreg_number(), local, NULL); | |
2782 java_index += type2size[t]; | |
2783 } | |
2784 | |
780
c96bf21b756f
6788527: Server vm intermittently fails with assertion "live value must not be garbage" with fastdebug bits
kvn
parents:
579
diff
changeset
|
2785 if (compilation()->env()->dtrace_method_probes()) { |
0 | 2786 BasicTypeList signature; |
2002 | 2787 signature.append(LP64_ONLY(T_LONG) NOT_LP64(T_INT)); // thread |
12969
9acbfe04b5c3
8026495: JVM Crashes when started with -XX:+DTraceMethodProbes on Solaris x86_64
iveresov
parents:
12962
diff
changeset
|
2788 signature.append(T_METADATA); // Method* |
0 | 2789 LIR_OprList* args = new LIR_OprList(); |
2790 args->append(getThreadPointer()); | |
6739
8a02ca5e5576
7195816: NPG: Crash in c1_ValueType - ShouldNotReachHere
roland
parents:
6731
diff
changeset
|
2791 LIR_Opr meth = new_register(T_METADATA); |
8a02ca5e5576
7195816: NPG: Crash in c1_ValueType - ShouldNotReachHere
roland
parents:
6731
diff
changeset
|
2792 __ metadata2reg(method()->constant_encoding(), meth); |
0 | 2793 args->append(meth); |
2794 call_runtime(&signature, args, CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_entry), voidType, NULL); | |
2795 } | |
2796 | |
2797 if (method()->is_synchronized()) { | |
2798 LIR_Opr obj; | |
2799 if (method()->is_static()) { | |
2800 obj = new_register(T_OBJECT); | |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
819
diff
changeset
|
2801 __ oop2reg(method()->holder()->java_mirror()->constant_encoding(), obj); |
0 | 2802 } else { |
2803 Local* receiver = x->state()->local_at(0)->as_Local(); | |
2804 assert(receiver != NULL, "must already exist"); | |
2805 obj = receiver->operand(); | |
2806 } | |
2807 assert(obj->is_valid(), "must be valid"); | |
2808 | |
2809 if (method()->is_synchronized() && GenerateSynchronizationCode) { | |
2810 LIR_Opr lock = new_register(T_INT); | |
2811 __ load_stack_address_monitor(0, lock); | |
2812 | |
8860 | 2813 CodeEmitInfo* info = new CodeEmitInfo(scope()->start()->state()->copy(ValueStack::StateBefore, SynchronizationEntryBCI), NULL, x->check_flag(Instruction::DeoptimizeOnException)); |
0 | 2814 CodeStub* slow_path = new MonitorEnterStub(obj, lock, info); |
2815 | |
2816 // receiver is guaranteed non-NULL so don't need CodeEmitInfo | |
2817 __ lock_object(syncTempOpr(), obj, lock, new_register(T_OBJECT), slow_path, NULL); | |
2818 } | |
2819 } | |
2820 | |
2821 // increment invocation counters if needed | |
1783 | 2822 if (!method()->is_accessor()) { // Accessors do not have MDOs, so no counting. |
12962
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
2823 profile_parameters(x); |
8860 | 2824 CodeEmitInfo* info = new CodeEmitInfo(scope()->start()->state()->copy(ValueStack::StateBefore, SynchronizationEntryBCI), NULL, false); |
1783 | 2825 increment_invocation_counter(info); |
2826 } | |
0 | 2827 |
2828 // all blocks with a successor must end with an unconditional jump | |
2829 // to the successor even if they are consecutive | |
2830 __ jump(x->default_sux()); | |
2831 } | |
2832 | |
2833 | |
2834 void LIRGenerator::do_OsrEntry(OsrEntry* x) { | |
2835 // construct our frame and model the production of incoming pointer | |
2836 // to the OSR buffer. | |
2837 __ osr_entry(LIR_Assembler::osrBufferPointer()); | |
2838 LIR_Opr result = rlock_result(x); | |
2839 __ move(LIR_Assembler::osrBufferPointer(), result); | |
2840 } | |
2841 | |
2842 | |
2843 void LIRGenerator::invoke_load_arguments(Invoke* x, LIRItemList* args, const LIR_OprList* arg_list) { | |
6616
7a302948f5a4
7192167: JSR 292: C1 has old broken code which needs to be removed
twisti
parents:
6615
diff
changeset
|
2844 assert(args->length() == arg_list->length(), |
7a302948f5a4
7192167: JSR 292: C1 has old broken code which needs to be removed
twisti
parents:
6615
diff
changeset
|
2845 err_msg_res("args=%d, arg_list=%d", args->length(), arg_list->length())); |
7a302948f5a4
7192167: JSR 292: C1 has old broken code which needs to be removed
twisti
parents:
6615
diff
changeset
|
2846 for (int i = x->has_receiver() ? 1 : 0; i < args->length(); i++) { |
0 | 2847 LIRItem* param = args->at(i); |
2848 LIR_Opr loc = arg_list->at(i); | |
2849 if (loc->is_register()) { | |
2850 param->load_item_force(loc); | |
2851 } else { | |
2852 LIR_Address* addr = loc->as_address_ptr(); | |
2853 param->load_for_store(addr->type()); | |
2002 | 2854 if (addr->type() == T_OBJECT) { |
2855 __ move_wide(param->result(), addr); | |
2856 } else | |
2857 if (addr->type() == T_LONG || addr->type() == T_DOUBLE) { | |
2858 __ unaligned_move(param->result(), addr); | |
2859 } else { | |
2860 __ move(param->result(), addr); | |
2861 } | |
0 | 2862 } |
2863 } | |
2864 | |
2865 if (x->has_receiver()) { | |
2866 LIRItem* receiver = args->at(0); | |
2867 LIR_Opr loc = arg_list->at(0); | |
2868 if (loc->is_register()) { | |
2869 receiver->load_item_force(loc); | |
2870 } else { | |
2871 assert(loc->is_address(), "just checking"); | |
2872 receiver->load_for_store(T_OBJECT); | |
2002 | 2873 __ move_wide(receiver->result(), loc->as_address_ptr()); |
0 | 2874 } |
2875 } | |
2876 } | |
2877 | |
2878 | |
2879 // Visits all arguments, returns appropriate items without loading them | |
2880 LIRItemList* LIRGenerator::invoke_visit_arguments(Invoke* x) { | |
2881 LIRItemList* argument_items = new LIRItemList(); | |
2882 if (x->has_receiver()) { | |
2883 LIRItem* receiver = new LIRItem(x->receiver(), this); | |
2884 argument_items->append(receiver); | |
2885 } | |
2886 for (int i = 0; i < x->number_of_arguments(); i++) { | |
2887 LIRItem* param = new LIRItem(x->argument_at(i), this); | |
2888 argument_items->append(param); | |
2889 } | |
2890 return argument_items; | |
2891 } | |
2892 | |
2893 | |
2894 // The invoke with receiver has following phases: | |
2895 // a) traverse and load/lock receiver; | |
2896 // b) traverse all arguments -> item-array (invoke_visit_argument) | |
2897 // c) push receiver on stack | |
2898 // d) load each of the items and push on stack | |
2899 // e) unlock receiver | |
2900 // f) move receiver into receiver-register %o0 | |
2901 // g) lock result registers and emit call operation | |
2902 // | |
2903 // Before issuing a call, we must spill-save all values on stack | |
2904 // that are in caller-save register. "spill-save" moves thos registers | |
2905 // either in a free callee-save register or spills them if no free | |
2906 // callee save register is available. | |
2907 // | |
2908 // The problem is where to invoke spill-save. | |
2909 // - if invoked between e) and f), we may lock callee save | |
2910 // register in "spill-save" that destroys the receiver register | |
2911 // before f) is executed | |
2912 // - if we rearange the f) to be earlier, by loading %o0, it | |
2913 // may destroy a value on the stack that is currently in %o0 | |
2914 // and is waiting to be spilled | |
2915 // - if we keep the receiver locked while doing spill-save, | |
2916 // we cannot spill it as it is spill-locked | |
2917 // | |
2918 void LIRGenerator::do_Invoke(Invoke* x) { | |
2919 CallingConvention* cc = frame_map()->java_calling_convention(x->signature(), true); | |
2920 | |
2921 LIR_OprList* arg_list = cc->args(); | |
2922 LIRItemList* args = invoke_visit_arguments(x); | |
2923 LIR_Opr receiver = LIR_OprFact::illegalOpr; | |
2924 | |
2925 // setup result register | |
2926 LIR_Opr result_register = LIR_OprFact::illegalOpr; | |
2927 if (x->type() != voidType) { | |
2928 result_register = result_register_for(x->type()); | |
2929 } | |
2930 | |
2931 CodeEmitInfo* info = state_for(x, x->state()); | |
2932 | |
2933 invoke_load_arguments(x, args, arg_list); | |
2934 | |
2935 if (x->has_receiver()) { | |
2936 args->at(0)->load_item_force(LIR_Assembler::receiverOpr()); | |
2937 receiver = args->at(0)->result(); | |
2938 } | |
2939 | |
2940 // emit invoke code | |
2941 bool optimized = x->target_is_loaded() && x->target_is_final(); | |
2942 assert(receiver->is_illegal() || receiver->is_equal(LIR_Assembler::receiverOpr()), "must match"); | |
2943 | |
1564 | 2944 // JSR 292 |
2945 // Preserve the SP over MethodHandle call sites. | |
2946 ciMethod* target = x->target(); | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6145
diff
changeset
|
2947 bool is_method_handle_invoke = (// %%% FIXME: Are both of these relevant? |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6145
diff
changeset
|
2948 target->is_method_handle_intrinsic() || |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6145
diff
changeset
|
2949 target->is_compiled_lambda_form()); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6145
diff
changeset
|
2950 if (is_method_handle_invoke) { |
1564 | 2951 info->set_is_method_handle_invoke(true); |
2952 __ move(FrameMap::stack_pointer(), FrameMap::method_handle_invoke_SP_save_opr()); | |
2953 } | |
2954 | |
0 | 2955 switch (x->code()) { |
2956 case Bytecodes::_invokestatic: | |
1564 | 2957 __ call_static(target, result_register, |
0 | 2958 SharedRuntime::get_resolve_static_call_stub(), |
2959 arg_list, info); | |
2960 break; | |
2961 case Bytecodes::_invokespecial: | |
2962 case Bytecodes::_invokevirtual: | |
2963 case Bytecodes::_invokeinterface: | |
2964 // for final target we still produce an inline cache, in order | |
2965 // to be able to call mixed mode | |
2966 if (x->code() == Bytecodes::_invokespecial || optimized) { | |
1564 | 2967 __ call_opt_virtual(target, receiver, result_register, |
0 | 2968 SharedRuntime::get_resolve_opt_virtual_call_stub(), |
2969 arg_list, info); | |
2970 } else if (x->vtable_index() < 0) { | |
1564 | 2971 __ call_icvirtual(target, receiver, result_register, |
0 | 2972 SharedRuntime::get_resolve_virtual_call_stub(), |
2973 arg_list, info); | |
2974 } else { | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6616
diff
changeset
|
2975 int entry_offset = InstanceKlass::vtable_start_offset() + x->vtable_index() * vtableEntry::size(); |
0 | 2976 int vtable_offset = entry_offset * wordSize + vtableEntry::method_offset_in_bytes(); |
1564 | 2977 __ call_virtual(target, receiver, result_register, vtable_offset, arg_list, info); |
0 | 2978 } |
2979 break; | |
1295 | 2980 case Bytecodes::_invokedynamic: { |
1564 | 2981 __ call_dynamic(target, receiver, result_register, |
6616
7a302948f5a4
7192167: JSR 292: C1 has old broken code which needs to be removed
twisti
parents:
6615
diff
changeset
|
2982 SharedRuntime::get_resolve_static_call_stub(), |
1295 | 2983 arg_list, info); |
2984 break; | |
2985 } | |
0 | 2986 default: |
6145
e2fe93124108
7174928: JSR 292: unresolved invokedynamic call sites deopt and osr infinitely
twisti
parents:
6143
diff
changeset
|
2987 fatal(err_msg("unexpected bytecode: %s", Bytecodes::name(x->code()))); |
0 | 2988 break; |
2989 } | |
2990 | |
1564 | 2991 // JSR 292 |
2992 // Restore the SP after MethodHandle call sites. | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6145
diff
changeset
|
2993 if (is_method_handle_invoke) { |
1564 | 2994 __ move(FrameMap::method_handle_invoke_SP_save_opr(), FrameMap::stack_pointer()); |
2995 } | |
2996 | |
0 | 2997 if (x->type()->is_float() || x->type()->is_double()) { |
2998 // Force rounding of results from non-strictfp when in strictfp | |
2999 // scope (or when we don't know the strictness of the callee, to | |
3000 // be safe.) | |
3001 if (method()->is_strict()) { | |
3002 if (!x->target_is_loaded() || !x->target_is_strictfp()) { | |
3003 result_register = round_item(result_register); | |
3004 } | |
3005 } | |
3006 } | |
3007 | |
3008 if (result_register->is_valid()) { | |
3009 LIR_Opr result = rlock_result(x); | |
3010 __ move(result_register, result); | |
3011 } | |
3012 } | |
3013 | |
3014 | |
3015 void LIRGenerator::do_FPIntrinsics(Intrinsic* x) { | |
3016 assert(x->number_of_arguments() == 1, "wrong type"); | |
3017 LIRItem value (x->argument_at(0), this); | |
3018 LIR_Opr reg = rlock_result(x); | |
3019 value.load_item(); | |
3020 LIR_Opr tmp = force_to_spill(value.result(), as_BasicType(x->type())); | |
3021 __ move(tmp, reg); | |
3022 } | |
3023 | |
3024 | |
3025 | |
3026 // Code for : x->x() {x->cond()} x->y() ? x->tval() : x->fval() | |
3027 void LIRGenerator::do_IfOp(IfOp* x) { | |
3028 #ifdef ASSERT | |
3029 { | |
3030 ValueTag xtag = x->x()->type()->tag(); | |
3031 ValueTag ttag = x->tval()->type()->tag(); | |
3032 assert(xtag == intTag || xtag == objectTag, "cannot handle others"); | |
3033 assert(ttag == addressTag || ttag == intTag || ttag == objectTag || ttag == longTag, "cannot handle others"); | |
3034 assert(ttag == x->fval()->type()->tag(), "cannot handle others"); | |
3035 } | |
3036 #endif | |
3037 | |
3038 LIRItem left(x->x(), this); | |
3039 LIRItem right(x->y(), this); | |
3040 left.load_item(); | |
3041 if (can_inline_as_constant(right.value())) { | |
3042 right.dont_load_item(); | |
3043 } else { | |
3044 right.load_item(); | |
3045 } | |
3046 | |
3047 LIRItem t_val(x->tval(), this); | |
3048 LIRItem f_val(x->fval(), this); | |
3049 t_val.dont_load_item(); | |
3050 f_val.dont_load_item(); | |
3051 LIR_Opr reg = rlock_result(x); | |
3052 | |
3053 __ cmp(lir_cond(x->cond()), left.result(), right.result()); | |
2089
037c727f35fb
7009231: C1: Incorrect CAS code for longs on SPARC 32bit
iveresov
parents:
2007
diff
changeset
|
3054 __ cmove(lir_cond(x->cond()), t_val.result(), f_val.result(), reg, as_BasicType(x->x()->type())); |
0 | 3055 } |
3056 | |
6006
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3057 void LIRGenerator::do_RuntimeCall(address routine, int expected_arguments, Intrinsic* x) { |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3058 assert(x->number_of_arguments() == expected_arguments, "wrong type"); |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3059 LIR_Opr reg = result_register_for(x->type()); |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3060 __ call_runtime_leaf(routine, getThreadTemp(), |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3061 reg, new LIR_OprList()); |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3062 LIR_Opr result = rlock_result(x); |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3063 __ move(reg, result); |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3064 } |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3065 |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3066 #ifdef TRACE_HAVE_INTRINSICS |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3067 void LIRGenerator::do_ThreadIDIntrinsic(Intrinsic* x) { |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3068 LIR_Opr thread = getThreadPointer(); |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3069 LIR_Opr osthread = new_pointer_register(); |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3070 __ move(new LIR_Address(thread, in_bytes(JavaThread::osthread_offset()), osthread->type()), osthread); |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3071 size_t thread_id_size = OSThread::thread_id_size(); |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3072 if (thread_id_size == (size_t) BytesPerLong) { |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3073 LIR_Opr id = new_register(T_LONG); |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3074 __ move(new LIR_Address(osthread, in_bytes(OSThread::thread_id_offset()), T_LONG), id); |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3075 __ convert(Bytecodes::_l2i, id, rlock_result(x)); |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3076 } else if (thread_id_size == (size_t) BytesPerInt) { |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3077 __ move(new LIR_Address(osthread, in_bytes(OSThread::thread_id_offset()), T_INT), rlock_result(x)); |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3078 } else { |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3079 ShouldNotReachHere(); |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3080 } |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3081 } |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3082 |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3083 void LIRGenerator::do_ClassIDIntrinsic(Intrinsic* x) { |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3084 CodeEmitInfo* info = state_for(x); |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3085 CodeEmitInfo* info2 = new CodeEmitInfo(info); // Clone for the second null check |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6616
diff
changeset
|
3086 BasicType klass_pointer_type = NOT_LP64(T_INT) LP64_ONLY(T_LONG); |
6006
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3087 assert(info != NULL, "must have info"); |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3088 LIRItem arg(x->argument_at(1), this); |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3089 arg.load_item(); |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6616
diff
changeset
|
3090 LIR_Opr klass = new_pointer_register(); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6616
diff
changeset
|
3091 __ move(new LIR_Address(arg.result(), java_lang_Class::klass_offset_in_bytes(), klass_pointer_type), klass, info); |
6006
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3092 LIR_Opr id = new_register(T_LONG); |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3093 ByteSize offset = TRACE_ID_OFFSET; |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3094 LIR_Address* trace_id_addr = new LIR_Address(klass, in_bytes(offset), T_LONG); |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3095 __ move(trace_id_addr, id); |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3096 __ logical_or(id, LIR_OprFact::longConst(0x01l), id); |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3097 __ store(id, trace_id_addr); |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3098 __ logical_and(id, LIR_OprFact::longConst(~0x3l), id); |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3099 __ move(id, rlock_result(x)); |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3100 } |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3101 #endif |
0 | 3102 |
3103 void LIRGenerator::do_Intrinsic(Intrinsic* x) { | |
3104 switch (x->id()) { | |
3105 case vmIntrinsics::_intBitsToFloat : | |
3106 case vmIntrinsics::_doubleToRawLongBits : | |
3107 case vmIntrinsics::_longBitsToDouble : | |
3108 case vmIntrinsics::_floatToRawIntBits : { | |
3109 do_FPIntrinsics(x); | |
3110 break; | |
3111 } | |
3112 | |
6006
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3113 #ifdef TRACE_HAVE_INTRINSICS |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3114 case vmIntrinsics::_threadID: do_ThreadIDIntrinsic(x); break; |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3115 case vmIntrinsics::_classID: do_ClassIDIntrinsic(x); break; |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3116 case vmIntrinsics::_counterTime: |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3117 do_RuntimeCall(CAST_FROM_FN_PTR(address, TRACE_TIME_METHOD), 0, x); |
0 | 3118 break; |
6006
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3119 #endif |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3120 |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3121 case vmIntrinsics::_currentTimeMillis: |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3122 do_RuntimeCall(CAST_FROM_FN_PTR(address, os::javaTimeMillis), 0, x); |
0 | 3123 break; |
6006
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3124 |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3125 case vmIntrinsics::_nanoTime: |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3126 do_RuntimeCall(CAST_FROM_FN_PTR(address, os::javaTimeNanos), 0, x); |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4966
diff
changeset
|
3127 break; |
0 | 3128 |
3129 case vmIntrinsics::_Object_init: do_RegisterFinalizer(x); break; | |
6135 | 3130 case vmIntrinsics::_isInstance: do_isInstance(x); break; |
0 | 3131 case vmIntrinsics::_getClass: do_getClass(x); break; |
3132 case vmIntrinsics::_currentThread: do_currentThread(x); break; | |
3133 | |
3134 case vmIntrinsics::_dlog: // fall through | |
3135 case vmIntrinsics::_dlog10: // fall through | |
3136 case vmIntrinsics::_dabs: // fall through | |
3137 case vmIntrinsics::_dsqrt: // fall through | |
3138 case vmIntrinsics::_dtan: // fall through | |
3139 case vmIntrinsics::_dsin : // fall through | |
6084
6759698e3140
7133857: exp() and pow() should use the x87 ISA on x86
roland
parents:
6006
diff
changeset
|
3140 case vmIntrinsics::_dcos : // fall through |
6759698e3140
7133857: exp() and pow() should use the x87 ISA on x86
roland
parents:
6006
diff
changeset
|
3141 case vmIntrinsics::_dexp : // fall through |
6759698e3140
7133857: exp() and pow() should use the x87 ISA on x86
roland
parents:
6006
diff
changeset
|
3142 case vmIntrinsics::_dpow : do_MathIntrinsic(x); break; |
0 | 3143 case vmIntrinsics::_arraycopy: do_ArrayCopy(x); break; |
3144 | |
3145 // java.nio.Buffer.checkIndex | |
3146 case vmIntrinsics::_checkIndex: do_NIOCheckIndex(x); break; | |
3147 | |
3148 case vmIntrinsics::_compareAndSwapObject: | |
3149 do_CompareAndSwap(x, objectType); | |
3150 break; | |
3151 case vmIntrinsics::_compareAndSwapInt: | |
3152 do_CompareAndSwap(x, intType); | |
3153 break; | |
3154 case vmIntrinsics::_compareAndSwapLong: | |
3155 do_CompareAndSwap(x, longType); | |
3156 break; | |
3157 | |
7425 | 3158 case vmIntrinsics::_loadFence : |
3159 if (os::is_MP()) __ membar_acquire(); | |
3160 break; | |
3161 case vmIntrinsics::_storeFence: | |
3162 if (os::is_MP()) __ membar_release(); | |
3163 break; | |
3164 case vmIntrinsics::_fullFence : | |
3165 if (os::is_MP()) __ membar(); | |
3166 break; | |
3167 | |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
3168 case vmIntrinsics::_Reference_get: |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
3169 do_Reference_get(x); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
3170 break; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
3171 |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10397
diff
changeset
|
3172 case vmIntrinsics::_updateCRC32: |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10397
diff
changeset
|
3173 case vmIntrinsics::_updateBytesCRC32: |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10397
diff
changeset
|
3174 case vmIntrinsics::_updateByteBufferCRC32: |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10397
diff
changeset
|
3175 do_update_CRC32(x); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10397
diff
changeset
|
3176 break; |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10397
diff
changeset
|
3177 |
0 | 3178 default: ShouldNotReachHere(); break; |
3179 } | |
3180 } | |
3181 | |
12875
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
3182 void LIRGenerator::profile_arguments(ProfileCall* x) { |
12962
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3183 if (compilation()->profile_arguments()) { |
12875
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
3184 int bci = x->bci_of_invoke(); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
3185 ciMethodData* md = x->method()->method_data_or_null(); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
3186 ciProfileData* data = md->bci_to_data(bci); |
12962
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3187 if ((data->is_CallTypeData() && data->as_CallTypeData()->has_arguments()) || |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3188 (data->is_VirtualCallTypeData() && data->as_VirtualCallTypeData()->has_arguments())) { |
12875
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
3189 ByteSize extra = data->is_CallTypeData() ? CallTypeData::args_data_offset() : VirtualCallTypeData::args_data_offset(); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
3190 int base_offset = md->byte_offset_of_slot(data, extra); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
3191 LIR_Opr mdp = LIR_OprFact::illegalOpr; |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
3192 ciTypeStackSlotEntries* args = data->is_CallTypeData() ? ((ciCallTypeData*)data)->args() : ((ciVirtualCallTypeData*)data)->args(); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
3193 |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
3194 Bytecodes::Code bc = x->method()->java_code_at_bci(bci); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
3195 int start = 0; |
12882
ce0cc25bc5e2
8026054: New type profiling points: type of return values at calls
roland
parents:
12875
diff
changeset
|
3196 int stop = data->is_CallTypeData() ? ((ciCallTypeData*)data)->number_of_arguments() : ((ciVirtualCallTypeData*)data)->number_of_arguments(); |
13078
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
3197 if (x->inlined() && x->callee()->is_static() && Bytecodes::has_receiver(bc)) { |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
3198 // first argument is not profiled at call (method handle invoke) |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
3199 assert(x->method()->raw_code_at_bci(bci) == Bytecodes::_invokehandle, "invokehandle expected"); |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
3200 start = 1; |
12875
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
3201 } |
13078
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
3202 ciSignature* callee_signature = x->callee()->signature(); |
12875
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
3203 // method handle call to virtual method |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
3204 bool has_receiver = x->inlined() && !x->callee()->is_static() && !Bytecodes::has_receiver(bc); |
13078
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
3205 ciSignatureStream callee_signature_stream(callee_signature, has_receiver ? x->callee()->holder() : NULL); |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
3206 |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
3207 bool ignored_will_link; |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
3208 ciSignature* signature_at_call = NULL; |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
3209 x->method()->get_method_at_bci(bci, ignored_will_link, &signature_at_call); |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
3210 ciSignatureStream signature_at_call_stream(signature_at_call); |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
3211 |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
3212 // if called through method handle invoke, some arguments may have been popped |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
3213 for (int i = 0; i < stop && i+start < x->nb_profiled_args(); i++) { |
12882
ce0cc25bc5e2
8026054: New type profiling points: type of return values at calls
roland
parents:
12875
diff
changeset
|
3214 int off = in_bytes(TypeEntriesAtCall::argument_type_offset(i)) - in_bytes(TypeEntriesAtCall::args_data_offset()); |
13078
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
3215 ciKlass* exact = profile_type(md, base_offset, off, |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
3216 args->type(i), x->profiled_arg_at(i+start), mdp, |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
3217 !x->arg_needs_null_check(i+start), |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
3218 signature_at_call_stream.next_klass(), callee_signature_stream.next_klass()); |
12875
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
3219 if (exact != NULL) { |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
3220 md->set_argument_type(bci, i, exact); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
3221 } |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
3222 } |
12962
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3223 } else { |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3224 #ifdef ASSERT |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3225 Bytecodes::Code code = x->method()->raw_code_at_bci(x->bci_of_invoke()); |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3226 int n = x->nb_profiled_args(); |
17900
ce9fd31ffd14
8039975: SIGSEGV in MethodData::next_data(ProfileData*)
roland
parents:
17628
diff
changeset
|
3227 assert(MethodData::profile_parameters() && (MethodData::profile_arguments_jsr292_only() || |
ce9fd31ffd14
8039975: SIGSEGV in MethodData::next_data(ProfileData*)
roland
parents:
17628
diff
changeset
|
3228 (x->inlined() && ((code == Bytecodes::_invokedynamic && n <= 1) || (code == Bytecodes::_invokehandle && n <= 2)))), |
12962
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3229 "only at JSR292 bytecodes"); |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3230 #endif |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3231 } |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3232 } |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3233 } |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3234 |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3235 // profile parameters on entry to an inlined method |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3236 void LIRGenerator::profile_parameters_at_call(ProfileCall* x) { |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3237 if (compilation()->profile_parameters() && x->inlined()) { |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3238 ciMethodData* md = x->callee()->method_data_or_null(); |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3239 if (md != NULL) { |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3240 ciParametersTypeData* parameters_type_data = md->parameters_type_data(); |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3241 if (parameters_type_data != NULL) { |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3242 ciTypeStackSlotEntries* parameters = parameters_type_data->parameters(); |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3243 LIR_Opr mdp = LIR_OprFact::illegalOpr; |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3244 bool has_receiver = !x->callee()->is_static(); |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3245 ciSignature* sig = x->callee()->signature(); |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3246 ciSignatureStream sig_stream(sig, has_receiver ? x->callee()->holder() : NULL); |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3247 int i = 0; // to iterate on the Instructions |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3248 Value arg = x->recv(); |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3249 bool not_null = false; |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3250 int bci = x->bci_of_invoke(); |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3251 Bytecodes::Code bc = x->method()->java_code_at_bci(bci); |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3252 // The first parameter is the receiver so that's what we start |
13078
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
3253 // with if it exists. One exception is method handle call to |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
3254 // virtual method: the receiver is in the args list |
12962
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3255 if (arg == NULL || !Bytecodes::has_receiver(bc)) { |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3256 i = 1; |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3257 arg = x->profiled_arg_at(0); |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3258 not_null = !x->arg_needs_null_check(0); |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3259 } |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3260 int k = 0; // to iterate on the profile data |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3261 for (;;) { |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3262 intptr_t profiled_k = parameters->type(k); |
13078
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
3263 ciKlass* exact = profile_type(md, md->byte_offset_of_slot(parameters_type_data, ParametersTypeData::type_offset(0)), |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
3264 in_bytes(ParametersTypeData::type_offset(k)) - in_bytes(ParametersTypeData::type_offset(0)), |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
3265 profiled_k, arg, mdp, not_null, sig_stream.next_klass(), NULL); |
12962
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3266 // If the profile is known statically set it once for all and do not emit any code |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3267 if (exact != NULL) { |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3268 md->set_parameter_type(k, exact); |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3269 } |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3270 k++; |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3271 if (k >= parameters_type_data->number_of_parameters()) { |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3272 #ifdef ASSERT |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3273 int extra = 0; |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3274 if (MethodData::profile_arguments() && TypeProfileParmsLimit != -1 && |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3275 x->nb_profiled_args() >= TypeProfileParmsLimit && |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3276 x->recv() != NULL && Bytecodes::has_receiver(bc)) { |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3277 extra += 1; |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3278 } |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3279 assert(i == x->nb_profiled_args() - extra || (TypeProfileParmsLimit != -1 && TypeProfileArgsLimit > TypeProfileParmsLimit), "unused parameters?"); |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3280 #endif |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3281 break; |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3282 } |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3283 arg = x->profiled_arg_at(i); |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3284 not_null = !x->arg_needs_null_check(i); |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3285 i++; |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3286 } |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3287 } |
12875
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
3288 } |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
3289 } |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
3290 } |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
3291 |
0 | 3292 void LIRGenerator::do_ProfileCall(ProfileCall* x) { |
3293 // Need recv in a temporary register so it interferes with the other temporaries | |
3294 LIR_Opr recv = LIR_OprFact::illegalOpr; | |
3295 LIR_Opr mdo = new_register(T_OBJECT); | |
1783 | 3296 // tmp is used to hold the counters on SPARC |
3297 LIR_Opr tmp = new_pointer_register(); | |
12875
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
3298 |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
3299 if (x->nb_profiled_args() > 0) { |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
3300 profile_arguments(x); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
3301 } |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12868
diff
changeset
|
3302 |
12962
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3303 // profile parameters on inlined method entry including receiver |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3304 if (x->recv() != NULL || x->nb_profiled_args() > 0) { |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3305 profile_parameters_at_call(x); |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3306 } |
5ccbab1c69f3
8026251: New type profiling points: parameters to methods
roland
parents:
12955
diff
changeset
|
3307 |
0 | 3308 if (x->recv() != NULL) { |
3309 LIRItem value(x->recv(), this); | |
3310 value.load_item(); | |
3311 recv = new_register(T_OBJECT); | |
3312 __ move(value.result(), recv); | |
3313 } | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6145
diff
changeset
|
3314 __ profile_call(x->method(), x->bci_of_invoke(), x->callee(), mdo, recv, tmp, x->known_holder()); |
0 | 3315 } |
3316 | |
12882
ce0cc25bc5e2
8026054: New type profiling points: type of return values at calls
roland
parents:
12875
diff
changeset
|
3317 void LIRGenerator::do_ProfileReturnType(ProfileReturnType* x) { |
ce0cc25bc5e2
8026054: New type profiling points: type of return values at calls
roland
parents:
12875
diff
changeset
|
3318 int bci = x->bci_of_invoke(); |
ce0cc25bc5e2
8026054: New type profiling points: type of return values at calls
roland
parents:
12875
diff
changeset
|
3319 ciMethodData* md = x->method()->method_data_or_null(); |
ce0cc25bc5e2
8026054: New type profiling points: type of return values at calls
roland
parents:
12875
diff
changeset
|
3320 ciProfileData* data = md->bci_to_data(bci); |
ce0cc25bc5e2
8026054: New type profiling points: type of return values at calls
roland
parents:
12875
diff
changeset
|
3321 assert(data->is_CallTypeData() || data->is_VirtualCallTypeData(), "wrong profile data type"); |
ce0cc25bc5e2
8026054: New type profiling points: type of return values at calls
roland
parents:
12875
diff
changeset
|
3322 ciReturnTypeEntry* ret = data->is_CallTypeData() ? ((ciCallTypeData*)data)->ret() : ((ciVirtualCallTypeData*)data)->ret(); |
ce0cc25bc5e2
8026054: New type profiling points: type of return values at calls
roland
parents:
12875
diff
changeset
|
3323 LIR_Opr mdp = LIR_OprFact::illegalOpr; |
13078
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
3324 |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
3325 bool ignored_will_link; |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
3326 ciSignature* signature_at_call = NULL; |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
3327 x->method()->get_method_at_bci(bci, ignored_will_link, &signature_at_call); |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
3328 |
17628 | 3329 // The offset within the MDO of the entry to update may be too large |
3330 // to be used in load/store instructions on some platforms. So have | |
3331 // profile_type() compute the address of the profile in a register. | |
3332 ciKlass* exact = profile_type(md, md->byte_offset_of_slot(data, ret->type_offset()), 0, | |
13078
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
3333 ret->type(), x->ret(), mdp, |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
3334 !x->needs_null_check(), |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
3335 signature_at_call->return_type()->as_klass(), |
e6ba215af802
8027631: "unexpected profiling mismatch" error with new type profiling
roland
parents:
12969
diff
changeset
|
3336 x->callee()->signature()->return_type()->as_klass()); |
12882
ce0cc25bc5e2
8026054: New type profiling points: type of return values at calls
roland
parents:
12875
diff
changeset
|
3337 if (exact != NULL) { |
ce0cc25bc5e2
8026054: New type profiling points: type of return values at calls
roland
parents:
12875
diff
changeset
|
3338 md->set_return_type(bci, exact); |
ce0cc25bc5e2
8026054: New type profiling points: type of return values at calls
roland
parents:
12875
diff
changeset
|
3339 } |
ce0cc25bc5e2
8026054: New type profiling points: type of return values at calls
roland
parents:
12875
diff
changeset
|
3340 } |
ce0cc25bc5e2
8026054: New type profiling points: type of return values at calls
roland
parents:
12875
diff
changeset
|
3341 |
1783 | 3342 void LIRGenerator::do_ProfileInvoke(ProfileInvoke* x) { |
3343 // We can safely ignore accessors here, since c2 will inline them anyway, | |
3344 // accessors are also always mature. | |
3345 if (!x->inlinee()->is_accessor()) { | |
3346 CodeEmitInfo* info = state_for(x, x->state(), true); | |
3964
dc45ae774613
7096639: Tiered: Incorrect counter overflow handling for inlined methods
iveresov
parents:
3756
diff
changeset
|
3347 // Notify the runtime very infrequently only to take care of counter overflows |
dc45ae774613
7096639: Tiered: Incorrect counter overflow handling for inlined methods
iveresov
parents:
3756
diff
changeset
|
3348 increment_event_counter_impl(info, x->inlinee(), (1 << Tier23InlineeNotifyFreqLog) - 1, InvocationEntryBci, false, true); |
1783 | 3349 } |
3350 } | |
3351 | |
3352 void LIRGenerator::increment_event_counter(CodeEmitInfo* info, int bci, bool backedge) { | |
3353 int freq_log; | |
3354 int level = compilation()->env()->comp_level(); | |
3355 if (level == CompLevel_limited_profile) { | |
3356 freq_log = (backedge ? Tier2BackedgeNotifyFreqLog : Tier2InvokeNotifyFreqLog); | |
3357 } else if (level == CompLevel_full_profile) { | |
3358 freq_log = (backedge ? Tier3BackedgeNotifyFreqLog : Tier3InvokeNotifyFreqLog); | |
3359 } else { | |
3360 ShouldNotReachHere(); | |
3361 } | |
3362 // Increment the appropriate invocation/backedge counter and notify the runtime. | |
3363 increment_event_counter_impl(info, info->scope()->method(), (1 << freq_log) - 1, bci, backedge, true); | |
0 | 3364 } |
3365 | |
1783 | 3366 void LIRGenerator::increment_event_counter_impl(CodeEmitInfo* info, |
3367 ciMethod *method, int frequency, | |
3368 int bci, bool backedge, bool notify) { | |
3369 assert(frequency == 0 || is_power_of_2(frequency + 1), "Frequency must be x^2 - 1 or 0"); | |
3370 int level = _compilation->env()->comp_level(); | |
3371 assert(level > CompLevel_simple, "Shouldn't be here"); | |
3372 | |
3373 int offset = -1; | |
10105
aeaca88565e6
8010862: The Method counter fields used for profiling can be allocated lazily.
jiangli
parents:
8869
diff
changeset
|
3374 LIR_Opr counter_holder; |
1783 | 3375 if (level == CompLevel_limited_profile) { |
12868
c775af091fe9
8025566: EXCEPTION_ACCESS_VIOLATION in compiled by C1 String.valueOf method
twisti
parents:
12000
diff
changeset
|
3376 MethodCounters* counters_adr = method->ensure_method_counters(); |
c775af091fe9
8025566: EXCEPTION_ACCESS_VIOLATION in compiled by C1 String.valueOf method
twisti
parents:
12000
diff
changeset
|
3377 if (counters_adr == NULL) { |
c775af091fe9
8025566: EXCEPTION_ACCESS_VIOLATION in compiled by C1 String.valueOf method
twisti
parents:
12000
diff
changeset
|
3378 bailout("method counters allocation failed"); |
c775af091fe9
8025566: EXCEPTION_ACCESS_VIOLATION in compiled by C1 String.valueOf method
twisti
parents:
12000
diff
changeset
|
3379 return; |
c775af091fe9
8025566: EXCEPTION_ACCESS_VIOLATION in compiled by C1 String.valueOf method
twisti
parents:
12000
diff
changeset
|
3380 } |
10105
aeaca88565e6
8010862: The Method counter fields used for profiling can be allocated lazily.
jiangli
parents:
8869
diff
changeset
|
3381 counter_holder = new_pointer_register(); |
aeaca88565e6
8010862: The Method counter fields used for profiling can be allocated lazily.
jiangli
parents:
8869
diff
changeset
|
3382 __ move(LIR_OprFact::intptrConst(counters_adr), counter_holder); |
aeaca88565e6
8010862: The Method counter fields used for profiling can be allocated lazily.
jiangli
parents:
8869
diff
changeset
|
3383 offset = in_bytes(backedge ? MethodCounters::backedge_counter_offset() : |
aeaca88565e6
8010862: The Method counter fields used for profiling can be allocated lazily.
jiangli
parents:
8869
diff
changeset
|
3384 MethodCounters::invocation_counter_offset()); |
1783 | 3385 } else if (level == CompLevel_full_profile) { |
10105
aeaca88565e6
8010862: The Method counter fields used for profiling can be allocated lazily.
jiangli
parents:
8869
diff
changeset
|
3386 counter_holder = new_register(T_METADATA); |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6616
diff
changeset
|
3387 offset = in_bytes(backedge ? MethodData::backedge_counter_offset() : |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6616
diff
changeset
|
3388 MethodData::invocation_counter_offset()); |
2007
5ddfcf4b079e
7003554: (tiered) assert(is_null_object() || handle() != NULL) failed: cannot embed null pointer
iveresov
parents:
2002
diff
changeset
|
3389 ciMethodData* md = method->method_data_or_null(); |
5ddfcf4b079e
7003554: (tiered) assert(is_null_object() || handle() != NULL) failed: cannot embed null pointer
iveresov
parents:
2002
diff
changeset
|
3390 assert(md != NULL, "Sanity"); |
6739
8a02ca5e5576
7195816: NPG: Crash in c1_ValueType - ShouldNotReachHere
roland
parents:
6731
diff
changeset
|
3391 __ metadata2reg(md->constant_encoding(), counter_holder); |
1783 | 3392 } else { |
3393 ShouldNotReachHere(); | |
3394 } | |
3395 LIR_Address* counter = new LIR_Address(counter_holder, offset, T_INT); | |
3396 LIR_Opr result = new_register(T_INT); | |
3397 __ load(counter, result); | |
3398 __ add(result, LIR_OprFact::intConst(InvocationCounter::count_increment), result); | |
3399 __ store(result, counter); | |
3400 if (notify) { | |
3401 LIR_Opr mask = load_immediate(frequency << InvocationCounter::count_shift, T_INT); | |
10105
aeaca88565e6
8010862: The Method counter fields used for profiling can be allocated lazily.
jiangli
parents:
8869
diff
changeset
|
3402 LIR_Opr meth = new_register(T_METADATA); |
aeaca88565e6
8010862: The Method counter fields used for profiling can be allocated lazily.
jiangli
parents:
8869
diff
changeset
|
3403 __ metadata2reg(method->constant_encoding(), meth); |
1783 | 3404 __ logical_and(result, mask, result); |
3405 __ cmp(lir_cond_equal, result, LIR_OprFact::intConst(0)); | |
3406 // The bci for info can point to cmp for if's we want the if bci | |
3407 CodeStub* overflow = new CounterOverflowStub(info, bci, meth); | |
3408 __ branch(lir_cond_equal, T_INT, overflow); | |
3409 __ branch_destination(overflow->continuation()); | |
3410 } | |
3411 } | |
0 | 3412 |
2166
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2089
diff
changeset
|
3413 void LIRGenerator::do_RuntimeCall(RuntimeCall* x) { |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2089
diff
changeset
|
3414 LIR_OprList* args = new LIR_OprList(x->number_of_arguments()); |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2089
diff
changeset
|
3415 BasicTypeList* signature = new BasicTypeList(x->number_of_arguments()); |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2089
diff
changeset
|
3416 |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2089
diff
changeset
|
3417 if (x->pass_thread()) { |
12969
9acbfe04b5c3
8026495: JVM Crashes when started with -XX:+DTraceMethodProbes on Solaris x86_64
iveresov
parents:
12962
diff
changeset
|
3418 signature->append(LP64_ONLY(T_LONG) NOT_LP64(T_INT)); // thread |
2166
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2089
diff
changeset
|
3419 args->append(getThreadPointer()); |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2089
diff
changeset
|
3420 } |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2089
diff
changeset
|
3421 |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2089
diff
changeset
|
3422 for (int i = 0; i < x->number_of_arguments(); i++) { |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2089
diff
changeset
|
3423 Value a = x->argument_at(i); |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2089
diff
changeset
|
3424 LIRItem* item = new LIRItem(a, this); |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2089
diff
changeset
|
3425 item->load_item(); |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2089
diff
changeset
|
3426 args->append(item->result()); |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2089
diff
changeset
|
3427 signature->append(as_BasicType(a->type())); |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2089
diff
changeset
|
3428 } |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2089
diff
changeset
|
3429 |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2089
diff
changeset
|
3430 LIR_Opr result = call_runtime(signature, args, x->entry(), x->type(), NULL); |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2089
diff
changeset
|
3431 if (x->type() == voidType) { |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2089
diff
changeset
|
3432 set_no_result(x); |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2089
diff
changeset
|
3433 } else { |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2089
diff
changeset
|
3434 __ move(result, rlock_result(x)); |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2089
diff
changeset
|
3435 } |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2089
diff
changeset
|
3436 } |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2089
diff
changeset
|
3437 |
9156
acadb114c818
8011648: C1: optimized build is broken after 7153771
roland
parents:
9062
diff
changeset
|
3438 #ifdef ASSERT |
8860 | 3439 void LIRGenerator::do_Assert(Assert *x) { |
3440 ValueTag tag = x->x()->type()->tag(); | |
3441 If::Condition cond = x->cond(); | |
3442 | |
3443 LIRItem xitem(x->x(), this); | |
3444 LIRItem yitem(x->y(), this); | |
3445 LIRItem* xin = &xitem; | |
3446 LIRItem* yin = &yitem; | |
3447 | |
3448 assert(tag == intTag, "Only integer assertions are valid!"); | |
3449 | |
3450 xin->load_item(); | |
3451 yin->dont_load_item(); | |
3452 | |
3453 set_no_result(x); | |
3454 | |
3455 LIR_Opr left = xin->result(); | |
3456 LIR_Opr right = yin->result(); | |
3457 | |
3458 __ lir_assert(lir_cond(x->cond()), left, right, x->message(), true); | |
9156
acadb114c818
8011648: C1: optimized build is broken after 7153771
roland
parents:
9062
diff
changeset
|
3459 } |
8860 | 3460 #endif |
3461 | |
3462 void LIRGenerator::do_RangeCheckPredicate(RangeCheckPredicate *x) { | |
3463 | |
3464 | |
3465 Instruction *a = x->x(); | |
3466 Instruction *b = x->y(); | |
3467 if (!a || StressRangeCheckElimination) { | |
3468 assert(!b || StressRangeCheckElimination, "B must also be null"); | |
3469 | |
3470 CodeEmitInfo *info = state_for(x, x->state()); | |
3471 CodeStub* stub = new PredicateFailedStub(info); | |
3472 | |
3473 __ jump(stub); | |
3474 } else if (a->type()->as_IntConstant() && b->type()->as_IntConstant()) { | |
3475 int a_int = a->type()->as_IntConstant()->value(); | |
3476 int b_int = b->type()->as_IntConstant()->value(); | |
3477 | |
3478 bool ok = false; | |
3479 | |
3480 switch(x->cond()) { | |
3481 case Instruction::eql: ok = (a_int == b_int); break; | |
3482 case Instruction::neq: ok = (a_int != b_int); break; | |
3483 case Instruction::lss: ok = (a_int < b_int); break; | |
3484 case Instruction::leq: ok = (a_int <= b_int); break; | |
3485 case Instruction::gtr: ok = (a_int > b_int); break; | |
3486 case Instruction::geq: ok = (a_int >= b_int); break; | |
3487 case Instruction::aeq: ok = ((unsigned int)a_int >= (unsigned int)b_int); break; | |
3488 case Instruction::beq: ok = ((unsigned int)a_int <= (unsigned int)b_int); break; | |
3489 default: ShouldNotReachHere(); | |
3490 } | |
3491 | |
3492 if (ok) { | |
3493 | |
3494 CodeEmitInfo *info = state_for(x, x->state()); | |
3495 CodeStub* stub = new PredicateFailedStub(info); | |
3496 | |
3497 __ jump(stub); | |
3498 } | |
3499 } else { | |
3500 | |
3501 ValueTag tag = x->x()->type()->tag(); | |
3502 If::Condition cond = x->cond(); | |
3503 LIRItem xitem(x->x(), this); | |
3504 LIRItem yitem(x->y(), this); | |
3505 LIRItem* xin = &xitem; | |
3506 LIRItem* yin = &yitem; | |
3507 | |
3508 assert(tag == intTag, "Only integer deoptimizations are valid!"); | |
3509 | |
3510 xin->load_item(); | |
3511 yin->dont_load_item(); | |
3512 set_no_result(x); | |
3513 | |
3514 LIR_Opr left = xin->result(); | |
3515 LIR_Opr right = yin->result(); | |
3516 | |
3517 CodeEmitInfo *info = state_for(x, x->state()); | |
3518 CodeStub* stub = new PredicateFailedStub(info); | |
3519 | |
3520 __ cmp(lir_cond(cond), left, right); | |
3521 __ branch(lir_cond(cond), right->type(), stub); | |
3522 } | |
3523 } | |
3524 | |
3525 | |
0 | 3526 LIR_Opr LIRGenerator::call_runtime(Value arg1, address entry, ValueType* result_type, CodeEmitInfo* info) { |
3527 LIRItemList args(1); | |
3528 LIRItem value(arg1, this); | |
3529 args.append(&value); | |
3530 BasicTypeList signature; | |
3531 signature.append(as_BasicType(arg1->type())); | |
3532 | |
3533 return call_runtime(&signature, &args, entry, result_type, info); | |
3534 } | |
3535 | |
3536 | |
3537 LIR_Opr LIRGenerator::call_runtime(Value arg1, Value arg2, address entry, ValueType* result_type, CodeEmitInfo* info) { | |
3538 LIRItemList args(2); | |
3539 LIRItem value1(arg1, this); | |
3540 LIRItem value2(arg2, this); | |
3541 args.append(&value1); | |
3542 args.append(&value2); | |
3543 BasicTypeList signature; | |
3544 signature.append(as_BasicType(arg1->type())); | |
3545 signature.append(as_BasicType(arg2->type())); | |
3546 | |
3547 return call_runtime(&signature, &args, entry, result_type, info); | |
3548 } | |
3549 | |
3550 | |
3551 LIR_Opr LIRGenerator::call_runtime(BasicTypeArray* signature, LIR_OprList* args, | |
3552 address entry, ValueType* result_type, CodeEmitInfo* info) { | |
3553 // get a result register | |
3554 LIR_Opr phys_reg = LIR_OprFact::illegalOpr; | |
3555 LIR_Opr result = LIR_OprFact::illegalOpr; | |
3556 if (result_type->tag() != voidTag) { | |
3557 result = new_register(result_type); | |
3558 phys_reg = result_register_for(result_type); | |
3559 } | |
3560 | |
3561 // move the arguments into the correct location | |
3562 CallingConvention* cc = frame_map()->c_calling_convention(signature); | |
3563 assert(cc->length() == args->length(), "argument mismatch"); | |
3564 for (int i = 0; i < args->length(); i++) { | |
3565 LIR_Opr arg = args->at(i); | |
3566 LIR_Opr loc = cc->at(i); | |
3567 if (loc->is_register()) { | |
3568 __ move(arg, loc); | |
3569 } else { | |
3570 LIR_Address* addr = loc->as_address_ptr(); | |
3571 // if (!can_store_as_constant(arg)) { | |
3572 // LIR_Opr tmp = new_register(arg->type()); | |
3573 // __ move(arg, tmp); | |
3574 // arg = tmp; | |
3575 // } | |
3576 if (addr->type() == T_LONG || addr->type() == T_DOUBLE) { | |
3577 __ unaligned_move(arg, addr); | |
3578 } else { | |
3579 __ move(arg, addr); | |
3580 } | |
3581 } | |
3582 } | |
3583 | |
3584 if (info) { | |
3585 __ call_runtime(entry, getThreadTemp(), phys_reg, cc->args(), info); | |
3586 } else { | |
3587 __ call_runtime_leaf(entry, getThreadTemp(), phys_reg, cc->args()); | |
3588 } | |
3589 if (result->is_valid()) { | |
3590 __ move(phys_reg, result); | |
3591 } | |
3592 return result; | |
3593 } | |
3594 | |
3595 | |
3596 LIR_Opr LIRGenerator::call_runtime(BasicTypeArray* signature, LIRItemList* args, | |
3597 address entry, ValueType* result_type, CodeEmitInfo* info) { | |
3598 // get a result register | |
3599 LIR_Opr phys_reg = LIR_OprFact::illegalOpr; | |
3600 LIR_Opr result = LIR_OprFact::illegalOpr; | |
3601 if (result_type->tag() != voidTag) { | |
3602 result = new_register(result_type); | |
3603 phys_reg = result_register_for(result_type); | |
3604 } | |
3605 | |
3606 // move the arguments into the correct location | |
3607 CallingConvention* cc = frame_map()->c_calling_convention(signature); | |
3608 | |
3609 assert(cc->length() == args->length(), "argument mismatch"); | |
3610 for (int i = 0; i < args->length(); i++) { | |
3611 LIRItem* arg = args->at(i); | |
3612 LIR_Opr loc = cc->at(i); | |
3613 if (loc->is_register()) { | |
3614 arg->load_item_force(loc); | |
3615 } else { | |
3616 LIR_Address* addr = loc->as_address_ptr(); | |
3617 arg->load_for_store(addr->type()); | |
3618 if (addr->type() == T_LONG || addr->type() == T_DOUBLE) { | |
3619 __ unaligned_move(arg->result(), addr); | |
3620 } else { | |
3621 __ move(arg->result(), addr); | |
3622 } | |
3623 } | |
3624 } | |
3625 | |
3626 if (info) { | |
3627 __ call_runtime(entry, getThreadTemp(), phys_reg, cc->args(), info); | |
3628 } else { | |
3629 __ call_runtime_leaf(entry, getThreadTemp(), phys_reg, cc->args()); | |
3630 } | |
3631 if (result->is_valid()) { | |
3632 __ move(phys_reg, result); | |
3633 } | |
3634 return result; | |
3635 } | |
4966
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4816
diff
changeset
|
3636 |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4816
diff
changeset
|
3637 void LIRGenerator::do_MemBar(MemBar* x) { |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4816
diff
changeset
|
3638 if (os::is_MP()) { |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4816
diff
changeset
|
3639 LIR_Code code = x->code(); |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4816
diff
changeset
|
3640 switch(code) { |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4816
diff
changeset
|
3641 case lir_membar_acquire : __ membar_acquire(); break; |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4816
diff
changeset
|
3642 case lir_membar_release : __ membar_release(); break; |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4816
diff
changeset
|
3643 case lir_membar : __ membar(); break; |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4816
diff
changeset
|
3644 case lir_membar_loadload : __ membar_loadload(); break; |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4816
diff
changeset
|
3645 case lir_membar_storestore: __ membar_storestore(); break; |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4816
diff
changeset
|
3646 case lir_membar_loadstore : __ membar_loadstore(); break; |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4816
diff
changeset
|
3647 case lir_membar_storeload : __ membar_storeload(); break; |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4816
diff
changeset
|
3648 default : ShouldNotReachHere(); break; |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4816
diff
changeset
|
3649 } |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4816
diff
changeset
|
3650 } |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4816
diff
changeset
|
3651 } |