* src/vm/Makefile.am (libvm_la_SOURCES): Added above file.
* src/vm/method.hpp (methodinfo): Added pointer to breakpoint table.
* src/vm/method.cpp (method_free): Frees breakpoint table if present.
* src/vm/jit/patcher-common.cpp (patcher_breakpoint): Added patcher method.
* src/vm/jit/patcher-common.hpp: Likewise.
* src/vm/jit/ir/icmd.hpp (ICMD_BREAKPOINT): Added.
* src/vm/jit/ir/icmdtable.inc: Adapted entry for above ICMD.
* src/vm/jit/parse.cpp (parse): Generate breakpoints if requested.
* src/vm/jit/stack.c: Correctly handles ICMD_BREAKPOINT.
* src/vm/jit/allocator/simplereg.c: Likewise.
* src/vm/jit/codegen-common.cpp (codegen_emit): Generate ICMD_BREAKPOINT code.
array.cpp \
array.hpp \
$(ASSERTION_SOURCES) \
+ breakpoint.hpp \
class.cpp \
class.hpp \
classcache.cpp \
--- /dev/null
+/* src/vm/breakpoint.hpp - breakpoint handling header
+
+ Copyright (C) 2009
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+ */
+
+
+#ifndef _BREAKPOINT_HPP
+#define _BREAKPOINT_HPP
+
+#include "config.h"
+
+#ifdef __cplusplus
+#include <map>
+
+
+/**
+ * This structure contains information about a breakpoint. Feel
+ * free to extend it to hold all the information you need. It is
+ * the responsibility of the user to set the fields accordingly.
+ */
+typedef struct Breakpoint {
+ bool is_oneshot; ///< Indicates a "one-shot".
+
+#if defined(ENABLE_JVMTI)
+ int32_t location; ///< Used for JVMTI breakpoints.
+ methodinfo* method; ///< Used for JVMTI breakpoints.
+#endif
+} Breakpoint;
+
+
+/**
+ * This class is used to record breakpoints in the methodinfo
+ * structure. The term "location" is used to refer to the bytecode
+ * index at which the breakpoint should be placed.
+ */
+class BreakpointTable {
+private:
+ std::map<int32_t, Breakpoint> _breakpoints;
+
+public:
+ // Querying operations.
+ bool is_empty();
+ bool contains(int32_t location);
+
+ // Modification operations.
+ Breakpoint* add_breakpoint (int32_t location);
+ Breakpoint* get_breakpoint (int32_t location);
+ void remove_breakpoint(int32_t location);
+};
+
+
+inline bool BreakpointTable::is_empty()
+{
+ return _breakpoints.empty();
+}
+
+inline bool BreakpointTable::contains(int32_t location)
+{
+ return (_breakpoints.find(location) != _breakpoints.end());
+}
+
+inline Breakpoint* BreakpointTable::add_breakpoint(int32_t location)
+{
+ assert(!contains(location));
+ _breakpoints.insert(std::make_pair(location, Breakpoint()));
+ return &(_breakpoints.find(location)->second);
+}
+
+inline Breakpoint* BreakpointTable::get_breakpoint(int32_t location)
+{
+ assert(contains(location));
+ return &(_breakpoints.find(location)->second);
+}
+
+inline void BreakpointTable::remove_breakpoint(int32_t location)
+{
+ assert(contains(location));
+ _breakpoints.erase(location);
+}
+
+
+#else // __cplusplus
+typedef struct BreakpointTable BreakpointTable;
+#endif // __cplusplus
+
+#endif /* _BREAKPOINT_HPP */
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
case ICMD_RET:
case ICMD_RETURN:
case ICMD_GOTO:
+ case ICMD_BREAKPOINT:
case ICMD_PUTSTATICCONST:
case ICMD_INLINE_START:
case ICMD_INLINE_END:
emit_nullpointer_check(cd, iptr, s1);
break;
+ case ICMD_BREAKPOINT: /* ... ==> ... */
+ /* sx.val.anyptr = Breakpoint */
+
+ patcher_add_patch_ref(jd, PATCHER_breakpoint, iptr->sx.val.anyptr, 0);
+ PATCHER_NOPS;
+ break;
+
#if defined(ENABLE_SSA)
case ICMD_GETEXCEPTION:
/* 200 */
/* 201 */
- /* 202 */
+
+ ICMD_BREAKPOINT = BC_breakpoint,
ICMD_IASTORECONST = 204,
ICMD_LASTORECONST = 205,
/*199*/ {N("IFNONNULL ") DF_1_TO_0 , CF_IF , 0 /* (A--) */},
/*200*/ {N("UNDEF200 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
/*201*/ {N("UNDEF201 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
-/*202*/ {N("UNDEF202 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
+/*202*/ {N("BREAKPOINT ") DF_0_TO_0 , CF_NORMAL, 0 /* (--) */},
/*203*/ {N("UNDEF203 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
/*204*/ {N("IASTORECONST ") DF_2_TO_0 , CF_NORMAL, PEI /* S+ (AI--) */},
/*205*/ {N("LASTORECONST ") DF_2_TO_0 , CF_NORMAL, PEI /* S+ (AI--) */},
/* src/vm/jit/parse.c - parser for JavaVM to intermediate code translation
- Copyright (C) 1996-2005, 2006, 2007, 2008
+ Copyright (C) 1996-2005, 2006, 2007, 2008, 2009
CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
s_count += bytecode[opcode].slots;
+ /* Generate a breakpoint instruction right before the actual
+ instruction, if the method contains a breakpoint at the
+ current bytecode index. */
+
+ if (m->breakpoints != NULL && m->breakpoints->contains(bcindex)) {
+ INSTRUCTIONS_CHECK(1);
+ OP_PREPARE_ZEROFLAGS(ICMD_BREAKPOINT);
+ iptr->sx.val.anyptr = m->breakpoints->get_breakpoint(bcindex);
+ PINC;
+ }
+
/* We check here for the space of 1 instruction in the
instruction array. If an opcode is converted to more than
1 instruction, this is checked in the corresponding
/* src/vm/jit/patcher-common.cpp - architecture independent code patching stuff
- Copyright (C) 2007, 2008
+ Copyright (C) 2007, 2008, 2009
CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
Copyright (C) 2008 Theobroma Systems Ltd.
#include "toolbox/list.hpp"
#include "toolbox/logging.hpp" /* XXX remove me! */
+#include "vm/breakpoint.hpp"
#include "vm/exceptions.hpp"
#include "vm/initialize.hpp"
#include "vm/options.h"
+#include "vm/os.hpp"
#include "vm/resolve.hpp"
-#include "vm/vm.hpp" /* for vm_abort */
#include "vm/jit/code.hpp"
#include "vm/jit/disass.h"
{ PATCHER_invokestatic_special, "invokestatic_special" },
{ PATCHER_invokevirtual, "invokevirtual" },
{ PATCHER_invokeinterface, "invokeinterface" },
+ { PATCHER_breakpoint, "breakpoint" },
{ NULL, "-UNKNOWN PATCHER FUNCTION-" }
};
#endif
#if !defined(NDEBUG)
if (patcher_list_find(code, (void*) (intptr_t) patchmpc) != NULL)
- vm_abort("patcher_add_patch_ref: different patchers at same position.");
+ os::abort("patcher_add_patch_ref: different patchers at same position.");
#endif
// Set patcher information (mpc is resolved later).
pr = patcher_list_find(code, pc);
if (pr == NULL)
- vm_abort("patcher_handler: Unable to find patcher reference.");
+ os::abort("patcher_handler: Unable to find patcher reference.");
if (pr->done) {
#if !defined(NDEBUG)
}
+/**
+ * Deals with breakpoint instructions (ICMD_BREAKPOINT) compiled
+ * into a JIT method. This patcher might never patch back the
+ * original machine code because breakpoints are kept active.
+ */
+bool patcher_breakpoint(patchref_t *pr)
+{
+ // Get stuff from the patcher reference.
+ Breakpoint* breakp = (Breakpoint*) pr->ref;
+
+#if defined(ENABLE_JVMTI)
+ methodinfo* m = breakp->method;
+ int32_t l = breakp->location;
+
+ log_message_method("JVMTI: Reached breakpoint in method ", m);
+ log_println("JVMTI: Reached breakpoint at location %d", l);
+#endif
+
+ // In case the breakpoint wants to be kept active, we simply
+ // fail to "patch" at this point.
+ if (!breakp->is_oneshot)
+ return false;
+
+ // Patch back original code.
+ patcher_patch_code(pr);
+
+ return true;
+}
+
+
/*
* These are local overrides for various environment variables in Emacs.
* Please do not remove this and leave it at the end of the file, where
/* src/vm/jit/patcher-common.hpp - architecture independent code patching stuff
- Copyright (C) 2007, 2008
+ Copyright (C) 2007, 2008, 2009
CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
bool patcher_resolve_native_function(patchref_t *pr);
#define PATCHER_resolve_native_function (functionptr) patcher_resolve_native_function
+bool patcher_breakpoint(patchref_t *pr);
+#define PATCHER_breakpoint (functionptr) patcher_breakpoint
+
/* old patcher functions */
bool patcher_get_putstatic(patchref_t *pr);
sd.jd->returnblock = sd.bptr;
break;
+ case ICMD_BREAKPOINT:
+ OP0_0;
+ break;
+
/* pop 0 push 1 const */
CompilerStub::remove(m->stubroutine);
}
}
+
+ if (m->breakpoints)
+ delete m->breakpoints;
}
#include "threads/mutex.hpp"
+#include "vm/breakpoint.hpp"
#include "vm/jit/builtin.hpp"
#include "vm/descriptor.hpp"
#include "vm/global.h"
methodinfo *overwrites; /* method that is directly overwritten */
method_assumption *assumptions; /* list of assumptions about this method */
+ BreakpointTable* breakpoints; /* breakpoints in this method */
+
#if defined(ENABLE_REPLACEMENT)
s4 hitcountdown; /* decreased for each hit */
#endif