Revision: 3351 Author: [email protected] Date: Tue Nov 24 06:29:16 2009 Log: Push version 2.0.2 to trunk.
Improved profiler support. Fixed bug that broke compilation of d8 with readline support. http://code.google.com/p/v8/source/detail?r=3351 Modified: /trunk/ChangeLog /trunk/src/allocation.h /trunk/src/builtins.cc /trunk/src/compiler.cc /trunk/src/flag-definitions.h /trunk/src/log-inl.h /trunk/src/log.cc /trunk/src/log.h /trunk/src/serialize.cc /trunk/src/v8.cc /trunk/src/version.cc /trunk/test/cctest/test-log.cc /trunk/test/cctest/test-thread-termination.cc /trunk/tools/gyp/v8.gyp ======================================= --- /trunk/ChangeLog Fri Nov 20 04:14:52 2009 +++ /trunk/ChangeLog Tue Nov 24 06:29:16 2009 @@ -1,3 +1,10 @@ +2009-11-24: Version 2.0.2 + + Improved profiler support. + + Fixed bug that broke compilation of d8 with readline support. + + 2009-11-20: Version 2.0.1 Fixed crash bug in String.prototype.replace. ======================================= --- /trunk/src/allocation.h Mon May 25 22:44:31 2009 +++ /trunk/src/allocation.h Tue Nov 24 06:29:16 2009 @@ -124,7 +124,7 @@ // and StrNDup uses new and calls the FatalProcessOutOfMemory handler // if allocation fails. char* StrDup(const char* str); -char* StrNDup(const char* str, size_t n); +char* StrNDup(const char* str, int n); // Allocation policy for allocating in the C free store using malloc ======================================= --- /trunk/src/builtins.cc Wed Oct 28 07:53:37 2009 +++ /trunk/src/builtins.cc Tue Nov 24 06:29:16 2009 @@ -380,6 +380,9 @@ { // Leaving JavaScript. VMState state(EXTERNAL); +#ifdef ENABLE_LOGGING_AND_PROFILING + state.set_external_callback(v8::ToCData<Address>(callback_obj)); +#endif value = callback(new_args); } if (value.IsEmpty()) { @@ -446,6 +449,9 @@ { // Leaving JavaScript. VMState state(EXTERNAL); +#ifdef ENABLE_LOGGING_AND_PROFILING + state.set_external_callback(v8::ToCData<Address>(callback_obj)); +#endif value = callback(new_args); } if (value.IsEmpty()) { ======================================= --- /trunk/src/compiler.cc Fri Nov 20 04:14:52 2009 +++ /trunk/src/compiler.cc Tue Nov 24 06:29:16 2009 @@ -646,9 +646,8 @@ void CodeGenSelector::VisitDeclaration(Declaration* decl) { - Variable* var = decl->proxy()->var(); - if (!var->is_global() || var->mode() == Variable::CONST) { - BAILOUT("Non-global declaration"); + if (decl->fun() != NULL) { + ProcessExpression(decl->fun(), Expression::kValue); } } ======================================= --- /trunk/src/flag-definitions.h Wed Nov 18 06:12:51 2009 +++ /trunk/src/flag-definitions.h Tue Nov 24 06:29:16 2009 @@ -143,7 +143,7 @@ DEFINE_bool(strict, false, "strict error checking") DEFINE_int(min_preparse_length, 1024, "minimum length for automatic enable preparsing") -DEFINE_bool(fast_compiler, true, +DEFINE_bool(fast_compiler, false, "use the fast-mode compiler for some top-level code") DEFINE_bool(trace_bailout, false, "print reasons for failing to use fast compilation") ======================================= --- /trunk/src/log-inl.h Wed Sep 9 12:27:10 2009 +++ /trunk/src/log-inl.h Tue Nov 24 06:29:16 2009 @@ -55,7 +55,7 @@ } } -VMState::VMState(StateTag state) : disabled_(true) { +VMState::VMState(StateTag state) : disabled_(true), external_callback_(NULL) { if (!Logger::is_logging()) { return; } ======================================= --- /trunk/src/log.cc Wed Nov 18 06:12:51 2009 +++ /trunk/src/log.cc Tue Nov 24 06:29:16 2009 @@ -30,6 +30,7 @@ #include "v8.h" #include "bootstrapper.h" +#include "global-handles.h" #include "log.h" #include "macro-assembler.h" #include "serialize.h" @@ -153,13 +154,19 @@ sample->frames_count = 0; return; } + + int i = 0; + const Address callback = Logger::current_state_ != NULL ? + Logger::current_state_->external_callback() : NULL; + if (callback != NULL) { + sample->stack[i++] = callback; + } SafeStackTraceFrameIterator it( reinterpret_cast<Address>(sample->fp), reinterpret_cast<Address>(sample->sp), reinterpret_cast<Address>(sample->sp), js_entry_sp); - int i = 0; while (!it.done() && i < TickSample::kMaxFramesCount) { sample->stack[i++] = it.frame()->pc(); it.Advance(); @@ -673,6 +680,26 @@ #endif // ENABLE_LOGGING_AND_PROFILING +void Logger::CallbackEvent(String* name, Address entry_point) { +#ifdef ENABLE_LOGGING_AND_PROFILING + if (!Log::IsEnabled() || !FLAG_log_code) return; + LogMessageBuilder msg; + msg.Append("%s,%s,", + log_events_[CODE_CREATION_EVENT], log_events_[CALLBACK_TAG]); + msg.AppendAddress(entry_point); + SmartPointer<char> str = + name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL); + msg.Append(",1,\"%s\"", *str); + if (FLAG_compress_log) { + ASSERT(compression_helper_ != NULL); + if (!compression_helper_->HandleMessage(&msg)) return; + } + msg.Append('\n'); + msg.WriteToLogFile(); +#endif +} + + void Logger::CodeCreateEvent(LogEventsAndTags tag, Code* code, const char* comment) { @@ -1191,11 +1218,25 @@ LOG(CodeCreateEvent(Logger::SCRIPT_TAG, shared->code(), *script_name)); } - continue; - } - } - // If no script or script has no name. - LOG(CodeCreateEvent(Logger::LAZY_COMPILE_TAG, shared->code(), *func_name)); + } else { + LOG(CodeCreateEvent( + Logger::LAZY_COMPILE_TAG, shared->code(), *func_name)); + } + } else if (shared->function_data()->IsFunctionTemplateInfo()) { + // API function. + FunctionTemplateInfo* fun_data = + FunctionTemplateInfo::cast(shared->function_data()); + Object* raw_call_data = fun_data->call_code(); + if (!raw_call_data->IsUndefined()) { + CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data); + Object* callback_obj = call_data->callback(); + Address entry_point = v8::ToCData<Address>(callback_obj); + LOG(CallbackEvent(*func_name, entry_point)); + } + } else { + LOG(CodeCreateEvent( + Logger::LAZY_COMPILE_TAG, shared->code(), *func_name)); + } } DeleteArray(sfis); ======================================= --- /trunk/src/log.h Wed Nov 18 06:12:51 2009 +++ /trunk/src/log.h Tue Nov 24 06:29:16 2009 @@ -91,15 +91,20 @@ class VMState BASE_EMBEDDED { #ifdef ENABLE_LOGGING_AND_PROFILING public: - inline explicit VMState(StateTag state); + inline VMState(StateTag state); inline ~VMState(); StateTag state() { return state_; } + Address external_callback() { return external_callback_; } + void set_external_callback(Address external_callback) { + external_callback_ = external_callback; + } private: bool disabled_; StateTag state_; VMState* previous_; + Address external_callback_; #else public: explicit VMState(StateTag state) {} @@ -122,6 +127,7 @@ V(CALL_MISS_TAG, "CallMiss", "cm") \ V(CALL_NORMAL_TAG, "CallNormal", "cn") \ V(CALL_PRE_MONOMORPHIC_TAG, "CallPreMonomorphic", "cpm") \ + V(CALLBACK_TAG, "Callback", "cb") \ V(EVAL_TAG, "Eval", "e") \ V(FUNCTION_TAG, "Function", "f") \ V(KEYED_LOAD_IC_TAG, "KeyedLoadIC", "klic") \ @@ -200,6 +206,8 @@ // ==== Events logged by --log-code. ==== + // Emits a code event for a callback function. + static void CallbackEvent(String* name, Address entry_point); // Emits a code create event. static void CodeCreateEvent(LogEventsAndTags tag, Code* code, const char* source); @@ -330,6 +338,7 @@ friend class TimeLog; friend class Profiler; friend class SlidingStateWindow; + friend class StackTracer; friend class VMState; friend class LoggerTestHelper; ======================================= --- /trunk/src/serialize.cc Wed Nov 18 06:12:51 2009 +++ /trunk/src/serialize.cc Tue Nov 24 06:29:16 2009 @@ -668,7 +668,7 @@ break; case OBJECT_SERIALIZATION + CODE_SPACE: ReadObject(CODE_SPACE, Heap::code_space(), current++); - Logger::LogCodeObject(current[-1]); + LOG(LogCodeObject(current[-1])); break; case OBJECT_SERIALIZATION + CELL_SPACE: ReadObject(CELL_SPACE, Heap::cell_space(), current++); @@ -678,7 +678,7 @@ break; case OBJECT_SERIALIZATION + kLargeCode: ReadObject(kLargeCode, Heap::lo_space(), current++); - Logger::LogCodeObject(current[-1]); + LOG(LogCodeObject(current[-1])); break; case OBJECT_SERIALIZATION + kLargeFixedArray: ReadObject(kLargeFixedArray, Heap::lo_space(), current++); @@ -687,7 +687,7 @@ Object* new_code_object = NULL; ReadObject(kLargeCode, Heap::lo_space(), &new_code_object); Code* code_object = reinterpret_cast<Code*>(new_code_object); - Logger::LogCodeObject(code_object); + LOG(LogCodeObject(code_object)); // Setting a branch/call to another code object from code. Address location_of_branch_data = reinterpret_cast<Address>(current); Assembler::set_target_at(location_of_branch_data, @@ -700,7 +700,7 @@ Object* new_code_object = NULL; ReadObject(CODE_SPACE, Heap::code_space(), &new_code_object); Code* code_object = reinterpret_cast<Code*>(new_code_object); - Logger::LogCodeObject(code_object); + LOG(LogCodeObject(code_object)); // Setting a branch/call to another code object from code. Address location_of_branch_data = reinterpret_cast<Address>(current); Assembler::set_target_at(location_of_branch_data, ======================================= --- /trunk/src/v8.cc Wed Nov 18 06:12:51 2009 +++ /trunk/src/v8.cc Tue Nov 24 06:29:16 2009 @@ -116,7 +116,7 @@ if (FLAG_log_code) { HandleScope scope; - Logger::LogCompiledFunctions(); + LOG(LogCompiledFunctions()); } return true; ======================================= --- /trunk/src/version.cc Fri Nov 20 04:14:52 2009 +++ /trunk/src/version.cc Tue Nov 24 06:29:16 2009 @@ -34,7 +34,7 @@ // cannot be changed without changing the SCons build script. #define MAJOR_VERSION 2 #define MINOR_VERSION 0 -#define BUILD_NUMBER 1 +#define BUILD_NUMBER 2 #define PATCH_LEVEL 0 #define CANDIDATE_VERSION false ======================================= --- /trunk/test/cctest/test-log.cc Wed Nov 18 06:12:51 2009 +++ /trunk/test/cctest/test-log.cc Tue Nov 24 06:29:16 2009 @@ -247,7 +247,7 @@ i::FLAG_logfile = "*"; // If tests are being run manually, V8 will be already initialized - // by the test below. + // by the bottom test. const bool need_to_set_up_logger = i::V8::IsRunning(); v8::HandleScope scope; v8::Handle<v8::Context> env = v8::Context::New(); @@ -472,6 +472,70 @@ // Must not crash. i::Logger::LogCompiledFunctions(); } + + +static v8::Handle<v8::Value> ObjMethod1(const v8::Arguments& args) { + return v8::Handle<v8::Value>(); +} + +TEST(LogCallbacks) { + const bool saved_prof_lazy = i::FLAG_prof_lazy; + const bool saved_prof = i::FLAG_prof; + const bool saved_prof_auto = i::FLAG_prof_auto; + i::FLAG_prof = true; + i::FLAG_prof_lazy = false; + i::FLAG_prof_auto = false; + i::FLAG_logfile = "*"; + + // If tests are being run manually, V8 will be already initialized + // by the bottom test. + const bool need_to_set_up_logger = i::V8::IsRunning(); + v8::HandleScope scope; + v8::Handle<v8::Context> env = v8::Context::New(); + if (need_to_set_up_logger) Logger::Setup(); + env->Enter(); + + // Skip all initially logged stuff. + EmbeddedVector<char, 102400> buffer; + int log_pos = GetLogLines(0, &buffer); + + v8::Persistent<v8::FunctionTemplate> obj = + v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New()); + obj->SetClassName(v8::String::New("Obj")); + v8::Handle<v8::ObjectTemplate> proto = obj->PrototypeTemplate(); + v8::Local<v8::Signature> signature = v8::Signature::New(obj); + proto->Set(v8::String::New("method1"), + v8::FunctionTemplate::New(ObjMethod1, + v8::Handle<v8::Value>(), + signature), + static_cast<v8::PropertyAttribute>(v8::DontDelete)); + + env->Global()->Set(v8_str("Obj"), obj->GetFunction()); + CompileAndRunScript("Obj.prototype.method1.toString();"); + + i::Logger::LogCompiledFunctions(); + log_pos = GetLogLines(log_pos, &buffer); + CHECK_GT(log_pos, 0); + buffer[log_pos] = 0; + + const char* callback_rec = "code-creation,Callback,"; + char* pos = strstr(buffer.start(), callback_rec); + CHECK_NE(NULL, pos); + pos += strlen(callback_rec); + EmbeddedVector<char, 100> ref_data; + i::OS::SNPrintF(ref_data, + "0x%" V8PRIxPTR ",1,\"method1\"", ObjMethod1); + *(pos + strlen(ref_data.start())) = '\0'; + CHECK_EQ(ref_data.start(), pos); + + obj.Dispose(); + + env->Exit(); + Logger::TearDown(); + i::FLAG_prof_lazy = saved_prof_lazy; + i::FLAG_prof = saved_prof; + i::FLAG_prof_auto = saved_prof_auto; +} static inline bool IsStringEqualTo(const char* r, const char* s) { ======================================= --- /trunk/test/cctest/test-thread-termination.cc Wed Sep 2 01:22:29 2009 +++ /trunk/test/cctest/test-thread-termination.cc Tue Nov 24 06:29:16 2009 @@ -80,16 +80,32 @@ CHECK(!try_catch.CanContinue()); return v8::Undefined(); } + + +v8::Handle<v8::Value> DoLoopNoCall(const v8::Arguments& args) { + v8::TryCatch try_catch; + v8::Script::Compile(v8::String::New("var term = true;" + "while(true) {" + " if (term) terminate();" + " term = false;" + "}"))->Run(); + CHECK(try_catch.HasCaught()); + CHECK(try_catch.Exception()->IsNull()); + CHECK(try_catch.Message().IsEmpty()); + CHECK(!try_catch.CanContinue()); + return v8::Undefined(); +} v8::Handle<v8::ObjectTemplate> CreateGlobalTemplate( - v8::InvocationCallback terminate) { + v8::InvocationCallback terminate, + v8::InvocationCallback doloop) { v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New(); global->Set(v8::String::New("terminate"), v8::FunctionTemplate::New(terminate)); global->Set(v8::String::New("fail"), v8::FunctionTemplate::New(Fail)); global->Set(v8::String::New("loop"), v8::FunctionTemplate::New(Loop)); - global->Set(v8::String::New("doloop"), v8::FunctionTemplate::New(DoLoop)); + global->Set(v8::String::New("doloop"), v8::FunctionTemplate::New(doloop)); return global; } @@ -99,7 +115,7 @@ TEST(TerminateOnlyV8ThreadFromThreadItself) { v8::HandleScope scope; v8::Handle<v8::ObjectTemplate> global = - CreateGlobalTemplate(TerminateCurrentThread); + CreateGlobalTemplate(TerminateCurrentThread, DoLoop); v8::Persistent<v8::Context> context = v8::Context::New(NULL, global); v8::Context::Scope context_scope(context); // Run a loop that will be infinite if thread termination does not work. @@ -110,6 +126,24 @@ v8::Script::Compile(source)->Run(); context.Dispose(); } + + +// Test that a single thread of JavaScript execution can terminate +// itself in a loop that performs no calls. +TEST(TerminateOnlyV8ThreadFromThreadItselfNoLoop) { + v8::HandleScope scope; + v8::Handle<v8::ObjectTemplate> global = + CreateGlobalTemplate(TerminateCurrentThread, DoLoopNoCall); + v8::Persistent<v8::Context> context = v8::Context::New(NULL, global); + v8::Context::Scope context_scope(context); + // Run a loop that will be infinite if thread termination does not work. + v8::Handle<v8::String> source = + v8::String::New("try { loop(); fail(); } catch(e) { fail(); }"); + v8::Script::Compile(source)->Run(); + // Test that we can run the code again after thread termination. + v8::Script::Compile(source)->Run(); + context.Dispose(); +} class TerminatorThread : public v8::internal::Thread { @@ -128,7 +162,7 @@ thread.Start(); v8::HandleScope scope; - v8::Handle<v8::ObjectTemplate> global = CreateGlobalTemplate(Signal); + v8::Handle<v8::ObjectTemplate> global = CreateGlobalTemplate(Signal, DoLoop); v8::Persistent<v8::Context> context = v8::Context::New(NULL, global); v8::Context::Scope context_scope(context); // Run a loop that will be infinite if thread termination does not work. @@ -149,7 +183,8 @@ v8::Locker locker; v8::HandleScope scope; v8_thread_id_ = v8::V8::GetCurrentThreadId(); - v8::Handle<v8::ObjectTemplate> global = CreateGlobalTemplate(Signal); + v8::Handle<v8::ObjectTemplate> global = + CreateGlobalTemplate(Signal, DoLoop); v8::Persistent<v8::Context> context = v8::Context::New(NULL, global); v8::Context::Scope context_scope(context); // Run a loop that will be infinite if thread termination does not work. ======================================= --- /trunk/tools/gyp/v8.gyp Wed Nov 18 06:12:51 2009 +++ /trunk/tools/gyp/v8.gyp Tue Nov 24 06:29:16 2009 @@ -81,6 +81,7 @@ ['OS=="linux"', { 'cflags!': [ '-O2', + '-Os', ], 'cflags': [ '-fomit-frame-pointer', --~--~---------~--~----~------------~-------~--~----~ v8-dev mailing list [email protected] http://groups.google.com/group/v8-dev -~----------~----~----~----~------~----~------~--~---
