Added runtime call to the logging infrastructure. Made some changes
to the way regexps are being logged. git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1028 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
2458742734
commit
afcc36a417
@ -2577,6 +2577,19 @@ void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CodeGenerator::GenerateLog(ZoneList<Expression*>* args) {
|
||||||
|
// See comment in CodeGenerator::GenerateLog in codegen-ia32.cc.
|
||||||
|
ASSERT_EQ(args->length(), 3);
|
||||||
|
if (ShouldGenerateLog(args->at(0))) {
|
||||||
|
Load(args->at(1));
|
||||||
|
Load(args->at(2));
|
||||||
|
__ CallRuntime(Runtime::kLog, 2);
|
||||||
|
}
|
||||||
|
__ mov(r0, Operand(Factory::undefined_value()));
|
||||||
|
frame_->Push(r0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) {
|
void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) {
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
Load(args->at(0));
|
Load(args->at(0));
|
||||||
|
@ -195,6 +195,8 @@ class CodeGenerator: public AstVisitor {
|
|||||||
Handle<Script> script,
|
Handle<Script> script,
|
||||||
bool is_eval);
|
bool is_eval);
|
||||||
|
|
||||||
|
static bool ShouldGenerateLog(Expression* type);
|
||||||
|
|
||||||
static void SetFunctionInfo(Handle<JSFunction> fun,
|
static void SetFunctionInfo(Handle<JSFunction> fun,
|
||||||
int length,
|
int length,
|
||||||
int function_token_position,
|
int function_token_position,
|
||||||
@ -324,6 +326,8 @@ class CodeGenerator: public AstVisitor {
|
|||||||
// Fast support for object equality testing.
|
// Fast support for object equality testing.
|
||||||
void GenerateObjectEquals(ZoneList<Expression*>* args);
|
void GenerateObjectEquals(ZoneList<Expression*>* args);
|
||||||
|
|
||||||
|
void GenerateLog(ZoneList<Expression*>* args);
|
||||||
|
|
||||||
// Methods and constants for fast case switch statement support.
|
// Methods and constants for fast case switch statement support.
|
||||||
//
|
//
|
||||||
// Only allow fast-case switch if the range of labels is at most
|
// Only allow fast-case switch if the range of labels is at most
|
||||||
|
@ -2900,6 +2900,25 @@ void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CodeGenerator::GenerateLog(ZoneList<Expression*>* args) {
|
||||||
|
// Conditionally generate a log call.
|
||||||
|
// Args:
|
||||||
|
// 0 (literal string): The type of logging (corresponds to the flags).
|
||||||
|
// This is used to determine whether or not to generate the log call.
|
||||||
|
// 1 (string): Format string. Access the string at argument index 2
|
||||||
|
// with '%2s' (see Logger::LogRuntime for all the formats).
|
||||||
|
// 2 (array): Arguments to the format string.
|
||||||
|
ASSERT_EQ(args->length(), 3);
|
||||||
|
if (ShouldGenerateLog(args->at(0))) {
|
||||||
|
Load(args->at(1));
|
||||||
|
Load(args->at(2));
|
||||||
|
__ CallRuntime(Runtime::kLog, 2);
|
||||||
|
}
|
||||||
|
// Finally, we're expected to leave a value on the top of the stack.
|
||||||
|
frame_->Push(Immediate(Factory::undefined_value()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) {
|
void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) {
|
||||||
ASSERT(args->length() == 1);
|
ASSERT(args->length() == 1);
|
||||||
Load(args->at(0));
|
Load(args->at(0));
|
||||||
|
@ -201,6 +201,8 @@ class CodeGenerator: public AstVisitor {
|
|||||||
Handle<Script> script,
|
Handle<Script> script,
|
||||||
bool is_eval);
|
bool is_eval);
|
||||||
|
|
||||||
|
static bool ShouldGenerateLog(Expression* type);
|
||||||
|
|
||||||
static void SetFunctionInfo(Handle<JSFunction> fun,
|
static void SetFunctionInfo(Handle<JSFunction> fun,
|
||||||
int length,
|
int length,
|
||||||
int function_token_position,
|
int function_token_position,
|
||||||
@ -348,6 +350,8 @@ class CodeGenerator: public AstVisitor {
|
|||||||
// Fast support for object equality testing.
|
// Fast support for object equality testing.
|
||||||
void GenerateObjectEquals(ZoneList<Expression*>* args);
|
void GenerateObjectEquals(ZoneList<Expression*>* args);
|
||||||
|
|
||||||
|
void GenerateLog(ZoneList<Expression*>* args);
|
||||||
|
|
||||||
|
|
||||||
// Methods and constants for fast case switch statement support.
|
// Methods and constants for fast case switch statement support.
|
||||||
//
|
//
|
||||||
|
@ -163,6 +163,19 @@ Handle<Code> CodeGenerator::MakeCode(FunctionLiteral* flit,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool CodeGenerator::ShouldGenerateLog(Expression* type) {
|
||||||
|
ASSERT(type != NULL);
|
||||||
|
if (!Logger::is_enabled()) return false;
|
||||||
|
Handle<String> name = Handle<String>::cast(type->AsLiteral()->handle());
|
||||||
|
if (FLAG_log_regexp) {
|
||||||
|
static Vector<const char> kRegexp = CStrVector("regexp");
|
||||||
|
if (name->IsEqualTo(kRegexp))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Sets the function info on a function.
|
// Sets the function info on a function.
|
||||||
// The start_position points to the first '(' character after the function name
|
// The start_position points to the first '(' character after the function name
|
||||||
// in the full script source. When counting characters in the script source the
|
// in the full script source. When counting characters in the script source the
|
||||||
@ -338,7 +351,9 @@ bool CodeGenerator::CheckForInlineRuntimeCall(CallRuntime* node) {
|
|||||||
{&v8::internal::CodeGenerator::GenerateFastCharCodeAt,
|
{&v8::internal::CodeGenerator::GenerateFastCharCodeAt,
|
||||||
"_FastCharCodeAt"},
|
"_FastCharCodeAt"},
|
||||||
{&v8::internal::CodeGenerator::GenerateObjectEquals,
|
{&v8::internal::CodeGenerator::GenerateObjectEquals,
|
||||||
"_ObjectEquals"}
|
"_ObjectEquals"},
|
||||||
|
{&v8::internal::CodeGenerator::GenerateLog,
|
||||||
|
"_Log"}
|
||||||
};
|
};
|
||||||
Handle<String> name = node->name();
|
Handle<String> name = node->name();
|
||||||
StringShape shape(*name);
|
StringShape shape(*name);
|
||||||
|
@ -373,7 +373,6 @@ Handle<Object> RegExpImpl::AtomExec(Handle<JSRegExp> re,
|
|||||||
return Handle<Smi>(Smi::FromInt(-1));
|
return Handle<Smi>(Smi::FromInt(-1));
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG(RegExpExecEvent(re, start_index, subject));
|
|
||||||
int value = Runtime::StringMatch(subject, needle, start_index);
|
int value = Runtime::StringMatch(subject, needle, start_index);
|
||||||
if (value == -1) return Factory::null_value();
|
if (value == -1) return Factory::null_value();
|
||||||
|
|
||||||
@ -393,7 +392,6 @@ Handle<Object> RegExpImpl::AtomExecGlobal(Handle<JSRegExp> re,
|
|||||||
int subject_length = subject->length();
|
int subject_length = subject->length();
|
||||||
int needle_length = needle->length();
|
int needle_length = needle->length();
|
||||||
while (true) {
|
while (true) {
|
||||||
LOG(RegExpExecEvent(re, index, subject));
|
|
||||||
int value = -1;
|
int value = -1;
|
||||||
if (index + needle_length <= subject_length) {
|
if (index + needle_length <= subject_length) {
|
||||||
value = Runtime::StringMatch(subject, needle, index);
|
value = Runtime::StringMatch(subject, needle, index);
|
||||||
@ -575,8 +573,6 @@ Handle<Object> RegExpImpl::JscreExecOnce(Handle<JSRegExp> regexp,
|
|||||||
reinterpret_cast<v8::jscre::JscreRegExp*>(
|
reinterpret_cast<v8::jscre::JscreRegExp*>(
|
||||||
internal->GetDataStartAddress());
|
internal->GetDataStartAddress());
|
||||||
|
|
||||||
LOG(RegExpExecEvent(regexp, previous_index, subject));
|
|
||||||
|
|
||||||
rc = v8::jscre::jsRegExpExecute(js_regexp,
|
rc = v8::jscre::jsRegExpExecute(js_regexp,
|
||||||
two_byte_subject,
|
two_byte_subject,
|
||||||
subject->length(),
|
subject->length(),
|
||||||
@ -791,7 +787,6 @@ Handle<Object> RegExpImpl::IrregexpExec(Handle<JSRegExp> regexp,
|
|||||||
PrintF("\n\nSubject string: '%s'\n\n", *(subject->ToCString()));
|
PrintF("\n\nSubject string: '%s'\n\n", *(subject->ToCString()));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
LOG(RegExpExecEvent(regexp, previous_index, subject));
|
|
||||||
|
|
||||||
if (!subject->IsFlat(StringShape(*subject))) {
|
if (!subject->IsFlat(StringShape(*subject))) {
|
||||||
FlattenString(subject);
|
FlattenString(subject);
|
||||||
@ -845,7 +840,6 @@ Handle<Object> RegExpImpl::IrregexpExecGlobal(Handle<JSRegExp> regexp,
|
|||||||
PrintF("\n\nSubject string: '%s'\n\n", *(subject->ToCString()));
|
PrintF("\n\nSubject string: '%s'\n\n", *(subject->ToCString()));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
LOG(RegExpExecEvent(regexp, previous_index, subject));
|
|
||||||
matches = IrregexpExecOnce(irregexp,
|
matches = IrregexpExecOnce(irregexp,
|
||||||
IrregexpNumberOfCaptures(irregexp),
|
IrregexpNumberOfCaptures(irregexp),
|
||||||
subject,
|
subject,
|
||||||
|
61
src/log.cc
61
src/log.cc
@ -350,11 +350,19 @@ void Logger::SharedLibraryEvent(const wchar_t* library_path,
|
|||||||
|
|
||||||
|
|
||||||
#ifdef ENABLE_LOGGING_AND_PROFILING
|
#ifdef ENABLE_LOGGING_AND_PROFILING
|
||||||
void Logger::LogString(Handle<String> str) {
|
void Logger::LogString(Handle<String> str, bool show_impl_info) {
|
||||||
StringShape shape(*str);
|
StringShape shape(*str);
|
||||||
int len = str->length(shape);
|
int len = str->length(shape);
|
||||||
if (len > 256)
|
if (len > 0x1000)
|
||||||
len = 256;
|
len = 0x1000;
|
||||||
|
if (show_impl_info) {
|
||||||
|
fputc(shape.IsAsciiRepresentation() ? 'a' : '2', logfile_);
|
||||||
|
if (shape.IsExternal())
|
||||||
|
fputc('e', logfile_);
|
||||||
|
if (shape.IsSymbol())
|
||||||
|
fputc('#', logfile_);
|
||||||
|
fprintf(logfile_, ":%i:", str->length());
|
||||||
|
}
|
||||||
for (int i = 0; i < len; i++) {
|
for (int i = 0; i < len; i++) {
|
||||||
uc32 c = str->Get(shape, i);
|
uc32 c = str->Get(shape, i);
|
||||||
if (c > 0xff) {
|
if (c > 0xff) {
|
||||||
@ -389,7 +397,7 @@ void Logger::LogRegExpSource(Handle<JSRegExp> regexp) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
fprintf(logfile_, "/");
|
fprintf(logfile_, "/");
|
||||||
LogString(Handle<String>::cast(source));
|
LogString(Handle<String>::cast(source), false);
|
||||||
fprintf(logfile_, "/");
|
fprintf(logfile_, "/");
|
||||||
|
|
||||||
// global flag
|
// global flag
|
||||||
@ -423,19 +431,40 @@ void Logger::RegExpCompileEvent(Handle<JSRegExp> regexp, bool in_cache) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Logger::RegExpExecEvent(Handle<JSRegExp> regexp,
|
void Logger::LogRuntime(Vector<const char> format, JSArray* args) {
|
||||||
int start_index,
|
|
||||||
Handle<String> input_string) {
|
|
||||||
#ifdef ENABLE_LOGGING_AND_PROFILING
|
|
||||||
if (logfile_ == NULL || !FLAG_log_regexp) return;
|
|
||||||
ScopedLock sl(mutex_);
|
ScopedLock sl(mutex_);
|
||||||
|
HandleScope scope;
|
||||||
fprintf(logfile_, "regexp-run,");
|
for (int i = 0; i < format.length(); i++) {
|
||||||
LogRegExpSource(regexp);
|
char c = format[i];
|
||||||
fprintf(logfile_, ",");
|
if (c == '%' && i <= format.length() - 2) {
|
||||||
LogString(input_string);
|
i++;
|
||||||
fprintf(logfile_, ",%d..%d\n", start_index, input_string->length());
|
ASSERT('0' <= format[i] && format[i] <= '9');
|
||||||
#endif
|
Object* obj = args->GetElement(format[i] - '0');
|
||||||
|
i++;
|
||||||
|
switch (format[i]) {
|
||||||
|
case 's':
|
||||||
|
Logger::LogString(Handle<String>(String::cast(obj)), false);
|
||||||
|
break;
|
||||||
|
case 'S':
|
||||||
|
Logger::LogString(Handle<String>(String::cast(obj)), true);
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
Logger::LogRegExpSource(Handle<JSRegExp>(JSRegExp::cast(obj)));
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
fprintf(logfile_, "0x%x", Smi::cast(obj)->value());
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
fprintf(logfile_, "%i", Smi::cast(obj)->value());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fputc(c, logfile_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fputc('\n', logfile_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
15
src/log.h
15
src/log.h
@ -72,7 +72,11 @@ class SlidingStateWindow;
|
|||||||
|
|
||||||
#undef LOG
|
#undef LOG
|
||||||
#ifdef ENABLE_LOGGING_AND_PROFILING
|
#ifdef ENABLE_LOGGING_AND_PROFILING
|
||||||
#define LOG(Call) v8::internal::Logger::Call
|
#define LOG(Call) \
|
||||||
|
do { \
|
||||||
|
if (v8::internal::Logger::is_enabled()) \
|
||||||
|
v8::internal::Logger::Call; \
|
||||||
|
} while (false)
|
||||||
#else
|
#else
|
||||||
#define LOG(Call) ((void) 0)
|
#define LOG(Call) ((void) 0)
|
||||||
#endif
|
#endif
|
||||||
@ -189,9 +193,8 @@ class Logger {
|
|||||||
|
|
||||||
static void RegExpCompileEvent(Handle<JSRegExp> regexp, bool in_cache);
|
static void RegExpCompileEvent(Handle<JSRegExp> regexp, bool in_cache);
|
||||||
|
|
||||||
static void RegExpExecEvent(Handle<JSRegExp> regexp,
|
// Log an event reported from generated code
|
||||||
int start_index,
|
static void LogRuntime(Vector<const char> format, JSArray* args);
|
||||||
Handle<String> input_string);
|
|
||||||
|
|
||||||
#ifdef ENABLE_LOGGING_AND_PROFILING
|
#ifdef ENABLE_LOGGING_AND_PROFILING
|
||||||
static StateTag state() {
|
static StateTag state() {
|
||||||
@ -199,13 +202,15 @@ class Logger {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static bool is_enabled() { return logfile_ != NULL; }
|
||||||
|
|
||||||
#ifdef ENABLE_LOGGING_AND_PROFILING
|
#ifdef ENABLE_LOGGING_AND_PROFILING
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// Emits the source code of a regexp. Used by regexp events.
|
// Emits the source code of a regexp. Used by regexp events.
|
||||||
static void LogRegExpSource(Handle<JSRegExp> regexp);
|
static void LogRegExpSource(Handle<JSRegExp> regexp);
|
||||||
|
|
||||||
static void LogString(Handle<String> str);
|
static void LogString(Handle<String> str, bool show_impl_info);
|
||||||
|
|
||||||
// Emits a profiler tick event. Used by the profiler thread.
|
// Emits a profiler tick event. Used by the profiler thread.
|
||||||
static void TickEvent(TickSample* sample, bool overflow);
|
static void TickEvent(TickSample* sample, bool overflow);
|
||||||
|
@ -178,6 +178,7 @@ function RegExpExec(string) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
%_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, s, lastIndex]);
|
||||||
// matchIndices is an array of integers with length of captures*2,
|
// matchIndices is an array of integers with length of captures*2,
|
||||||
// each pair of integers specified the start and the end of index
|
// each pair of integers specified the start and the end of index
|
||||||
// in the string.
|
// in the string.
|
||||||
|
@ -5840,6 +5840,16 @@ static Object* Runtime_ListNatives(Arguments args) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
static Object* Runtime_Log(Arguments args) {
|
||||||
|
ASSERT(args.length() == 2);
|
||||||
|
String* format = String::cast(args[0]);
|
||||||
|
Vector<const char> chars = format->ToAsciiVector();
|
||||||
|
JSArray* elms = JSArray::cast(args[1]);
|
||||||
|
Logger::LogRuntime(chars, elms);
|
||||||
|
return Heap::undefined_value();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static Object* Runtime_IS_VAR(Arguments args) {
|
static Object* Runtime_IS_VAR(Arguments args) {
|
||||||
UNREACHABLE(); // implemented as macro in the parser
|
UNREACHABLE(); // implemented as macro in the parser
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -285,6 +285,8 @@ namespace v8 { namespace internal {
|
|||||||
F(DebugBreak, 0) \
|
F(DebugBreak, 0) \
|
||||||
F(FunctionGetAssemblerCode, 1) \
|
F(FunctionGetAssemblerCode, 1) \
|
||||||
F(Abort, 2) \
|
F(Abort, 2) \
|
||||||
|
/* Logging */ \
|
||||||
|
F(Log, 2) \
|
||||||
\
|
\
|
||||||
/* Pseudo functions - handled as macros by parser */ \
|
/* Pseudo functions - handled as macros by parser */ \
|
||||||
F(IS_VAR, 1)
|
F(IS_VAR, 1)
|
||||||
|
@ -152,6 +152,7 @@ function StringMatch(regexp) {
|
|||||||
var subject = ToString(this);
|
var subject = ToString(this);
|
||||||
|
|
||||||
if (!regexp.global) return regexp.exec(subject);
|
if (!regexp.global) return regexp.exec(subject);
|
||||||
|
%_Log('regexp', 'regexp-match,%0S,%1r', [subject, regexp]);
|
||||||
var matches = DoRegExpExecGlobal(regexp, subject);
|
var matches = DoRegExpExecGlobal(regexp, subject);
|
||||||
|
|
||||||
// If the regexp did not match, return null.
|
// If the regexp did not match, return null.
|
||||||
@ -185,6 +186,7 @@ function StringReplace(search, replace) {
|
|||||||
|
|
||||||
// Delegate to one of the regular expression variants if necessary.
|
// Delegate to one of the regular expression variants if necessary.
|
||||||
if (IS_REGEXP(search)) {
|
if (IS_REGEXP(search)) {
|
||||||
|
%_Log('regexp', 'regexp-replace,%0r,%1S', [search, subject]);
|
||||||
if (IS_FUNCTION(replace)) {
|
if (IS_FUNCTION(replace)) {
|
||||||
return StringReplaceRegExpWithFunction(subject, search, replace);
|
return StringReplaceRegExpWithFunction(subject, search, replace);
|
||||||
} else {
|
} else {
|
||||||
@ -513,7 +515,13 @@ function StringSplit(separator, limit) {
|
|||||||
var currentIndex = 0;
|
var currentIndex = 0;
|
||||||
var startIndex = 0;
|
var startIndex = 0;
|
||||||
|
|
||||||
var sep = IS_REGEXP(separator) ? separator : ToString(separator);
|
var sep;
|
||||||
|
if (IS_REGEXP(separator)) {
|
||||||
|
sep = separator;
|
||||||
|
%_Log('regexp', 'regexp-split,%0S,%1r', [subject, sep]);
|
||||||
|
} else {
|
||||||
|
sep = ToString(separator);
|
||||||
|
}
|
||||||
|
|
||||||
if (length === 0) {
|
if (length === 0) {
|
||||||
if (splitMatch(sep, subject, 0, 0) != null) return result;
|
if (splitMatch(sep, subject, 0, 0) != null) return result;
|
||||||
|
@ -123,7 +123,8 @@ var knownProblems = {
|
|||||||
"CreateObjectLiteralBoilerplate": true,
|
"CreateObjectLiteralBoilerplate": true,
|
||||||
"CloneObjectLiteralBoilerplate": true,
|
"CloneObjectLiteralBoilerplate": true,
|
||||||
"IS_VAR": true,
|
"IS_VAR": true,
|
||||||
"ResolvePossiblyDirectEval": true
|
"ResolvePossiblyDirectEval": true,
|
||||||
|
"Log": true
|
||||||
};
|
};
|
||||||
|
|
||||||
var currentlyUncallable = {
|
var currentlyUncallable = {
|
||||||
|
Loading…
Reference in New Issue
Block a user