static volatile int read_kernel_memory(long offset, int virtualized, int size) { int result; map_offset(offset, virtualized); int scaled_offset = (offset-(offset&~0xFFFF)); if(size==1) result = mem_8[scaled_offset/sizeof(char)]; else if(size==2) result = mem_16[scaled_offset/sizeof(short)]; else result = mem_32[scaled_offset/sizeof(long)]; return result; }
Label* CacheStub::prologue(bool immediateOnly) { assert(((Float_Tag | Int_Tag) & Mem_Tag) == 0, "tagging scheme changed"); Label* miss = NULL; Label* loadMapAfterHandlingImmediates = NULL; pc_t floatAddr, smiAddr; computeJumpAddr(nsmi, theSendDesc, stsmi, smiAddr); computeJumpAddr(nfloat, theSendDesc, stfloat, floatAddr); // put rcvr in Temp1 a->movl(esp, leaf_rcvr_offset * oopSize, NumberOperand, Temp1); // Load map if needed if (immediateOnly) ; else { a->btl(Mem_Tag_bit_i386, Temp1); loadMapAfterHandlingImmediates = new Label(a->printing); a->jc(loadMapAfterHandlingImmediates); // jump if memOop } if (nsmi && nfloat) { Label* not_smi = br_if_not_smi(); add_case(nsmi, stsmi, smiAddr); not_smi->define(); // if immediateOnly = false and we're down here, we've already tested for memOop // and hence there's no need to test for the float tag. if (immediateOnly) miss = br_if_not_float(); // br if mem else miss = NULL; add_case(nfloat, stfloat, floatAddr); } else if (nsmi) { miss = br_if_not_smi(); add_case(nsmi, stsmi, smiAddr); } else if (nfloat) { miss = br_if_not_float(); add_case(nfloat, stfloat, floatAddr); } else { // tested for Oop above, so rcvr is int or float, // but there are no smi or float cases, so must be a miss miss = new Label(a->printing); a->jmp(miss); } if (loadMapAfterHandlingImmediates) { loadMapAfterHandlingImmediates->define(); // CacheStub::test expects Temp1 to contain the receiver's map a->movl(Temp1, map_offset(), NumberOperand, Temp1); } return miss; }
fint CodeGen::verifyParents(objectLookupTarget* target, Location t, fint count) { a.Comment("verify"); assert(target->links != NULL, "expecting an assignable parent link"); for ( assignableSlotLink* l = target->links; ; ) { // load assignable parent slot value a.movl(t, smiOop(l->slot->data)->byte_count() - Mem_Tag, VMAddressOperand, Temp1); Label ok; Label miss; Map* targetMap = l->target->obj->map(); if (l->target->value_constrained) { // constraint for a particular oop (ambiguity resolution) loadOop(Temp2, l->target->obj); // load assumed value a.cmpl(Temp1, Temp2); // compare values a.je(&ok); // will branch } // check if map of parent is correct else if (targetMap == Memory->smi_map) { a.testl(Tag_Mask, NumberOperand, Temp1); // test for integer tag a.je( &ok ); // branch if parent is integer } else if (targetMap == Memory->float_map) { a.btl( Float_Tag_bit_i386, Temp1); // if bit set must be hit, otherwise is mark a.jc(&ok); // branch if parent is a float } else { // must be mem tag a.btl(Mem_Tag_bit_i386, Temp1); // if bit set must be hit, otherwise is mark a.jnc(&miss); // branch if parent is not mem oop a.movl(Temp1, map_offset(), NumberOperand, Temp2); // load receiver map a.cmpl((int32)targetMap->enclosing_mapOop(), OopOperand, Temp2); // cmp to map constraint a.je(&ok); // correct } miss.define(); // This will be backpatched to call an nmethod, so need to leave incoming link alone. // Must look like the original call to me plus extra info in regs // Pass a link to the branch and nmln in the DILinkReg. a.movl(count, NumberOperand, DICountReg); // count of parents verified // must align nmln to follow // There is a call coming, each 5 bytes, so want pc + 5 to be 0 mod 4. // See align * in asmDefs_gcc_i386.[sS] // get ic value to pass in, cannot use call cause of backpatching, etc. Label next; a.call(&next); next.define(); // two tasks: compute amount to add to savedPC so it simulates a call: must point to after the jmp below // Also, just add enough nops so that nmln after call is word-alligned fint bytes_from_here_to_after_jmp_before_alignment = 1 /* popl */ + 3 /* addl */ + 5 /* jmp */; int32 here = a.offset(); fint word_fraction_from_here_to_after_jmp_before_alignment = (here + bytes_from_here_to_after_jmp_before_alignment ) & 3; fint num_nops = (BytesPerWord - word_fraction_from_here_to_after_jmp_before_alignment) & (BytesPerWord-1); fint bytes_from_here_to_after_jmp = bytes_from_here_to_after_jmp_before_alignment + num_nops; for (fint i = 0; i < num_nops; ++i) a.nop(); a.popl(DIInlineCacheReg); // 1 byte, prepare to calculate IC addr below a.addl(bytes_from_here_to_after_jmp, NumberOperand, DIInlineCacheReg); // 3 bytes, finish calc IC addr below // following must be parsable to set_target_of_Self_call_site a.jmp( (int32)SendDIMessage_stub, DIVMAddressOperand); assert( a.offset() == here + bytes_from_here_to_after_jmp, "checking"); assert((a.offset() & (BytesPerWord-1)) == 0, "must be aligned"); a.Data(0); // first part of DI nmln a.Data(0); // second part of DI nmln a.hlt(); ok.define(); ++count; if (l->target->links) count = verifyParents(l->target, Temp1, count); l = l->next; if (l == 0) break; // if multiple dynamic parents, reload slot holder before looping (HACK!) t = loadPath(Temp1, target, LReceiverReg, Temp1); } return count; }
fint CodeGen::verifyParents(objectLookupTarget* target, Location t, fint count) { assignableSlotLink* l = target->links; assert(l != 0, "expecting an assignable parent link"); for (;;) { a.LoadI(t, smiOop(l->slot->data)->byte_count() - Mem_Tag, Temp1); // load assignable parent slot value Label* ok; Map* targetMap = l->target->obj->map(); if (l->target->value_constrained) { // constraint for a particular oop (ambiguity resolution) loadOop(Temp2, l->target->obj); // load assumed value a.SubCCR(Temp1, Temp2, G0); // compare values ok = a.BeqForward(false); // branch if value OK if (l->target->links) a.Nop(); } else { // check if map of parent is correct if (targetMap == Memory->smi_map) { a.AndCCI(Temp1, Tag_Mask, G0); // test for integer tag ok = a.BeqForward(false); // branch if parent is integer if (l->target->links) a.Nop(); } else if (targetMap == Memory->float_map) { a.AndCCI(Temp1, Float_Tag, G0); // test for float tag ok = a.BneForward(false); // branch if parent is a float if (l->target->links) a.Nop(); } else { Label* miss = NULL; if (!FastMapTest) { a.AndCCI(Temp1, Mem_Tag, G0); // test for mem tag Label* mem = a.BneForward(true); // branch if parent is mem oop a.LoadI(Temp1, map_offset(), Temp2); // load receiver map miss = a.BraForward(true); // branch to diLookup section mem->define(); } else { a.LoadI(Temp1, map_offset(), Temp2); // load receiver map } loadOop(Temp3, targetMap->enclosing_mapOop()); // load map constraint a.SubCCR(Temp2, Temp3, G0); // compare w/ parent's map ok = a.BeqForward(false); // correct if (l->target->links) a.Nop(); if (miss) miss->define(); } } void* addr = Memory->code->trapdoors->SendDIMessage_stub_td(); a.SetHiD(addr, Temp1); a.JmpLD(Temp1, addr, DILinkReg); loadImmediate(DICountReg, count); // count of parents verified a.Data(0); // first part of DI nmln a.Data(0); // second part of DI nmln ok->define(); count ++; if (l->target->links) count = verifyParents(l->target, Temp1, count); l = l->next; if (l == 0) break; // if multiple dynamic parents, reload slot holder before looping (HACK!) t = loadPath(Temp1, target, ReceiverReg, Temp1); } return count; }
fint TypeTestNode::prologue(Assembler* a, Location rcvr, fint smiIndex, fint floatIndex, bool immediateOnly, Label*& firstMemOopTest) { // handle immediate cases of type test and load map if necessary // smiIndex/Float are the indices of the smi/float case in the map list // (+ 1, so that "not present" == 0) // returns the index (+ 1) of the fall-through case assert(((Float_Tag | Int_Tag) & Mem_Tag) == 0, "tagging scheme changed"); assert(!immediateOnly || !needMapLoad, "immediateOnly implies !needMapLoad"); fint fallThrough = 0; if (needMapLoad) { if (!FastMapTest || smiIndex || floatIndex) { a->AndCCI(rcvr, Mem_Tag, G0); firstMemOopTest = a->BneForward(true); } a->LoadI(rcvr, map_offset(), RcvrMapReg); } if (smiIndex) { a->AndCCI(rcvr, Tag_Mask, G0); if (SICCountTypeTests) theAssembler->doOneTypeTest(); if (SICCountIntTagTests && immediateOnly) { // check if this tag test is on behalf of integer arithmetic methodMap* mm = (methodMap*)scope()->method()->map(); stringOop sel = mm->get_selector_at(bci()); bool isArith = (sel == VMString[PLUS] || sel == VMString[MINUS]); theAssembler->markTagTest(1, isArith); } define(smiIndex, a->BeqForward(SICCountTypeTests)); if (SICCountTypeTests) a->endTypeTest(); if (floatIndex) { a->AndCCI(rcvr, Float_Tag, G0); // test for float (delay slot) if (needMapLoad && !FastMapTest) { // already tested for memTag, so it must be a float fallThrough = floatIndex; } else { // need to test float tag // andcc rcvr, Float_Tag (done in delay slot of prev. test) if (SICCountTypeTests) theAssembler->doOneTypeTest(); define(floatIndex, a->BneForward(true)); if (SICCountTypeTests) { a->endTypeTest(); } else { a->Nop(); // must be here because next instr could be unimp } } } else { if (SICCountTypeTests) { // already filled delay slot } else { a->Nop(); // must be here because next instr could be unimp } } } else if (floatIndex) { a->AndCCI(rcvr, Float_Tag, G0); if (SICCountTypeTests) theAssembler->doOneTypeTest(); define(floatIndex, a->BneForward(true)); if (SICCountTypeTests) { a->endTypeTest(); // only executed in success case } else { a->Nop(); // must be here because next instr could be unimp } // if we get here, it must be an int (if needMapLoad) or a memOop (if // !needMapLoad), but we didn't expect this so jump to the unknown case define(0, a->BraForward(!SICCountTypeTests)); if (SICCountTypeTests) a->endTypeTest(); } else if (needMapLoad) { // neither int nor float case assert(maps->length(), "should have at least one memOop case"); if (FastMapTest) { // no test for memOop-ness, i.e. just fall through to first memOop case } else { // it's not a memOop and we have no immediate case, so jump to unknown assert(fallThrough == 0, "shouldn't have a fall-through"); define(0, a->BraForward(true)); } } else { // neither int not float nor mapLoad - empty prologue } return fallThrough; }
Label* CacheStub::prologue(bool immediateOnly) { // prologue: andcc rcvr, 1 // bnz,a _mapTest // load [rcvr+map_offset], t // *if nsmi // andcc rcvr, Tag_Mask // bne _next // <jmpl smi_addr> // *if nfloat // next: // <jmpl float_addr> // *endif float // *else if nfloat // andcc rcvr, Float_Mask // beq _next // <jmpl float_addr> // *endif // * if !(nsmi && nfloat) // next: // nop // bra,a _miss // *endif // mapTest: // setHi ..., t1 (may be delay slot) assert(((Float_Tag | Int_Tag) & Mem_Tag) == 0, "tagging scheme changed"); prevAddr = NULL; Label* result = NULL; Label* next = NULL; Label* mapTest = NULL; char *floatAddr, *smiAddr; computeJumpAddr(nsmi, theSendDesc, stsmi, smiAddr); computeJumpAddr(nfloat, theSendDesc, stfloat, floatAddr); if (immediateOnly) ; else if (FastMapTest && nsmi == NULL && nfloat == NULL) a->LoadI(ReceiverReg, map_offset(), Temp1); else { a->AndCCI(ReceiverReg, Mem_Tag, G0); mapTest = a->BneForward(true); a->LoadI(ReceiverReg, map_offset(), Temp1); // in delay slot, only do me if branch goes } if (nsmi) { n[newMethods] = nsmi; st[newMethods++] = stsmi; if (SICCountIntTagTests) a->markTagTest(1); a->AndCCI(ReceiverReg, Tag_Mask, G0); next = a->BneForward(true); a->AndCCI(ReceiverReg, Float_Tag, G0); // test for float (delay slot) jump(smiAddr); a->Nop(); if (nfloat) { n[newMethods] = nfloat; st[newMethods++] = stfloat; next->define(); if (immediateOnly) { // need to test float tag (test done in delay slot of int case) result = a->BeqForward(false); } else { // already tested for memTag, so it must be a float } jump(floatAddr); a->Nop(); } else { result = next; } } else if (nfloat) { n[newMethods] = nfloat; st[newMethods++] = stfloat; a->AndCCI(ReceiverReg, Float_Tag, G0); result = a->BeqForward(false); jump(floatAddr); a->Nop(); } else { assert(!nsmi && !nfloat, "just checkin'"); if (next) next->define(); if (FastMapTest) { assert(!next && !mapTest, "should not be set"); } else { result = a->BraForward(true); } } if (mapTest) mapTest->define(); return result; }
bool isMapLoad(int* instp) { return isLoadWord(instp) && getArithImm(instp) == map_offset(); }