Index: jitrino/src/jet/bcproc.cpp =================================================================== RCS file: /cvs/drl/mrt/vm/jitrino/src/jet/bcproc.cpp,v retrieving revision 1.4.12.3.2.2 diff -u -w -r1.4.12.3.2.2 bcproc.cpp --- jitrino/src/jet/bcproc.cpp 4 Apr 2006 12:22:03 -0000 1.4.12.3.2.2 +++ jitrino/src/jet/bcproc.cpp 28 Jul 2006 11:28:28 -0000 @@ -112,7 +112,7 @@ default: assert(jinst.opcode == OPCODE_NOP); break; - }; + } // ~switch(opcodegroup) #ifdef _DEBUG if (do_stack_check) { @@ -404,7 +404,7 @@ case OPCODE_IASTORE: gen_check_null(2); gen_check_bounds(2,1); - gen_astore(i32); + gen_astore(i32, true); break; default: assert(false); break; } @@ -437,7 +437,7 @@ Timers::vmResolve.stop(); if (meth != NULL) { Class_Handle klass = method_get_class(meth); - if (class_needs_initialization(klass)) { + if (klass != m_klass && class_needs_initialization(klass)) { gen_call_vm(rt_helper_init_class, 1, klass); } } @@ -537,7 +537,7 @@ // stack: [.., aref, idx, val] gen_check_null(big ? 3 : 2); gen_check_bounds(big ? 3 : 2, big ? 2 : 1); - gen_astore(jt); + gen_astore(jt, true); } else { // stack: [.., aref, idx] @@ -578,7 +578,7 @@ } if (fld) { Class_Handle klass = field_get_class(fld); - if (class_needs_initialization(klass)) { + if (klass != m_klass && class_needs_initialization(klass)) { gen_call_vm(rt_helper_init_class, 1, klass); } } @@ -627,7 +627,7 @@ ah = class_get_allocation_handle(klass); } } - gen_new_array(ah); + gen_new_array(ah, jinst.opcode, jinst.op0); } break; case OPCODE_NEWARRAY: @@ -647,7 +647,7 @@ Class_Handle elem_class = class_get_class_of_primitive_type(atype); Class_Handle array_class = class_get_array_of_class(elem_class); Allocation_Handle ah = class_get_allocation_handle(array_class); - gen_new_array(ah); + gen_new_array(ah, jinst.opcode, jinst.op0); } break; case OPCODE_MULTIANEWARRAY: Index: jitrino/src/jet/cg_ia32.cpp =================================================================== RCS file: /cvs/drl/mrt/vm/jitrino/src/jet/cg_ia32.cpp,v retrieving revision 1.6.12.3.2.5 diff -u -w -r1.6.12.3.2.5 cg_ia32.cpp --- jitrino/src/jet/cg_ia32.cpp 5 Apr 2006 05:18:08 -0000 1.6.12.3.2.5 +++ jitrino/src/jet/cg_ia32.cpp 28 Jul 2006 11:28:33 -0000 @@ -1495,10 +1495,11 @@ } } -void Compiler::gen_astore(jtype jt) +void Compiler::gen_astore(jtype jt, bool helperOK) { // the stack is: [... array_ref, index, value] - if (jt == jobj) { + if (jt == jobj && helperOK) { + gen_wb(OPCODE_AASTORE, NULL); static const jtype args[3] = {jobj, i32, jobj}; gen_stack_to_args(true, 3, args); gen_call_vm(rt_helper_aastore, 0); @@ -1910,32 +1911,30 @@ } } -void Compiler::gen_new_array(Allocation_Handle ah) +void Compiler::gen_new_array(Allocation_Handle ah, JavaByteCodes opcode, + unsigned op0) { - const JInst& jinst = *m_curr_inst; - assert(jinst.opcode == OPCODE_NEWARRAY || - jinst.opcode == OPCODE_ANEWARRAY); + assert(opcode == OPCODE_NEWARRAY || opcode == OPCODE_ANEWARRAY); static const jtype args[1] = { i32 }; gen_stack_to_args(true, 1, args); // Free EAX veax(); const bool do_lazily = (m_infoBlock.get_flags() & JMF_LAZY_RESOLUTION) && - jinst.opcode == OPCODE_ANEWARRAY; + opcode == OPCODE_ANEWARRAY; - if (jinst.opcode == OPCODE_NEWARRAY) { + if (opcode == OPCODE_NEWARRAY) { // it's unexpected that that something failed for a primitive type assert(ah != 0); } if (do_lazily) { - gen_lazy_resolve(jinst.op0, jinst.opcode); + gen_lazy_resolve(op0, opcode); // EAX = allocation handle voper(Mnemonic_PUSH, RegName_EAX); } else if (ah == 0) { - gen_call_throw(rt_helper_throw_linking_exc, 3, m_klass, jinst.op0, - jinst.opcode); + gen_call_throw(rt_helper_throw_linking_exc, 3, m_klass, op0, opcode); } else { voper(Mnemonic_PUSH, MK_IMM32(ah)); @@ -2072,6 +2071,7 @@ lazy ? 1 : 0, // scale fld_offset); // disp if (put) { + gen_wb(op, fld); voper(typeInfo[jt].mov, pfield, vstack(0)); if (is_big(jt)) { assert(jt == i64); @@ -2139,6 +2139,7 @@ 0, (int)fld_addr); if (put) { + gen_wb(op, fld); voper(typeInfo[jt].mov, pstatic, vstack(0)); if (is_big(jt)) { assert(jt == i64); Index: jitrino/src/jet/compiler.cpp =================================================================== RCS file: /cvs/drl/mrt/vm/jitrino/src/jet/compiler.cpp,v retrieving revision 1.7.12.4.2.4 diff -u -w -r1.7.12.4.2.4 compiler.cpp --- jitrino/src/jet/compiler.cpp 4 Apr 2006 12:22:03 -0000 1.7.12.4.2.4 +++ jitrino/src/jet/compiler.cpp 28 Jul 2006 11:28:36 -0000 @@ -85,6 +85,8 @@ #endif unsigned Compiler::defaultFlags = JMF_BBPOOLING; +bool g_no_wb = false; + JIT_Result Compiler::compile(Compile_Handle ch, Method_Handle method) { @@ -117,6 +119,11 @@ compile_flags |= DBG_TRACE_SUMM; #endif + compilation_params.exe_insert_write_barriers = 1; + if (g_no_wb) { + compilation_params.exe_insert_write_barriers = 0; + } + if (compile_flags & DBG_TRACE_SUMM) { dbg_trace_comp_start(); } Index: jitrino/src/jet/compiler.h =================================================================== RCS file: /cvs/drl/mrt/vm/jitrino/src/jet/compiler.h,v retrieving revision 1.4.12.4.2.3 diff -u -w -r1.4.12.4.2.3 compiler.h --- jitrino/src/jet/compiler.h 4 Apr 2006 12:22:03 -0000 1.4.12.4.2.3 +++ jitrino/src/jet/compiler.h 28 Jul 2006 11:28:39 -0000 @@ -933,8 +933,11 @@ * @brief Generates ASTORE instruction. * * @note Does not check bounds. It must be done separately. + * @param helperOK - \b true if it's necessary to invoke VM helper to + * store #jobj item. With \c jt == \c jobj and \c helperOK == \b false + * gen_astore() is used for magics implementation. */ - void gen_astore(jtype jt); + void gen_astore(jtype jt, bool helperOK); /** * @brief Generates PUTFIELD and GETFIELD operations. */ @@ -1016,7 +1019,7 @@ /** * @brief Generates ANEWARRAY, NEWARRAY. */ - void gen_new_array(Allocation_Handle ah); + void gen_new_array(Allocation_Handle ah, JavaByteCodes opcode, unsigned op0); /** * @brief Generates MULTIANEWARRAY. */ @@ -1030,6 +1033,8 @@ */ void gen_lazy_resolve(unsigned idx, JavaByteCodes opkod); + void gen_wb(JavaByteCodes opcod, Field_Handle fld); + //*********************************************************************** //* Code patching and code buffer related routines //*********************************************************************** @@ -1301,7 +1306,7 @@ /** * @brief Compilation parameters. */ - const OpenMethodExecutionParams& compilation_params; + /*const*/ OpenMethodExecutionParams compilation_params; /** * @brief JIT handle. */ Index: jitrino/src/jet/jet.cpp =================================================================== RCS file: /cvs/drl/mrt/vm/jitrino/src/jet/jet.cpp,v retrieving revision 1.7.12.3.2.2 diff -u -w -r1.7.12.3.2.2 jet.cpp --- jitrino/src/jet/jet.cpp 4 Apr 2006 12:22:03 -0000 1.7.12.3.2.2 +++ jitrino/src/jet/jet.cpp 28 Jul 2006 11:28:40 -0000 @@ -102,6 +102,7 @@ } static bool id_done = false; +extern bool g_no_wb; void cmd_line_arg(JIT_Handle jit, const char* name, const char* arg) { @@ -110,6 +111,7 @@ " jet::help - prints out this text \n" " jet::info, jet::id - prints out build info \n" " jet::lazyres, jet::lr - generate code with lazy (runtime) resolution\n" +" jet::nowb - turn off generation of write barriers \n" #ifdef JET_PROTO " jet::stackalign, jet::sa - generate methods with stack alignment \n" #endif @@ -122,6 +124,7 @@ key_help[] = "jet::help", key_info[] = "jet::info", key_id[] = "jet::id", + key_no_wb[] = "jet::nowb", key_lazyres[] = "jet::lazyres", key_lr[] = "jet::lr", #ifdef JET_PROTO key_stackalign[] = "jet::stackalign", key_sa[] = "jet::sa", @@ -160,6 +163,9 @@ !strncmp(arg, key_no_bbp, sizeof(key_no_bbp)-1)) { Compiler::defaultFlags &= ~JMF_BBPOOLING; } + else if (!strncmp(arg, key_no_wb, sizeof(key_no_wb)-1)) { + g_no_wb = true; + } else if (!strncmp(arg, key_invalid, sizeof(key_invalid)-1)) { printf("Warning: unknown flag - %s\n", arg); } @@ -314,8 +320,6 @@ OpenMethodExecutionParams params) { ::Jitrino::Jet::Compiler jit(hjit, params); - JIT_Flags flags; - flags.insert_write_barriers = false; return jit.compile(compilation, method); } Index: jitrino/src/jet/trace.cpp =================================================================== RCS file: /cvs/drl/mrt/vm/jitrino/src/jet/trace.cpp,v retrieving revision 1.4.12.3.2.2 diff -u -w -r1.4.12.3.2.2 trace.cpp --- jitrino/src/jet/trace.cpp 4 Apr 2006 12:22:04 -0000 1.4.12.3.2.2 +++ jitrino/src/jet/trace.cpp 28 Jul 2006 11:28:41 -0000 @@ -522,9 +522,7 @@ // ... and stack after that dbg(";; stack.size=%d\n;; ", jframe.size()); for (unsigned i = 0; i < jframe.size(); i++) { - if (i && !(i % 5)) { dbg("\n;; "); - } const JFrame::Slot & s = jframe.get_stack(i); dbg(" %s", toStr2(s, true).c_str()); } Index: jitrino/src/jet/wbs.cpp =================================================================== RCS file: jitrino/src/jet/wbs.cpp diff -N jitrino/src/jet/wbs.cpp --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ jitrino/src/jet/wbs.cpp 28 Jul 2006 11:28:41 -0000 @@ -0,0 +1,114 @@ +/* + * Copyright 2005-2006 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed 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. + */ +/** + * @author Alexander V. Astapchuk + * @version $Revision$ + */ +/** + * @file + * @brief Write barriers + */ + +#include "compiler.h" +#include "trace.h" +#include "open/vm.h" +#include "jit_import.h" +#include "jit_intf.h" +#include "open/gc.h" +#include +using std::vector; + +namespace Jitrino { +namespace Jet { + +void Compiler::gen_wb(JavaByteCodes opcod, Field_Handle fld) +{ + // No request to generate WBs - nothing to do + if (!compilation_params.exe_insert_write_barriers) { + return; + } + if (m_jframe->top() != jobj) { + // item on the top of operand stack is not Object + // - not interested for GC - nothing to do. + return; + } + // + // Push other args according to the following signature: + // + //(object written to, slot written to, value written to slo) + + // operand stack for astore: arr, idx, ref + // operand stack for putfld: base, ref + // operand stack for putstc: ref + RegName rtmp = vlocal(jobj, -1, false, true).reg(); + + static EncoderBase::Operand stack0(OpndSize_32, RegName_ESP, 0); + static EncoderBase::Operand stack1(OpndSize_32, RegName_ESP, STACK_SLOT_SIZE); + static EncoderBase::Operand stack2(OpndSize_32, RegName_ESP, STACK_SLOT_SIZE*2); + + voper(Mnemonic_SUB, REG_STACK, (int)STACK_SLOT_SIZE*3); + + if (opcod == OPCODE_PUTSTATIC) { + // Currently, in DRLVM the static fields lies outside of + // regular GC heap, and should not be reported. + return; + /* + if (fld == NULL) { + // resolution error - nothing to do. + return; + } + void* addr = field_get_addr(fld); + voper(Mnemonic_MOV, stack0, 0); // wb.arg.0.src = NULL + voper(Mnemonic_MOV, stack1, (int)addr); // wb.arg.1.slot = addr of static + */ + } + else if (opcod == OPCODE_PUTFIELD) { + if (fld == NULL) { + // resolution error - nothing to do. + return; + } + RegName base = vstack(1); + int off = field_get_offset(fld); + EncoderBase::Operand slot(OpndSize_32, base, off); + voper(Mnemonic_LEA, rtmp, slot); + voper(Mnemonic_MOV, stack0, base); // wb.arg.0.src = base + voper(Mnemonic_MOV, stack1, rtmp); // wb.arg.1.slot = base + field offset + } + else { + assert(opcod == OPCODE_AASTORE); + RegName base = vstack(2); + RegName ridx = vstack(1); + EncoderBase::Operand slot(typeInfo[jobj].size, + base, ridx, jtypes[jobj].size, jtypes[jobj].rt_offset); + voper(Mnemonic_LEA, rtmp, slot); + voper(Mnemonic_MOV, stack0, base); // wb.arg.0.src = base + voper(Mnemonic_MOV, stack1, rtmp); // wb.arg.1.slot = base + idx*sizeof(void*) + } + RegName ref = vstack(0); + voper(Mnemonic_MOV, stack2, ref); // wb.arg.2.tgt = reference being written + // + // Now, the stack args are ready, may call the WB helper + static char* wb_helper = (char*)gc_heap_slot_write_ref; + // + // according t contract with CG guys, the WB code neither + // throws an exception nor may lead to GC - no need for gen_call_vm() + gen_call_novm(wb_helper, 0); + // Somehow, the function is not stdcall and does not remove its args + // from the stack + voper(Mnemonic_ADD, REG_STACK, (int)STACK_SLOT_SIZE*3); +} + +}}; // ~namespace Jitrino::Jet