Mercurial > hg > graal-jvmci-8
annotate src/share/vm/c1/c1_LIRGenerator.cpp @ 3249:e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
Summary: A referent object that is only weakly reachable at the start of concurrent marking but is re-attached to the strongly reachable object graph during marking may not be marked as live. This can cause the reference object to be processed prematurely and leave dangling pointers to the referent object. Implement a read barrier for the java.lang.ref.Reference::referent field by intrinsifying the Reference.get() method, and intercepting accesses though JNI, reflection, and Unsafe, so that when a non-null referent object is read it is also logged in an SATB buffer.
Reviewed-by: kvn, iveresov, never, tonyp, dholmes
author | johnc |
---|---|
date | Thu, 07 Apr 2011 09:53:20 -0700 |
parents | 8033953d67ff |
children | 59766fd005ff |
rev | line source |
---|---|
0 | 1 /* |
2166
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2089
diff
changeset
|
2 * Copyright (c) 2005, 2011, 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/ciCPCache.hpp" | |
34 #include "ci/ciInstance.hpp" | |
35 #include "runtime/sharedRuntime.hpp" | |
36 #include "runtime/stubRoutines.hpp" | |
37 #include "utilities/bitMap.inline.hpp" | |
38 #ifndef SERIALGC | |
39 #include "gc_implementation/g1/heapRegion.hpp" | |
40 #endif | |
0 | 41 |
42 #ifdef ASSERT | |
43 #define __ gen()->lir(__FILE__, __LINE__)-> | |
44 #else | |
45 #define __ gen()->lir()-> | |
46 #endif | |
47 | |
1681
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
48 // 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
|
49 #ifdef ARM |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
50 #define PATCHED_ADDR (204) |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
51 #else |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
52 #define PATCHED_ADDR (max_jint) |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
53 #endif |
0 | 54 |
55 void PhiResolverState::reset(int max_vregs) { | |
56 // Initialize array sizes | |
57 _virtual_operands.at_put_grow(max_vregs - 1, NULL, NULL); | |
58 _virtual_operands.trunc_to(0); | |
59 _other_operands.at_put_grow(max_vregs - 1, NULL, NULL); | |
60 _other_operands.trunc_to(0); | |
61 _vreg_table.at_put_grow(max_vregs - 1, NULL, NULL); | |
62 _vreg_table.trunc_to(0); | |
63 } | |
64 | |
65 | |
66 | |
67 //-------------------------------------------------------------- | |
68 // PhiResolver | |
69 | |
70 // Resolves cycles: | |
71 // | |
72 // r1 := r2 becomes temp := r1 | |
73 // r2 := r1 r1 := r2 | |
74 // r2 := temp | |
75 // and orders moves: | |
76 // | |
77 // r2 := r3 becomes r1 := r2 | |
78 // r1 := r2 r2 := r3 | |
79 | |
80 PhiResolver::PhiResolver(LIRGenerator* gen, int max_vregs) | |
81 : _gen(gen) | |
82 , _state(gen->resolver_state()) | |
83 , _temp(LIR_OprFact::illegalOpr) | |
84 { | |
85 // reinitialize the shared state arrays | |
86 _state.reset(max_vregs); | |
87 } | |
88 | |
89 | |
90 void PhiResolver::emit_move(LIR_Opr src, LIR_Opr dest) { | |
91 assert(src->is_valid(), ""); | |
92 assert(dest->is_valid(), ""); | |
93 __ move(src, dest); | |
94 } | |
95 | |
96 | |
97 void PhiResolver::move_temp_to(LIR_Opr dest) { | |
98 assert(_temp->is_valid(), ""); | |
99 emit_move(_temp, dest); | |
100 NOT_PRODUCT(_temp = LIR_OprFact::illegalOpr); | |
101 } | |
102 | |
103 | |
104 void PhiResolver::move_to_temp(LIR_Opr src) { | |
105 assert(_temp->is_illegal(), ""); | |
106 _temp = _gen->new_register(src->type()); | |
107 emit_move(src, _temp); | |
108 } | |
109 | |
110 | |
111 // Traverse assignment graph in depth first order and generate moves in post order | |
112 // ie. two assignments: b := c, a := b start with node c: | |
113 // Call graph: move(NULL, c) -> move(c, b) -> move(b, a) | |
114 // Generates moves in this order: move b to a and move c to b | |
115 // ie. cycle a := b, b := a start with node a | |
116 // Call graph: move(NULL, a) -> move(a, b) -> move(b, a) | |
117 // Generates moves in this order: move b to temp, move a to b, move temp to a | |
118 void PhiResolver::move(ResolveNode* src, ResolveNode* dest) { | |
119 if (!dest->visited()) { | |
120 dest->set_visited(); | |
121 for (int i = dest->no_of_destinations()-1; i >= 0; i --) { | |
122 move(dest, dest->destination_at(i)); | |
123 } | |
124 } else if (!dest->start_node()) { | |
125 // cylce in graph detected | |
126 assert(_loop == NULL, "only one loop valid!"); | |
127 _loop = dest; | |
128 move_to_temp(src->operand()); | |
129 return; | |
130 } // else dest is a start node | |
131 | |
132 if (!dest->assigned()) { | |
133 if (_loop == dest) { | |
134 move_temp_to(dest->operand()); | |
135 dest->set_assigned(); | |
136 } else if (src != NULL) { | |
137 emit_move(src->operand(), dest->operand()); | |
138 dest->set_assigned(); | |
139 } | |
140 } | |
141 } | |
142 | |
143 | |
144 PhiResolver::~PhiResolver() { | |
145 int i; | |
146 // resolve any cycles in moves from and to virtual registers | |
147 for (i = virtual_operands().length() - 1; i >= 0; i --) { | |
148 ResolveNode* node = virtual_operands()[i]; | |
149 if (!node->visited()) { | |
150 _loop = NULL; | |
151 move(NULL, node); | |
152 node->set_start_node(); | |
153 assert(_temp->is_illegal(), "move_temp_to() call missing"); | |
154 } | |
155 } | |
156 | |
157 // generate move for move from non virtual register to abitrary destination | |
158 for (i = other_operands().length() - 1; i >= 0; i --) { | |
159 ResolveNode* node = other_operands()[i]; | |
160 for (int j = node->no_of_destinations() - 1; j >= 0; j --) { | |
161 emit_move(node->operand(), node->destination_at(j)->operand()); | |
162 } | |
163 } | |
164 } | |
165 | |
166 | |
167 ResolveNode* PhiResolver::create_node(LIR_Opr opr, bool source) { | |
168 ResolveNode* node; | |
169 if (opr->is_virtual()) { | |
170 int vreg_num = opr->vreg_number(); | |
171 node = vreg_table().at_grow(vreg_num, NULL); | |
172 assert(node == NULL || node->operand() == opr, ""); | |
173 if (node == NULL) { | |
174 node = new ResolveNode(opr); | |
175 vreg_table()[vreg_num] = node; | |
176 } | |
177 // Make sure that all virtual operands show up in the list when | |
178 // they are used as the source of a move. | |
179 if (source && !virtual_operands().contains(node)) { | |
180 virtual_operands().append(node); | |
181 } | |
182 } else { | |
183 assert(source, ""); | |
184 node = new ResolveNode(opr); | |
185 other_operands().append(node); | |
186 } | |
187 return node; | |
188 } | |
189 | |
190 | |
191 void PhiResolver::move(LIR_Opr src, LIR_Opr dest) { | |
192 assert(dest->is_virtual(), ""); | |
193 // tty->print("move "); src->print(); tty->print(" to "); dest->print(); tty->cr(); | |
194 assert(src->is_valid(), ""); | |
195 assert(dest->is_valid(), ""); | |
196 ResolveNode* source = source_node(src); | |
197 source->append(destination_node(dest)); | |
198 } | |
199 | |
200 | |
201 //-------------------------------------------------------------- | |
202 // LIRItem | |
203 | |
204 void LIRItem::set_result(LIR_Opr opr) { | |
205 assert(value()->operand()->is_illegal() || value()->operand()->is_constant(), "operand should never change"); | |
206 value()->set_operand(opr); | |
207 | |
208 if (opr->is_virtual()) { | |
209 _gen->_instruction_for_operand.at_put_grow(opr->vreg_number(), value(), NULL); | |
210 } | |
211 | |
212 _result = opr; | |
213 } | |
214 | |
215 void LIRItem::load_item() { | |
216 if (result()->is_illegal()) { | |
217 // update the items result | |
218 _result = value()->operand(); | |
219 } | |
220 if (!result()->is_register()) { | |
221 LIR_Opr reg = _gen->new_register(value()->type()); | |
222 __ move(result(), reg); | |
223 if (result()->is_constant()) { | |
224 _result = reg; | |
225 } else { | |
226 set_result(reg); | |
227 } | |
228 } | |
229 } | |
230 | |
231 | |
232 void LIRItem::load_for_store(BasicType type) { | |
233 if (_gen->can_store_as_constant(value(), type)) { | |
234 _result = value()->operand(); | |
235 if (!_result->is_constant()) { | |
236 _result = LIR_OprFact::value_type(value()->type()); | |
237 } | |
238 } else if (type == T_BYTE || type == T_BOOLEAN) { | |
239 load_byte_item(); | |
240 } else { | |
241 load_item(); | |
242 } | |
243 } | |
244 | |
245 void LIRItem::load_item_force(LIR_Opr reg) { | |
246 LIR_Opr r = result(); | |
247 if (r != reg) { | |
1681
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
248 #if !defined(ARM) && !defined(E500V2) |
0 | 249 if (r->type() != reg->type()) { |
250 // moves between different types need an intervening spill slot | |
1681
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
251 r = _gen->force_to_spill(r, reg->type()); |
0 | 252 } |
1681
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
253 #endif |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
254 __ move(r, reg); |
0 | 255 _result = reg; |
256 } | |
257 } | |
258 | |
259 ciObject* LIRItem::get_jobject_constant() const { | |
260 ObjectType* oc = type()->as_ObjectType(); | |
261 if (oc) { | |
262 return oc->constant_value(); | |
263 } | |
264 return NULL; | |
265 } | |
266 | |
267 | |
268 jint LIRItem::get_jint_constant() const { | |
269 assert(is_constant() && value() != NULL, ""); | |
270 assert(type()->as_IntConstant() != NULL, "type check"); | |
271 return type()->as_IntConstant()->value(); | |
272 } | |
273 | |
274 | |
275 jint LIRItem::get_address_constant() const { | |
276 assert(is_constant() && value() != NULL, ""); | |
277 assert(type()->as_AddressConstant() != NULL, "type check"); | |
278 return type()->as_AddressConstant()->value(); | |
279 } | |
280 | |
281 | |
282 jfloat LIRItem::get_jfloat_constant() const { | |
283 assert(is_constant() && value() != NULL, ""); | |
284 assert(type()->as_FloatConstant() != NULL, "type check"); | |
285 return type()->as_FloatConstant()->value(); | |
286 } | |
287 | |
288 | |
289 jdouble LIRItem::get_jdouble_constant() const { | |
290 assert(is_constant() && value() != NULL, ""); | |
291 assert(type()->as_DoubleConstant() != NULL, "type check"); | |
292 return type()->as_DoubleConstant()->value(); | |
293 } | |
294 | |
295 | |
296 jlong LIRItem::get_jlong_constant() const { | |
297 assert(is_constant() && value() != NULL, ""); | |
298 assert(type()->as_LongConstant() != NULL, "type check"); | |
299 return type()->as_LongConstant()->value(); | |
300 } | |
301 | |
302 | |
303 | |
304 //-------------------------------------------------------------- | |
305 | |
306 | |
307 void LIRGenerator::init() { | |
342 | 308 _bs = Universe::heap()->barrier_set(); |
0 | 309 } |
310 | |
311 | |
312 void LIRGenerator::block_do_prolog(BlockBegin* block) { | |
313 #ifndef PRODUCT | |
314 if (PrintIRWithLIR) { | |
315 block->print(); | |
316 } | |
317 #endif | |
318 | |
319 // set up the list of LIR instructions | |
320 assert(block->lir() == NULL, "LIR list already computed for this block"); | |
321 _lir = new LIR_List(compilation(), block); | |
322 block->set_lir(_lir); | |
323 | |
324 __ branch_destination(block->label()); | |
325 | |
326 if (LIRTraceExecution && | |
1584 | 327 Compilation::current()->hir()->start()->block_id() != block->block_id() && |
0 | 328 !block->is_set(BlockBegin::exception_entry_flag)) { |
329 assert(block->lir()->instructions_list()->length() == 1, "should come right after br_dst"); | |
330 trace_block_entry(block); | |
331 } | |
332 } | |
333 | |
334 | |
335 void LIRGenerator::block_do_epilog(BlockBegin* block) { | |
336 #ifndef PRODUCT | |
337 if (PrintIRWithLIR) { | |
338 tty->cr(); | |
339 } | |
340 #endif | |
341 | |
342 // LIR_Opr for unpinned constants shouldn't be referenced by other | |
343 // blocks so clear them out after processing the block. | |
344 for (int i = 0; i < _unpinned_constants.length(); i++) { | |
345 _unpinned_constants.at(i)->clear_operand(); | |
346 } | |
347 _unpinned_constants.trunc_to(0); | |
348 | |
349 // clear our any registers for other local constants | |
350 _constants.trunc_to(0); | |
351 _reg_for_constants.trunc_to(0); | |
352 } | |
353 | |
354 | |
355 void LIRGenerator::block_do(BlockBegin* block) { | |
356 CHECK_BAILOUT(); | |
357 | |
358 block_do_prolog(block); | |
359 set_block(block); | |
360 | |
361 for (Instruction* instr = block; instr != NULL; instr = instr->next()) { | |
362 if (instr->is_pinned()) do_root(instr); | |
363 } | |
364 | |
365 set_block(NULL); | |
366 block_do_epilog(block); | |
367 } | |
368 | |
369 | |
370 //-------------------------LIRGenerator----------------------------- | |
371 | |
372 // This is where the tree-walk starts; instr must be root; | |
373 void LIRGenerator::do_root(Value instr) { | |
374 CHECK_BAILOUT(); | |
375 | |
376 InstructionMark im(compilation(), instr); | |
377 | |
378 assert(instr->is_pinned(), "use only with roots"); | |
379 assert(instr->subst() == instr, "shouldn't have missed substitution"); | |
380 | |
381 instr->visit(this); | |
382 | |
383 assert(!instr->has_uses() || instr->operand()->is_valid() || | |
384 instr->as_Constant() != NULL || bailed_out(), "invalid item set"); | |
385 } | |
386 | |
387 | |
388 // This is called for each node in tree; the walk stops if a root is reached | |
389 void LIRGenerator::walk(Value instr) { | |
390 InstructionMark im(compilation(), instr); | |
391 //stop walk when encounter a root | |
392 if (instr->is_pinned() && instr->as_Phi() == NULL || instr->operand()->is_valid()) { | |
393 assert(instr->operand() != LIR_OprFact::illegalOpr || instr->as_Constant() != NULL, "this root has not yet been visited"); | |
394 } else { | |
395 assert(instr->subst() == instr, "shouldn't have missed substitution"); | |
396 instr->visit(this); | |
397 // assert(instr->use_count() > 0 || instr->as_Phi() != NULL, "leaf instruction must have a use"); | |
398 } | |
399 } | |
400 | |
401 | |
402 CodeEmitInfo* LIRGenerator::state_for(Instruction* x, ValueStack* state, bool ignore_xhandler) { | |
1819 | 403 assert(state != NULL, "state must be defined"); |
404 | |
405 ValueStack* s = state; | |
406 for_each_state(s) { | |
407 if (s->kind() == ValueStack::EmptyExceptionState) { | |
408 assert(s->stack_size() == 0 && s->locals_size() == 0 && (s->locks_size() == 0 || s->locks_size() == 1), "state must be empty"); | |
409 continue; | |
0 | 410 } |
1819 | 411 |
412 int index; | |
413 Value value; | |
414 for_each_stack_value(s, index, value) { | |
415 assert(value->subst() == value, "missed substitution"); | |
416 if (!value->is_pinned() && value->as_Constant() == NULL && value->as_Local() == NULL) { | |
417 walk(value); | |
418 assert(value->operand()->is_valid(), "must be evaluated now"); | |
419 } | |
420 } | |
421 | |
422 int bci = s->bci(); | |
0 | 423 IRScope* scope = s->scope(); |
424 ciMethod* method = scope->method(); | |
425 | |
426 MethodLivenessResult liveness = method->liveness_at_bci(bci); | |
427 if (bci == SynchronizationEntryBCI) { | |
428 if (x->as_ExceptionObject() || x->as_Throw()) { | |
429 // all locals are dead on exit from the synthetic unlocker | |
430 liveness.clear(); | |
431 } else { | |
432 assert(x->as_MonitorEnter(), "only other case is MonitorEnter"); | |
433 } | |
434 } | |
435 if (!liveness.is_valid()) { | |
436 // Degenerate or breakpointed method. | |
437 bailout("Degenerate or breakpointed method"); | |
438 } else { | |
439 assert((int)liveness.size() == s->locals_size(), "error in use of liveness"); | |
440 for_each_local_value(s, index, value) { | |
441 assert(value->subst() == value, "missed substition"); | |
442 if (liveness.at(index) && !value->type()->is_illegal()) { | |
443 if (!value->is_pinned() && value->as_Constant() == NULL && value->as_Local() == NULL) { | |
444 walk(value); | |
445 assert(value->operand()->is_valid(), "must be evaluated now"); | |
446 } | |
447 } else { | |
448 // NULL out this local so that linear scan can assume that all non-NULL values are live. | |
449 s->invalidate_local(index); | |
450 } | |
451 } | |
452 } | |
453 } | |
454 | |
1819 | 455 return new CodeEmitInfo(state, ignore_xhandler ? NULL : x->exception_handlers()); |
0 | 456 } |
457 | |
458 | |
459 CodeEmitInfo* LIRGenerator::state_for(Instruction* x) { | |
1819 | 460 return state_for(x, x->exception_state()); |
0 | 461 } |
462 | |
463 | |
464 void LIRGenerator::jobject2reg_with_patching(LIR_Opr r, ciObject* obj, CodeEmitInfo* info) { | |
465 if (!obj->is_loaded() || PatchALot) { | |
466 assert(info != NULL, "info must be set if class is not loaded"); | |
467 __ oop2reg_patch(NULL, r, info); | |
468 } else { | |
469 // no patching needed | |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
819
diff
changeset
|
470 __ oop2reg(obj->constant_encoding(), r); |
0 | 471 } |
472 } | |
473 | |
474 | |
475 void LIRGenerator::array_range_check(LIR_Opr array, LIR_Opr index, | |
476 CodeEmitInfo* null_check_info, CodeEmitInfo* range_check_info) { | |
477 CodeStub* stub = new RangeCheckStub(range_check_info, index); | |
478 if (index->is_constant()) { | |
479 cmp_mem_int(lir_cond_belowEqual, array, arrayOopDesc::length_offset_in_bytes(), | |
480 index->as_jint(), null_check_info); | |
481 __ branch(lir_cond_belowEqual, T_INT, stub); // forward branch | |
482 } else { | |
483 cmp_reg_mem(lir_cond_aboveEqual, index, array, | |
484 arrayOopDesc::length_offset_in_bytes(), T_INT, null_check_info); | |
485 __ branch(lir_cond_aboveEqual, T_INT, stub); // forward branch | |
486 } | |
487 } | |
488 | |
489 | |
490 void LIRGenerator::nio_range_check(LIR_Opr buffer, LIR_Opr index, LIR_Opr result, CodeEmitInfo* info) { | |
491 CodeStub* stub = new RangeCheckStub(info, index, true); | |
492 if (index->is_constant()) { | |
493 cmp_mem_int(lir_cond_belowEqual, buffer, java_nio_Buffer::limit_offset(), index->as_jint(), info); | |
494 __ branch(lir_cond_belowEqual, T_INT, stub); // forward branch | |
495 } else { | |
496 cmp_reg_mem(lir_cond_aboveEqual, index, buffer, | |
497 java_nio_Buffer::limit_offset(), T_INT, info); | |
498 __ branch(lir_cond_aboveEqual, T_INT, stub); // forward branch | |
499 } | |
500 __ move(index, result); | |
501 } | |
502 | |
503 | |
504 | |
505 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) { | |
506 LIR_Opr result_op = result; | |
507 LIR_Opr left_op = left; | |
508 LIR_Opr right_op = right; | |
509 | |
510 if (TwoOperandLIRForm && left_op != result_op) { | |
511 assert(right_op != result_op, "malformed"); | |
512 __ move(left_op, result_op); | |
513 left_op = result_op; | |
514 } | |
515 | |
516 switch(code) { | |
517 case Bytecodes::_dadd: | |
518 case Bytecodes::_fadd: | |
519 case Bytecodes::_ladd: | |
520 case Bytecodes::_iadd: __ add(left_op, right_op, result_op); break; | |
521 case Bytecodes::_fmul: | |
522 case Bytecodes::_lmul: __ mul(left_op, right_op, result_op); break; | |
523 | |
524 case Bytecodes::_dmul: | |
525 { | |
526 if (is_strictfp) { | |
527 __ mul_strictfp(left_op, right_op, result_op, tmp_op); break; | |
528 } else { | |
529 __ mul(left_op, right_op, result_op); break; | |
530 } | |
531 } | |
532 break; | |
533 | |
534 case Bytecodes::_imul: | |
535 { | |
536 bool did_strength_reduce = false; | |
537 | |
538 if (right->is_constant()) { | |
539 int c = right->as_jint(); | |
540 if (is_power_of_2(c)) { | |
541 // do not need tmp here | |
542 __ shift_left(left_op, exact_log2(c), result_op); | |
543 did_strength_reduce = true; | |
544 } else { | |
545 did_strength_reduce = strength_reduce_multiply(left_op, c, result_op, tmp_op); | |
546 } | |
547 } | |
548 // we couldn't strength reduce so just emit the multiply | |
549 if (!did_strength_reduce) { | |
550 __ mul(left_op, right_op, result_op); | |
551 } | |
552 } | |
553 break; | |
554 | |
555 case Bytecodes::_dsub: | |
556 case Bytecodes::_fsub: | |
557 case Bytecodes::_lsub: | |
558 case Bytecodes::_isub: __ sub(left_op, right_op, result_op); break; | |
559 | |
560 case Bytecodes::_fdiv: __ div (left_op, right_op, result_op); break; | |
561 // ldiv and lrem are implemented with a direct runtime call | |
562 | |
563 case Bytecodes::_ddiv: | |
564 { | |
565 if (is_strictfp) { | |
566 __ div_strictfp (left_op, right_op, result_op, tmp_op); break; | |
567 } else { | |
568 __ div (left_op, right_op, result_op); break; | |
569 } | |
570 } | |
571 break; | |
572 | |
573 case Bytecodes::_drem: | |
574 case Bytecodes::_frem: __ rem (left_op, right_op, result_op); break; | |
575 | |
576 default: ShouldNotReachHere(); | |
577 } | |
578 } | |
579 | |
580 | |
581 void LIRGenerator::arithmetic_op_int(Bytecodes::Code code, LIR_Opr result, LIR_Opr left, LIR_Opr right, LIR_Opr tmp) { | |
582 arithmetic_op(code, result, left, right, false, tmp); | |
583 } | |
584 | |
585 | |
586 void LIRGenerator::arithmetic_op_long(Bytecodes::Code code, LIR_Opr result, LIR_Opr left, LIR_Opr right, CodeEmitInfo* info) { | |
587 arithmetic_op(code, result, left, right, false, LIR_OprFact::illegalOpr, info); | |
588 } | |
589 | |
590 | |
591 void LIRGenerator::arithmetic_op_fpu(Bytecodes::Code code, LIR_Opr result, LIR_Opr left, LIR_Opr right, bool is_strictfp, LIR_Opr tmp) { | |
592 arithmetic_op(code, result, left, right, is_strictfp, tmp); | |
593 } | |
594 | |
595 | |
596 void LIRGenerator::shift_op(Bytecodes::Code code, LIR_Opr result_op, LIR_Opr value, LIR_Opr count, LIR_Opr tmp) { | |
597 if (TwoOperandLIRForm && value != result_op) { | |
598 assert(count != result_op, "malformed"); | |
599 __ move(value, result_op); | |
600 value = result_op; | |
601 } | |
602 | |
603 assert(count->is_constant() || count->is_register(), "must be"); | |
604 switch(code) { | |
605 case Bytecodes::_ishl: | |
606 case Bytecodes::_lshl: __ shift_left(value, count, result_op, tmp); break; | |
607 case Bytecodes::_ishr: | |
608 case Bytecodes::_lshr: __ shift_right(value, count, result_op, tmp); break; | |
609 case Bytecodes::_iushr: | |
610 case Bytecodes::_lushr: __ unsigned_shift_right(value, count, result_op, tmp); break; | |
611 default: ShouldNotReachHere(); | |
612 } | |
613 } | |
614 | |
615 | |
616 void LIRGenerator::logic_op (Bytecodes::Code code, LIR_Opr result_op, LIR_Opr left_op, LIR_Opr right_op) { | |
617 if (TwoOperandLIRForm && left_op != result_op) { | |
618 assert(right_op != result_op, "malformed"); | |
619 __ move(left_op, result_op); | |
620 left_op = result_op; | |
621 } | |
622 | |
623 switch(code) { | |
624 case Bytecodes::_iand: | |
625 case Bytecodes::_land: __ logical_and(left_op, right_op, result_op); break; | |
626 | |
627 case Bytecodes::_ior: | |
628 case Bytecodes::_lor: __ logical_or(left_op, right_op, result_op); break; | |
629 | |
630 case Bytecodes::_ixor: | |
631 case Bytecodes::_lxor: __ logical_xor(left_op, right_op, result_op); break; | |
632 | |
633 default: ShouldNotReachHere(); | |
634 } | |
635 } | |
636 | |
637 | |
638 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) { | |
639 if (!GenerateSynchronizationCode) return; | |
640 // for slow path, use debug info for state after successful locking | |
641 CodeStub* slow_path = new MonitorEnterStub(object, lock, info); | |
642 __ load_stack_address_monitor(monitor_no, lock); | |
643 // for handling NullPointerException, use debug info representing just the lock stack before this monitorenter | |
644 __ lock_object(hdr, object, lock, scratch, slow_path, info_for_exception); | |
645 } | |
646 | |
647 | |
1681
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
648 void LIRGenerator::monitor_exit(LIR_Opr object, LIR_Opr lock, LIR_Opr new_hdr, LIR_Opr scratch, int monitor_no) { |
0 | 649 if (!GenerateSynchronizationCode) return; |
650 // setup registers | |
651 LIR_Opr hdr = lock; | |
652 lock = new_hdr; | |
653 CodeStub* slow_path = new MonitorExitStub(lock, UseFastLocking, monitor_no); | |
654 __ load_stack_address_monitor(monitor_no, lock); | |
1681
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
655 __ unlock_object(hdr, object, lock, scratch, slow_path); |
0 | 656 } |
657 | |
658 | |
659 void LIRGenerator::new_instance(LIR_Opr dst, ciInstanceKlass* klass, LIR_Opr scratch1, LIR_Opr scratch2, LIR_Opr scratch3, LIR_Opr scratch4, LIR_Opr klass_reg, CodeEmitInfo* info) { | |
660 jobject2reg_with_patching(klass_reg, klass, info); | |
661 // If klass is not loaded we do not know if the klass has finalizers: | |
662 if (UseFastNewInstance && klass->is_loaded() | |
663 && !Klass::layout_helper_needs_slow_path(klass->layout_helper())) { | |
664 | |
665 Runtime1::StubID stub_id = klass->is_initialized() ? Runtime1::fast_new_instance_id : Runtime1::fast_new_instance_init_check_id; | |
666 | |
667 CodeStub* slow_path = new NewInstanceStub(klass_reg, dst, klass, info, stub_id); | |
668 | |
669 assert(klass->is_loaded(), "must be loaded"); | |
670 // allocate space for instance | |
671 assert(klass->size_helper() >= 0, "illegal instance size"); | |
672 const int instance_size = align_object_size(klass->size_helper()); | |
673 __ allocate_object(dst, scratch1, scratch2, scratch3, scratch4, | |
674 oopDesc::header_size(), instance_size, klass_reg, !klass->is_initialized(), slow_path); | |
675 } else { | |
676 CodeStub* slow_path = new NewInstanceStub(klass_reg, dst, klass, info, Runtime1::new_instance_id); | |
677 __ branch(lir_cond_always, T_ILLEGAL, slow_path); | |
678 __ branch_destination(slow_path->continuation()); | |
679 } | |
680 } | |
681 | |
682 | |
683 static bool is_constant_zero(Instruction* inst) { | |
684 IntConstant* c = inst->type()->as_IntConstant(); | |
685 if (c) { | |
686 return (c->value() == 0); | |
687 } | |
688 return false; | |
689 } | |
690 | |
691 | |
692 static bool positive_constant(Instruction* inst) { | |
693 IntConstant* c = inst->type()->as_IntConstant(); | |
694 if (c) { | |
695 return (c->value() >= 0); | |
696 } | |
697 return false; | |
698 } | |
699 | |
700 | |
701 static ciArrayKlass* as_array_klass(ciType* type) { | |
702 if (type != NULL && type->is_array_klass() && type->is_loaded()) { | |
703 return (ciArrayKlass*)type; | |
704 } else { | |
705 return NULL; | |
706 } | |
707 } | |
708 | |
709 void LIRGenerator::arraycopy_helper(Intrinsic* x, int* flagsp, ciArrayKlass** expected_typep) { | |
710 Instruction* src = x->argument_at(0); | |
711 Instruction* src_pos = x->argument_at(1); | |
712 Instruction* dst = x->argument_at(2); | |
713 Instruction* dst_pos = x->argument_at(3); | |
714 Instruction* length = x->argument_at(4); | |
715 | |
716 // first try to identify the likely type of the arrays involved | |
717 ciArrayKlass* expected_type = NULL; | |
718 bool is_exact = false; | |
719 { | |
720 ciArrayKlass* src_exact_type = as_array_klass(src->exact_type()); | |
721 ciArrayKlass* src_declared_type = as_array_klass(src->declared_type()); | |
722 ciArrayKlass* dst_exact_type = as_array_klass(dst->exact_type()); | |
723 ciArrayKlass* dst_declared_type = as_array_klass(dst->declared_type()); | |
724 if (src_exact_type != NULL && src_exact_type == dst_exact_type) { | |
725 // the types exactly match so the type is fully known | |
726 is_exact = true; | |
727 expected_type = src_exact_type; | |
728 } else if (dst_exact_type != NULL && dst_exact_type->is_obj_array_klass()) { | |
729 ciArrayKlass* dst_type = (ciArrayKlass*) dst_exact_type; | |
730 ciArrayKlass* src_type = NULL; | |
731 if (src_exact_type != NULL && src_exact_type->is_obj_array_klass()) { | |
732 src_type = (ciArrayKlass*) src_exact_type; | |
733 } else if (src_declared_type != NULL && src_declared_type->is_obj_array_klass()) { | |
734 src_type = (ciArrayKlass*) src_declared_type; | |
735 } | |
736 if (src_type != NULL) { | |
737 if (src_type->element_type()->is_subtype_of(dst_type->element_type())) { | |
738 is_exact = true; | |
739 expected_type = dst_type; | |
740 } | |
741 } | |
742 } | |
743 // at least pass along a good guess | |
744 if (expected_type == NULL) expected_type = dst_exact_type; | |
745 if (expected_type == NULL) expected_type = src_declared_type; | |
746 if (expected_type == NULL) expected_type = dst_declared_type; | |
747 } | |
748 | |
749 // if a probable array type has been identified, figure out if any | |
750 // of the required checks for a fast case can be elided. | |
751 int flags = LIR_OpArrayCopy::all_flags; | |
752 if (expected_type != NULL) { | |
753 // try to skip null checks | |
754 if (src->as_NewArray() != NULL) | |
755 flags &= ~LIR_OpArrayCopy::src_null_check; | |
756 if (dst->as_NewArray() != NULL) | |
757 flags &= ~LIR_OpArrayCopy::dst_null_check; | |
758 | |
759 // check from incoming constant values | |
760 if (positive_constant(src_pos)) | |
761 flags &= ~LIR_OpArrayCopy::src_pos_positive_check; | |
762 if (positive_constant(dst_pos)) | |
763 flags &= ~LIR_OpArrayCopy::dst_pos_positive_check; | |
764 if (positive_constant(length)) | |
765 flags &= ~LIR_OpArrayCopy::length_positive_check; | |
766 | |
767 // see if the range check can be elided, which might also imply | |
768 // that src or dst is non-null. | |
769 ArrayLength* al = length->as_ArrayLength(); | |
770 if (al != NULL) { | |
771 if (al->array() == src) { | |
772 // it's the length of the source array | |
773 flags &= ~LIR_OpArrayCopy::length_positive_check; | |
774 flags &= ~LIR_OpArrayCopy::src_null_check; | |
775 if (is_constant_zero(src_pos)) | |
776 flags &= ~LIR_OpArrayCopy::src_range_check; | |
777 } | |
778 if (al->array() == dst) { | |
779 // it's the length of the destination array | |
780 flags &= ~LIR_OpArrayCopy::length_positive_check; | |
781 flags &= ~LIR_OpArrayCopy::dst_null_check; | |
782 if (is_constant_zero(dst_pos)) | |
783 flags &= ~LIR_OpArrayCopy::dst_range_check; | |
784 } | |
785 } | |
786 if (is_exact) { | |
787 flags &= ~LIR_OpArrayCopy::type_check; | |
788 } | |
789 } | |
790 | |
791 if (src == dst) { | |
792 // moving within a single array so no type checks are needed | |
793 if (flags & LIR_OpArrayCopy::type_check) { | |
794 flags &= ~LIR_OpArrayCopy::type_check; | |
795 } | |
796 } | |
797 *flagsp = flags; | |
798 *expected_typep = (ciArrayKlass*)expected_type; | |
799 } | |
800 | |
801 | |
802 LIR_Opr LIRGenerator::round_item(LIR_Opr opr) { | |
803 assert(opr->is_register(), "why spill if item is not register?"); | |
804 | |
805 if (RoundFPResults && UseSSE < 1 && opr->is_single_fpu()) { | |
806 LIR_Opr result = new_register(T_FLOAT); | |
807 set_vreg_flag(result, must_start_in_memory); | |
808 assert(opr->is_register(), "only a register can be spilled"); | |
809 assert(opr->value_type()->is_float(), "rounding only for floats available"); | |
810 __ roundfp(opr, LIR_OprFact::illegalOpr, result); | |
811 return result; | |
812 } | |
813 return opr; | |
814 } | |
815 | |
816 | |
817 LIR_Opr LIRGenerator::force_to_spill(LIR_Opr value, BasicType t) { | |
818 assert(type2size[t] == type2size[value->type()], "size mismatch"); | |
819 if (!value->is_register()) { | |
820 // force into a register | |
821 LIR_Opr r = new_register(value->type()); | |
822 __ move(value, r); | |
823 value = r; | |
824 } | |
825 | |
826 // create a spill location | |
827 LIR_Opr tmp = new_register(t); | |
828 set_vreg_flag(tmp, LIRGenerator::must_start_in_memory); | |
829 | |
830 // move from register to spill | |
831 __ move(value, tmp); | |
832 return tmp; | |
833 } | |
834 | |
835 void LIRGenerator::profile_branch(If* if_instr, If::Condition cond) { | |
836 if (if_instr->should_profile()) { | |
837 ciMethod* method = if_instr->profiled_method(); | |
838 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
|
839 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
|
840 assert(md != NULL, "Sanity"); |
0 | 841 ciProfileData* data = md->bci_to_data(if_instr->profiled_bci()); |
842 assert(data != NULL, "must have profiling data"); | |
843 assert(data->is_BranchData(), "need BranchData for two-way branches"); | |
844 int taken_count_offset = md->byte_offset_of_slot(data, BranchData::taken_offset()); | |
845 int not_taken_count_offset = md->byte_offset_of_slot(data, BranchData::not_taken_offset()); | |
1783 | 846 if (if_instr->is_swapped()) { |
847 int t = taken_count_offset; | |
848 taken_count_offset = not_taken_count_offset; | |
849 not_taken_count_offset = t; | |
850 } | |
851 | |
0 | 852 LIR_Opr md_reg = new_register(T_OBJECT); |
1783 | 853 __ oop2reg(md->constant_encoding(), md_reg); |
854 | |
855 LIR_Opr data_offset_reg = new_pointer_register(); | |
0 | 856 __ cmove(lir_cond(cond), |
1783 | 857 LIR_OprFact::intptrConst(taken_count_offset), |
858 LIR_OprFact::intptrConst(not_taken_count_offset), | |
2089
037c727f35fb
7009231: C1: Incorrect CAS code for longs on SPARC 32bit
iveresov
parents:
2007
diff
changeset
|
859 data_offset_reg, as_BasicType(if_instr->x()->type())); |
1783 | 860 |
861 // MDO cells are intptr_t, so the data_reg width is arch-dependent. | |
862 LIR_Opr data_reg = new_pointer_register(); | |
863 LIR_Address* data_addr = new LIR_Address(md_reg, data_offset_reg, data_reg->type()); | |
2002 | 864 __ move(data_addr, data_reg); |
1783 | 865 // Use leal instead of add to avoid destroying condition codes on x86 |
0 | 866 LIR_Address* fake_incr_value = new LIR_Address(data_reg, DataLayout::counter_increment, T_INT); |
867 __ leal(LIR_OprFact::address(fake_incr_value), data_reg); | |
2002 | 868 __ move(data_reg, data_addr); |
0 | 869 } |
870 } | |
871 | |
872 // Phi technique: | |
873 // This is about passing live values from one basic block to the other. | |
874 // In code generated with Java it is rather rare that more than one | |
875 // value is on the stack from one basic block to the other. | |
876 // We optimize our technique for efficient passing of one value | |
877 // (of type long, int, double..) but it can be extended. | |
878 // When entering or leaving a basic block, all registers and all spill | |
879 // slots are release and empty. We use the released registers | |
880 // and spill slots to pass the live values from one block | |
881 // to the other. The topmost value, i.e., the value on TOS of expression | |
882 // stack is passed in registers. All other values are stored in spilling | |
883 // area. Every Phi has an index which designates its spill slot | |
884 // At exit of a basic block, we fill the register(s) and spill slots. | |
885 // At entry of a basic block, the block_prolog sets up the content of phi nodes | |
886 // and locks necessary registers and spilling slots. | |
887 | |
888 | |
889 // move current value to referenced phi function | |
890 void LIRGenerator::move_to_phi(PhiResolver* resolver, Value cur_val, Value sux_val) { | |
891 Phi* phi = sux_val->as_Phi(); | |
892 // cur_val can be null without phi being null in conjunction with inlining | |
893 if (phi != NULL && cur_val != NULL && cur_val != phi && !phi->is_illegal()) { | |
894 LIR_Opr operand = cur_val->operand(); | |
895 if (cur_val->operand()->is_illegal()) { | |
896 assert(cur_val->as_Constant() != NULL || cur_val->as_Local() != NULL, | |
897 "these can be produced lazily"); | |
898 operand = operand_for_instruction(cur_val); | |
899 } | |
900 resolver->move(operand, operand_for_instruction(phi)); | |
901 } | |
902 } | |
903 | |
904 | |
905 // Moves all stack values into their PHI position | |
906 void LIRGenerator::move_to_phi(ValueStack* cur_state) { | |
907 BlockBegin* bb = block(); | |
908 if (bb->number_of_sux() == 1) { | |
909 BlockBegin* sux = bb->sux_at(0); | |
910 assert(sux->number_of_preds() > 0, "invalid CFG"); | |
911 | |
912 // a block with only one predecessor never has phi functions | |
913 if (sux->number_of_preds() > 1) { | |
914 int max_phis = cur_state->stack_size() + cur_state->locals_size(); | |
915 PhiResolver resolver(this, _virtual_register_number + max_phis * 2); | |
916 | |
917 ValueStack* sux_state = sux->state(); | |
918 Value sux_value; | |
919 int index; | |
920 | |
1819 | 921 assert(cur_state->scope() == sux_state->scope(), "not matching"); |
922 assert(cur_state->locals_size() == sux_state->locals_size(), "not matching"); | |
923 assert(cur_state->stack_size() == sux_state->stack_size(), "not matching"); | |
924 | |
0 | 925 for_each_stack_value(sux_state, index, sux_value) { |
926 move_to_phi(&resolver, cur_state->stack_at(index), sux_value); | |
927 } | |
928 | |
929 for_each_local_value(sux_state, index, sux_value) { | |
930 move_to_phi(&resolver, cur_state->local_at(index), sux_value); | |
931 } | |
932 | |
933 assert(cur_state->caller_state() == sux_state->caller_state(), "caller states must be equal"); | |
934 } | |
935 } | |
936 } | |
937 | |
938 | |
939 LIR_Opr LIRGenerator::new_register(BasicType type) { | |
940 int vreg = _virtual_register_number; | |
941 // add a little fudge factor for the bailout, since the bailout is | |
942 // only checked periodically. This gives a few extra registers to | |
943 // hand out before we really run out, which helps us keep from | |
944 // tripping over assertions. | |
945 if (vreg + 20 >= LIR_OprDesc::vreg_max) { | |
946 bailout("out of virtual registers"); | |
947 if (vreg + 2 >= LIR_OprDesc::vreg_max) { | |
948 // wrap it around | |
949 _virtual_register_number = LIR_OprDesc::vreg_base; | |
950 } | |
951 } | |
952 _virtual_register_number += 1; | |
953 return LIR_OprFact::virtual_register(vreg, type); | |
954 } | |
955 | |
956 | |
957 // Try to lock using register in hint | |
958 LIR_Opr LIRGenerator::rlock(Value instr) { | |
959 return new_register(instr->type()); | |
960 } | |
961 | |
962 | |
963 // does an rlock and sets result | |
964 LIR_Opr LIRGenerator::rlock_result(Value x) { | |
965 LIR_Opr reg = rlock(x); | |
966 set_result(x, reg); | |
967 return reg; | |
968 } | |
969 | |
970 | |
971 // does an rlock and sets result | |
972 LIR_Opr LIRGenerator::rlock_result(Value x, BasicType type) { | |
973 LIR_Opr reg; | |
974 switch (type) { | |
975 case T_BYTE: | |
976 case T_BOOLEAN: | |
977 reg = rlock_byte(type); | |
978 break; | |
979 default: | |
980 reg = rlock(x); | |
981 break; | |
982 } | |
983 | |
984 set_result(x, reg); | |
985 return reg; | |
986 } | |
987 | |
988 | |
989 //--------------------------------------------------------------------- | |
990 ciObject* LIRGenerator::get_jobject_constant(Value value) { | |
991 ObjectType* oc = value->type()->as_ObjectType(); | |
992 if (oc) { | |
993 return oc->constant_value(); | |
994 } | |
995 return NULL; | |
996 } | |
997 | |
998 | |
999 void LIRGenerator::do_ExceptionObject(ExceptionObject* x) { | |
1000 assert(block()->is_set(BlockBegin::exception_entry_flag), "ExceptionObject only allowed in exception handler block"); | |
1001 assert(block()->next() == x, "ExceptionObject must be first instruction of block"); | |
1002 | |
1003 // no moves are created for phi functions at the begin of exception | |
1004 // handlers, so assign operands manually here | |
1005 for_each_phi_fun(block(), phi, | |
1006 operand_for_instruction(phi)); | |
1007 | |
1008 LIR_Opr thread_reg = getThreadPointer(); | |
2002 | 1009 __ move_wide(new LIR_Address(thread_reg, in_bytes(JavaThread::exception_oop_offset()), T_OBJECT), |
1010 exceptionOopOpr()); | |
1011 __ move_wide(LIR_OprFact::oopConst(NULL), | |
1012 new LIR_Address(thread_reg, in_bytes(JavaThread::exception_oop_offset()), T_OBJECT)); | |
1013 __ move_wide(LIR_OprFact::oopConst(NULL), | |
1014 new LIR_Address(thread_reg, in_bytes(JavaThread::exception_pc_offset()), T_OBJECT)); | |
0 | 1015 |
1016 LIR_Opr result = new_register(T_OBJECT); | |
1017 __ move(exceptionOopOpr(), result); | |
1018 set_result(x, result); | |
1019 } | |
1020 | |
1021 | |
1022 //---------------------------------------------------------------------- | |
1023 //---------------------------------------------------------------------- | |
1024 //---------------------------------------------------------------------- | |
1025 //---------------------------------------------------------------------- | |
1026 // visitor functions | |
1027 //---------------------------------------------------------------------- | |
1028 //---------------------------------------------------------------------- | |
1029 //---------------------------------------------------------------------- | |
1030 //---------------------------------------------------------------------- | |
1031 | |
1032 void LIRGenerator::do_Phi(Phi* x) { | |
1033 // phi functions are never visited directly | |
1034 ShouldNotReachHere(); | |
1035 } | |
1036 | |
1037 | |
1038 // Code for a constant is generated lazily unless the constant is frequently used and can't be inlined. | |
1039 void LIRGenerator::do_Constant(Constant* x) { | |
1819 | 1040 if (x->state_before() != NULL) { |
0 | 1041 // Any constant with a ValueStack requires patching so emit the patch here |
1042 LIR_Opr reg = rlock_result(x); | |
1819 | 1043 CodeEmitInfo* info = state_for(x, x->state_before()); |
0 | 1044 __ oop2reg_patch(NULL, reg, info); |
1045 } else if (x->use_count() > 1 && !can_inline_as_constant(x)) { | |
1046 if (!x->is_pinned()) { | |
1047 // unpinned constants are handled specially so that they can be | |
1048 // put into registers when they are used multiple times within a | |
1049 // block. After the block completes their operand will be | |
1050 // cleared so that other blocks can't refer to that register. | |
1051 set_result(x, load_constant(x)); | |
1052 } else { | |
1053 LIR_Opr res = x->operand(); | |
1054 if (!res->is_valid()) { | |
1055 res = LIR_OprFact::value_type(x->type()); | |
1056 } | |
1057 if (res->is_constant()) { | |
1058 LIR_Opr reg = rlock_result(x); | |
1059 __ move(res, reg); | |
1060 } else { | |
1061 set_result(x, res); | |
1062 } | |
1063 } | |
1064 } else { | |
1065 set_result(x, LIR_OprFact::value_type(x->type())); | |
1066 } | |
1067 } | |
1068 | |
1069 | |
1070 void LIRGenerator::do_Local(Local* x) { | |
1071 // operand_for_instruction has the side effect of setting the result | |
1072 // so there's no need to do it here. | |
1073 operand_for_instruction(x); | |
1074 } | |
1075 | |
1076 | |
1077 void LIRGenerator::do_IfInstanceOf(IfInstanceOf* x) { | |
1078 Unimplemented(); | |
1079 } | |
1080 | |
1081 | |
1082 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
|
1083 if (compilation()->env()->dtrace_method_probes()) { |
0 | 1084 BasicTypeList signature; |
2002 | 1085 signature.append(LP64_ONLY(T_LONG) NOT_LP64(T_INT)); // thread |
0 | 1086 signature.append(T_OBJECT); // methodOop |
1087 LIR_OprList* args = new LIR_OprList(); | |
1088 args->append(getThreadPointer()); | |
1089 LIR_Opr meth = new_register(T_OBJECT); | |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
819
diff
changeset
|
1090 __ oop2reg(method()->constant_encoding(), meth); |
0 | 1091 args->append(meth); |
1092 call_runtime(&signature, args, CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit), voidType, NULL); | |
1093 } | |
1094 | |
1095 if (x->type()->is_void()) { | |
1096 __ return_op(LIR_OprFact::illegalOpr); | |
1097 } else { | |
1098 LIR_Opr reg = result_register_for(x->type(), /*callee=*/true); | |
1099 LIRItem result(x->result(), this); | |
1100 | |
1101 result.load_item_force(reg); | |
1102 __ return_op(result.result()); | |
1103 } | |
1104 set_no_result(x); | |
1105 } | |
1106 | |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1107 // Examble: ref.get() |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1108 // 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
|
1109 void LIRGenerator::do_Reference_get(Intrinsic* x) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1110 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1111 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
|
1112 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
|
1113 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1114 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
|
1115 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1116 LIRItem reference(x->argument_at(0), this); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1117 reference.load_item(); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1118 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1119 // 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
|
1120 CodeEmitInfo* info = NULL; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1121 if (x->needs_null_check()) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1122 info = state_for(x); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1123 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1124 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1125 LIR_Address* referent_field_adr = |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1126 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
|
1127 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1128 LIR_Opr result = rlock_result(x); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1129 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1130 __ load(referent_field_adr, result, info); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1131 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1132 // 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
|
1133 pre_barrier(LIR_OprFact::illegalOpr /* addr_opr */, |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1134 result /* pre_val */, |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1135 false /* do_load */, |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1136 false /* patch */, |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1137 NULL /* info */); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1138 } |
0 | 1139 |
1140 // Example: object.getClass () | |
1141 void LIRGenerator::do_getClass(Intrinsic* x) { | |
1142 assert(x->number_of_arguments() == 1, "wrong type"); | |
1143 | |
1144 LIRItem rcvr(x->argument_at(0), this); | |
1145 rcvr.load_item(); | |
1146 LIR_Opr result = rlock_result(x); | |
1147 | |
1148 // need to perform the null check on the rcvr | |
1149 CodeEmitInfo* info = NULL; | |
1150 if (x->needs_null_check()) { | |
1819 | 1151 info = state_for(x); |
0 | 1152 } |
1153 __ move(new LIR_Address(rcvr.result(), oopDesc::klass_offset_in_bytes(), T_OBJECT), result, info); | |
2002 | 1154 __ move_wide(new LIR_Address(result, Klass::java_mirror_offset_in_bytes() + |
1155 klassOopDesc::klass_part_offset_in_bytes(), T_OBJECT), result); | |
0 | 1156 } |
1157 | |
1158 | |
1159 // Example: Thread.currentThread() | |
1160 void LIRGenerator::do_currentThread(Intrinsic* x) { | |
1161 assert(x->number_of_arguments() == 0, "wrong type"); | |
1162 LIR_Opr reg = rlock_result(x); | |
2002 | 1163 __ move_wide(new LIR_Address(getThreadPointer(), in_bytes(JavaThread::threadObj_offset()), T_OBJECT), reg); |
0 | 1164 } |
1165 | |
1166 | |
1167 void LIRGenerator::do_RegisterFinalizer(Intrinsic* x) { | |
1168 assert(x->number_of_arguments() == 1, "wrong type"); | |
1169 LIRItem receiver(x->argument_at(0), this); | |
1170 | |
1171 receiver.load_item(); | |
1172 BasicTypeList signature; | |
1173 signature.append(T_OBJECT); // receiver | |
1174 LIR_OprList* args = new LIR_OprList(); | |
1175 args->append(receiver.result()); | |
1176 CodeEmitInfo* info = state_for(x, x->state()); | |
1177 call_runtime(&signature, args, | |
1178 CAST_FROM_FN_PTR(address, Runtime1::entry_for(Runtime1::register_finalizer_id)), | |
1179 voidType, info); | |
1180 | |
1181 set_no_result(x); | |
1182 } | |
1183 | |
1184 | |
1185 //------------------------local access-------------------------------------- | |
1186 | |
1187 LIR_Opr LIRGenerator::operand_for_instruction(Instruction* x) { | |
1188 if (x->operand()->is_illegal()) { | |
1189 Constant* c = x->as_Constant(); | |
1190 if (c != NULL) { | |
1191 x->set_operand(LIR_OprFact::value_type(c->type())); | |
1192 } else { | |
1193 assert(x->as_Phi() || x->as_Local() != NULL, "only for Phi and Local"); | |
1194 // allocate a virtual register for this local or phi | |
1195 x->set_operand(rlock(x)); | |
1196 _instruction_for_operand.at_put_grow(x->operand()->vreg_number(), x, NULL); | |
1197 } | |
1198 } | |
1199 return x->operand(); | |
1200 } | |
1201 | |
1202 | |
1203 Instruction* LIRGenerator::instruction_for_opr(LIR_Opr opr) { | |
1204 if (opr->is_virtual()) { | |
1205 return instruction_for_vreg(opr->vreg_number()); | |
1206 } | |
1207 return NULL; | |
1208 } | |
1209 | |
1210 | |
1211 Instruction* LIRGenerator::instruction_for_vreg(int reg_num) { | |
1212 if (reg_num < _instruction_for_operand.length()) { | |
1213 return _instruction_for_operand.at(reg_num); | |
1214 } | |
1215 return NULL; | |
1216 } | |
1217 | |
1218 | |
1219 void LIRGenerator::set_vreg_flag(int vreg_num, VregFlag f) { | |
1220 if (_vreg_flags.size_in_bits() == 0) { | |
1221 BitMap2D temp(100, num_vreg_flags); | |
1222 temp.clear(); | |
1223 _vreg_flags = temp; | |
1224 } | |
1225 _vreg_flags.at_put_grow(vreg_num, f, true); | |
1226 } | |
1227 | |
1228 bool LIRGenerator::is_vreg_flag_set(int vreg_num, VregFlag f) { | |
1229 if (!_vreg_flags.is_valid_index(vreg_num, f)) { | |
1230 return false; | |
1231 } | |
1232 return _vreg_flags.at(vreg_num, f); | |
1233 } | |
1234 | |
1235 | |
1236 // Block local constant handling. This code is useful for keeping | |
1237 // unpinned constants and constants which aren't exposed in the IR in | |
1238 // registers. Unpinned Constant instructions have their operands | |
1239 // cleared when the block is finished so that other blocks can't end | |
1240 // up referring to their registers. | |
1241 | |
1242 LIR_Opr LIRGenerator::load_constant(Constant* x) { | |
1243 assert(!x->is_pinned(), "only for unpinned constants"); | |
1244 _unpinned_constants.append(x); | |
1245 return load_constant(LIR_OprFact::value_type(x->type())->as_constant_ptr()); | |
1246 } | |
1247 | |
1248 | |
1249 LIR_Opr LIRGenerator::load_constant(LIR_Const* c) { | |
1250 BasicType t = c->type(); | |
1251 for (int i = 0; i < _constants.length(); i++) { | |
1252 LIR_Const* other = _constants.at(i); | |
1253 if (t == other->type()) { | |
1254 switch (t) { | |
1255 case T_INT: | |
1256 case T_FLOAT: | |
1257 if (c->as_jint_bits() != other->as_jint_bits()) continue; | |
1258 break; | |
1259 case T_LONG: | |
1260 case T_DOUBLE: | |
486
a738a625039a
6757316: load_constant() produces a wrong long constant, with high a low words swapped
never
parents:
380
diff
changeset
|
1261 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
|
1262 if (c->as_jint_lo_bits() != other->as_jint_lo_bits()) continue; |
0 | 1263 break; |
1264 case T_OBJECT: | |
1265 if (c->as_jobject() != other->as_jobject()) continue; | |
1266 break; | |
1267 } | |
1268 return _reg_for_constants.at(i); | |
1269 } | |
1270 } | |
1271 | |
1272 LIR_Opr result = new_register(t); | |
1273 __ move((LIR_Opr)c, result); | |
1274 _constants.append(c); | |
1275 _reg_for_constants.append(result); | |
1276 return result; | |
1277 } | |
1278 | |
1279 // Various barriers | |
1280 | |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1281 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
|
1282 bool do_load, bool patch, CodeEmitInfo* info) { |
342 | 1283 // Do the pre-write barrier, if any. |
1284 switch (_bs->kind()) { | |
1285 #ifndef SERIALGC | |
1286 case BarrierSet::G1SATBCT: | |
1287 case BarrierSet::G1SATBCTLogging: | |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1288 G1SATBCardTableModRef_pre_barrier(addr_opr, pre_val, do_load, patch, info); |
342 | 1289 break; |
1290 #endif // SERIALGC | |
1291 case BarrierSet::CardTableModRef: | |
1292 case BarrierSet::CardTableExtension: | |
1293 // No pre barriers | |
1294 break; | |
1295 case BarrierSet::ModRef: | |
1296 case BarrierSet::Other: | |
1297 // No pre barriers | |
1298 break; | |
1299 default : | |
1300 ShouldNotReachHere(); | |
1301 | |
1302 } | |
1303 } | |
1304 | |
0 | 1305 void LIRGenerator::post_barrier(LIR_OprDesc* addr, LIR_OprDesc* new_val) { |
342 | 1306 switch (_bs->kind()) { |
1307 #ifndef SERIALGC | |
1308 case BarrierSet::G1SATBCT: | |
1309 case BarrierSet::G1SATBCTLogging: | |
1310 G1SATBCardTableModRef_post_barrier(addr, new_val); | |
1311 break; | |
1312 #endif // SERIALGC | |
0 | 1313 case BarrierSet::CardTableModRef: |
1314 case BarrierSet::CardTableExtension: | |
1315 CardTableModRef_post_barrier(addr, new_val); | |
1316 break; | |
1317 case BarrierSet::ModRef: | |
1318 case BarrierSet::Other: | |
1319 // No post barriers | |
1320 break; | |
1321 default : | |
1322 ShouldNotReachHere(); | |
1323 } | |
1324 } | |
1325 | |
342 | 1326 //////////////////////////////////////////////////////////////////////// |
1327 #ifndef SERIALGC | |
1328 | |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1329 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
|
1330 bool do_load, bool patch, CodeEmitInfo* info) { |
342 | 1331 // First we test whether marking is in progress. |
1332 BasicType flag_type; | |
1333 if (in_bytes(PtrQueue::byte_width_of_active()) == 4) { | |
1334 flag_type = T_INT; | |
1335 } else { | |
1336 guarantee(in_bytes(PtrQueue::byte_width_of_active()) == 1, | |
1337 "Assumption"); | |
1338 flag_type = T_BYTE; | |
1339 } | |
1340 LIR_Opr thrd = getThreadPointer(); | |
1341 LIR_Address* mark_active_flag_addr = | |
1342 new LIR_Address(thrd, | |
1343 in_bytes(JavaThread::satb_mark_queue_offset() + | |
1344 PtrQueue::byte_offset_of_active()), | |
1345 flag_type); | |
1346 // Read the marking-in-progress flag. | |
1347 LIR_Opr flag_val = new_register(T_INT); | |
1348 __ load(mark_active_flag_addr, flag_val); | |
1349 __ 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
|
1350 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1351 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
|
1352 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1353 CodeStub* slow; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1354 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1355 if (do_load) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1356 assert(pre_val == LIR_OprFact::illegalOpr, "sanity"); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1357 assert(addr_opr != LIR_OprFact::illegalOpr, "sanity"); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1358 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1359 if (patch) |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1360 pre_val_patch_code = lir_patch_normal; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1361 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1362 pre_val = new_register(T_OBJECT); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1363 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1364 if (!addr_opr->is_address()) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1365 assert(addr_opr->is_register(), "must be"); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1366 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
|
1367 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1368 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
|
1369 } else { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1370 assert(addr_opr == LIR_OprFact::illegalOpr, "sanity"); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1371 assert(pre_val->is_register(), "must be"); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1372 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
|
1373 assert(info == NULL, "sanity"); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1374 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1375 slow = new G1PreBarrierStub(pre_val); |
342 | 1376 } |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1377 |
342 | 1378 __ branch(lir_cond_notEqual, T_INT, slow); |
1379 __ branch_destination(slow->continuation()); | |
1380 } | |
1381 | |
1382 void LIRGenerator::G1SATBCardTableModRef_post_barrier(LIR_OprDesc* addr, LIR_OprDesc* new_val) { | |
1383 // If the "new_val" is a constant NULL, no barrier is necessary. | |
1384 if (new_val->is_constant() && | |
1385 new_val->as_constant_ptr()->as_jobject() == NULL) return; | |
1386 | |
1387 if (!new_val->is_register()) { | |
1572 | 1388 LIR_Opr new_val_reg = new_register(T_OBJECT); |
342 | 1389 if (new_val->is_constant()) { |
1390 __ move(new_val, new_val_reg); | |
1391 } else { | |
1392 __ leal(new_val, new_val_reg); | |
1393 } | |
1394 new_val = new_val_reg; | |
1395 } | |
1396 assert(new_val->is_register(), "must be a register at this point"); | |
1397 | |
1398 if (addr->is_address()) { | |
1399 LIR_Address* address = addr->as_address_ptr(); | |
1572 | 1400 LIR_Opr ptr = new_register(T_OBJECT); |
342 | 1401 if (!address->index()->is_valid() && address->disp() == 0) { |
1402 __ move(address->base(), ptr); | |
1403 } else { | |
1404 assert(address->disp() != max_jint, "lea doesn't support patched addresses!"); | |
1405 __ leal(addr, ptr); | |
1406 } | |
1407 addr = ptr; | |
1408 } | |
1409 assert(addr->is_register(), "must be a register at this point"); | |
1410 | |
1411 LIR_Opr xor_res = new_pointer_register(); | |
1412 LIR_Opr xor_shift_res = new_pointer_register(); | |
1413 if (TwoOperandLIRForm ) { | |
1414 __ move(addr, xor_res); | |
1415 __ logical_xor(xor_res, new_val, xor_res); | |
1416 __ move(xor_res, xor_shift_res); | |
1417 __ unsigned_shift_right(xor_shift_res, | |
1418 LIR_OprFact::intConst(HeapRegion::LogOfHRGrainBytes), | |
1419 xor_shift_res, | |
1420 LIR_OprDesc::illegalOpr()); | |
1421 } else { | |
1422 __ logical_xor(addr, new_val, xor_res); | |
1423 __ unsigned_shift_right(xor_res, | |
1424 LIR_OprFact::intConst(HeapRegion::LogOfHRGrainBytes), | |
1425 xor_shift_res, | |
1426 LIR_OprDesc::illegalOpr()); | |
1427 } | |
1428 | |
1429 if (!new_val->is_register()) { | |
1572 | 1430 LIR_Opr new_val_reg = new_register(T_OBJECT); |
342 | 1431 __ leal(new_val, new_val_reg); |
1432 new_val = new_val_reg; | |
1433 } | |
1434 assert(new_val->is_register(), "must be a register at this point"); | |
1435 | |
1436 __ cmp(lir_cond_notEqual, xor_shift_res, LIR_OprFact::intptrConst(NULL_WORD)); | |
1437 | |
1438 CodeStub* slow = new G1PostBarrierStub(addr, new_val); | |
1572 | 1439 __ branch(lir_cond_notEqual, LP64_ONLY(T_LONG) NOT_LP64(T_INT), slow); |
342 | 1440 __ branch_destination(slow->continuation()); |
1441 } | |
1442 | |
1443 #endif // SERIALGC | |
1444 //////////////////////////////////////////////////////////////////////// | |
1445 | |
0 | 1446 void LIRGenerator::CardTableModRef_post_barrier(LIR_OprDesc* addr, LIR_OprDesc* new_val) { |
1447 | |
342 | 1448 assert(sizeof(*((CardTableModRefBS*)_bs)->byte_map_base) == sizeof(jbyte), "adjust this code"); |
1449 LIR_Const* card_table_base = new LIR_Const(((CardTableModRefBS*)_bs)->byte_map_base); | |
0 | 1450 if (addr->is_address()) { |
1451 LIR_Address* address = addr->as_address_ptr(); | |
1452 LIR_Opr ptr = new_register(T_OBJECT); | |
1453 if (!address->index()->is_valid() && address->disp() == 0) { | |
1454 __ move(address->base(), ptr); | |
1455 } else { | |
1456 assert(address->disp() != max_jint, "lea doesn't support patched addresses!"); | |
1457 __ leal(addr, ptr); | |
1458 } | |
1459 addr = ptr; | |
1460 } | |
1461 assert(addr->is_register(), "must be a register at this point"); | |
1462 | |
1681
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
1463 #ifdef ARM |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
1464 // TODO: ARM - move to platform-dependent code |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
1465 LIR_Opr tmp = FrameMap::R14_opr; |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
1466 if (VM_Version::supports_movw()) { |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
1467 __ move((LIR_Opr)card_table_base, tmp); |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
1468 } else { |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
1469 __ 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
|
1470 } |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
1471 |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
1472 CardTableModRefBS* ct = (CardTableModRefBS*)_bs; |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
1473 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
|
1474 if(((int)ct->byte_map_base & 0xff) == 0) { |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
1475 __ move(tmp, card_addr); |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
1476 } else { |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
1477 LIR_Opr tmp_zero = new_register(T_INT); |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
1478 __ move(LIR_OprFact::intConst(0), tmp_zero); |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
1479 __ move(tmp_zero, card_addr); |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
1480 } |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
1481 #else // ARM |
0 | 1482 LIR_Opr tmp = new_pointer_register(); |
1483 if (TwoOperandLIRForm) { | |
1484 __ move(addr, tmp); | |
1485 __ unsigned_shift_right(tmp, CardTableModRefBS::card_shift, tmp); | |
1486 } else { | |
1487 __ unsigned_shift_right(addr, CardTableModRefBS::card_shift, tmp); | |
1488 } | |
1489 if (can_inline_as_constant(card_table_base)) { | |
1490 __ move(LIR_OprFact::intConst(0), | |
1491 new LIR_Address(tmp, card_table_base->as_jint(), T_BYTE)); | |
1492 } else { | |
1493 __ move(LIR_OprFact::intConst(0), | |
1494 new LIR_Address(tmp, load_constant(card_table_base), | |
1495 T_BYTE)); | |
1496 } | |
1681
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
1497 #endif // ARM |
0 | 1498 } |
1499 | |
1500 | |
1501 //------------------------field access-------------------------------------- | |
1502 | |
1503 // Comment copied form templateTable_i486.cpp | |
1504 // ---------------------------------------------------------------------------- | |
1505 // Volatile variables demand their effects be made known to all CPU's in | |
1506 // order. Store buffers on most chips allow reads & writes to reorder; the | |
1507 // JMM's ReadAfterWrite.java test fails in -Xint mode without some kind of | |
1508 // memory barrier (i.e., it's not sufficient that the interpreter does not | |
1509 // reorder volatile references, the hardware also must not reorder them). | |
1510 // | |
1511 // According to the new Java Memory Model (JMM): | |
1512 // (1) All volatiles are serialized wrt to each other. | |
1513 // ALSO reads & writes act as aquire & release, so: | |
1514 // (2) A read cannot let unrelated NON-volatile memory refs that happen after | |
1515 // the read float up to before the read. It's OK for non-volatile memory refs | |
1516 // that happen before the volatile read to float down below it. | |
1517 // (3) Similar a volatile write cannot let unrelated NON-volatile memory refs | |
1518 // that happen BEFORE the write float down to after the write. It's OK for | |
1519 // non-volatile memory refs that happen after the volatile write to float up | |
1520 // before it. | |
1521 // | |
1522 // We only put in barriers around volatile refs (they are expensive), not | |
1523 // _between_ memory refs (that would require us to track the flavor of the | |
1524 // previous memory refs). Requirements (2) and (3) require some barriers | |
1525 // before volatile stores and after volatile loads. These nearly cover | |
1526 // requirement (1) but miss the volatile-store-volatile-load case. This final | |
1527 // case is placed after volatile-stores although it could just as well go | |
1528 // before volatile-loads. | |
1529 | |
1530 | |
1531 void LIRGenerator::do_StoreField(StoreField* x) { | |
1532 bool needs_patching = x->needs_patching(); | |
1533 bool is_volatile = x->field()->is_volatile(); | |
1534 BasicType field_type = x->field_type(); | |
1535 bool is_oop = (field_type == T_ARRAY || field_type == T_OBJECT); | |
1536 | |
1537 CodeEmitInfo* info = NULL; | |
1538 if (needs_patching) { | |
1539 assert(x->explicit_null_check() == NULL, "can't fold null check into patching field access"); | |
1540 info = state_for(x, x->state_before()); | |
1541 } else if (x->needs_null_check()) { | |
1542 NullCheck* nc = x->explicit_null_check(); | |
1543 if (nc == NULL) { | |
1819 | 1544 info = state_for(x); |
0 | 1545 } else { |
1546 info = state_for(nc); | |
1547 } | |
1548 } | |
1549 | |
1550 | |
1551 LIRItem object(x->obj(), this); | |
1552 LIRItem value(x->value(), this); | |
1553 | |
1554 object.load_item(); | |
1555 | |
1556 if (is_volatile || needs_patching) { | |
1557 // load item if field is volatile (fewer special cases for volatiles) | |
1558 // load item if field not initialized | |
1559 // load item if field not constant | |
1560 // because of code patching we cannot inline constants | |
1561 if (field_type == T_BYTE || field_type == T_BOOLEAN) { | |
1562 value.load_byte_item(); | |
1563 } else { | |
1564 value.load_item(); | |
1565 } | |
1566 } else { | |
1567 value.load_for_store(field_type); | |
1568 } | |
1569 | |
1570 set_no_result(x); | |
1571 | |
1819 | 1572 #ifndef PRODUCT |
0 | 1573 if (PrintNotLoaded && needs_patching) { |
1574 tty->print_cr(" ###class not loaded at store_%s bci %d", | |
1819 | 1575 x->is_static() ? "static" : "field", x->printable_bci()); |
0 | 1576 } |
1819 | 1577 #endif |
0 | 1578 |
1579 if (x->needs_null_check() && | |
1580 (needs_patching || | |
1581 MacroAssembler::needs_explicit_null_check(x->offset()))) { | |
1582 // emit an explicit null check because the offset is too large | |
1583 __ null_check(object.result(), new CodeEmitInfo(info)); | |
1584 } | |
1585 | |
1586 LIR_Address* address; | |
1587 if (needs_patching) { | |
1588 // we need to patch the offset in the instruction so don't allow | |
1589 // generate_address to try to be smart about emitting the -1. | |
1590 // Otherwise the patching code won't know how to find the | |
1591 // instruction to patch. | |
1681
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
1592 address = new LIR_Address(object.result(), PATCHED_ADDR, field_type); |
0 | 1593 } else { |
1594 address = generate_address(object.result(), x->offset(), field_type); | |
1595 } | |
1596 | |
1597 if (is_volatile && os::is_MP()) { | |
1598 __ membar_release(); | |
1599 } | |
1600 | |
342 | 1601 if (is_oop) { |
1602 // Do the pre-write barrier, if any. | |
1603 pre_barrier(LIR_OprFact::address(address), | |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1604 LIR_OprFact::illegalOpr /* pre_val */, |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
1605 true /* do_load*/, |
342 | 1606 needs_patching, |
1607 (info ? new CodeEmitInfo(info) : NULL)); | |
1608 } | |
1609 | |
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
|
1610 if (is_volatile && !needs_patching) { |
0 | 1611 volatile_field_store(value.result(), address, info); |
1612 } else { | |
1613 LIR_PatchCode patch_code = needs_patching ? lir_patch_normal : lir_patch_none; | |
1614 __ store(value.result(), address, info, patch_code); | |
1615 } | |
1616 | |
1617 if (is_oop) { | |
819
c6386080541b
6849574: VM crash using NonBlockingHashMap (high_scale_lib)
never
parents:
780
diff
changeset
|
1618 // Store to object so mark the card of the header |
0 | 1619 post_barrier(object.result(), value.result()); |
1620 } | |
1621 | |
1622 if (is_volatile && os::is_MP()) { | |
1623 __ membar(); | |
1624 } | |
1625 } | |
1626 | |
1627 | |
1628 void LIRGenerator::do_LoadField(LoadField* x) { | |
1629 bool needs_patching = x->needs_patching(); | |
1630 bool is_volatile = x->field()->is_volatile(); | |
1631 BasicType field_type = x->field_type(); | |
1632 | |
1633 CodeEmitInfo* info = NULL; | |
1634 if (needs_patching) { | |
1635 assert(x->explicit_null_check() == NULL, "can't fold null check into patching field access"); | |
1636 info = state_for(x, x->state_before()); | |
1637 } else if (x->needs_null_check()) { | |
1638 NullCheck* nc = x->explicit_null_check(); | |
1639 if (nc == NULL) { | |
1819 | 1640 info = state_for(x); |
0 | 1641 } else { |
1642 info = state_for(nc); | |
1643 } | |
1644 } | |
1645 | |
1646 LIRItem object(x->obj(), this); | |
1647 | |
1648 object.load_item(); | |
1649 | |
1819 | 1650 #ifndef PRODUCT |
0 | 1651 if (PrintNotLoaded && needs_patching) { |
1652 tty->print_cr(" ###class not loaded at load_%s bci %d", | |
1819 | 1653 x->is_static() ? "static" : "field", x->printable_bci()); |
0 | 1654 } |
1819 | 1655 #endif |
0 | 1656 |
1657 if (x->needs_null_check() && | |
1658 (needs_patching || | |
1659 MacroAssembler::needs_explicit_null_check(x->offset()))) { | |
1660 // emit an explicit null check because the offset is too large | |
1661 __ null_check(object.result(), new CodeEmitInfo(info)); | |
1662 } | |
1663 | |
1664 LIR_Opr reg = rlock_result(x, field_type); | |
1665 LIR_Address* address; | |
1666 if (needs_patching) { | |
1667 // we need to patch the offset in the instruction so don't allow | |
1668 // generate_address to try to be smart about emitting the -1. | |
1669 // Otherwise the patching code won't know how to find the | |
1670 // instruction to patch. | |
1681
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
1671 address = new LIR_Address(object.result(), PATCHED_ADDR, field_type); |
0 | 1672 } else { |
1673 address = generate_address(object.result(), x->offset(), field_type); | |
1674 } | |
1675 | |
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
|
1676 if (is_volatile && !needs_patching) { |
0 | 1677 volatile_field_load(address, reg, info); |
1678 } else { | |
1679 LIR_PatchCode patch_code = needs_patching ? lir_patch_normal : lir_patch_none; | |
1680 __ load(address, reg, info, patch_code); | |
1681 } | |
1682 | |
1683 if (is_volatile && os::is_MP()) { | |
1684 __ membar_acquire(); | |
1685 } | |
1686 } | |
1687 | |
1688 | |
1689 //------------------------java.nio.Buffer.checkIndex------------------------ | |
1690 | |
1691 // int java.nio.Buffer.checkIndex(int) | |
1692 void LIRGenerator::do_NIOCheckIndex(Intrinsic* x) { | |
1693 // NOTE: by the time we are in checkIndex() we are guaranteed that | |
1694 // the buffer is non-null (because checkIndex is package-private and | |
1695 // only called from within other methods in the buffer). | |
1696 assert(x->number_of_arguments() == 2, "wrong type"); | |
1697 LIRItem buf (x->argument_at(0), this); | |
1698 LIRItem index(x->argument_at(1), this); | |
1699 buf.load_item(); | |
1700 index.load_item(); | |
1701 | |
1702 LIR_Opr result = rlock_result(x); | |
1703 if (GenerateRangeChecks) { | |
1704 CodeEmitInfo* info = state_for(x); | |
1705 CodeStub* stub = new RangeCheckStub(info, index.result(), true); | |
1706 if (index.result()->is_constant()) { | |
1707 cmp_mem_int(lir_cond_belowEqual, buf.result(), java_nio_Buffer::limit_offset(), index.result()->as_jint(), info); | |
1708 __ branch(lir_cond_belowEqual, T_INT, stub); | |
1709 } else { | |
1710 cmp_reg_mem(lir_cond_aboveEqual, index.result(), buf.result(), | |
1711 java_nio_Buffer::limit_offset(), T_INT, info); | |
1712 __ branch(lir_cond_aboveEqual, T_INT, stub); | |
1713 } | |
1714 __ move(index.result(), result); | |
1715 } else { | |
1716 // Just load the index into the result register | |
1717 __ move(index.result(), result); | |
1718 } | |
1719 } | |
1720 | |
1721 | |
1722 //------------------------array access-------------------------------------- | |
1723 | |
1724 | |
1725 void LIRGenerator::do_ArrayLength(ArrayLength* x) { | |
1726 LIRItem array(x->array(), this); | |
1727 array.load_item(); | |
1728 LIR_Opr reg = rlock_result(x); | |
1729 | |
1730 CodeEmitInfo* info = NULL; | |
1731 if (x->needs_null_check()) { | |
1732 NullCheck* nc = x->explicit_null_check(); | |
1733 if (nc == NULL) { | |
1734 info = state_for(x); | |
1735 } else { | |
1736 info = state_for(nc); | |
1737 } | |
1738 } | |
1739 __ load(new LIR_Address(array.result(), arrayOopDesc::length_offset_in_bytes(), T_INT), reg, info, lir_patch_none); | |
1740 } | |
1741 | |
1742 | |
1743 void LIRGenerator::do_LoadIndexed(LoadIndexed* x) { | |
1744 bool use_length = x->length() != NULL; | |
1745 LIRItem array(x->array(), this); | |
1746 LIRItem index(x->index(), this); | |
1747 LIRItem length(this); | |
1748 bool needs_range_check = true; | |
1749 | |
1750 if (use_length) { | |
1751 needs_range_check = x->compute_needs_range_check(); | |
1752 if (needs_range_check) { | |
1753 length.set_instruction(x->length()); | |
1754 length.load_item(); | |
1755 } | |
1756 } | |
1757 | |
1758 array.load_item(); | |
1759 if (index.is_constant() && can_inline_as_constant(x->index())) { | |
1760 // let it be a constant | |
1761 index.dont_load_item(); | |
1762 } else { | |
1763 index.load_item(); | |
1764 } | |
1765 | |
1766 CodeEmitInfo* range_check_info = state_for(x); | |
1767 CodeEmitInfo* null_check_info = NULL; | |
1768 if (x->needs_null_check()) { | |
1769 NullCheck* nc = x->explicit_null_check(); | |
1770 if (nc != NULL) { | |
1771 null_check_info = state_for(nc); | |
1772 } else { | |
1773 null_check_info = range_check_info; | |
1774 } | |
1775 } | |
1776 | |
1777 // emit array address setup early so it schedules better | |
1778 LIR_Address* array_addr = emit_array_address(array.result(), index.result(), x->elt_type(), false); | |
1779 | |
1780 if (GenerateRangeChecks && needs_range_check) { | |
1781 if (use_length) { | |
1782 // TODO: use a (modified) version of array_range_check that does not require a | |
1783 // constant length to be loaded to a register | |
1784 __ cmp(lir_cond_belowEqual, length.result(), index.result()); | |
1785 __ branch(lir_cond_belowEqual, T_INT, new RangeCheckStub(range_check_info, index.result())); | |
1786 } else { | |
1787 array_range_check(array.result(), index.result(), null_check_info, range_check_info); | |
1788 // The range check performs the null check, so clear it out for the load | |
1789 null_check_info = NULL; | |
1790 } | |
1791 } | |
1792 | |
1793 __ move(array_addr, rlock_result(x, x->elt_type()), null_check_info); | |
1794 } | |
1795 | |
1796 | |
1797 void LIRGenerator::do_NullCheck(NullCheck* x) { | |
1798 if (x->can_trap()) { | |
1799 LIRItem value(x->obj(), this); | |
1800 value.load_item(); | |
1801 CodeEmitInfo* info = state_for(x); | |
1802 __ null_check(value.result(), info); | |
1803 } | |
1804 } | |
1805 | |
1806 | |
1807 void LIRGenerator::do_Throw(Throw* x) { | |
1808 LIRItem exception(x->exception(), this); | |
1809 exception.load_item(); | |
1810 set_no_result(x); | |
1811 LIR_Opr exception_opr = exception.result(); | |
1812 CodeEmitInfo* info = state_for(x, x->state()); | |
1813 | |
1814 #ifndef PRODUCT | |
1815 if (PrintC1Statistics) { | |
1783 | 1816 increment_counter(Runtime1::throw_count_address(), T_INT); |
0 | 1817 } |
1818 #endif | |
1819 | |
1820 // check if the instruction has an xhandler in any of the nested scopes | |
1821 bool unwind = false; | |
1822 if (info->exception_handlers()->length() == 0) { | |
1823 // this throw is not inside an xhandler | |
1824 unwind = true; | |
1825 } else { | |
1826 // get some idea of the throw type | |
1827 bool type_is_exact = true; | |
1828 ciType* throw_type = x->exception()->exact_type(); | |
1829 if (throw_type == NULL) { | |
1830 type_is_exact = false; | |
1831 throw_type = x->exception()->declared_type(); | |
1832 } | |
1833 if (throw_type != NULL && throw_type->is_instance_klass()) { | |
1834 ciInstanceKlass* throw_klass = (ciInstanceKlass*)throw_type; | |
1835 unwind = !x->exception_handlers()->could_catch(throw_klass, type_is_exact); | |
1836 } | |
1837 } | |
1838 | |
1839 // do null check before moving exception oop into fixed register | |
1840 // to avoid a fixed interval with an oop during the null check. | |
1841 // Use a copy of the CodeEmitInfo because debug information is | |
1842 // different for null_check and throw. | |
1843 if (GenerateCompilerNullChecks && | |
1844 (x->exception()->as_NewInstance() == NULL && x->exception()->as_ExceptionObject() == NULL)) { | |
1845 // if the exception object wasn't created using new then it might be null. | |
1819 | 1846 __ null_check(exception_opr, new CodeEmitInfo(info, x->state()->copy(ValueStack::ExceptionState, x->state()->bci()))); |
0 | 1847 } |
1848 | |
1378
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1304
diff
changeset
|
1849 if (compilation()->env()->jvmti_can_post_on_exceptions()) { |
0 | 1850 // we need to go through the exception lookup path to get JVMTI |
1851 // notification done | |
1852 unwind = false; | |
1853 } | |
1854 | |
1855 // move exception oop into fixed register | |
1856 __ move(exception_opr, exceptionOopOpr()); | |
1857 | |
1858 if (unwind) { | |
1378
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1304
diff
changeset
|
1859 __ unwind_exception(exceptionOopOpr()); |
0 | 1860 } else { |
1861 __ throw_exception(exceptionPcOpr(), exceptionOopOpr(), info); | |
1862 } | |
1863 } | |
1864 | |
1865 | |
1866 void LIRGenerator::do_RoundFP(RoundFP* x) { | |
1867 LIRItem input(x->input(), this); | |
1868 input.load_item(); | |
1869 LIR_Opr input_opr = input.result(); | |
1870 assert(input_opr->is_register(), "why round if value is not in a register?"); | |
1871 assert(input_opr->is_single_fpu() || input_opr->is_double_fpu(), "input should be floating-point value"); | |
1872 if (input_opr->is_single_fpu()) { | |
1873 set_result(x, round_item(input_opr)); // This code path not currently taken | |
1874 } else { | |
1875 LIR_Opr result = new_register(T_DOUBLE); | |
1876 set_vreg_flag(result, must_start_in_memory); | |
1877 __ roundfp(input_opr, LIR_OprFact::illegalOpr, result); | |
1878 set_result(x, result); | |
1879 } | |
1880 } | |
1881 | |
1882 void LIRGenerator::do_UnsafeGetRaw(UnsafeGetRaw* x) { | |
1883 LIRItem base(x->base(), this); | |
1884 LIRItem idx(this); | |
1885 | |
1886 base.load_item(); | |
1887 if (x->has_index()) { | |
1888 idx.set_instruction(x->index()); | |
1889 idx.load_nonconstant(); | |
1890 } | |
1891 | |
1892 LIR_Opr reg = rlock_result(x, x->basic_type()); | |
1893 | |
1894 int log2_scale = 0; | |
1895 if (x->has_index()) { | |
1896 assert(x->index()->type()->tag() == intTag, "should not find non-int index"); | |
1897 log2_scale = x->log2_scale(); | |
1898 } | |
1899 | |
1900 assert(!x->has_index() || idx.value() == x->index(), "should match"); | |
1901 | |
1902 LIR_Opr base_op = base.result(); | |
1903 #ifndef _LP64 | |
1904 if (x->base()->type()->tag() == longTag) { | |
1905 base_op = new_register(T_INT); | |
1906 __ convert(Bytecodes::_l2i, base.result(), base_op); | |
1907 } else { | |
1908 assert(x->base()->type()->tag() == intTag, "must be"); | |
1909 } | |
1910 #endif | |
1911 | |
1912 BasicType dst_type = x->basic_type(); | |
1913 LIR_Opr index_op = idx.result(); | |
1914 | |
1915 LIR_Address* addr; | |
1916 if (index_op->is_constant()) { | |
1917 assert(log2_scale == 0, "must not have a scale"); | |
1918 addr = new LIR_Address(base_op, index_op->as_jint(), dst_type); | |
1919 } else { | |
304 | 1920 #ifdef X86 |
1060 | 1921 #ifdef _LP64 |
1922 if (!index_op->is_illegal() && index_op->type() == T_INT) { | |
1923 LIR_Opr tmp = new_pointer_register(); | |
1924 __ convert(Bytecodes::_i2l, index_op, tmp); | |
1925 index_op = tmp; | |
1926 } | |
1927 #endif | |
0 | 1928 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
|
1929 #elif defined(ARM) |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
1930 addr = generate_address(base_op, index_op, log2_scale, 0, dst_type); |
0 | 1931 #else |
1932 if (index_op->is_illegal() || log2_scale == 0) { | |
1060 | 1933 #ifdef _LP64 |
1934 if (!index_op->is_illegal() && index_op->type() == T_INT) { | |
1935 LIR_Opr tmp = new_pointer_register(); | |
1936 __ convert(Bytecodes::_i2l, index_op, tmp); | |
1937 index_op = tmp; | |
1938 } | |
1939 #endif | |
0 | 1940 addr = new LIR_Address(base_op, index_op, dst_type); |
1941 } else { | |
1060 | 1942 LIR_Opr tmp = new_pointer_register(); |
0 | 1943 __ shift_left(index_op, log2_scale, tmp); |
1944 addr = new LIR_Address(base_op, tmp, dst_type); | |
1945 } | |
1946 #endif | |
1947 } | |
1948 | |
1949 if (x->may_be_unaligned() && (dst_type == T_LONG || dst_type == T_DOUBLE)) { | |
1950 __ unaligned_move(addr, reg); | |
1951 } else { | |
2002 | 1952 if (dst_type == T_OBJECT && x->is_wide()) { |
1953 __ move_wide(addr, reg); | |
1954 } else { | |
1955 __ move(addr, reg); | |
1956 } | |
0 | 1957 } |
1958 } | |
1959 | |
1960 | |
1961 void LIRGenerator::do_UnsafePutRaw(UnsafePutRaw* x) { | |
1962 int log2_scale = 0; | |
1963 BasicType type = x->basic_type(); | |
1964 | |
1965 if (x->has_index()) { | |
1966 assert(x->index()->type()->tag() == intTag, "should not find non-int index"); | |
1967 log2_scale = x->log2_scale(); | |
1968 } | |
1969 | |
1970 LIRItem base(x->base(), this); | |
1971 LIRItem value(x->value(), this); | |
1972 LIRItem idx(this); | |
1973 | |
1974 base.load_item(); | |
1975 if (x->has_index()) { | |
1976 idx.set_instruction(x->index()); | |
1977 idx.load_item(); | |
1978 } | |
1979 | |
1980 if (type == T_BYTE || type == T_BOOLEAN) { | |
1981 value.load_byte_item(); | |
1982 } else { | |
1983 value.load_item(); | |
1984 } | |
1985 | |
1986 set_no_result(x); | |
1987 | |
1988 LIR_Opr base_op = base.result(); | |
1989 #ifndef _LP64 | |
1990 if (x->base()->type()->tag() == longTag) { | |
1991 base_op = new_register(T_INT); | |
1992 __ convert(Bytecodes::_l2i, base.result(), base_op); | |
1993 } else { | |
1994 assert(x->base()->type()->tag() == intTag, "must be"); | |
1995 } | |
1996 #endif | |
1997 | |
1998 LIR_Opr index_op = idx.result(); | |
1999 if (log2_scale != 0) { | |
2000 // temporary fix (platform dependent code without shift on Intel would be better) | |
1060 | 2001 index_op = new_pointer_register(); |
2002 #ifdef _LP64 | |
2003 if(idx.result()->type() == T_INT) { | |
2004 __ convert(Bytecodes::_i2l, idx.result(), index_op); | |
2005 } else { | |
2006 #endif | |
1681
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
2007 // TODO: ARM also allows embedded shift in the address |
1060 | 2008 __ move(idx.result(), index_op); |
2009 #ifdef _LP64 | |
2010 } | |
2011 #endif | |
0 | 2012 __ shift_left(index_op, log2_scale, index_op); |
2013 } | |
1060 | 2014 #ifdef _LP64 |
2015 else if(!index_op->is_illegal() && index_op->type() == T_INT) { | |
2016 LIR_Opr tmp = new_pointer_register(); | |
2017 __ convert(Bytecodes::_i2l, index_op, tmp); | |
2018 index_op = tmp; | |
2019 } | |
2020 #endif | |
0 | 2021 |
2022 LIR_Address* addr = new LIR_Address(base_op, index_op, x->basic_type()); | |
2023 __ move(value.result(), addr); | |
2024 } | |
2025 | |
2026 | |
2027 void LIRGenerator::do_UnsafeGetObject(UnsafeGetObject* x) { | |
2028 BasicType type = x->basic_type(); | |
2029 LIRItem src(x->object(), this); | |
2030 LIRItem off(x->offset(), this); | |
2031 | |
2032 off.load_item(); | |
2033 src.load_item(); | |
2034 | |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2035 LIR_Opr reg = rlock_result(x, x->basic_type()); |
0 | 2036 |
2123
df307487d610
7010665: Misplaced membar in C1 implementation of Unsafe.get/putXXX
dholmes
parents:
2007
diff
changeset
|
2037 get_Object_unsafe(reg, 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
|
2038 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2039 #ifndef SERIALGC |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2040 // 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
|
2041 // 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
|
2042 // 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
|
2043 // 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
|
2044 // |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2045 // 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
|
2046 // |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2047 // 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
|
2048 // if (src != NULL) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2049 // if (klass(src)->reference_type() != REF_NONE) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2050 // pre_barrier(..., reg, ...); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2051 // } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2052 // } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2053 // } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2054 // |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2055 // The first non-constant check of either the offset or |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2056 // the src operand will be done here; the remainder |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2057 // will take place in the generated code stub. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2058 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2059 if (UseG1GC && type == T_OBJECT) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2060 bool gen_code_stub = true; // Assume we need to generate the slow code stub. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2061 bool gen_offset_check = true; // Assume the code stub has to generate the offset guard. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2062 bool gen_source_check = true; // Assume the code stub has to check the src object for null. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2063 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2064 if (off.is_constant()) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2065 jint off_con = off.get_jint_constant(); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2066 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2067 if (off_con != java_lang_ref_Reference::referent_offset) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2068 // 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
|
2069 // 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
|
2070 // skip generation of the code stub. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2071 gen_code_stub = false; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2072 } else { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2073 // 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
|
2074 // 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
|
2075 gen_offset_check = false; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2076 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2077 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2078 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2079 // We don't need to generate stub if the source object is an array |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2080 if (gen_code_stub && src.type()->is_array()) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2081 gen_code_stub = false; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2082 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2083 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2084 if (gen_code_stub) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2085 // 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
|
2086 if (src.is_constant()) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2087 ciObject* src_con = src.get_jobject_constant(); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2088 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2089 if (src_con->is_null_object()) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2090 // 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
|
2091 // generating the code stub. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2092 gen_code_stub = false; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2093 } else { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2094 // 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
|
2095 // 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
|
2096 // null object check. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2097 gen_source_check = false; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2098 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2099 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2100 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2101 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2102 if (gen_code_stub) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2103 // Temoraries. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2104 LIR_Opr src_klass = new_register(T_OBJECT); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2105 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2106 // Get the thread pointer for the pre-barrier |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2107 LIR_Opr thread = getThreadPointer(); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2108 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2109 CodeStub* stub; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2110 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2111 // 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
|
2112 // the offset check. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2113 if (gen_offset_check) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2114 // if (offset == referent_offset) -> slow code stub |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2115 __ cmp(lir_cond_equal, off.result(), |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2116 LIR_OprFact::intConst(java_lang_ref_Reference::referent_offset)); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2117 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2118 // Optionally generate "src == null" check. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2119 stub = new G1UnsafeGetObjSATBBarrierStub(reg, src.result(), |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2120 src_klass, thread, |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2121 gen_source_check); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2122 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2123 __ branch(lir_cond_equal, T_INT, stub); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2124 } else { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2125 if (gen_source_check) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2126 // offset is a const and equals referent offset |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2127 // if (source != null) -> slow code stub |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2128 __ cmp(lir_cond_notEqual, src.result(), LIR_OprFact::oopConst(NULL)); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2129 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2130 // Since we are generating the "if src == null" guard here, |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2131 // there is no need to generate the "src == null" check again. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2132 stub = new G1UnsafeGetObjSATBBarrierStub(reg, src.result(), |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2133 src_klass, thread, |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2134 false); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2135 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2136 __ branch(lir_cond_notEqual, T_OBJECT, stub); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2137 } else { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2138 // We have statically determined that offset == referent_offset |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2139 // && src != null so we unconditionally branch to code stub |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2140 // to perform the guards and record reg in the SATB log buffer. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2141 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2142 stub = new G1UnsafeGetObjSATBBarrierStub(reg, src.result(), |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2143 src_klass, thread, |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2144 false); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2145 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2146 __ branch(lir_cond_always, T_ILLEGAL, stub); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2147 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2148 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2149 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2150 // Continuation point |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2151 __ branch_destination(stub->continuation()); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2152 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2153 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2154 #endif // SERIALGC |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2155 |
0 | 2156 if (x->is_volatile() && os::is_MP()) __ membar_acquire(); |
2157 } | |
2158 | |
2159 | |
2160 void LIRGenerator::do_UnsafePutObject(UnsafePutObject* x) { | |
2161 BasicType type = x->basic_type(); | |
2162 LIRItem src(x->object(), this); | |
2163 LIRItem off(x->offset(), this); | |
2164 LIRItem data(x->value(), this); | |
2165 | |
2166 src.load_item(); | |
2167 if (type == T_BOOLEAN || type == T_BYTE) { | |
2168 data.load_byte_item(); | |
2169 } else { | |
2170 data.load_item(); | |
2171 } | |
2172 off.load_item(); | |
2173 | |
2174 set_no_result(x); | |
2175 | |
2176 if (x->is_volatile() && os::is_MP()) __ membar_release(); | |
2177 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
|
2178 if (x->is_volatile() && os::is_MP()) __ membar(); |
0 | 2179 } |
2180 | |
2181 | |
2182 void LIRGenerator::do_UnsafePrefetch(UnsafePrefetch* x, bool is_store) { | |
2183 LIRItem src(x->object(), this); | |
2184 LIRItem off(x->offset(), this); | |
2185 | |
2186 src.load_item(); | |
2187 if (off.is_constant() && can_inline_as_constant(x->offset())) { | |
2188 // let it be a constant | |
2189 off.dont_load_item(); | |
2190 } else { | |
2191 off.load_item(); | |
2192 } | |
2193 | |
2194 set_no_result(x); | |
2195 | |
2196 LIR_Address* addr = generate_address(src.result(), off.result(), 0, 0, T_BYTE); | |
2197 __ prefetch(addr, is_store); | |
2198 } | |
2199 | |
2200 | |
2201 void LIRGenerator::do_UnsafePrefetchRead(UnsafePrefetchRead* x) { | |
2202 do_UnsafePrefetch(x, false); | |
2203 } | |
2204 | |
2205 | |
2206 void LIRGenerator::do_UnsafePrefetchWrite(UnsafePrefetchWrite* x) { | |
2207 do_UnsafePrefetch(x, true); | |
2208 } | |
2209 | |
2210 | |
2211 void LIRGenerator::do_SwitchRanges(SwitchRangeArray* x, LIR_Opr value, BlockBegin* default_sux) { | |
2212 int lng = x->length(); | |
2213 | |
2214 for (int i = 0; i < lng; i++) { | |
2215 SwitchRange* one_range = x->at(i); | |
2216 int low_key = one_range->low_key(); | |
2217 int high_key = one_range->high_key(); | |
2218 BlockBegin* dest = one_range->sux(); | |
2219 if (low_key == high_key) { | |
2220 __ cmp(lir_cond_equal, value, low_key); | |
2221 __ branch(lir_cond_equal, T_INT, dest); | |
2222 } else if (high_key - low_key == 1) { | |
2223 __ cmp(lir_cond_equal, value, low_key); | |
2224 __ branch(lir_cond_equal, T_INT, dest); | |
2225 __ cmp(lir_cond_equal, value, high_key); | |
2226 __ branch(lir_cond_equal, T_INT, dest); | |
2227 } else { | |
2228 LabelObj* L = new LabelObj(); | |
2229 __ cmp(lir_cond_less, value, low_key); | |
2230 __ branch(lir_cond_less, L->label()); | |
2231 __ cmp(lir_cond_lessEqual, value, high_key); | |
2232 __ branch(lir_cond_lessEqual, T_INT, dest); | |
2233 __ branch_destination(L->label()); | |
2234 } | |
2235 } | |
2236 __ jump(default_sux); | |
2237 } | |
2238 | |
2239 | |
2240 SwitchRangeArray* LIRGenerator::create_lookup_ranges(TableSwitch* x) { | |
2241 SwitchRangeList* res = new SwitchRangeList(); | |
2242 int len = x->length(); | |
2243 if (len > 0) { | |
2244 BlockBegin* sux = x->sux_at(0); | |
2245 int key = x->lo_key(); | |
2246 BlockBegin* default_sux = x->default_sux(); | |
2247 SwitchRange* range = new SwitchRange(key, sux); | |
2248 for (int i = 0; i < len; i++, key++) { | |
2249 BlockBegin* new_sux = x->sux_at(i); | |
2250 if (sux == new_sux) { | |
2251 // still in same range | |
2252 range->set_high_key(key); | |
2253 } else { | |
2254 // skip tests which explicitly dispatch to the default | |
2255 if (sux != default_sux) { | |
2256 res->append(range); | |
2257 } | |
2258 range = new SwitchRange(key, new_sux); | |
2259 } | |
2260 sux = new_sux; | |
2261 } | |
2262 if (res->length() == 0 || res->last() != range) res->append(range); | |
2263 } | |
2264 return res; | |
2265 } | |
2266 | |
2267 | |
2268 // we expect the keys to be sorted by increasing value | |
2269 SwitchRangeArray* LIRGenerator::create_lookup_ranges(LookupSwitch* x) { | |
2270 SwitchRangeList* res = new SwitchRangeList(); | |
2271 int len = x->length(); | |
2272 if (len > 0) { | |
2273 BlockBegin* default_sux = x->default_sux(); | |
2274 int key = x->key_at(0); | |
2275 BlockBegin* sux = x->sux_at(0); | |
2276 SwitchRange* range = new SwitchRange(key, sux); | |
2277 for (int i = 1; i < len; i++) { | |
2278 int new_key = x->key_at(i); | |
2279 BlockBegin* new_sux = x->sux_at(i); | |
2280 if (key+1 == new_key && sux == new_sux) { | |
2281 // still in same range | |
2282 range->set_high_key(new_key); | |
2283 } else { | |
2284 // skip tests which explicitly dispatch to the default | |
2285 if (range->sux() != default_sux) { | |
2286 res->append(range); | |
2287 } | |
2288 range = new SwitchRange(new_key, new_sux); | |
2289 } | |
2290 key = new_key; | |
2291 sux = new_sux; | |
2292 } | |
2293 if (res->length() == 0 || res->last() != range) res->append(range); | |
2294 } | |
2295 return res; | |
2296 } | |
2297 | |
2298 | |
2299 void LIRGenerator::do_TableSwitch(TableSwitch* x) { | |
2300 LIRItem tag(x->tag(), this); | |
2301 tag.load_item(); | |
2302 set_no_result(x); | |
2303 | |
2304 if (x->is_safepoint()) { | |
2305 __ safepoint(safepoint_poll_register(), state_for(x, x->state_before())); | |
2306 } | |
2307 | |
2308 // move values into phi locations | |
2309 move_to_phi(x->state()); | |
2310 | |
2311 int lo_key = x->lo_key(); | |
2312 int hi_key = x->hi_key(); | |
2313 int len = x->length(); | |
2314 LIR_Opr value = tag.result(); | |
2315 if (UseTableRanges) { | |
2316 do_SwitchRanges(create_lookup_ranges(x), value, x->default_sux()); | |
2317 } else { | |
2318 for (int i = 0; i < len; i++) { | |
2319 __ cmp(lir_cond_equal, value, i + lo_key); | |
2320 __ branch(lir_cond_equal, T_INT, x->sux_at(i)); | |
2321 } | |
2322 __ jump(x->default_sux()); | |
2323 } | |
2324 } | |
2325 | |
2326 | |
2327 void LIRGenerator::do_LookupSwitch(LookupSwitch* x) { | |
2328 LIRItem tag(x->tag(), this); | |
2329 tag.load_item(); | |
2330 set_no_result(x); | |
2331 | |
2332 if (x->is_safepoint()) { | |
2333 __ safepoint(safepoint_poll_register(), state_for(x, x->state_before())); | |
2334 } | |
2335 | |
2336 // move values into phi locations | |
2337 move_to_phi(x->state()); | |
2338 | |
2339 LIR_Opr value = tag.result(); | |
2340 if (UseTableRanges) { | |
2341 do_SwitchRanges(create_lookup_ranges(x), value, x->default_sux()); | |
2342 } else { | |
2343 int len = x->length(); | |
2344 for (int i = 0; i < len; i++) { | |
2345 __ cmp(lir_cond_equal, value, x->key_at(i)); | |
2346 __ branch(lir_cond_equal, T_INT, x->sux_at(i)); | |
2347 } | |
2348 __ jump(x->default_sux()); | |
2349 } | |
2350 } | |
2351 | |
2352 | |
2353 void LIRGenerator::do_Goto(Goto* x) { | |
2354 set_no_result(x); | |
2355 | |
2356 if (block()->next()->as_OsrEntry()) { | |
2357 // need to free up storage used for OSR entry point | |
2358 LIR_Opr osrBuffer = block()->next()->operand(); | |
2359 BasicTypeList signature; | |
2360 signature.append(T_INT); | |
2361 CallingConvention* cc = frame_map()->c_calling_convention(&signature); | |
2362 __ move(osrBuffer, cc->args()->at(0)); | |
2363 __ call_runtime_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::OSR_migration_end), | |
2364 getThreadTemp(), LIR_OprFact::illegalOpr, cc->args()); | |
2365 } | |
2366 | |
2367 if (x->is_safepoint()) { | |
2368 ValueStack* state = x->state_before() ? x->state_before() : x->state(); | |
2369 | |
2370 // increment backedge counter if needed | |
1783 | 2371 CodeEmitInfo* info = state_for(x, state); |
1819 | 2372 increment_backedge_counter(info, info->stack()->bci()); |
0 | 2373 CodeEmitInfo* safepoint_info = state_for(x, state); |
2374 __ safepoint(safepoint_poll_register(), safepoint_info); | |
2375 } | |
2376 | |
1783 | 2377 // Gotos can be folded Ifs, handle this case. |
2378 if (x->should_profile()) { | |
2379 ciMethod* method = x->profiled_method(); | |
2380 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
|
2381 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
|
2382 assert(md != NULL, "Sanity"); |
1783 | 2383 ciProfileData* data = md->bci_to_data(x->profiled_bci()); |
2384 assert(data != NULL, "must have profiling data"); | |
2385 int offset; | |
2386 if (x->direction() == Goto::taken) { | |
2387 assert(data->is_BranchData(), "need BranchData for two-way branches"); | |
2388 offset = md->byte_offset_of_slot(data, BranchData::taken_offset()); | |
2389 } else if (x->direction() == Goto::not_taken) { | |
2390 assert(data->is_BranchData(), "need BranchData for two-way branches"); | |
2391 offset = md->byte_offset_of_slot(data, BranchData::not_taken_offset()); | |
2392 } else { | |
2393 assert(data->is_JumpData(), "need JumpData for branches"); | |
2394 offset = md->byte_offset_of_slot(data, JumpData::taken_offset()); | |
2395 } | |
2396 LIR_Opr md_reg = new_register(T_OBJECT); | |
2397 __ oop2reg(md->constant_encoding(), md_reg); | |
2398 | |
2399 increment_counter(new LIR_Address(md_reg, offset, | |
2400 NOT_LP64(T_INT) LP64_ONLY(T_LONG)), DataLayout::counter_increment); | |
2401 } | |
2402 | |
0 | 2403 // emit phi-instruction move after safepoint since this simplifies |
2404 // describing the state as the safepoint. | |
2405 move_to_phi(x->state()); | |
2406 | |
2407 __ jump(x->default_sux()); | |
2408 } | |
2409 | |
2410 | |
2411 void LIRGenerator::do_Base(Base* x) { | |
2412 __ std_entry(LIR_OprFact::illegalOpr); | |
2413 // Emit moves from physical registers / stack slots to virtual registers | |
2414 CallingConvention* args = compilation()->frame_map()->incoming_arguments(); | |
2415 IRScope* irScope = compilation()->hir()->top_scope(); | |
2416 int java_index = 0; | |
2417 for (int i = 0; i < args->length(); i++) { | |
2418 LIR_Opr src = args->at(i); | |
2419 assert(!src->is_illegal(), "check"); | |
2420 BasicType t = src->type(); | |
2421 | |
2422 // Types which are smaller than int are passed as int, so | |
2423 // correct the type which passed. | |
2424 switch (t) { | |
2425 case T_BYTE: | |
2426 case T_BOOLEAN: | |
2427 case T_SHORT: | |
2428 case T_CHAR: | |
2429 t = T_INT; | |
2430 break; | |
2431 } | |
2432 | |
2433 LIR_Opr dest = new_register(t); | |
2434 __ move(src, dest); | |
2435 | |
2436 // Assign new location to Local instruction for this local | |
2437 Local* local = x->state()->local_at(java_index)->as_Local(); | |
2438 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
|
2439 #ifndef __SOFTFP__ |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
2440 // The java calling convention passes double as long and float as int. |
0 | 2441 assert(as_ValueType(t)->tag() == local->type()->tag(), "check"); |
1681
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
2442 #endif // __SOFTFP__ |
0 | 2443 local->set_operand(dest); |
2444 _instruction_for_operand.at_put_grow(dest->vreg_number(), local, NULL); | |
2445 java_index += type2size[t]; | |
2446 } | |
2447 | |
780
c96bf21b756f
6788527: Server vm intermittently fails with assertion "live value must not be garbage" with fastdebug bits
kvn
parents:
579
diff
changeset
|
2448 if (compilation()->env()->dtrace_method_probes()) { |
0 | 2449 BasicTypeList signature; |
2002 | 2450 signature.append(LP64_ONLY(T_LONG) NOT_LP64(T_INT)); // thread |
0 | 2451 signature.append(T_OBJECT); // methodOop |
2452 LIR_OprList* args = new LIR_OprList(); | |
2453 args->append(getThreadPointer()); | |
2454 LIR_Opr meth = new_register(T_OBJECT); | |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
819
diff
changeset
|
2455 __ oop2reg(method()->constant_encoding(), meth); |
0 | 2456 args->append(meth); |
2457 call_runtime(&signature, args, CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_entry), voidType, NULL); | |
2458 } | |
2459 | |
2460 if (method()->is_synchronized()) { | |
2461 LIR_Opr obj; | |
2462 if (method()->is_static()) { | |
2463 obj = new_register(T_OBJECT); | |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
819
diff
changeset
|
2464 __ oop2reg(method()->holder()->java_mirror()->constant_encoding(), obj); |
0 | 2465 } else { |
2466 Local* receiver = x->state()->local_at(0)->as_Local(); | |
2467 assert(receiver != NULL, "must already exist"); | |
2468 obj = receiver->operand(); | |
2469 } | |
2470 assert(obj->is_valid(), "must be valid"); | |
2471 | |
2472 if (method()->is_synchronized() && GenerateSynchronizationCode) { | |
2473 LIR_Opr lock = new_register(T_INT); | |
2474 __ load_stack_address_monitor(0, lock); | |
2475 | |
1819 | 2476 CodeEmitInfo* info = new CodeEmitInfo(scope()->start()->state()->copy(ValueStack::StateBefore, SynchronizationEntryBCI), NULL); |
0 | 2477 CodeStub* slow_path = new MonitorEnterStub(obj, lock, info); |
2478 | |
2479 // receiver is guaranteed non-NULL so don't need CodeEmitInfo | |
2480 __ lock_object(syncTempOpr(), obj, lock, new_register(T_OBJECT), slow_path, NULL); | |
2481 } | |
2482 } | |
2483 | |
2484 // increment invocation counters if needed | |
1783 | 2485 if (!method()->is_accessor()) { // Accessors do not have MDOs, so no counting. |
1825 | 2486 CodeEmitInfo* info = new CodeEmitInfo(scope()->start()->state()->copy(ValueStack::StateBefore, SynchronizationEntryBCI), NULL); |
1783 | 2487 increment_invocation_counter(info); |
2488 } | |
0 | 2489 |
2490 // all blocks with a successor must end with an unconditional jump | |
2491 // to the successor even if they are consecutive | |
2492 __ jump(x->default_sux()); | |
2493 } | |
2494 | |
2495 | |
2496 void LIRGenerator::do_OsrEntry(OsrEntry* x) { | |
2497 // construct our frame and model the production of incoming pointer | |
2498 // to the OSR buffer. | |
2499 __ osr_entry(LIR_Assembler::osrBufferPointer()); | |
2500 LIR_Opr result = rlock_result(x); | |
2501 __ move(LIR_Assembler::osrBufferPointer(), result); | |
2502 } | |
2503 | |
2504 | |
2505 void LIRGenerator::invoke_load_arguments(Invoke* x, LIRItemList* args, const LIR_OprList* arg_list) { | |
1295 | 2506 int i = (x->has_receiver() || x->is_invokedynamic()) ? 1 : 0; |
0 | 2507 for (; i < args->length(); i++) { |
2508 LIRItem* param = args->at(i); | |
2509 LIR_Opr loc = arg_list->at(i); | |
2510 if (loc->is_register()) { | |
2511 param->load_item_force(loc); | |
2512 } else { | |
2513 LIR_Address* addr = loc->as_address_ptr(); | |
2514 param->load_for_store(addr->type()); | |
2002 | 2515 if (addr->type() == T_OBJECT) { |
2516 __ move_wide(param->result(), addr); | |
2517 } else | |
2518 if (addr->type() == T_LONG || addr->type() == T_DOUBLE) { | |
2519 __ unaligned_move(param->result(), addr); | |
2520 } else { | |
2521 __ move(param->result(), addr); | |
2522 } | |
0 | 2523 } |
2524 } | |
2525 | |
2526 if (x->has_receiver()) { | |
2527 LIRItem* receiver = args->at(0); | |
2528 LIR_Opr loc = arg_list->at(0); | |
2529 if (loc->is_register()) { | |
2530 receiver->load_item_force(loc); | |
2531 } else { | |
2532 assert(loc->is_address(), "just checking"); | |
2533 receiver->load_for_store(T_OBJECT); | |
2002 | 2534 __ move_wide(receiver->result(), loc->as_address_ptr()); |
0 | 2535 } |
2536 } | |
2537 } | |
2538 | |
2539 | |
2540 // Visits all arguments, returns appropriate items without loading them | |
2541 LIRItemList* LIRGenerator::invoke_visit_arguments(Invoke* x) { | |
2542 LIRItemList* argument_items = new LIRItemList(); | |
2543 if (x->has_receiver()) { | |
2544 LIRItem* receiver = new LIRItem(x->receiver(), this); | |
2545 argument_items->append(receiver); | |
2546 } | |
1295 | 2547 if (x->is_invokedynamic()) { |
2548 // Insert a dummy for the synthetic MethodHandle argument. | |
2549 argument_items->append(NULL); | |
2550 } | |
0 | 2551 int idx = x->has_receiver() ? 1 : 0; |
2552 for (int i = 0; i < x->number_of_arguments(); i++) { | |
2553 LIRItem* param = new LIRItem(x->argument_at(i), this); | |
2554 argument_items->append(param); | |
2555 idx += (param->type()->is_double_word() ? 2 : 1); | |
2556 } | |
2557 return argument_items; | |
2558 } | |
2559 | |
2560 | |
2561 // The invoke with receiver has following phases: | |
2562 // a) traverse and load/lock receiver; | |
2563 // b) traverse all arguments -> item-array (invoke_visit_argument) | |
2564 // c) push receiver on stack | |
2565 // d) load each of the items and push on stack | |
2566 // e) unlock receiver | |
2567 // f) move receiver into receiver-register %o0 | |
2568 // g) lock result registers and emit call operation | |
2569 // | |
2570 // Before issuing a call, we must spill-save all values on stack | |
2571 // that are in caller-save register. "spill-save" moves thos registers | |
2572 // either in a free callee-save register or spills them if no free | |
2573 // callee save register is available. | |
2574 // | |
2575 // The problem is where to invoke spill-save. | |
2576 // - if invoked between e) and f), we may lock callee save | |
2577 // register in "spill-save" that destroys the receiver register | |
2578 // before f) is executed | |
2579 // - if we rearange the f) to be earlier, by loading %o0, it | |
2580 // may destroy a value on the stack that is currently in %o0 | |
2581 // and is waiting to be spilled | |
2582 // - if we keep the receiver locked while doing spill-save, | |
2583 // we cannot spill it as it is spill-locked | |
2584 // | |
2585 void LIRGenerator::do_Invoke(Invoke* x) { | |
2586 CallingConvention* cc = frame_map()->java_calling_convention(x->signature(), true); | |
2587 | |
2588 LIR_OprList* arg_list = cc->args(); | |
2589 LIRItemList* args = invoke_visit_arguments(x); | |
2590 LIR_Opr receiver = LIR_OprFact::illegalOpr; | |
2591 | |
2592 // setup result register | |
2593 LIR_Opr result_register = LIR_OprFact::illegalOpr; | |
2594 if (x->type() != voidType) { | |
2595 result_register = result_register_for(x->type()); | |
2596 } | |
2597 | |
2598 CodeEmitInfo* info = state_for(x, x->state()); | |
2599 | |
1295 | 2600 // invokedynamics can deoptimize. |
1304 | 2601 CodeEmitInfo* deopt_info = x->is_invokedynamic() ? state_for(x, x->state_before()) : NULL; |
1295 | 2602 |
0 | 2603 invoke_load_arguments(x, args, arg_list); |
2604 | |
2605 if (x->has_receiver()) { | |
2606 args->at(0)->load_item_force(LIR_Assembler::receiverOpr()); | |
2607 receiver = args->at(0)->result(); | |
2608 } | |
2609 | |
2610 // emit invoke code | |
2611 bool optimized = x->target_is_loaded() && x->target_is_final(); | |
2612 assert(receiver->is_illegal() || receiver->is_equal(LIR_Assembler::receiverOpr()), "must match"); | |
2613 | |
1564 | 2614 // JSR 292 |
2615 // Preserve the SP over MethodHandle call sites. | |
2616 ciMethod* target = x->target(); | |
2617 if (target->is_method_handle_invoke()) { | |
2618 info->set_is_method_handle_invoke(true); | |
2619 __ move(FrameMap::stack_pointer(), FrameMap::method_handle_invoke_SP_save_opr()); | |
2620 } | |
2621 | |
0 | 2622 switch (x->code()) { |
2623 case Bytecodes::_invokestatic: | |
1564 | 2624 __ call_static(target, result_register, |
0 | 2625 SharedRuntime::get_resolve_static_call_stub(), |
2626 arg_list, info); | |
2627 break; | |
2628 case Bytecodes::_invokespecial: | |
2629 case Bytecodes::_invokevirtual: | |
2630 case Bytecodes::_invokeinterface: | |
2631 // for final target we still produce an inline cache, in order | |
2632 // to be able to call mixed mode | |
2633 if (x->code() == Bytecodes::_invokespecial || optimized) { | |
1564 | 2634 __ call_opt_virtual(target, receiver, result_register, |
0 | 2635 SharedRuntime::get_resolve_opt_virtual_call_stub(), |
2636 arg_list, info); | |
2637 } else if (x->vtable_index() < 0) { | |
1564 | 2638 __ call_icvirtual(target, receiver, result_register, |
0 | 2639 SharedRuntime::get_resolve_virtual_call_stub(), |
2640 arg_list, info); | |
2641 } else { | |
2642 int entry_offset = instanceKlass::vtable_start_offset() + x->vtable_index() * vtableEntry::size(); | |
2643 int vtable_offset = entry_offset * wordSize + vtableEntry::method_offset_in_bytes(); | |
1564 | 2644 __ call_virtual(target, receiver, result_register, vtable_offset, arg_list, info); |
0 | 2645 } |
2646 break; | |
1295 | 2647 case Bytecodes::_invokedynamic: { |
2648 ciBytecodeStream bcs(x->scope()->method()); | |
1819 | 2649 bcs.force_bci(x->state()->bci()); |
1295 | 2650 assert(bcs.cur_bc() == Bytecodes::_invokedynamic, "wrong stream"); |
2651 ciCPCache* cpcache = bcs.get_cpcache(); | |
2652 | |
2653 // Get CallSite offset from constant pool cache pointer. | |
2654 int index = bcs.get_method_index(); | |
2655 size_t call_site_offset = cpcache->get_f1_offset(index); | |
2656 | |
2657 // If this invokedynamic call site hasn't been executed yet in | |
2658 // the interpreter, the CallSite object in the constant pool | |
2659 // cache is still null and we need to deoptimize. | |
2660 if (cpcache->is_f1_null_at(index)) { | |
2661 // Cannot re-use same xhandlers for multiple CodeEmitInfos, so | |
2662 // clone all handlers. This is handled transparently in other | |
2663 // places by the CodeEmitInfo cloning logic but is handled | |
2664 // specially here because a stub isn't being used. | |
2665 x->set_exception_handlers(new XHandlers(x->exception_handlers())); | |
2666 | |
2667 DeoptimizeStub* deopt_stub = new DeoptimizeStub(deopt_info); | |
2668 __ jump(deopt_stub); | |
2669 } | |
2670 | |
2671 // Use the receiver register for the synthetic MethodHandle | |
2672 // argument. | |
2673 receiver = LIR_Assembler::receiverOpr(); | |
2674 LIR_Opr tmp = new_register(objectType); | |
2675 | |
2676 // Load CallSite object from constant pool cache. | |
2677 __ oop2reg(cpcache->constant_encoding(), tmp); | |
2678 __ load(new LIR_Address(tmp, call_site_offset, T_OBJECT), tmp); | |
2679 | |
2680 // Load target MethodHandle from CallSite object. | |
2357
8033953d67ff
7012648: move JSR 292 to package java.lang.invoke and adjust names
jrose
parents:
2352
diff
changeset
|
2681 __ load(new LIR_Address(tmp, java_lang_invoke_CallSite::target_offset_in_bytes(), T_OBJECT), receiver); |
1295 | 2682 |
1564 | 2683 __ call_dynamic(target, receiver, result_register, |
1295 | 2684 SharedRuntime::get_resolve_opt_virtual_call_stub(), |
2685 arg_list, info); | |
2686 break; | |
2687 } | |
0 | 2688 default: |
2689 ShouldNotReachHere(); | |
2690 break; | |
2691 } | |
2692 | |
1564 | 2693 // JSR 292 |
2694 // Restore the SP after MethodHandle call sites. | |
2695 if (target->is_method_handle_invoke()) { | |
2696 __ move(FrameMap::method_handle_invoke_SP_save_opr(), FrameMap::stack_pointer()); | |
2697 } | |
2698 | |
0 | 2699 if (x->type()->is_float() || x->type()->is_double()) { |
2700 // Force rounding of results from non-strictfp when in strictfp | |
2701 // scope (or when we don't know the strictness of the callee, to | |
2702 // be safe.) | |
2703 if (method()->is_strict()) { | |
2704 if (!x->target_is_loaded() || !x->target_is_strictfp()) { | |
2705 result_register = round_item(result_register); | |
2706 } | |
2707 } | |
2708 } | |
2709 | |
2710 if (result_register->is_valid()) { | |
2711 LIR_Opr result = rlock_result(x); | |
2712 __ move(result_register, result); | |
2713 } | |
2714 } | |
2715 | |
2716 | |
2717 void LIRGenerator::do_FPIntrinsics(Intrinsic* x) { | |
2718 assert(x->number_of_arguments() == 1, "wrong type"); | |
2719 LIRItem value (x->argument_at(0), this); | |
2720 LIR_Opr reg = rlock_result(x); | |
2721 value.load_item(); | |
2722 LIR_Opr tmp = force_to_spill(value.result(), as_BasicType(x->type())); | |
2723 __ move(tmp, reg); | |
2724 } | |
2725 | |
2726 | |
2727 | |
2728 // Code for : x->x() {x->cond()} x->y() ? x->tval() : x->fval() | |
2729 void LIRGenerator::do_IfOp(IfOp* x) { | |
2730 #ifdef ASSERT | |
2731 { | |
2732 ValueTag xtag = x->x()->type()->tag(); | |
2733 ValueTag ttag = x->tval()->type()->tag(); | |
2734 assert(xtag == intTag || xtag == objectTag, "cannot handle others"); | |
2735 assert(ttag == addressTag || ttag == intTag || ttag == objectTag || ttag == longTag, "cannot handle others"); | |
2736 assert(ttag == x->fval()->type()->tag(), "cannot handle others"); | |
2737 } | |
2738 #endif | |
2739 | |
2740 LIRItem left(x->x(), this); | |
2741 LIRItem right(x->y(), this); | |
2742 left.load_item(); | |
2743 if (can_inline_as_constant(right.value())) { | |
2744 right.dont_load_item(); | |
2745 } else { | |
2746 right.load_item(); | |
2747 } | |
2748 | |
2749 LIRItem t_val(x->tval(), this); | |
2750 LIRItem f_val(x->fval(), this); | |
2751 t_val.dont_load_item(); | |
2752 f_val.dont_load_item(); | |
2753 LIR_Opr reg = rlock_result(x); | |
2754 | |
2755 __ 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
|
2756 __ cmove(lir_cond(x->cond()), t_val.result(), f_val.result(), reg, as_BasicType(x->x()->type())); |
0 | 2757 } |
2758 | |
2759 | |
2760 void LIRGenerator::do_Intrinsic(Intrinsic* x) { | |
2761 switch (x->id()) { | |
2762 case vmIntrinsics::_intBitsToFloat : | |
2763 case vmIntrinsics::_doubleToRawLongBits : | |
2764 case vmIntrinsics::_longBitsToDouble : | |
2765 case vmIntrinsics::_floatToRawIntBits : { | |
2766 do_FPIntrinsics(x); | |
2767 break; | |
2768 } | |
2769 | |
2770 case vmIntrinsics::_currentTimeMillis: { | |
2771 assert(x->number_of_arguments() == 0, "wrong type"); | |
2772 LIR_Opr reg = result_register_for(x->type()); | |
2773 __ call_runtime_leaf(CAST_FROM_FN_PTR(address, os::javaTimeMillis), getThreadTemp(), | |
2774 reg, new LIR_OprList()); | |
2775 LIR_Opr result = rlock_result(x); | |
2776 __ move(reg, result); | |
2777 break; | |
2778 } | |
2779 | |
2780 case vmIntrinsics::_nanoTime: { | |
2781 assert(x->number_of_arguments() == 0, "wrong type"); | |
2782 LIR_Opr reg = result_register_for(x->type()); | |
2783 __ call_runtime_leaf(CAST_FROM_FN_PTR(address, os::javaTimeNanos), getThreadTemp(), | |
2784 reg, new LIR_OprList()); | |
2785 LIR_Opr result = rlock_result(x); | |
2786 __ move(reg, result); | |
2787 break; | |
2788 } | |
2789 | |
2790 case vmIntrinsics::_Object_init: do_RegisterFinalizer(x); break; | |
2791 case vmIntrinsics::_getClass: do_getClass(x); break; | |
2792 case vmIntrinsics::_currentThread: do_currentThread(x); break; | |
2793 | |
2794 case vmIntrinsics::_dlog: // fall through | |
2795 case vmIntrinsics::_dlog10: // fall through | |
2796 case vmIntrinsics::_dabs: // fall through | |
2797 case vmIntrinsics::_dsqrt: // fall through | |
2798 case vmIntrinsics::_dtan: // fall through | |
2799 case vmIntrinsics::_dsin : // fall through | |
2800 case vmIntrinsics::_dcos : do_MathIntrinsic(x); break; | |
2801 case vmIntrinsics::_arraycopy: do_ArrayCopy(x); break; | |
2802 | |
2803 // java.nio.Buffer.checkIndex | |
2804 case vmIntrinsics::_checkIndex: do_NIOCheckIndex(x); break; | |
2805 | |
2806 case vmIntrinsics::_compareAndSwapObject: | |
2807 do_CompareAndSwap(x, objectType); | |
2808 break; | |
2809 case vmIntrinsics::_compareAndSwapInt: | |
2810 do_CompareAndSwap(x, intType); | |
2811 break; | |
2812 case vmIntrinsics::_compareAndSwapLong: | |
2813 do_CompareAndSwap(x, longType); | |
2814 break; | |
2815 | |
2816 // sun.misc.AtomicLongCSImpl.attemptUpdate | |
2817 case vmIntrinsics::_attemptUpdate: | |
2818 do_AttemptUpdate(x); | |
2819 break; | |
2820 | |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2821 case vmIntrinsics::_Reference_get: |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2822 do_Reference_get(x); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2823 break; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
2824 |
0 | 2825 default: ShouldNotReachHere(); break; |
2826 } | |
2827 } | |
2828 | |
2829 void LIRGenerator::do_ProfileCall(ProfileCall* x) { | |
2830 // Need recv in a temporary register so it interferes with the other temporaries | |
2831 LIR_Opr recv = LIR_OprFact::illegalOpr; | |
2832 LIR_Opr mdo = new_register(T_OBJECT); | |
1783 | 2833 // tmp is used to hold the counters on SPARC |
2834 LIR_Opr tmp = new_pointer_register(); | |
0 | 2835 if (x->recv() != NULL) { |
2836 LIRItem value(x->recv(), this); | |
2837 value.load_item(); | |
2838 recv = new_register(T_OBJECT); | |
2839 __ move(value.result(), recv); | |
2840 } | |
2841 __ profile_call(x->method(), x->bci_of_invoke(), mdo, recv, tmp, x->known_holder()); | |
2842 } | |
2843 | |
1783 | 2844 void LIRGenerator::do_ProfileInvoke(ProfileInvoke* x) { |
2845 // We can safely ignore accessors here, since c2 will inline them anyway, | |
2846 // accessors are also always mature. | |
2847 if (!x->inlinee()->is_accessor()) { | |
2848 CodeEmitInfo* info = state_for(x, x->state(), true); | |
2849 // Increment invocation counter, don't notify the runtime, because we don't inline loops, | |
2850 increment_event_counter_impl(info, x->inlinee(), 0, InvocationEntryBci, false, false); | |
2851 } | |
2852 } | |
2853 | |
2854 void LIRGenerator::increment_event_counter(CodeEmitInfo* info, int bci, bool backedge) { | |
2855 int freq_log; | |
2856 int level = compilation()->env()->comp_level(); | |
2857 if (level == CompLevel_limited_profile) { | |
2858 freq_log = (backedge ? Tier2BackedgeNotifyFreqLog : Tier2InvokeNotifyFreqLog); | |
2859 } else if (level == CompLevel_full_profile) { | |
2860 freq_log = (backedge ? Tier3BackedgeNotifyFreqLog : Tier3InvokeNotifyFreqLog); | |
2861 } else { | |
2862 ShouldNotReachHere(); | |
2863 } | |
2864 // Increment the appropriate invocation/backedge counter and notify the runtime. | |
2865 increment_event_counter_impl(info, info->scope()->method(), (1 << freq_log) - 1, bci, backedge, true); | |
0 | 2866 } |
2867 | |
1783 | 2868 void LIRGenerator::increment_event_counter_impl(CodeEmitInfo* info, |
2869 ciMethod *method, int frequency, | |
2870 int bci, bool backedge, bool notify) { | |
2871 assert(frequency == 0 || is_power_of_2(frequency + 1), "Frequency must be x^2 - 1 or 0"); | |
2872 int level = _compilation->env()->comp_level(); | |
2873 assert(level > CompLevel_simple, "Shouldn't be here"); | |
2874 | |
2875 int offset = -1; | |
2876 LIR_Opr counter_holder = new_register(T_OBJECT); | |
2877 LIR_Opr meth; | |
2878 if (level == CompLevel_limited_profile) { | |
2879 offset = in_bytes(backedge ? methodOopDesc::backedge_counter_offset() : | |
2880 methodOopDesc::invocation_counter_offset()); | |
2881 __ oop2reg(method->constant_encoding(), counter_holder); | |
2882 meth = counter_holder; | |
2883 } else if (level == CompLevel_full_profile) { | |
2884 offset = in_bytes(backedge ? methodDataOopDesc::backedge_counter_offset() : | |
2885 methodDataOopDesc::invocation_counter_offset()); | |
2007
5ddfcf4b079e
7003554: (tiered) assert(is_null_object() || handle() != NULL) failed: cannot embed null pointer
iveresov
parents:
2002
diff
changeset
|
2886 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
|
2887 assert(md != NULL, "Sanity"); |
5ddfcf4b079e
7003554: (tiered) assert(is_null_object() || handle() != NULL) failed: cannot embed null pointer
iveresov
parents:
2002
diff
changeset
|
2888 __ oop2reg(md->constant_encoding(), counter_holder); |
1783 | 2889 meth = new_register(T_OBJECT); |
2890 __ oop2reg(method->constant_encoding(), meth); | |
2891 } else { | |
2892 ShouldNotReachHere(); | |
2893 } | |
2894 LIR_Address* counter = new LIR_Address(counter_holder, offset, T_INT); | |
2895 LIR_Opr result = new_register(T_INT); | |
2896 __ load(counter, result); | |
2897 __ add(result, LIR_OprFact::intConst(InvocationCounter::count_increment), result); | |
2898 __ store(result, counter); | |
2899 if (notify) { | |
2900 LIR_Opr mask = load_immediate(frequency << InvocationCounter::count_shift, T_INT); | |
2901 __ logical_and(result, mask, result); | |
2902 __ cmp(lir_cond_equal, result, LIR_OprFact::intConst(0)); | |
2903 // The bci for info can point to cmp for if's we want the if bci | |
2904 CodeStub* overflow = new CounterOverflowStub(info, bci, meth); | |
2905 __ branch(lir_cond_equal, T_INT, overflow); | |
2906 __ branch_destination(overflow->continuation()); | |
2907 } | |
2908 } | |
0 | 2909 |
2166
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2089
diff
changeset
|
2910 void LIRGenerator::do_RuntimeCall(RuntimeCall* x) { |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2089
diff
changeset
|
2911 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
|
2912 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
|
2913 |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2089
diff
changeset
|
2914 if (x->pass_thread()) { |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2089
diff
changeset
|
2915 signature->append(T_ADDRESS); |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2089
diff
changeset
|
2916 args->append(getThreadPointer()); |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2089
diff
changeset
|
2917 } |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2089
diff
changeset
|
2918 |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2089
diff
changeset
|
2919 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
|
2920 Value a = x->argument_at(i); |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2089
diff
changeset
|
2921 LIRItem* item = new LIRItem(a, this); |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2089
diff
changeset
|
2922 item->load_item(); |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2089
diff
changeset
|
2923 args->append(item->result()); |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2089
diff
changeset
|
2924 signature->append(as_BasicType(a->type())); |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2089
diff
changeset
|
2925 } |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2089
diff
changeset
|
2926 |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2089
diff
changeset
|
2927 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
|
2928 if (x->type() == voidType) { |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2089
diff
changeset
|
2929 set_no_result(x); |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2089
diff
changeset
|
2930 } else { |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2089
diff
changeset
|
2931 __ move(result, rlock_result(x)); |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2089
diff
changeset
|
2932 } |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2089
diff
changeset
|
2933 } |
403dc4c1d7f5
6809483: hotspot:::method_entry are not correctly generated for "method()V"
never
parents:
2089
diff
changeset
|
2934 |
0 | 2935 LIR_Opr LIRGenerator::call_runtime(Value arg1, address entry, ValueType* result_type, CodeEmitInfo* info) { |
2936 LIRItemList args(1); | |
2937 LIRItem value(arg1, this); | |
2938 args.append(&value); | |
2939 BasicTypeList signature; | |
2940 signature.append(as_BasicType(arg1->type())); | |
2941 | |
2942 return call_runtime(&signature, &args, entry, result_type, info); | |
2943 } | |
2944 | |
2945 | |
2946 LIR_Opr LIRGenerator::call_runtime(Value arg1, Value arg2, address entry, ValueType* result_type, CodeEmitInfo* info) { | |
2947 LIRItemList args(2); | |
2948 LIRItem value1(arg1, this); | |
2949 LIRItem value2(arg2, this); | |
2950 args.append(&value1); | |
2951 args.append(&value2); | |
2952 BasicTypeList signature; | |
2953 signature.append(as_BasicType(arg1->type())); | |
2954 signature.append(as_BasicType(arg2->type())); | |
2955 | |
2956 return call_runtime(&signature, &args, entry, result_type, info); | |
2957 } | |
2958 | |
2959 | |
2960 LIR_Opr LIRGenerator::call_runtime(BasicTypeArray* signature, LIR_OprList* args, | |
2961 address entry, ValueType* result_type, CodeEmitInfo* info) { | |
2962 // get a result register | |
2963 LIR_Opr phys_reg = LIR_OprFact::illegalOpr; | |
2964 LIR_Opr result = LIR_OprFact::illegalOpr; | |
2965 if (result_type->tag() != voidTag) { | |
2966 result = new_register(result_type); | |
2967 phys_reg = result_register_for(result_type); | |
2968 } | |
2969 | |
2970 // move the arguments into the correct location | |
2971 CallingConvention* cc = frame_map()->c_calling_convention(signature); | |
2972 assert(cc->length() == args->length(), "argument mismatch"); | |
2973 for (int i = 0; i < args->length(); i++) { | |
2974 LIR_Opr arg = args->at(i); | |
2975 LIR_Opr loc = cc->at(i); | |
2976 if (loc->is_register()) { | |
2977 __ move(arg, loc); | |
2978 } else { | |
2979 LIR_Address* addr = loc->as_address_ptr(); | |
2980 // if (!can_store_as_constant(arg)) { | |
2981 // LIR_Opr tmp = new_register(arg->type()); | |
2982 // __ move(arg, tmp); | |
2983 // arg = tmp; | |
2984 // } | |
2985 if (addr->type() == T_LONG || addr->type() == T_DOUBLE) { | |
2986 __ unaligned_move(arg, addr); | |
2987 } else { | |
2988 __ move(arg, addr); | |
2989 } | |
2990 } | |
2991 } | |
2992 | |
2993 if (info) { | |
2994 __ call_runtime(entry, getThreadTemp(), phys_reg, cc->args(), info); | |
2995 } else { | |
2996 __ call_runtime_leaf(entry, getThreadTemp(), phys_reg, cc->args()); | |
2997 } | |
2998 if (result->is_valid()) { | |
2999 __ move(phys_reg, result); | |
3000 } | |
3001 return result; | |
3002 } | |
3003 | |
3004 | |
3005 LIR_Opr LIRGenerator::call_runtime(BasicTypeArray* signature, LIRItemList* args, | |
3006 address entry, ValueType* result_type, CodeEmitInfo* info) { | |
3007 // get a result register | |
3008 LIR_Opr phys_reg = LIR_OprFact::illegalOpr; | |
3009 LIR_Opr result = LIR_OprFact::illegalOpr; | |
3010 if (result_type->tag() != voidTag) { | |
3011 result = new_register(result_type); | |
3012 phys_reg = result_register_for(result_type); | |
3013 } | |
3014 | |
3015 // move the arguments into the correct location | |
3016 CallingConvention* cc = frame_map()->c_calling_convention(signature); | |
3017 | |
3018 assert(cc->length() == args->length(), "argument mismatch"); | |
3019 for (int i = 0; i < args->length(); i++) { | |
3020 LIRItem* arg = args->at(i); | |
3021 LIR_Opr loc = cc->at(i); | |
3022 if (loc->is_register()) { | |
3023 arg->load_item_force(loc); | |
3024 } else { | |
3025 LIR_Address* addr = loc->as_address_ptr(); | |
3026 arg->load_for_store(addr->type()); | |
3027 if (addr->type() == T_LONG || addr->type() == T_DOUBLE) { | |
3028 __ unaligned_move(arg->result(), addr); | |
3029 } else { | |
3030 __ move(arg->result(), addr); | |
3031 } | |
3032 } | |
3033 } | |
3034 | |
3035 if (info) { | |
3036 __ call_runtime(entry, getThreadTemp(), phys_reg, cc->args(), info); | |
3037 } else { | |
3038 __ call_runtime_leaf(entry, getThreadTemp(), phys_reg, cc->args()); | |
3039 } | |
3040 if (result->is_valid()) { | |
3041 __ move(phys_reg, result); | |
3042 } | |
3043 return result; | |
3044 } |