map;
- };
-
- /**
- Use this class to initialize the log4cxx environment using a DOM tree.
-
- Sometimes it is useful to see how log4cxx is reading configuration
- files. You can enable log4cxx internal logging by setting the
- debug attribute in the
- log4cxx element. As in
-
- <log4j:configuration debug="true" xmlns:log4j="http://jakarta.apache.org/log4j/">
- ...
- </log4j:configuration>
-
-
- There are sample XML files included in the package.
- */
- class LOG4CXX_EXPORT DOMConfigurator :
- virtual public spi::Configurator,
- virtual public helpers::ObjectImpl
- {
- protected:
- /**
- Used internally to parse appenders by IDREF name.
- */
- AppenderPtr findAppenderByName(helpers::XMLDOMDocumentPtr doc,
- const LogString& appenderName);
-
- /**
- Used internally to parse appenders by IDREF element.
- */
- AppenderPtr findAppenderByReference(
- helpers::XMLDOMElementPtr appenderRef);
-
- /**
- Used internally to parse an appender element.
- */
- AppenderPtr parseAppender(helpers::XMLDOMElementPtr appenderElement);
-
- /**
- Used internally to parse an {@link spi::ErrorHandler ErrorHandler } element.
- */
- void parseErrorHandler(helpers::XMLDOMElementPtr element, AppenderPtr appender);
-
- /**
- Used internally to parse a filter element.
- */
- void parseFilters(helpers::XMLDOMElementPtr element,
- std::vector& filters);
-
- /**
- Used internally to parse a logger element.
- */
- void parseLogger(helpers::XMLDOMElementPtr loggerElement);
-
- /**
- Used internally to parse the logger factory element.
- */
- void parseLoggerFactory(helpers::XMLDOMElementPtr factoryElement);
-
- /**
- Used internally to parse the logger factory element.
- */
- log4cxx::rolling::TriggeringPolicyPtr parseTriggeringPolicy(helpers::XMLDOMElementPtr factoryElement);
-
- /**
- Used internally to parse the logger factory element.
- */
- log4cxx::rolling::RollingPolicyPtr parseRollingPolicy(helpers::XMLDOMElementPtr factoryElement);
-
- /**
- Used internally to parse the roor category element.
- */
- void parseRoot(helpers::XMLDOMElementPtr rootElement);
-
- /**
- Used internally to parse the children of a category element.
- */
- void parseChildrenOfLoggerElement(helpers::XMLDOMElementPtr catElement,
- LoggerPtr logger, bool isRoot);
-
- /**
- Used internally to parse a layout element.
- */
- LayoutPtr parseLayout(helpers::XMLDOMElementPtr layout_element);
-
- /**
- Used internally to parse a level element.
- */
- void parseLevel(helpers::XMLDOMElementPtr element,
- LoggerPtr logger, bool isRoot);
-
- void setParameter(helpers::XMLDOMElementPtr elem,
- config::PropertySetter& propSetter);
-
- /**
- Used internally to configure the log4cxx framework by parsing a DOM
- tree of XML elements based on log4j.dtd.
-
- */
- void parse(helpers::XMLDOMElementPtr element);
-
- public:
- DOMConfigurator();
-
- DECLARE_LOG4CXX_OBJECT(DOMConfigurator)
- BEGIN_LOG4CXX_CAST_MAP()
- LOG4CXX_CAST_ENTRY(spi::Configurator)
- END_LOG4CXX_CAST_MAP()
-
- DOMConfigurator(log4cxx::helpers::Pool& p);
-
- /**
- A static version of #doConfigure.
- */
- static void configure(const std::string& filename);
-#if LOG4CXX_HAS_WCHAR_T
- static void configure(const std::wstring& filename);
-#endif
- /**
- Like #configureAndWatch(const String& configFilename, long delay)
- except that the default delay as defined by
- helpers::FileWatchdog#DEFAULT_DELAY is used.
- @param configFilename A log4j configuration file in XML format.
- */
- static void configureAndWatch(const std::string& configFilename);
-#if LOG4CXX_HAS_WCHAR_T
- static void configureAndWatch(const std::wstring& configFilename);
-#endif
- /**
- Read the configuration file configFilename if it
- exists. Moreover, a thread will be created that will periodically
- check if configFilename has been created or
- modified. The period is determined by the delay
- argument. If a change or file creation is detected, then
- configFilename is read to configure log4cxx.
-
- @param configFilename A log4j configuration file in XML format.
- @param delay The delay in milliseconds to wait between each check.
- */
- static void configureAndWatch(const std::string& configFilename,
- long delay);
-#if LOG4CXX_HAS_WCHAR_T
- static void configureAndWatch(const std::wstring& configFilename,
- long delay);
-#endif
-
- /**
- Interpret the XML file pointed by filename and set up
- log4cxx accordingly.
- The configuration is done relative to the hierarchy parameter.
- @param filename The file to parse.
- @param repository The hierarchy to operation upon.
- */
- void doConfigure(const File& filename,
- spi::LoggerRepositoryPtr& repository);
-
- protected:
- LogString subst(const LogString& value);
-
- protected:
- void * appenderBag;
-
- helpers::Properties props;
- spi::LoggerRepositoryPtr repository;
- spi::LoggerFactoryPtr loggerFactory;
-
- private:
- // prevent assignment or copy statements
- DOMConfigurator(const DOMConfigurator&);
- DOMConfigurator& operator=(const DOMConfigurator&);
- };
- } // namespace xml
-} // namespace log4cxx
-
-#endif // _LOG4CXX_XML_DOM_CONFIGURATOR_H
diff --git vm/em/src/DrlEMImpl.cpp vm/em/src/DrlEMImpl.cpp
index d067e28..5fc6d1d 100644
--- vm/em/src/DrlEMImpl.cpp
+++ vm/em/src/DrlEMImpl.cpp
@@ -21,6 +21,7 @@
#include "DrlEMImpl.h"
#include "EBProfileCollector.h"
+#include "EdgeProfileCollector.h"
#include "jit_import.h"
#include "em_intf.h"
@@ -34,10 +35,14 @@ #include
#include
-#define DEFAULT_JIT_DLL "jitrino"
#define DEFAULT_INTERPRETER_DLL "interpreter"
#define LOG_DOMAIN "em"
+#define EDGE_PROFILER_STR "EDGE_PROFILER"
+#define ENTRY_BACKEDGE_PROFILER_STR "EB_PROFILER"
+
+#define EM_CONFIG_EXT std::string(".emconf")
+
DrlEMImpl* DrlEMFactory::emInstance = NULL;
DrlEMImpl* DrlEMFactory::createAndInitEMInstance() {
@@ -67,8 +72,7 @@ void DrlEMFactory::deinitEMInstance() {
static EM_PCTYPE get_pc_type(EM_Handle _this, PC_Handle pc) {
assert(_this!=NULL);
assert(pc!=NULL);
- assert(((ProfileCollector*)pc)->type == EM_PCTYPE_ENTRY_BACKEDGE);
- return EM_PCTYPE_ENTRY_BACKEDGE;
+ return ((ProfileCollector*)pc)->type;
}
static PC_Handle get_pc(EM_Handle _this, EM_PCTYPE profile_type, JIT_Handle jh, EM_JIT_PC_Role jit_role) {
@@ -96,14 +100,13 @@ RStep::RStep(JIT_Handle _jit, const std:
//todo!! replace inlined strings with defines!!
-DrlEMImpl::DrlEMImpl() : jh(NULL), _execute_method(NULL), interpreterMode(false) {
+DrlEMImpl::DrlEMImpl() : jh(NULL), _execute_method(NULL),
+ interpreterMode(false), jitTiMode(false) {
nMethodsCompiled=0;
nMethodsRecompiled=0;
tick=0;
hymutex_create(&recompilationLock, TM_MUTEX_NESTED);
-#ifndef _EM64T_
initProfileAccess();
-#endif
}
DrlEMImpl::~DrlEMImpl() {
@@ -124,9 +127,22 @@ void DrlEMImpl::initProfileAccess() {
profileAccessInterface.eb_profiler_get_entry_threshold = eb_profiler_get_entry_threshold;
profileAccessInterface.eb_profiler_sync_mode_callback = (void (*)(Method_Profile_Handle))vm_create_helper_for_function((void *(*)(void *))eb_profiler_sync_mode_callback);
profileAccessInterface.eb_profiler_get_backedge_threshold = eb_profiler_get_backedge_threshold;
+
+
+ //EDGE profile
+ profileAccessInterface.edge_profiler_create_profile = edge_profiler_create_profile;
+ profileAccessInterface.edge_profiler_get_num_counters = edge_profiler_get_num_counters;
+ profileAccessInterface.edge_profiler_get_checksum = edge_profiler_get_checksum;
+ profileAccessInterface.edge_profiler_get_counter_addr = edge_profiler_get_counter_addr;
+ profileAccessInterface.edge_profiler_get_entry_counter_addr = edge_profiler_get_entry_counter_addr;
+ profileAccessInterface.edge_profiler_get_entry_threshold = edge_profiler_get_entry_threshold;
+ profileAccessInterface.edge_profiler_get_backedge_threshold = edge_profiler_get_backedge_threshold;
+
+ return;
}
+
void DrlEMImpl::deallocateResources() {
tbsClients.clear();
@@ -151,15 +167,32 @@ void DrlEMImpl::deallocateResources() {
//_____________________________________________________________________
// Reading and parsing configuration
+static bool endsWith(const std::string& str, const std::string& suffix) {
+ if (str.length() < suffix.length()) {
+ return false;
+ }
+ return std::equal(suffix.rbegin(), suffix.rend(), str.rbegin());
+}
-std::string buildDefaultLibPath(const std::string& dll_name) {
- std::string library_path = vm_get_property_value("vm.boot.library.path");
+std::string prepareLibPath(const std::string& origPath) {
#ifdef PLATFORM_NT
- std::string fullPath = library_path + "\\"+ dll_name+".dll";
-#else
- std::string fullPath = library_path + "/lib" + dll_name + ".so";
+ std::string separator("\\"), libPrefix(""), libSuffix(".dll");
+#else
+ std::string separator("/"), libPrefix("lib"), libSuffix(".so");
#endif
- return fullPath;
+
+ std::string path = origPath;
+ if (path.find('/') == path.npos && path.find('\\') == path.npos ) {
+ std::string dir = vm_get_property_value("vm.boot.library.path");
+ if (libPrefix.length() > 0 && !startsWith(path, libPrefix)) {
+ path = libPrefix + path;
+ }
+ path = dir + separator + path;
+ }
+ if (!endsWith(path, libSuffix)) {
+ path+=libSuffix;
+ }
+ return path;
}
static std::string getParam(const std::string& config, const std::string& name) {
@@ -213,95 +246,52 @@ static StringList getAllParamsAsList(con
return res;
}
-static std::string single2Chain(const string& pathToDll, const std::string& jitName) {
- return "chains=chain1\nchain1.jits="+jitName+"\n"+jitName+".file="+pathToDll+"\n";
-}
-
-static std::string dpgo2Chain(const string& pathToDll, bool async) {
- std::string res = std::string("chains=chain1,chain2\n")
- +"chain1.jits=JET_CLINIT\n"
- +"chain2.jits=JET_DPGO,OPT\n"
-
- +"chain1.filter=+::\n"
- +"chain1.filter=-\n"
-
- +"JET_CLINIT.file="+pathToDll+"\n"
- +"JET_DPGO.file="+pathToDll+"\n"
- +"OPT.file="+pathToDll+"\n"
-
- +"JET_DPGO.genProfile=JET_DPGO_PROFILE\n"
- +"JET_DPGO_PROFILE.profilerType=ENTRY_BACKEDGE_PROFILER\n"
- +"OPT.useProfile=JET_DPGO_PROFILE\n"
- +"JET_DPGO_PROFILE.mode="+(async ? "ASYNC" : "SYNC")+"\n"
- +"JET_DPGO_PROFILE.entryThreshold=10000\n"
- +"JET_DPGO_PROFILE.backedgeThreshold=100000\n"
- +"JET_DPGO_PROFILE.tbsTimeout=5\n"
- +"JET_DPGO_PROFILE.tbsInitialTimeout=0\n";
-
- return res;
-}
-
-static std::string readEMConfiguration() {
- std::string prop = vm_get_property_value("em.properties");
+static std::string readFile(const std::string& fileName) {
std::string config;
- bool isJet=false, isOpt = false;
- if (prop.empty()) {
-#ifdef _IPF_
- config = single2Chain(buildDefaultLibPath(std::string(DEFAULT_JIT_DLL)), std::string("JIT"));
-#else
- config = dpgo2Chain(buildDefaultLibPath(std::string(DEFAULT_JIT_DLL)), false);
-// config = single2Chain(buildDefaultLibPath(std::string(DEFAULT_JIT_DLL)), std::string("JIT"));
-#endif
- } else if (startsWith(prop, "single:")
- || (isOpt = startsWith(prop, "opt:") || prop == "opt")
- || (isJet = startsWith(prop, "jet:") || prop == "jet")) {
-
- if (isJet) {
- prop = std::string("single:")+ "JET:" + (prop.length() > 4 ? prop.substr(4) : std::string(""));
- } else if (isOpt) {
- prop = std::string("single:")+ "OPT:" + (prop.length() > 4 ? prop.substr(4) : std::string(""));
- }
- std::string jitName, fileName;
- size_t jitNameStartIdx = strlen("single:");
- size_t jitNameEndIdx = prop.find(':', jitNameStartIdx);
- if (jitNameEndIdx!=std::string::npos) {
- jitName = prop.substr(jitNameStartIdx, jitNameEndIdx - jitNameStartIdx);
- fileName = prop.substr(jitNameEndIdx+1);
- }
- if (fileName.empty()) {
- fileName = buildDefaultLibPath(std::string(DEFAULT_JIT_DLL));
+ std::ifstream configFile;
+ configFile.open(fileName.c_str(), std::ios::in);
+ bool rc = false;
+ if (configFile.is_open()) {
+ std::string line;
+ size_t idx = std::string::npos;
+ while (getline(configFile, line)) {
+ if (startsWith(line, "#")) {
+ continue;
+ } else if (startsWith(line, "-D") && (idx = line.find('=')) != std::string::npos) {
+ std::string name = line.substr(2, idx-2);
+ std::string value = line.substr(idx+1);
+ const char* old_value = vm_get_property_value(name.c_str());
+ if (old_value == NULL || *old_value == 0) {
+ vm_properties_set_value(name.c_str(), value.c_str());
+ }
+ continue;
+ }
+ config+=line + "\n";
}
- config = single2Chain(fileName, jitName);
- } else if (startsWith(prop, "dpgo:") || prop == "dpgo"
- || startsWith(prop, "dpgo_sync:") || prop == "dpgo_sync"
- || startsWith(prop, "dpgo_async:") || prop == "dpgo_async" )
- {
- bool async = startsWith(prop, "dpgo_async");
- std::string jitPath;
- size_t colonPos = prop.find(':');
- if (colonPos!= std::string::npos && prop.length() > colonPos) {
- jitPath = prop.substr(colonPos+1);
- } else {
- jitPath = buildDefaultLibPath(DEFAULT_JIT_DLL);
+ rc = !config.empty();
+ }
+ if (!rc) {
+ std::string errMsg = "EM: Can't read configuration from '" + fileName+ "'";
+ ECHO(errMsg.c_str());
+ }
+ return config;
+}
+
+std::string DrlEMImpl::readConfiguration() {
+ std::string configFileName = vm_get_property_value("em.properties");
+ if (configFileName.empty()) {
+ configFileName = jitTiMode ? "ti" : "client";
+ }
+ if (!endsWith(configFileName, EM_CONFIG_EXT)) {
+ configFileName = configFileName+EM_CONFIG_EXT;
}
- config = dpgo2Chain(jitPath, async);
- } else {
- std::ifstream configFile;
- configFile.open(prop.c_str(), std::ios::in);
- bool rc = false;
- if (configFile.is_open()) {
- std::string line;
- while (getline(configFile, line)) {
- config+=line+"\n";
- }
- rc = !config.empty();
- }
- if (!rc) {
- std::string errMsg = "EM: Can't read configuration from '" + prop + "'";
- ECHO(errMsg.c_str());
+
+ if (configFileName.find('/') == configFileName.npos && configFileName.find('\\') == configFileName.npos ) {
+ std::string defaultConfigDir = vm_get_property_value("vm.boot.library.path");
+ configFileName = defaultConfigDir + "/" + configFileName;
}
- }
+ std::string config = readFile(configFileName);
return config;
}
@@ -310,9 +300,10 @@ #endif
bool DrlEMImpl::init() {
interpreterMode = vm_get_boolean_property_value_with_default("vm.use_interpreter");
+ jitTiMode = vm_get_property_value_boolean("vm.jvmti.enabled", false);
if (interpreterMode) {
apr_dso_handle_t* libHandle;
- std::string interpreterLib = buildDefaultLibPath(DEFAULT_INTERPRETER_DLL);
+ std::string interpreterLib = prepareLibPath(DEFAULT_INTERPRETER_DLL);
jh = vm_load_jit(interpreterLib.c_str(), &libHandle);
if (jh == NULL) {
@@ -331,7 +322,7 @@ bool DrlEMImpl::init() {
}
//normal mode with recompilation chains..
_execute_method = JIT_execute_method_default;
- std::string config = readEMConfiguration();
+ std::string config = readConfiguration();
if (!config.empty()) {
buildChains(config);
}
@@ -368,6 +359,15 @@ bool DrlEMImpl::initJIT(const std::strin
return true;
}
+std::string DrlEMImpl::getJITLibFromCmdLine(const std::string& jitName) const {
+ std::string propName = std::string("em.")+jitName+".jitPath";
+ std::string jitLib = vm_get_property_value(propName.c_str());
+ if (jitLib.empty()) {
+ jitLib = vm_get_property_value("em.jitPath");
+ }
+ return jitLib;
+}
+
void DrlEMImpl::buildChains(std::string& config) {
bool loggingEnabled = is_info_enabled(LOG_DOMAIN);
StringList chainNames = getParamAsList(config, "chains", ',', true);
@@ -387,16 +387,20 @@ void DrlEMImpl::buildChains(std::string&
StringList jitsInChain= getParamAsList(config, chainName + ".jits", ',', true);
for (StringList::const_iterator jitIt = jitsInChain.begin(), jitEnd = jitsInChain.end(); jitIt!=jitEnd; ++jitIt) {
std::string jitName= *jitIt;
- std::string libName = getParam(config, jitName+".file");
- if (libName.empty()) {
- ECHO(("EM: No JIT library specified for JIT :'" + jitName+ "'").c_str());
+ std::string jitLib = getJITLibFromCmdLine(jitName);
+ if (jitLib.empty()) {
+ jitLib = getParam(config, jitName+".file");
+ }
+ if (jitLib.empty()) {
+ ECHO(("EM: No JIT library specified for JIT :'" + jitLib + "'").c_str());
failed = true;
break;
}
+ std::string fullJitLibPath = prepareLibPath(jitLib);
apr_dso_handle_t* libHandle;
- JIT_Handle jh = vm_load_jit(libName.c_str(), &libHandle); //todo: do not load the same dll twice!!!
+ JIT_Handle jh = vm_load_jit(fullJitLibPath.c_str(), &libHandle); //todo: do not load the same dll twice!!!
if (jh == NULL) {
- ECHO(("EM: JIT library loading error:'" + libName + "'").c_str());
+ ECHO(("EM: JIT library loading error:'" + fullJitLibPath + "'").c_str());
failed = true;
break;
}
@@ -404,7 +408,7 @@ void DrlEMImpl::buildChains(std::string&
step->loggingEnabled = loggingEnabled || is_info_enabled(step->catName.c_str());
chain->steps.push_back(step);
- if (!initJIT(libName, libHandle, *step)) {
+ if (!initJIT(fullJitLibPath, libHandle, *step)) {
failed = true;
break;
}
@@ -515,12 +519,13 @@ ProfileCollector* DrlEMImpl::createProfi
return NULL;
}
std::string profilerType = getParam(config, profilerName+".profilerType");
- if (profilerType!="ENTRY_BACKEDGE_PROFILER") {
+ if (profilerType!=ENTRY_BACKEDGE_PROFILER_STR && profilerType!=EDGE_PROFILER_STR) {
ECHO("EM: Unsupported profiler type");
return NULL;
}
EBProfileCollector::EB_ProfilerMode ebMode = EBProfileCollector::EB_PCMODE_SYNC;
- std::string mode = getParam(config, profilerName+".mode");
+ std::string mode = profilerType==EDGE_PROFILER_STR ? "ASYNC" : getParam(config, profilerName+".mode");
+
if (mode == "ASYNC") {
ebMode = EBProfileCollector::EB_PCMODE_ASYNC;
} else if (mode!="SYNC") {
@@ -552,7 +557,11 @@ ProfileCollector* DrlEMImpl::createProfi
return NULL;
}
}
+ if (profilerType == EDGE_PROFILER_STR) {
+ pc = new EdgeProfileCollector(this, profilerName, step->jit, tbsInitialTimeout, tbsTimeout, eThreshold, bThreshold);
+ } else {
pc = new EBProfileCollector(this, profilerName, step->jit, ebMode, eThreshold, bThreshold, tbsInitialTimeout, tbsTimeout);
+ }
return pc;
}
@@ -720,7 +729,7 @@ void DrlEMImpl::tbsTimeout() {
int DrlEMImpl::getTbsTimeout() const {
- return 100;
-}
+ return 100;
+}
+
-
diff --git vm/em/src/DrlEMImpl.h vm/em/src/DrlEMImpl.h
index a8f260e..94af23c 100644
--- vm/em/src/DrlEMImpl.h
+++ vm/em/src/DrlEMImpl.h
@@ -96,18 +96,20 @@ public:
virtual bool needTbsThreadSupport() const;
virtual void tbsTimeout();
- virtual int getTbsTimeout() const;
+ virtual int getTbsTimeout() const;
//EM PC access interface
ProfileCollector* getProfileCollector(EM_PCTYPE type, JIT_Handle jh, EM_JIT_PC_Role jitRole) const;
private:
void initProfileAccess();
+ std::string readConfiguration();
void buildChains(std::string& config);
bool initJIT(const std::string& libName, apr_dso_handle_t* libHandle, RStep& step);
bool initProfileCollectors(RChain* chain, const std::string& config);
ProfileCollector* createProfileCollector(const std::string& profilerName, const std::string& config, RStep* step);
ProfileCollector* getProfileCollector(const std::string& name) const;
+ std::string getJITLibFromCmdLine(const std::string& jitName) const;
void deallocateResources();
@@ -115,6 +117,7 @@ private:
JIT_Handle jh;
void (*_execute_method) (JIT_Handle jit, jmethodID method, jvalue *return_value, jvalue *args);
bool interpreterMode;
+ bool jitTiMode;
RChains chains;
size_t nMethodsCompiled, nMethodsRecompiled;
diff --git vm/em/src/EdgeProfileCollector.cpp vm/em/src/EdgeProfileCollector.cpp
new file mode 100644
index 0000000..07e0e53
--- /dev/null
+++ vm/em/src/EdgeProfileCollector.cpp
@@ -0,0 +1,270 @@
+/*
+* Copyright 2005 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 Jack Liu, Mikhail Y. Fursov, Chen-Dong Yuan
+* @version $Revision$
+*/
+
+#include "EdgeProfileCollector.h"
+
+#include
+#include
+#include "cxxlog.h"
+#include
+
+#define LOG_DOMAIN "em"
+
+Method_Profile_Handle edge_profiler_create_profile( PC_Handle ph,
+ Method_Handle mh,
+ uint32 numCounters,
+ uint32* counterKeys,
+ uint32 checkSum )
+{
+ ProfileCollector* pc = (ProfileCollector*)ph;
+ assert(pc->type == EM_PCTYPE_EDGE);
+
+ EdgeMethodProfile* profile =
+ ((EdgeProfileCollector*)pc)->createProfile(mh, numCounters, counterKeys, checkSum);
+ return (Method_Profile_Handle)profile;
+}
+
+void* edge_profiler_get_entry_counter_addr(Method_Profile_Handle mph) {
+ MethodProfile* mp = (MethodProfile*)mph;
+ assert(mp->pc->type == EM_PCTYPE_EDGE);
+ EdgeMethodProfile* emp = (EdgeMethodProfile*)mp;
+ return &emp->entryCounter;
+}
+
+void* edge_profiler_get_counter_addr(Method_Profile_Handle mph, uint32 key)
+{
+ MethodProfile* mp = (MethodProfile*)mph;
+ assert(mp->pc->type == EM_PCTYPE_EDGE);
+ return ((EdgeMethodProfile*)mp)->getCounter( key );
+}
+
+
+uint32 edge_profiler_get_num_counters(Method_Profile_Handle mph)
+{
+ MethodProfile* mp = (MethodProfile*)mph;
+ assert(mp->pc->type == EM_PCTYPE_EDGE);
+ return ((EdgeMethodProfile*)mp)->counters.size();
+}
+
+
+uint32 edge_profiler_get_checksum(Method_Profile_Handle mph)
+{
+ MethodProfile* mp = (MethodProfile*)mph;
+ assert(mp->pc->type == EM_PCTYPE_EDGE);
+ return ((EdgeMethodProfile*)mp)->checkSum;
+}
+
+uint32 edge_profiler_get_entry_threshold(PC_Handle pch) {
+ assert(pch!=NULL);
+ ProfileCollector* pc = (ProfileCollector*)pch;
+ assert(pc->type == EM_PCTYPE_EDGE);
+ return ((EdgeProfileCollector*)pc)->getEntryThreshold();
+}
+
+uint32 edge_profiler_get_backedge_threshold(PC_Handle pch) {
+ assert(pch!=NULL);
+ ProfileCollector* pc = (ProfileCollector*)pch;
+ assert(pc->type == EM_PCTYPE_EDGE);
+ return ((EdgeProfileCollector*)pc)->getBackedgeThreshold();
+}
+
+
+
+
+EdgeProfileCollector::EdgeProfileCollector(EM_PC_Interface* em, const std::string& name, JIT_Handle genJit,
+ uint32 _initialTimeout, uint32 _timeout,
+ uint32 _eThreshold, uint32 _bThreshold)
+ : ProfileCollector(em, name, EM_PCTYPE_EDGE, genJit), initialTimeout(_initialTimeout),
+ timeout(_timeout),eThreshold(_eThreshold), bThreshold(_bThreshold)
+{
+ hymutex_create(&profilesLock, TM_MUTEX_NESTED);
+ catName = std::string(LOG_DOMAIN) + ".profiler." + name;
+ loggingEnabled = is_info_enabled(LOG_DOMAIN) || is_info_enabled(catName.c_str());
+ if (loggingEnabled) {
+ std::ostringstream msg;
+ msg<< "EM: edge profiler intialized: "<second;
+ delete profile;
+ }
+ hymutex_destroy(profilesLock);
+}
+
+
+MethodProfile* EdgeProfileCollector::getMethodProfile(Method_Handle mh) const
+{
+ EdgeProfilesMap::const_iterator it = profilesByMethod.find(mh);
+ if (it == profilesByMethod.end()) {
+ return NULL;
+ }
+ return it->second;
+}
+
+
+
+uint32* EdgeMethodProfile::getCounter( uint32 key ) const
+{
+ //log2 search
+ EdgeMap::const_iterator it = lower_bound(cntMap.begin(), cntMap.end(), key);
+ assert(it!=cntMap.end());
+ uint32 val = *it;
+ if (val!=key) {
+ return NULL;
+ }
+ uint32 idx = it - cntMap.begin();
+ return (uint32*)&counters.front() + idx;
+}
+
+void EdgeMethodProfile::dump( const char* banner )
+{
+ const char* methodName = method_get_name(mh);
+ Class_Handle ch = method_get_class(mh);
+ const char* className = class_get_name(ch);
+ const char* signature = method_get_descriptor(mh);
+ uint32 backEdgeCounter = entryCounter;
+ uint32 instrCost = entryCounter;
+
+ assert( banner != NULL );
+
+ fprintf( stderr, "%s: %s::%s%s\n", banner, className, methodName, signature );
+
+ for( uint32 i = 0; i < counters.size(); i++ ){
+ instrCost += counters[i];
+ if( counters[i] > backEdgeCounter ){
+ backEdgeCounter = counters[i];
+ }
+ }
+
+ assert( instrCost >= backEdgeCounter );
+
+ fprintf( stderr, "\t%s entry: %d\tcounters: %d\tbackedge: %d\tcost: %u\n",
+ _isHot ? "hot" : "cold",
+ entryCounter, counters.size(), backEdgeCounter, instrCost );
+
+ return;
+}
+
+
+EdgeMethodProfile* EdgeProfileCollector::createProfile( Method_Handle mh,
+ uint32 numCounters,
+ uint32* counterKeys,
+ uint32 checkSum)
+{
+ hymutex_lock(profilesLock);
+
+ EdgeMethodProfile* profile = new EdgeMethodProfile(this, mh);
+
+ // Allocate space for edge counters.
+ assert( profile->cntMap.empty() );
+ profile->counters.resize(numCounters);
+ profile->checkSum = checkSum;
+ profile->cntMap.insert(profile->cntMap.begin(), counterKeys, counterKeys + numCounters);
+ std::sort(profile->cntMap.begin(), profile->cntMap.end());
+
+ assert(std::adjacent_find(profile->cntMap.begin(), profile->cntMap.end())==profile->cntMap.end());
+ assert(profilesByMethod.find(mh) == profilesByMethod.end());
+ profilesByMethod[mh] = profile;
+ newProfiles.push_back(profile);
+
+ hymutex_unlock(profilesLock);
+
+ return profile;
+}
+
+
+bool EdgeProfileCollector::isMethodHot( EdgeMethodProfile* profile )
+{
+ uint32 entryCounter = profile->entryCounter;
+ if( entryCounter >= eThreshold ){
+ return true;
+ }
+
+ const uint32 cutoff = bThreshold;
+
+ for( uint32 i = 0; i < profile->counters.size(); i++ ){
+ if( profile->counters[i] >= cutoff ){
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+static void logReadyProfile(const std::string& catName, const std::string& profilerName, EdgeMethodProfile* mp) {
+ const char* methodName = method_get_name(mp->mh);
+ Class_Handle ch = method_get_class(mp->mh);
+ const char* className = class_get_name(ch);
+ const char* signature = method_get_descriptor(mp->mh);
+
+ uint32 backEgdeMaxValue = mp->counters.empty() ? 0 : *std::max_element( mp->counters.begin(), mp->counters.end());
+ std::ostringstream msg;
+ msg <<"EM: profiler["<entryCounter<<" b:"<::iterator it = greenProfiles.begin();
+ std::vector::iterator end = greenProfiles.end();
+
+ while( it != end ){
+ EdgeMethodProfile* profile = *it;
+
+ if( isMethodHot( profile ) ){
+ profile->setHotMethod();
+ tmpProfiles.push_back(profile);
+ *it = NULL;
+ }
+ it++;
+ }
+
+ if (!tmpProfiles.empty()) {
+ std::remove(greenProfiles.begin(), greenProfiles.end(), (EdgeMethodProfile*)NULL);
+ greenProfiles.resize(greenProfiles.size() - tmpProfiles.size());
+ for (std::vector::iterator it = tmpProfiles.begin(), end = tmpProfiles.end(); it!=end; ++it) {
+ EdgeMethodProfile* profile = *it;
+ if (loggingEnabled) {
+ logReadyProfile(catName, name, profile);
+ }
+ em->methodProfileIsReady(profile);
+ }
+ tmpProfiles.clear();
+ }
+
+ return;
+}
diff --git vm/em/src/EdgeProfileCollector.h vm/em/src/EdgeProfileCollector.h
new file mode 100644
index 0000000..11a5a40
--- /dev/null
+++ vm/em/src/EdgeProfileCollector.h
@@ -0,0 +1,101 @@
+/*
+* Copyright 2005 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 Jack Liu, Mikhail Y. Fursov, Chen-Dong Yuan
+* @version $Revision$
+*/
+
+#ifndef _EDGE_PROFILE_COLLECTOR_H_
+#define _EDGE_PROFILE_COLLECTOR_H_
+
+#include "DrlProfileCollectionFramework.h"
+#include "open/vm_util.h"
+
+#include
+#include