blob: 8a307f2c1cc6e67d85ce6314e8a77850ba934a95 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "verifier_common.h"
#include "verify_mutator_effect.h"
/*<-----------verify allocation----------------->*/
void verifier_init_allocation_verifier( Heap_Verifier* heap_verifier)
{
Allocation_Verifier* allocation_verifier = (Allocation_Verifier*)STD_MALLOC(sizeof(Allocation_Verifier));
assert(allocation_verifier);
memset(allocation_verifier, 0, sizeof(Allocation_Verifier));
allocation_verifier->size_nos_newobjs = allocation_verifier->num_nos_newobjs = 0;
allocation_verifier->size_los_newobjs = allocation_verifier->size_los_newobjs = 0;
allocation_verifier->size_nos_objs = allocation_verifier->num_nos_objs = 0;
allocation_verifier->size_los_objs = allocation_verifier->num_los_objs = 0;
allocation_verifier->last_size_los_objs = allocation_verifier->last_num_los_objs = 0;
allocation_verifier->new_objects_set = NULL;
allocation_verifier->new_objects_set
= verifier_free_set_pool_get_entry(heap_verifier->heap_verifier_metadata->free_set_pool);
heap_verifier->allocation_verifier = allocation_verifier;
}
void verifier_destruct_allocation_verifier(Heap_Verifier* heap_verifier)
{
//assert(heap_verifier->allocation_verifier->new_objects_set == NULL);
STD_FREE(heap_verifier->allocation_verifier);
heap_verifier->allocation_verifier = NULL;
}
void verify_allocation_reset(Heap_Verifier* heap_verifier)
{
Allocation_Verifier* alloc_verifier = heap_verifier->allocation_verifier;
GC_Gen* gc = (GC_Gen*)heap_verifier->gc;
Space* lspace = gc_get_los(gc);
alloc_verifier->size_los_objs = alloc_verifier->num_los_objs = 0;
verifier_scan_los_objects(lspace, heap_verifier);
alloc_verifier->last_size_los_objs = alloc_verifier->size_los_objs;
alloc_verifier->last_num_los_objs = alloc_verifier->num_los_objs;
alloc_verifier->size_nos_newobjs = alloc_verifier->num_nos_newobjs = 0;
alloc_verifier->size_los_newobjs = alloc_verifier->num_los_newobjs = 0;
alloc_verifier->size_nos_objs = alloc_verifier->num_nos_objs = 0;
alloc_verifier->size_los_objs = alloc_verifier->num_los_objs = 0;
assert(alloc_verifier->new_objects_set == NULL);
alloc_verifier->new_objects_set = verifier_free_set_pool_get_entry(verifier_metadata->free_set_pool);
assert(alloc_verifier->new_objects_set);
}
Boolean verify_new_object(New_Object* new_obj, Heap_Verifier* heap_verifier)
{
if(!heap_verifier->need_verify_allocation) return TRUE;
GC_Gen* gc =(GC_Gen*) heap_verifier->gc;
Space* mspace = gc_get_mos(gc);
assert(mspace);
if(obj_belongs_to_space(new_obj->address, mspace)){
assert(0);
printf("GC Verify ==> Verify Allocation: new Objects in MOS...\n ");
return FALSE;
}
Partial_Reveal_Object* p_newobj = new_obj->address;
if(obj_get_vt_raw(p_newobj) != new_obj->vt_raw){
assert(0);
printf("GC Verify ==> Verify Allocation: new Objects Vtable Error...\n ");
return FALSE;
}
if(vm_object_size(p_newobj) != new_obj->size){
assert(0);
printf("GC Verify ==> Verify Allocation: new Objects size Error...\n ");
return FALSE;
}
return TRUE;
}
void verify_allocation(Heap_Verifier* heap_verifier)
{
Allocation_Verifier* alloc_verifier = heap_verifier->allocation_verifier;
Heap_Verifier_Metadata* verifier_metadata = heap_verifier->heap_verifier_metadata;
pool_put_entry(verifier_metadata->new_objects_pool, alloc_verifier->new_objects_set);
alloc_verifier->new_objects_set = NULL;
GC_Gen* gc = (GC_Gen*)heap_verifier->gc;
Space* nspace = gc_get_nos(gc);
Space* lspace = gc_get_los(gc);
assert(nspace);
assert(lspace);
POINTER_SIZE_INT size_los_newobjs
= alloc_verifier->size_los_objs - alloc_verifier->last_size_los_objs;
POINTER_SIZE_INT num_los_newobjs
= alloc_verifier->num_los_objs - alloc_verifier->last_num_los_objs;
assert(alloc_verifier->size_nos_objs == alloc_verifier->size_nos_newobjs);
assert(alloc_verifier->num_nos_objs == alloc_verifier->num_nos_newobjs);
if(alloc_verifier->size_nos_objs != alloc_verifier->size_nos_newobjs){
printf("GC Verify ==> Verify Allocation: NOS new objects size error.\n");
alloc_verifier->is_verification_passed = FALSE;
}
if(alloc_verifier->num_nos_objs != alloc_verifier->num_nos_newobjs){
printf("GC Verify ==> Verify Allocation: NOS new objects number error.\n");
alloc_verifier->is_verification_passed = FALSE;
}
assert(size_los_newobjs == alloc_verifier->size_los_newobjs);
assert(num_los_newobjs == alloc_verifier->num_los_newobjs);
if(size_los_newobjs != alloc_verifier->size_los_newobjs){
printf("GC Verify ==> Verify Allocation: LOS new objects size error.\n");
alloc_verifier->is_verification_passed = FALSE;
}
if(num_los_newobjs != alloc_verifier->num_los_newobjs){
printf("GC Verify ==> Verify Allocation: LOS new objects number error.\n");
alloc_verifier->is_verification_passed = FALSE;
}
assert(alloc_verifier->new_objects_set == NULL);
Vector_Block* new_objects = pool_get_entry(verifier_metadata->new_objects_pool);
while(new_objects){
POINTER_SIZE_INT* iter = vector_block_iterator_init(new_objects);
while(!vector_block_iterator_end(new_objects, iter)){
New_Object* p_newobj = (New_Object*) *iter;
iter = vector_block_iterator_advance(new_objects, iter);
if(!verify_new_object(p_newobj, heap_verifier)){
assert(0);
printf("GC Verify ==> Verify Allocation: new objects verify error.\n");
alloc_verifier->is_verification_passed = FALSE;
}
STD_FREE(p_newobj);
}
vector_block_clear(new_objects);
pool_put_entry(verifier_metadata->free_set_pool, new_objects);
new_objects = pool_get_entry(verifier_metadata->new_objects_pool);
}
}
void verifier_allocation_update_info(Partial_Reveal_Object *p_obj, Heap_Verifier* heap_verifier)
{
if(!heap_verifier->need_verify_allocation) return;
Allocation_Verifier* alloc_verifier = heap_verifier->allocation_verifier;
GC_Gen* gc = (GC_Gen*)heap_verifier->gc;
Space* nspace = gc_get_nos(gc);
Space* mspace = gc_get_mos(gc);
Space* lspace = gc_get_los(gc);
assert(nspace);
assert(lspace);
if(obj_belongs_to_space(p_obj, nspace)){
alloc_verifier->size_nos_objs += vm_object_size(p_obj);
alloc_verifier->num_nos_objs ++;
return;
}else if(obj_belongs_to_space(p_obj, lspace)){
alloc_verifier->size_los_objs += vm_object_size(p_obj);
alloc_verifier->num_los_objs ++;
return;
}else if(obj_belongs_to_space(p_obj, mspace)){
return;
}
assert(0);
}
void verifier_event_mutator_allocate_newobj(Partial_Reveal_Object* p_newobj, POINTER_SIZE_INT size, VT vt_raw)
{
Heap_Verifier* heap_verifier = get_heap_verifier();
if(!heap_verifier->need_verify_allocation) return;
assert(p_newobj);
assert(obj_get_vt(p_newobj));
assert(obj_get_vt(p_newobj) == vt_raw);
New_Object* new_obj = (New_Object*) STD_MALLOC(sizeof(New_Object));
assert(new_obj);
new_obj->address = p_newobj;
new_obj->size = size;
new_obj->vt_raw = (VT) vt_raw;
Heap_Verifier_Metadata* verifier_metadata = heap_verifier->heap_verifier_metadata;
Allocation_Verifier* alloc_verifier = heap_verifier->allocation_verifier;
/*FIXME: Replace lock */
lock(alloc_verifier->alloc_lock);
verifier_set_push((void*)new_obj, alloc_verifier->new_objects_set, verifier_metadata->new_objects_pool);
GC_Gen* gc =(GC_Gen*) heap_verifier->gc;
Space* nspace = gc_get_nos(gc);
Space* lspace = gc_get_los(gc);
//FIXME:
//assert(size == vm_object_size(p_newobj));
if(obj_belongs_to_space(p_newobj, nspace)){
alloc_verifier->size_nos_newobjs += size;
alloc_verifier->num_nos_newobjs ++;
}else if (obj_belongs_to_space(p_newobj, lspace)){
alloc_verifier->size_los_newobjs += size;
alloc_verifier->num_los_newobjs ++;
}else{
assert(0);
alloc_verifier->is_verification_passed = FALSE;
}
unlock(alloc_verifier->alloc_lock);
}
/*<-----------verify root sets----------------->*/
/*FIXME: where should root set verifier be placed*/
/*The rootset set verifier is placed here, so the rootset verifier
verifys the rootset that vm enumerated before GC. The rootset
verifying processes before and after gc will be integrated in gc verifying pass,
the rootset verifying is considered as slot verifying while verifying heap. */
void verifier_init_rootset_verifier( Heap_Verifier* heap_verifier)
{
RootSet_Verifier* rs_verifier = (RootSet_Verifier*)STD_MALLOC(sizeof(RootSet_Verifier));
assert(rs_verifier);
memset(rs_verifier, 0, sizeof(RootSet_Verifier));
rs_verifier->num_slots_in_rootset = 0;
rs_verifier->num_error_slots = 0;
rs_verifier->is_verification_passed = FALSE;
heap_verifier->rootset_verifier = rs_verifier;
}
void verifier_destruct_rootset_verifier( Heap_Verifier* heap_verifier)
{
assert(heap_verifier != NULL);
assert(heap_verifier->rootset_verifier != NULL);
STD_FREE(heap_verifier->rootset_verifier);
heap_verifier->rootset_verifier = NULL;
}
void verifier_reset_rootset_verifier( Heap_Verifier* heap_verifier)
{
RootSet_Verifier* rootset_verifier = heap_verifier->rootset_verifier;
rootset_verifier->num_slots_in_rootset = 0;
rootset_verifier->num_error_slots = 0;
}
void verify_root_set(Heap_Verifier* heap_verifier)
{
assert(heap_verifier);
GC_Gen* gc = (GC_Gen*)heap_verifier->gc;
GC_Metadata* gc_metadata = gc->metadata;
assert(gc);
assert(gc_metadata);
assert(gc_metadata->gc_rootset_pool);
RootSet_Verifier* rootset_verifier = heap_verifier->rootset_verifier;
pool_iterator_init(gc_metadata->gc_rootset_pool);
Vector_Block* root_set = pool_iterator_next(gc_metadata->gc_rootset_pool);
/* first step: copy all root objects to trace tasks. */
while(root_set){
POINTER_SIZE_INT* iter = vector_block_iterator_init(root_set);
while(!vector_block_iterator_end(root_set,iter)){
REF* p_ref = (REF* )*iter;
iter = vector_block_iterator_advance(root_set,iter);
rootset_verifier->num_slots_in_rootset ++;
if(!verify_rootset_slot(p_ref, heap_verifier)){
rootset_verifier->is_verification_passed = FALSE;
rootset_verifier->num_error_slots ++;
assert(0);
continue;
}
}
root_set = pool_iterator_next(gc_metadata->gc_rootset_pool);
}
}
/*<-----------verify write barrier----------------->*/
void verifier_init_wb_verifier( Heap_Verifier* heap_verifier)
{
WriteBarrier_Verifier* wb_verifier = (WriteBarrier_Verifier*) STD_MALLOC(sizeof(WriteBarrier_Verifier));
assert(wb_verifier);
memset(wb_verifier, 0, sizeof(WriteBarrier_Verifier));
wb_verifier->num_ref_wb_after_scanning = 0;
wb_verifier->num_ref_wb_in_remset = 0;
wb_verifier->num_slots_in_remset = 0;
wb_verifier->is_verification_passed = FALSE;
heap_verifier->writebarrier_verifier = wb_verifier;
}
void verifier_destruct_wb_verifier( Heap_Verifier* heap_verifier)
{
assert(heap_verifier != NULL);
assert(heap_verifier->writebarrier_verifier != NULL);
STD_FREE(heap_verifier->writebarrier_verifier);
heap_verifier->writebarrier_verifier = NULL;
}
void verifier_reset_wb_verifier(Heap_Verifier* heap_verifier)
{
WriteBarrier_Verifier* wb_verifier = heap_verifier->writebarrier_verifier;
wb_verifier->num_ref_wb_after_scanning = 0;
wb_verifier->num_ref_wb_in_remset = 0;
wb_verifier->num_slots_in_remset = 0;
}
void verifier_mark_wb_slots(Heap_Verifier* heap_verifier)
{
GC_Gen* gc = (GC_Gen*)(heap_verifier->gc);
if(collect_is_major() ||!gc_is_gen_mode()) return;
GC_Metadata*gc_metadata = gc->metadata;
Space* nspace = gc_get_nos(gc);
WriteBarrier_Verifier* wb_verifier = heap_verifier->writebarrier_verifier;
assert(wb_verifier);
pool_iterator_init(gc_metadata->gc_rootset_pool);
Vector_Block* rem_set = pool_iterator_next(gc_metadata->gc_rootset_pool);
while(rem_set){
if(rem_set == gc->root_set) break;
POINTER_SIZE_INT* iter = vector_block_iterator_init(rem_set);
while(!vector_block_iterator_end(rem_set, iter)){
REF* p_ref = (REF* )*iter;
wb_verifier->num_slots_in_remset ++;
if(!address_belongs_to_space((void*)p_ref, nspace) && address_belongs_to_space(read_slot(p_ref), nspace)){
if(!wb_is_marked_in_slot(p_ref)){
wb_mark_in_slot(p_ref);
wb_verifier->num_ref_wb_in_remset ++;
}
}
iter = vector_block_iterator_advance(rem_set, iter);
}
rem_set = pool_iterator_next(gc_metadata->gc_rootset_pool);
}
}
void verify_write_barrier(REF* p_ref, Heap_Verifier* heap_verifier)
{
GC_Gen* gc = (GC_Gen*)heap_verifier->gc;
if(collect_is_major() ||!gc_is_gen_mode()) return;
Space* nspace = gc_get_nos(gc);
assert(address_belongs_to_gc_heap((void*)p_ref, (GC *) gc));
WriteBarrier_Verifier* wb_verifier = heap_verifier->writebarrier_verifier;
assert(wb_verifier);
if(!address_belongs_to_space((void*)p_ref, nspace) && address_belongs_to_space(read_slot(p_ref), nspace)){
if(!wb_is_marked_in_slot(p_ref)){
assert(0);
printf("GC Verify ==> Verify Write Barrier: unbuffered error!!!\n");
wb_verifier->is_verification_passed = FALSE;
}else{
wb_unmark_in_slot(p_ref);
wb_verifier->num_ref_wb_after_scanning ++;
}
return;
}else{
if(wb_is_marked_in_slot(p_ref)){
assert(0);
printf("GC Verify ==>Verify Write Barrier: buffered error!!!\n");
}
return;
}
}
/*<------------verify mutator effect common--------------->*/
void verifier_init_mutator_verifiers( Heap_Verifier* heap_verifier)
{
verifier_init_allocation_verifier(heap_verifier);
verifier_init_wb_verifier(heap_verifier);
verifier_init_rootset_verifier(heap_verifier);
}
void verifier_destruct_mutator_verifiers( Heap_Verifier* heap_verifier)
{
verifier_destruct_allocation_verifier(heap_verifier);
verifier_destruct_wb_verifier(heap_verifier);
verifier_destruct_rootset_verifier(heap_verifier);
}
void verifier_reset_mutator_verification(Heap_Verifier* heap_verifier)
{
heap_verifier->allocation_verifier->is_verification_passed = TRUE;
heap_verifier->writebarrier_verifier->is_verification_passed = TRUE;
heap_verifier->rootset_verifier->is_verification_passed = TRUE;
verifier_reset_wb_verifier(heap_verifier);
verifier_reset_rootset_verifier(heap_verifier);
if(heap_verifier->need_verify_writebarrier && heap_verifier->gc_is_gen_mode)
verifier_mark_wb_slots(heap_verifier);
}
void verifier_clear_mutator_verification(Heap_Verifier* heap_verifier)
{
if(heap_verifier->need_verify_allocation) verify_allocation_reset(heap_verifier);
}
void verify_mutator_effect(Heap_Verifier* heap_verifier)
{
if(heap_verifier->need_verify_rootset) verify_root_set(heap_verifier);
if(heap_verifier->need_verify_allocation) verify_allocation(heap_verifier);
}