<commit_before>/*
 *  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.
 */
/**
 * @author <NAME>
 * @version $Revision$
 */
/**
 * @file
 * @brief CodeGen's routines for instrumentation and profiling.
 */
 
#include "cg.h"
#include "trace.h"
#include "jit_runtime_support.h"
#include "jit_intf.h"

namespace Jitrino {
namespace Jet {

//Number of nops to put before counter instruction to be able to atomically
//replace beginning of the instruction with jump
#define NOPS_PER_COUNTER 1

void CodeGen::gen_prof_be(void)
{
    if (!is_set(JMF_PROF_ENTRY_BE)) {
        return;
    }

#ifdef _IA32_
    AR addr = ar_x;
    int off = (int)m_p_backedge_counter;
#else
    AR addr = valloc(jobj);
    movp(addr, m_p_backedge_counter);
    int off = 0;
#endif
    uint32 offset = (uint32)(m_codeStream.ip() - m_codeStream.data() - m_bbinfo->ipoff); //store offsets inside of BB now. Fix it to method's offset after code layout
    //put number of nops to align counter instruction
    nop(NOPS_PER_COUNTER);
    alu(alu_add, Opnd(i32, addr, off), 1);

   //store information about profiling counters
    uint32 new_offset = (uint32)(m_codeStream.ip() - m_codeStream.data() - m_bbinfo->ipoff);
    ProfileCounterInfo info;
    info.bb = m_bbinfo;
    info.offsetInfo = ProfileCounterInfo::createOffsetInfo(new_offset - offset, offset);
    m_profileCountersMap.push_back(info);
}

void CodeGen::gen_gc_safe_point()
{
    if (!is_set(JMF_BBPOLLING)) {
        return;
    }
    if (m_bbstate->seen_gcpt) {
        if (is_set(DBG_TRACE_CG)) {
            dbg(";;>gc.safepoint - skipped\n");
        }
        return;
    }
    m_bbstate->seen_gcpt = true;
    // On Windows we could use a bit, but tricky way - we know about VM 
    // internals and we know how Windows manages TIB, and thus we can get a 
    // direct access to the flag, without need to call VM:
    //      mov eax, fs:14
    //      test [eax+rt_suspend_req_flag_offset], 0
    // I don't believe this will gain any improvements for .jet, so using 
    // portable and 'official' way:
    gen_call_vm(platform_v, rt_helper_get_tls_base_ptr, 0);
    // The address of flag is now in gr_ret
    Opnd mem(i32, gr_ret, rt_suspend_req_flag_offset);
    alu(alu_cmp, mem, Opnd(0));
    unsigned br_off = br(z, 0, 0, taken);
    gen_call_vm_restore(false, helper_v, rt_helper_gc_safepoint, 0);
    patch(br_off, ip());
}

void CodeGen::gen_modification_watchpoint(JavaByteCodes opcode, jtype jt, Field_Handle fld) {

    unsigned ref_depth = is_wide(jt) ? 2 : 1;
    bool field_op = (opcode == OPCODE_PUTFIELD) ? true : false;

    // Check whether VM need modification notifications

    char* fld_tr_add;
    char fld_tr_mask;
    field_get_track_modification_flag(fld, &fld_tr_add, &fld_tr_mask);

    Val fld_track_mask((int)fld_tr_mask);

    AR fld_trackAr = valloc(jobj);
    movp(fld_trackAr, (void*)fld_tr_add);
    Opnd fld_track_opnd(i32, fld_trackAr, 0);
    //mov(fld_trackAr, Opnd(0xFFFFFFFF)); // Emulation to check access flag enabled
    //Opnd fld_track_opnd(fld_trackAr);
    
    rlock(fld_track_opnd);

    alu(alu_test, fld_track_opnd, fld_track_mask.as_opnd());
    runlock(fld_track_opnd);

    unsigned br_off = br(z, 0, 0, taken);
    
    // Store all scratch registers and operand stack state
    BBState saveBB;
    push_all_state(&saveBB);

    //JVMTI helper takes field handle, method handle, byte code location, pointer
    //to reference for fields or NULL for statics, pointer to field value

    AR fieldValBaseAr = valloc(jobj);
    Val fieldValPtr = Val(jobj, fieldValBaseAr);
    rlock(fieldValPtr);
    

    if (jt != jvoid) {
        // Make sure the value item is on the memory
        vswap(0);
        if (is_big(jt)) {
            vswap(1);
        }
        const Val& s = vstack(0);
        assert(s.is_mem());
        lea(fieldValPtr.as_opnd(), s.as_opnd());
    } else {
        Opnd stackTop(jobj, m_base, voff(m_stack.unused()));
        lea(fieldValPtr.as_opnd(), stackTop);
    }
    runlock(fieldValPtr);

#ifndef _EM64T_
    // Workaround since do_mov do not put jlong on stack in gen_args on ia32
    const CallSig cs_ti_fmodif(CCONV_HELPERS, jobj, jobj, i32, i32, jobj, jobj);
    Val vlocation((jlong)m_pc);
    Val vlocationHi((jlong)0);
#else
    const CallSig cs_ti_fmodif(CCONV_HELPERS, jobj, jobj, i64, jobj, jobj);
    Val vlocation((jlong)m_pc);
#endif

    Val vfield(jobj, fld);
    Val vmeth(jobj, m_method);
    Val vobject =  Val(jobj, NULL);

    if (field_op) {
        vobject = vstack(ref_depth);
    }
#ifndef _EM64T_
    // Workaround since do_mov do not put jlong on stack in gen_args on ia32
    gen_args(cs_ti_fmodif, 0, &vfield, &vmeth, &vlocationHi, &vlocation, &vobject, &fieldValPtr);
#else
    gen_args(cs_ti_fmodif, 0, &vfield, &vmeth, &vlocation, &vobject, &fieldValPtr);
#endif

    // 2. Park all locals and operand stack
    vpark();
    // Store gc info
    gen_gc_stack(-1, true);

    // 3. Call VM
    rlock(cs_ti_fmodif);
    AR gr = valloc(jobj);
    call( is_set(DBG_CHECK_STACK), gr, rt_helper_ti_field_modification, cs_ti_fmodif, cs_ti_fmodif.count());
    runlock(cs_ti_fmodif);
    
    //Restore operand stack state and scratch registers
    pop_all_state(&saveBB);

    patch(br_off, ip());
}


void CodeGen::gen_access_watchpoint(JavaByteCodes opcode, jtype jt, Field_Handle fld) {

    bool field_op = (opcode == OPCODE_GETFIELD) ? true : false;

    // Check whether VM need access notifications
    
    char* fld_tr_add;
    char fld_tr_mask;
    field_get_track_access_flag(fld, &fld_tr_add, &fld_tr_mask);

    Val fld_track_mask((int)fld_tr_mask);

    AR fld_trackAr = valloc(jobj);
    rlock(fld_trackAr);
    
    //mov(fld_trackAr, Opnd(0xFFFFFFFF)); // Emulation to check access flag enabled
    //Opnd fld_track_opnd(fld_trackAr);
    movp(fld_trackAr, (void*)fld_tr_add);
    Opnd fld_track_opnd(i32, fld_trackAr, 0);
    alu(alu_test, fld_track_opnd, fld_track_mask.as_opnd());<commit_msg>Applied HARMONY-5035 [drlvm][jit][JET] Parameters are passed incorrectly to rt_helper_ti_field_modification stub<commit_after>/*
 *  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.
 */
/**
 * @author <NAME>
 * @version $Revision$
 */
/**
 * @file
 * @brief CodeGen's routines for instrumentation and profiling.
 */
 
#include "cg.h"
#include "trace.h"
#include "jit_runtime_support.h"
#include "jit_intf.h"

namespace Jitrino {
namespace Jet {

//Number of nops to put before counter instruction to be able to atomically
//replace beginning of the instruction with jump
#define NOPS_PER_COUNTER 1

void CodeGen::gen_prof_be(void)
{
    if (!is_set(JMF_PROF_ENTRY_BE)) {
        return;
    }

#ifdef _IA32_
    AR addr = ar_x;
    int off = (int)m_p_backedge_counter;
#else
    AR addr = valloc(jobj);
    movp(addr, m_p_backedge_counter);
    int off = 0;
#endif
    uint32 offset = (uint32)(m_codeStream.ip() - m_codeStream.data() - m_bbinfo->ipoff); //store offsets inside of BB now. Fix it to method's offset after code layout
    //put number of nops to align counter instruction
    nop(NOPS_PER_COUNTER);
    alu(alu_add, Opnd(i32, addr, off), 1);

   //store information about profiling counters
    uint32 new_offset = (uint32)(m_codeStream.ip() - m_codeStream.data() - m_bbinfo->ipoff);
    ProfileCounterInfo info;
    info.bb = m_bbinfo;
    info.offsetInfo = ProfileCounterInfo::createOffsetInfo(new_offset - offset, offset);
    m_profileCountersMap.push_back(info);
}

void CodeGen::gen_gc_safe_point()
{
    if (!is_set(JMF_BBPOLLING)) {
        return;
    }
    if (m_bbstate->seen_gcpt) {
        if (is_set(DBG_TRACE_CG)) {
            dbg(";;>gc.safepoint - skipped\n");
        }
        return;
    }
    m_bbstate->seen_gcpt = true;
    // On Windows we could use a bit, but tricky way - we know about VM 
    // internals and we know how Windows manages TIB, and thus we can get a 
    // direct access to the flag, without need to call VM:
    //      mov eax, fs:14
    //      test [eax+rt_suspend_req_flag_offset], 0
    // I don't believe this will gain any improvements for .jet, so using 
    // portable and 'official' way:
    gen_call_vm(platform_v, rt_helper_get_tls_base_ptr, 0);
    // The address of flag is now in gr_ret
    Opnd mem(i32, gr_ret, rt_suspend_req_flag_offset);
    alu(alu_cmp, mem, Opnd(0));
    unsigned br_off = br(z, 0, 0, taken);
    gen_call_vm_restore(false, helper_v, rt_helper_gc_safepoint, 0);
    patch(br_off, ip());
}

void CodeGen::gen_modification_watchpoint(JavaByteCodes opcode, jtype jt, Field_Handle fld) {

    unsigned ref_depth = is_wide(jt) ? 2 : 1;
    bool field_op = (opcode == OPCODE_PUTFIELD) ? true : false;

    // Check whether VM need modification notifications

    char* fld_tr_add;
    char fld_tr_mask;
    field_get_track_modification_flag(fld, &fld_tr_add, &fld_tr_mask);

    Val fld_track_mask((int)fld_tr_mask);

    AR fld_trackAr = valloc(jobj);
    movp(fld_trackAr, (void*)fld_tr_add);
    Opnd fld_track_opnd(i32, fld_trackAr, 0);
    //mov(fld_trackAr, Opnd(0xFFFFFFFF)); // Emulation to check access flag enabled
    //Opnd fld_track_opnd(fld_trackAr);
    
    rlock(fld_track_opnd);

    alu(alu_test, fld_track_opnd, fld_track_mask.as_opnd());
    runlock(fld_track_opnd);

    unsigned br_off = br(z, 0, 0, taken);
    
    // Store all scratch registers and operand stack state
    BBState saveBB;
    push_all_state(&saveBB);

    //JVMTI helper takes field handle, method handle, byte code location, pointer
    //to reference for fields or NULL for statics, pointer to field value

#ifndef _EM64T_
    // Workaround since do_mov do not put jlong on stack in gen_args on ia32
    const CallSig cs_ti_fmodif(CCONV_HELPERS, jobj, jobj, i32, i32, jobj, jobj);
    Val vlocation((jlong)m_pc);
    Val vlocationHi((jlong)0);
#else
    const CallSig cs_ti_fmodif(CCONV_HELPERS, jobj, jobj, i64, jobj, jobj);
    Val vlocation((jlong)m_pc);
#endif

    rlock(cs_ti_fmodif);

    AR fieldValBaseAr = valloc(jobj);
    Val fieldValPtr = Val(jobj, fieldValBaseAr);
    rlock(fieldValPtr);
    

    if (jt != jvoid) {
        // Make sure the value item is on the memory
        vswap(0);
        if (is_big(jt)) {
            vswap(1);
        }
        const Val& s = vstack(0);
        assert(s.is_mem());
        lea(fieldValPtr.as_opnd(), s.as_opnd());
    } else {
        Opnd stackTop(jobj, m_base, voff(m_stack.unused()));
        lea(fieldValPtr.as_opnd(), stackTop);
    }

    Val vfield(jobj, fld);
    Val vmeth(jobj, m_method);
    Val vobject =  Val(jobj, NULL);

    if (field_op) {
        vobject = vstack(ref_depth);
    }
#ifndef _EM64T_
    // Workaround since do_mov do not put jlong on stack in gen_args on ia32
    gen_args(cs_ti_fmodif, 0, &vfield, &vmeth, &vlocationHi, &vlocation, &vobject, &fieldValPtr);
#else
    gen_args(cs_ti_fmodif, 0, &vfield, &vmeth, &vlocation, &vobject, &fieldValPtr);
#endif

    // 2. Park all locals and operand stack
    vpark();
    // Store gc info
    gen_gc_stack(-1, true);

    // 3. Call VM
    AR gr = valloc(jobj);
    call( is_set(DBG_CHECK_STACK), gr, rt_helper_ti_field_modification, cs_ti_fmodif, cs_ti_fmodif.count());

    runlock(fieldValPtr);
    runlock(cs_ti_fmodif);
    
    //Restore operand stack state and scratch registers
    pop_all_state(&saveBB);

    patch(br_off, ip());
}


void CodeGen::gen_access_watchpoint(JavaByteCodes opcode, jtype jt, Field_Handle fld) {

    bool field_op = (opcode == OPCODE_GETFIELD) ? true : false;

    // Check whether VM need access notifications
    
    char* fld_tr_add;
    char fld_tr_mask;
    field_get_track_access_flag(fld, &fld_tr_add, &fld_tr_mask);

    Val fld_track_mask((int)fld_tr_mask);

    AR fld_trackAr = valloc(jobj);
    rlock(fld_trackAr);
    
    //mov(fld_trackAr, Opnd(0xFFFFFFFF)); // Emulation to check access flag enabled
    //Opnd fld_track_opnd(fld_trackAr);
    movp(fld_trackAr, (void*)fld_tr_add);
    Opnd fld_track_opnd(i32, fld_trackAr, 0);
    alu(alu_test, fld_track_opnd, fld_track_mask.as_opnd());
{'fraction_non_alphanumeric': 0.1050025862705978, 'fraction_numerical': 0.009753934825980935, 'mean_word_length': 3.372859450726979, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 4, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7584623', 'n_tokens_mistral': 4949, 'n_tokens_neox': 4803, 'n_words': 1306}