Index: jitrino/src/codegenerator/CodeGenIntfc.h =================================================================== --- jitrino/src/codegenerator/CodeGenIntfc.h (revision 465123) +++ jitrino/src/codegenerator/CodeGenIntfc.h (working copy) @@ -405,6 +405,11 @@ CG_OpndHandle* tauBaseNonNull, CG_OpndHandle* tauAddressInRange, CG_OpndHandle* tauElemTypeChecked) = 0; + virtual void tau_stRef(CG_OpndHandle* src, CG_OpndHandle* ptr, CG_OpndHandle* base, Type::Tag memType, + bool autoCompressRef, + CG_OpndHandle* tauBaseNonNull, + CG_OpndHandle* tauAddressInRange, + CG_OpndHandle* tauElemTypeChecked) = 0; // COMPRESSED_PTR note: var is already uncompressed, so compression doesn't affect it virtual void stVar(CG_OpndHandle* src, uint32 varId) = 0; Index: jitrino/src/codegenerator/ia32/Ia32InstCodeSelector.cpp =================================================================== --- jitrino/src/codegenerator/ia32/Ia32InstCodeSelector.cpp (revision 465123) +++ jitrino/src/codegenerator/ia32/Ia32InstCodeSelector.cpp (working copy) @@ -2102,6 +2102,22 @@ return simpleStInd((Opnd*)ptr, (Opnd*)src, memType, autoCompressRef, (Opnd*)tauBaseNonNull, (Opnd*)tauElemTypeChecked); } +void InstCodeSelector::tau_stRef(CG_OpndHandle* src, + CG_OpndHandle* ptr, + CG_OpndHandle* base, + Type::Tag memType, + bool autoCompressRef, + CG_OpndHandle* tauBaseNonNull, + CG_OpndHandle* tauAddressInRange, + CG_OpndHandle* tauElemTypeChecked) +{ + Opnd* helperOpnds[] = {(Opnd*)base,(Opnd*)ptr,(Opnd*)src}; + CallInst * callInst = irManager.newRuntimeHelperCallInst( + CompilationInterface::Helper_WriteBarrier, + 3,helperOpnds,NULL); + appendInsts(callInst); +} + //_______________________________________________________________________________________________________________ // Load variable address Index: jitrino/src/codegenerator/ia32/Ia32InstCodeSelector.h =================================================================== --- jitrino/src/codegenerator/ia32/Ia32InstCodeSelector.h (revision 465123) +++ jitrino/src/codegenerator/ia32/Ia32InstCodeSelector.h (working copy) @@ -186,6 +186,10 @@ void tau_stElem(CG_OpndHandle* src,CG_OpndHandle* array, CG_OpndHandle* index, bool autoCompressRef, CG_OpndHandle* tauBaseNonNull, CG_OpndHandle* tauAddressInRange, CG_OpndHandle* tauElemTypeChecked); + void tau_stRef(CG_OpndHandle* src, CG_OpndHandle* ptr, CG_OpndHandle* base, Type::Tag memType, + bool autoCompressRef, CG_OpndHandle* tauBaseNonNull, + CG_OpndHandle* tauAddressInRange, CG_OpndHandle* tauElemTypeChecked); + void stVar(CG_OpndHandle* src, uint32 varId); CG_OpndHandle* newObj(ObjectType* objType); CG_OpndHandle* newArray(ArrayType* arrayType, CG_OpndHandle* numElems); Index: jitrino/src/dynopt/StaticProfiler.cpp =================================================================== --- jitrino/src/dynopt/StaticProfiler.cpp (revision 465123) +++ jitrino/src/dynopt/StaticProfiler.cpp (working copy) @@ -555,8 +555,8 @@ static double storeHeuristic(const StaticProfilerContext* c) { Node* node1 = c->edge1->getTargetNode(); Node* node2 = c->edge2->getTargetNode(); - bool node1Accepted = findInst(node1, Op_TauStInd)!=NULL; - bool node2Accepted = findInst(node2, Op_TauStInd)!=NULL; + bool node1Accepted = (findInst(node1, Op_TauStInd)!=NULL||findInst(node1, Op_TauStRef)!=NULL); + bool node2Accepted = (findInst(node2, Op_TauStInd)!=NULL||findInst(node2, Op_TauStRef)!=NULL); if (!node1Accepted && !node2Accepted) { return PROB_HEURISTIC_FAIL; } Index: jitrino/src/optimizer/CodeGenerator.cpp =================================================================== --- jitrino/src/optimizer/CodeGenerator.cpp (revision 465123) +++ jitrino/src/optimizer/CodeGenerator.cpp (working copy) @@ -1520,6 +1520,42 @@ getCGInst(tauElemTypeChecked)); } break; + case Op_TauStRef: + { + assert(inst->getNumSrcOperands() == 6); + + Opnd *src = inst->getSrc(0); + Opnd *ptr = inst->getSrc(1); + Opnd *base = inst->getSrc(2); + + Opnd *tauNonNullBase = inst->getSrc(3); + Opnd *tauTypeHasField = inst->getSrc(4); + Opnd *tauFieldTypeChecked = inst->getSrc(5); + + assert(tauNonNullBase->getType()->tag == Type::Tau); + assert(tauTypeHasField->getType()->tag == Type::Tau); + assert(tauFieldTypeChecked->getType()->tag == Type::Tau); + + AutoCompressModifier acmod = inst->getAutoCompressModifier(); + StoreModifier UNUSED stmod = inst->getStoreModifier(); + + bool autocompress = (acmod == AutoCompress_Yes); + Type::Tag type = inst->getType(); + if (acmod == AutoCompress_Yes) { + assert(Type::isReference(type)); + assert(!Type::isCompressedReference(type)); + } + assert(stmod == Store_WriteBarrier); + instructionCallback.tau_stRef(getCGInst(src), + getCGInst(ptr), + getCGInst(base), + type, + autocompress, + getCGInst(tauNonNullBase), + getCGInst(tauTypeHasField), + getCGInst(tauFieldTypeChecked)); + } + break; case Op_TauCheckBounds: { assert(inst->getNumSrcOperands() == 2); Index: jitrino/src/optimizer/hashvaluenumberer.cpp =================================================================== --- jitrino/src/optimizer/hashvaluenumberer.cpp (revision 465123) +++ jitrino/src/optimizer/hashvaluenumberer.cpp (working copy) @@ -300,7 +300,7 @@ if (memOpt) memOpt->remMemInst(inst); return res; } - } else if (res->getOpcode() == Op_TauStInd) { + } else if (res->getOpcode() == Op_TauStInd ||res->getOpcode() == Op_TauStRef) { if ((!memOpt) || memOpt->hasDefReachesUse(res, inst)) { if (memOpt) memOpt->remMemInst(inst); return res->getSrc(0)->getInst(); @@ -349,7 +349,7 @@ if (memOpt) memOpt->remMemInst(inst); dataOpnd = res->getDst(); } - } else if (res->getOpcode() == Op_TauStInd) { + } else if (res->getOpcode() == Op_TauStInd ||res->getOpcode() == Op_TauStRef) { if ((!memOpt) || memOpt->hasDefReachesUse(res, inst)) { if (memOpt) memOpt->remMemInst(inst); dataOpnd = res->getSrc(0); @@ -641,12 +641,48 @@ } } Inst* caseTauStRef(Inst* inst) { - if (memOpt) { - assert(0); // dunno what to do here. + bool is_final = false; + bool is_volatile = false; + { + Inst *ptrInst = inst->getSrc(1)->getInst(); + if ((ptrInst->getOpcode() == Op_LdFieldAddr) ) { + FieldAccessInst *faInst = ptrInst->asFieldAccessInst(); + FieldDesc *fd = faInst->getFieldDesc(); + is_volatile = fd->isVolatile(); + if (fd->isInitOnly()) { + is_final = true; + // first check for System stream final fields which vary + NamedType *td = fd->getParentType(); + if (strncmp(td->getName(),"java/lang/System",20)==0) { + const char *fdname = fd->getName(); + if ((strncmp(fdname,"in",5)==0) || + (strncmp(fdname,"out",5)==0) || + (strncmp(fdname,"err",5)==0)) { + is_final = false; + } + } + } + } + } + if ((cse_final && is_final) || (memOpt && !is_volatile)) { + Opnd *addrOp = inst->getSrc(1); + Type::Tag typetag = inst->getType(); + Operation op(Op_TauLdInd, typetag); + if (Log::isEnabled()) { + Log::out() << "StRef hashing Ldind : " + << (int) op.encodeForHashing() + << ", " + << (int) addrOp->getId() + << ::std::endl; + } + Modifier m(Modifier(inst->getAutoCompressModifier()) | Modifier(Speculative_No)); + setHashToInst(inst, getKey(Operation(Op_TauLdInd, inst->getType(), m), + addrOp->getId())); return inst; } else { return caseDefault(inst); } + } // checks Index: jitrino/src/optimizer/IRBuilder.cpp =================================================================== --- jitrino/src/optimizer/IRBuilder.cpp (revision 465123) +++ jitrino/src/optimizer/IRBuilder.cpp (working copy) @@ -2498,17 +2498,16 @@ !type->isCompressedReference()); Modifier compressMod = Modifier(compress ? AutoCompress_Yes : AutoCompress_No); - if (irBuilderFlags.insertWriteBarriers) { appendInst(instFactory->makeTauStRef((Modifier(Store_WriteBarrier)| compressMod), - type->tag, src, objectbase, ptr, + type->tag, src, ptr, objectbase, tauBaseNonNull, tauAddressInRange, tauElemTypeChecked)); } else { appendInst(instFactory->makeTauStRef((Modifier(Store_NoWriteBarrier)| compressMod), - type->tag, src, objectbase, ptr, + type->tag, src, ptr, objectbase, tauBaseNonNull, tauAddressInRange, tauElemTypeChecked)); } @@ -2534,7 +2533,7 @@ : genTauSafe()); // safe, not an object if (irBuilderFlags.expandMemAddrs) { // do not expand ldField of stack values Opnd *ptr = genLdFieldAddr(type, base, fieldDesc); - if (irBuilderFlags.insertWriteBarriers) { + if (irBuilderFlags.insertWriteBarriers && src->getType()->isObject()) { genTauStRef(type, base, ptr, src, tauBaseNonNull, tauBaseTypeIsOk, @@ -2625,7 +2624,7 @@ } else { ptr = genLdElemAddr(elemType, array, index); } - if (irBuilderFlags.insertWriteBarriers) { + if (irBuilderFlags.insertWriteBarriers && elemType->isObject()) { genTauStRef(elemType, array, ptr, src, tauNullChecked, tauAddressInRange, tauElemTypeChecked); } else { Index: jitrino/src/optimizer/lazyexceptionopt.cpp =================================================================== --- jitrino/src/optimizer/lazyexceptionopt.cpp (revision 465123) +++ jitrino/src/optimizer/lazyexceptionopt.cpp (working copy) @@ -1037,12 +1037,26 @@ if (inst_src1->getOpcode()==Op_LdFieldAddr ) return checkField(inst_src1); } - return true; + return true; + case Op_TauStRef: + { + Inst* inst_src1 = inst->getSrc(1)->getInst(); +#ifdef _DEBUG + if (Log::isEnabled()) { + Log::out() << " stref: "; + inst->print(Log::out()); Log::out() << std::endl; + Log::out() << " "; + inst_src1->print(Log::out()); Log::out() << std::endl; + } +#endif + if (inst_src1->getOpcode()==Op_LdFieldAddr ) + return checkField(inst_src1); + } + return true; case Op_TauStField: return true; // case Op_TauStElem: case Op_TauStStatic: - case Op_TauStRef: case Op_TauCheckBounds: case Op_TauCheckLowerBound: case Op_TauCheckUpperBound: Index: jitrino/src/optimizer/memoryopt.cpp =================================================================== --- jitrino/src/optimizer/memoryopt.cpp (revision 465123) +++ jitrino/src/optimizer/memoryopt.cpp (working copy) @@ -747,6 +747,12 @@ } break; + case Op_TauStRef: + { + thePass->effectWrite(n, i, i->getSrc(1)); + } + break; + case Op_TauCheckElemType: { thePass->effectReadVtable(n, i, i->getSrc(0)); // array @@ -971,8 +977,8 @@ case Op_PredBranch: break; - case Op_TauStRef: - assert(0); + //case Op_TauStRef: + // assert(0); case Op_TauLdField: case Op_LdStatic: @@ -2404,6 +2410,7 @@ case Op_TauStField: case Op_TauStStatic: case Op_TauStElem: + case Op_TauStRef: // maybe eliminate inst; break; default: @@ -2433,6 +2440,21 @@ } } break; + + case Op_TauStRef: + { + Opnd *usingAddr = usingInst->getSrc(1); + Opnd *thisAddr = inst->getSrc(1); + if ((usingAddr == thisAddr) && + (getBitWidth(usingInst->getType()) >= + getBitWidth(inst->getType()))) { + // eliminate inst; + thePass->remMemInst(inst); + inst->unlink(); + } + } + break; + case Op_TauStField: { Opnd *usingBase = usingInst->getSrc(1); Index: jitrino/src/optimizer/simplifier.cpp =================================================================== --- jitrino/src/optimizer/simplifier.cpp (revision 465123) +++ jitrino/src/optimizer/simplifier.cpp (working copy) @@ -3428,7 +3428,7 @@ Modifier mod = inst->getModifier(); assert(inst->getNumSrcOperands() == 6); Opnd *src = inst->getSrc(0); - Opnd *pointer = inst->getSrc(2); + Opnd *pointer = inst->getSrc(1); Type *ptrType = pointer->getType(); assert(ptrType->isPtr()); Index: jitrino/src/vm/drl/DrlVMInterface.cpp =================================================================== --- jitrino/src/vm/drl/DrlVMInterface.cpp (revision 465123) +++ jitrino/src/vm/drl/DrlVMInterface.cpp (working copy) @@ -583,6 +583,8 @@ case Helper_ConvDtoI64: vmHelperId = VM_RT_D2L; break; case Helper_MethodEntry: vmHelperId = VM_RT_JVMTI_METHOD_ENTER_CALLBACK; break; case Helper_MethodExit: vmHelperId = VM_RT_JVMTI_METHOD_EXIT_CALLBACK; break; + case Helper_WriteBarrier: vmHelperId = VM_RT_GC_HEAP_WRITE_REF; break; + default: assert(0); } @@ -646,7 +648,8 @@ CompilationInterface::VmCallingConvention DrlVMCompilationInterface::getRuntimeHelperCallingConvention(RuntimeHelperId id) { switch(id) { - case Helper_NewMultiArray: + case Helper_NewMultiArray: + case Helper_WriteBarrier: return CallingConvention_Cdecl; case Helper_ShlI64: case Helper_ShrI64: Index: jitrino/src/vm/VMInterface.cpp =================================================================== --- jitrino/src/vm/VMInterface.cpp (revision 465123) +++ jitrino/src/vm/VMInterface.cpp (working copy) @@ -103,6 +103,7 @@ DECL_HELPER_ITEM(GetSuspReqFlag), DECL_HELPER_ITEM(MethodEntry), DECL_HELPER_ITEM(MethodExit), + DECL_HELPER_ITEM(WriteBarrier), #undef DECL_HELPER_ITEM }; static const unsigned runtime_helpers_names_count = sizeof(runtime_helpers_names)/sizeof(runtime_helpers_names[0]); Index: jitrino/src/vm/VMInterface.h =================================================================== --- jitrino/src/vm/VMInterface.h (revision 465123) +++ jitrino/src/vm/VMInterface.h (working copy) @@ -374,6 +374,7 @@ Helper_GetSuspReqFlag,// int * = f() Helper_MethodEntry, // f(MethodHandle) Helper_MethodExit, // f(MethodHandle, void* ret_value) + Helper_WriteBarrier, Num_Helpers }; // Index: vmcore/src/thread/object_generic.cpp =================================================================== --- vmcore/src/thread/object_generic.cpp (revision 465123) +++ vmcore/src/thread/object_generic.cpp (working copy) @@ -151,6 +151,9 @@ exn_raise_object(VM_Global_State::loader_env->java_lang_OutOfMemoryError); return NULL; } + if(gc_requires_barriers()) + gc_heap_wrote_object(result); + memcpy(result, h->object, size); result->set_obj_info(0); ObjectHandle new_handle = oh_allocate_local_handle();