Mercurial > hg > truffle
comparison src/share/vm/opto/compile.cpp @ 13045:94a83e0f9ce1
8017065: C2 allows safepoint checks to leak into G1 pre-barriers
Summary: Make all raw loads strictly respect control dependencies, make sure RCE doesn't move raw loads, add verification of G1 pre-barriers.
Reviewed-by: kvn, roland
author | iveresov |
---|---|
date | Tue, 05 Nov 2013 01:57:18 -0800 |
parents | b2ee5dc63353 |
children | 613e6a6fc328 |
comparison
equal
deleted
inserted
replaced
13044:a905d33ce13a | 13045:94a83e0f9ce1 |
---|---|
846 xtty->tail("ideal"); | 846 xtty->tail("ideal"); |
847 } | 847 } |
848 } | 848 } |
849 #endif | 849 #endif |
850 | 850 |
851 NOT_PRODUCT( verify_barriers(); ) | |
851 // Now that we know the size of all the monitors we can add a fixed slot | 852 // Now that we know the size of all the monitors we can add a fixed slot |
852 // for the original deopt pc. | 853 // for the original deopt pc. |
853 | 854 |
854 _orig_pc_slot = fixed_slots(); | 855 _orig_pc_slot = fixed_slots(); |
855 int next_slot = _orig_pc_slot + (sizeof(address) / VMRegImpl::stack_slot_size); | 856 int next_slot = _orig_pc_slot + (sizeof(address) / VMRegImpl::stack_slot_size); |
3366 } | 3367 } |
3367 assert(dead_nodes == 0, "using nodes must be reachable from root"); | 3368 assert(dead_nodes == 0, "using nodes must be reachable from root"); |
3368 } | 3369 } |
3369 } | 3370 } |
3370 } | 3371 } |
3372 | |
3373 // Verify GC barriers consistency | |
3374 // Currently supported: | |
3375 // - G1 pre-barriers (see GraphKit::g1_write_barrier_pre()) | |
3376 void Compile::verify_barriers() { | |
3377 if (UseG1GC) { | |
3378 // Verify G1 pre-barriers | |
3379 const int marking_offset = in_bytes(JavaThread::satb_mark_queue_offset() + PtrQueue::byte_offset_of_active()); | |
3380 | |
3381 ResourceArea *area = Thread::current()->resource_area(); | |
3382 Unique_Node_List visited(area); | |
3383 Node_List worklist(area); | |
3384 // We're going to walk control flow backwards starting from the Root | |
3385 worklist.push(_root); | |
3386 while (worklist.size() > 0) { | |
3387 Node* x = worklist.pop(); | |
3388 if (x == NULL || x == top()) continue; | |
3389 if (visited.member(x)) { | |
3390 continue; | |
3391 } else { | |
3392 visited.push(x); | |
3393 } | |
3394 | |
3395 if (x->is_Region()) { | |
3396 for (uint i = 1; i < x->req(); i++) { | |
3397 worklist.push(x->in(i)); | |
3398 } | |
3399 } else { | |
3400 worklist.push(x->in(0)); | |
3401 // We are looking for the pattern: | |
3402 // /->ThreadLocal | |
3403 // If->Bool->CmpI->LoadB->AddP->ConL(marking_offset) | |
3404 // \->ConI(0) | |
3405 // We want to verify that the If and the LoadB have the same control | |
3406 // See GraphKit::g1_write_barrier_pre() | |
3407 if (x->is_If()) { | |
3408 IfNode *iff = x->as_If(); | |
3409 if (iff->in(1)->is_Bool() && iff->in(1)->in(1)->is_Cmp()) { | |
3410 CmpNode *cmp = iff->in(1)->in(1)->as_Cmp(); | |
3411 if (cmp->Opcode() == Op_CmpI && cmp->in(2)->is_Con() && cmp->in(2)->bottom_type()->is_int()->get_con() == 0 | |
3412 && cmp->in(1)->is_Load()) { | |
3413 LoadNode* load = cmp->in(1)->as_Load(); | |
3414 if (load->Opcode() == Op_LoadB && load->in(2)->is_AddP() && load->in(2)->in(2)->Opcode() == Op_ThreadLocal | |
3415 && load->in(2)->in(3)->is_Con() | |
3416 && load->in(2)->in(3)->bottom_type()->is_intptr_t()->get_con() == marking_offset) { | |
3417 | |
3418 Node* if_ctrl = iff->in(0); | |
3419 Node* load_ctrl = load->in(0); | |
3420 | |
3421 if (if_ctrl != load_ctrl) { | |
3422 // Skip possible CProj->NeverBranch in infinite loops | |
3423 if ((if_ctrl->is_Proj() && if_ctrl->Opcode() == Op_CProj) | |
3424 && (if_ctrl->in(0)->is_MultiBranch() && if_ctrl->in(0)->Opcode() == Op_NeverBranch)) { | |
3425 if_ctrl = if_ctrl->in(0)->in(0); | |
3426 } | |
3427 } | |
3428 assert(load_ctrl != NULL && if_ctrl == load_ctrl, "controls must match"); | |
3429 } | |
3430 } | |
3431 } | |
3432 } | |
3433 } | |
3434 } | |
3435 } | |
3436 } | |
3437 | |
3371 #endif | 3438 #endif |
3372 | 3439 |
3373 // The Compile object keeps track of failure reasons separately from the ciEnv. | 3440 // The Compile object keeps track of failure reasons separately from the ciEnv. |
3374 // This is required because there is not quite a 1-1 relation between the | 3441 // This is required because there is not quite a 1-1 relation between the |
3375 // ciEnv and its compilation task and the Compile object. Note that one | 3442 // ciEnv and its compilation task and the Compile object. Note that one |