Author: [email protected]
Date: Thu Feb 19 03:42:34 2009
New Revision: 1313
Modified:
branches/experimental/toiger/ (props changed)
branches/experimental/toiger/ChangeLog
branches/experimental/toiger/src/api.cc
branches/experimental/toiger/src/d8.js
branches/experimental/toiger/src/debug-arm.cc
branches/experimental/toiger/src/debug-delay.js
branches/experimental/toiger/src/debug-ia32.cc
branches/experimental/toiger/src/debug.cc
branches/experimental/toiger/src/debug.h
branches/experimental/toiger/src/jsregexp.cc
branches/experimental/toiger/src/jsregexp.h
branches/experimental/toiger/src/objects-debug.cc
branches/experimental/toiger/src/objects.cc
branches/experimental/toiger/src/regexp-macro-assembler-irregexp-inl.h
(props changed)
branches/experimental/toiger/test/cctest/test-debug.cc
branches/experimental/toiger/test/mjsunit/debug-evaluate-recursive.js
Log:
Experimental: merge from the bleeding_edge branch. Merge
bleeding_edge revisions 1261-1275.
Modified: branches/experimental/toiger/ChangeLog
==============================================================================
--- branches/experimental/toiger/ChangeLog (original)
+++ branches/experimental/toiger/ChangeLog Thu Feb 19 03:42:34 2009
@@ -1,16 +1,28 @@
+2009-02-13: Version 1.0.1
+
+ Fixed two crash-bugs in irregexp (issue 231 and 233).
+
+ Fixed a number of minor bugs (issue 87, 227 and 228).
+
+ Added support for morphing strings to external strings on demand
+ to avoid having to create copies in the embedding code.
+
+ Removed experimental support for external symbol callbacks.
+
+
2009-02-09: Version 1.0.0
Fixed crash-bug in the code generation for case independent 16 bit
backreferences.
-
+
Made shells more robust in the presence of string conversion
failures (issue 224).
-
+
Fixed a potential infinite loop when attempting to resolve
eval (issue 221).
-
+
Miscellaneous fixes to the new regular expression engine.
-
+
Reduced binary by stripping unneeded text from JavaScript library
and
minifying some JavaScript files.
Modified: branches/experimental/toiger/src/api.cc
==============================================================================
--- branches/experimental/toiger/src/api.cc (original)
+++ branches/experimental/toiger/src/api.cc Thu Feb 19 03:42:34 2009
@@ -2184,7 +2184,7 @@
const char* v8::V8::GetVersion() {
- return "1.0.1 (candidate)";
+ return "1.0.2 (candidate)";
}
@@ -2888,8 +2888,11 @@
EnsureInitialized("v8::Debug::SetDebugEventListener()");
ON_BAILOUT("v8::Debug::SetDebugEventListener()", return false);
HandleScope scope;
- i::Debugger::SetEventListener(i::Factory::NewProxy(FUNCTION_ADDR(that)),
- Utils::OpenHandle(*data));
+ i::Handle<i::Object> proxy = i::Factory::undefined_value();
+ if (that != NULL) {
+ proxy = i::Factory::NewProxy(FUNCTION_ADDR(that));
+ }
+ i::Debugger::SetEventListener(proxy, Utils::OpenHandle(*data));
return true;
}
Modified: branches/experimental/toiger/src/d8.js
==============================================================================
--- branches/experimental/toiger/src/d8.js (original)
+++ branches/experimental/toiger/src/d8.js Thu Feb 19 03:42:34 2009
@@ -381,6 +381,10 @@
var request = this.createRequest('evaluate');
request.arguments = {};
request.arguments.expression = expression;
+ // Request a global evaluation if there is no current frame.
+ if (Debug.State.currentFrame == kNoFrame) {
+ request.arguments.global = true;
+ }
return request.toJSONProtocol();
}
};
@@ -795,7 +799,7 @@
case 'evaluate':
case 'lookup':
if (last_cmd == 'p' || last_cmd == 'print') {
- details.text = body.text;
+ result = body.text;
} else {
var value = response.bodyValue();
if (value.isObject()) {
@@ -984,10 +988,10 @@
ProtocolPackage.prototype.bodyValue = function(index) {
- if (IS_UNDEFINED(index)) {
- return new ProtocolValue(this.packet_.body, this);
- } else {
+ if (index) {
return new ProtocolValue(this.packet_.body[index], this);
+ } else {
+ return new ProtocolValue(this.packet_.body, this);
}
}
Modified: branches/experimental/toiger/src/debug-arm.cc
==============================================================================
--- branches/experimental/toiger/src/debug-arm.cc (original)
+++ branches/experimental/toiger/src/debug-arm.cc Thu Feb 19 03:42:34 2009
@@ -51,6 +51,13 @@
}
+bool Debug::IsDebugBreakAtReturn(RelocInfo* rinfo) {
+ ASSERT(RelocInfo::IsJSReturn(rinfo->rmode()));
+ // Currently debug break is not supported in frame exit code on ARM.
+ return false;
+}
+
+
#define __ masm->
Modified: branches/experimental/toiger/src/debug-delay.js
==============================================================================
--- branches/experimental/toiger/src/debug-delay.js (original)
+++ branches/experimental/toiger/src/debug-delay.js Thu Feb 19 03:42:34 2009
@@ -1421,6 +1421,11 @@
disable_break = true;
}
+ // No frames no evaluate in frame.
+ if (this.exec_state_.frameCount() == 0) {
+ return response.failed('No frames');
+ }
+
// Check whether a frame was specified.
if (!IS_UNDEFINED(frame)) {
var frame_number = %ToNumber(frame);
Modified: branches/experimental/toiger/src/debug-ia32.cc
==============================================================================
--- branches/experimental/toiger/src/debug-ia32.cc (original)
+++ branches/experimental/toiger/src/debug-ia32.cc Thu Feb 19 03:42:34 2009
@@ -37,7 +37,7 @@
// A debug break in the frame exit code is identified by a call
instruction.
bool BreakLocationIterator::IsDebugBreakAtReturn() {
// Opcode E8 is call.
- return (*(rinfo()->pc()) == 0xE8);
+ return Debug::IsDebugBreakAtReturn(rinfo());
}
@@ -56,6 +56,14 @@
void BreakLocationIterator::ClearDebugBreakAtReturn() {
rinfo()->PatchCode(original_rinfo()->pc(),
Debug::kIa32JSReturnSequenceLength);
+}
+
+
+// Check whether the JS frame exit code has been patched with a debug
break.
+bool Debug::IsDebugBreakAtReturn(RelocInfo* rinfo) {
+ ASSERT(RelocInfo::IsJSReturn(rinfo->rmode()));
+ // Opcode E8 is call.
+ return (*(rinfo->pc()) == 0xE8);
}
Modified: branches/experimental/toiger/src/debug.cc
==============================================================================
--- branches/experimental/toiger/src/debug.cc (original)
+++ branches/experimental/toiger/src/debug.cc Thu Feb 19 03:42:34 2009
@@ -314,6 +314,8 @@
void BreakLocationIterator::PrepareStepIn() {
+ HandleScope scope;
+
// Step in can only be prepared if currently positioned on an IC call or
// construct call.
Address target = rinfo()->target_address();
@@ -363,6 +365,17 @@
}
+// Clear out all the debug break code. This is ONLY supposed to be used
when
+// shutting down the debugger as it will leave the break point information
in
+// DebugInfo even though the code is patched back to the non break point
state.
+void BreakLocationIterator::ClearAllDebugBreak() {
+ while (!Done()) {
+ ClearDebugBreak();
+ Next();
+ }
+}
+
+
bool BreakLocationIterator::RinfoDone() const {
ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done());
return reloc_iterator_->done();
@@ -589,6 +602,9 @@
return;
}
+ // Get rid of all break points and related information.
+ ClearAllBreakPoints();
+
// Clear debugger context global handle.
GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_context_.location()));
debug_context_ = Handle<Context>();
@@ -715,6 +731,8 @@
// Check whether a single break point object is triggered.
bool Debug::CheckBreakPoint(Handle<Object> break_point_object) {
+ HandleScope scope;
+
// Ignore check if break point object is not a JSObject.
if (!break_point_object->IsJSObject()) return true;
@@ -765,6 +783,8 @@
void Debug::SetBreakPoint(Handle<SharedFunctionInfo> shared,
int source_position,
Handle<Object> break_point_object) {
+ HandleScope scope;
+
if (!EnsureDebugInfo(shared)) {
// Return if retrieving debug info failed.
return;
@@ -785,6 +805,8 @@
void Debug::ClearBreakPoint(Handle<Object> break_point_object) {
+ HandleScope scope;
+
DebugInfoListNode* node = debug_info_list_;
while (node != NULL) {
Object* result = DebugInfo::FindBreakPointInfo(node->debug_info(),
@@ -817,6 +839,22 @@
}
+void Debug::ClearAllBreakPoints() {
+ DebugInfoListNode* node = debug_info_list_;
+ while (node != NULL) {
+ // Remove all debug break code.
+ BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
+ it.ClearAllDebugBreak();
+ node = node->next();
+ }
+
+ // Remove all debug info.
+ while (debug_info_list_ != NULL) {
+ RemoveDebugInfo(debug_info_list_->debug_info());
+ }
+}
+
+
void Debug::FloodWithOneShot(Handle<SharedFunctionInfo> shared) {
// Make sure the function has setup the debug info.
if (!EnsureDebugInfo(shared)) {
@@ -1214,6 +1252,8 @@
void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) {
+ HandleScope scope;
+
// Get the executing function in which the debug break occurred.
Handle<SharedFunctionInfo> shared =
Handle<SharedFunctionInfo>(JSFunction::cast(frame->function())->shared());
@@ -1297,6 +1337,7 @@
void Debug::ClearMirrorCache() {
+ HandleScope scope;
ASSERT(Top::context() == *Debug::debug_context());
// Clear the mirror cache.
@@ -1596,6 +1637,8 @@
void Debugger::ProcessDebugEvent(v8::DebugEvent event,
Handle<Object> event_data) {
+ HandleScope scope;
+
// Create the execution state.
bool caught_exception = false;
Handle<Object> exec_state = MakeExecutionState(&caught_exception);
@@ -1712,6 +1755,9 @@
if (!debugger_active() && message_thread_) {
message_thread_->OnDebuggerInactive();
}
+ if (!debugger_active()) {
+ Debug::Unload();
+ }
}
@@ -1816,6 +1862,8 @@
void DebugMessageThread::DebugEvent(v8::DebugEvent event,
Handle<Object> exec_state,
Handle<Object> event_data) {
+ HandleScope scope;
+
if (!Debug::Load()) return;
// Process the individual events.
Modified: branches/experimental/toiger/src/debug.h
==============================================================================
--- branches/experimental/toiger/src/debug.h (original)
+++ branches/experimental/toiger/src/debug.h Thu Feb 19 03:42:34 2009
@@ -89,6 +89,7 @@
bool HasBreakPoint();
bool IsDebugBreak();
Object* BreakPointObjects();
+ void ClearAllDebugBreak();
inline int code_position() { return pc() - debug_info_->code()->entry();
}
@@ -172,6 +173,7 @@
int source_position,
Handle<Object> break_point_object);
static void ClearBreakPoint(Handle<Object> break_point_object);
+ static void ClearAllBreakPoints();
static void FloodWithOneShot(Handle<SharedFunctionInfo> shared);
static void FloodHandlerWithOneShot();
static void ChangeBreakOnException(ExceptionBreakType type, bool enable);
@@ -186,6 +188,7 @@
static bool EnsureDebugInfo(Handle<SharedFunctionInfo> shared);
static bool IsDebugBreak(Address addr);
+ static bool IsDebugBreakAtReturn(RelocInfo* rinfo);
// Check whether a code stub with the specified major key is a possible
break
// point location.
@@ -257,7 +260,8 @@
static void HandleWeakDebugInfo(v8::Persistent<v8::Value> obj, void*
data);
friend class Debugger;
- friend Handle<FixedArray> GetDebuggedFunctions(); // Found in
test-debug.cc
+ friend Handle<FixedArray> GetDebuggedFunctions(); // In test-debug.cc
+ friend void CheckDebuggerUnloaded(bool check_functions); // In
test-debug.cc
// Threading support.
static char* ArchiveDebug(char* to);
Modified: branches/experimental/toiger/src/jsregexp.cc
==============================================================================
--- branches/experimental/toiger/src/jsregexp.cc (original)
+++ branches/experimental/toiger/src/jsregexp.cc Thu Feb 19 03:42:34 2009
@@ -298,7 +298,7 @@
return AtomExec(regexp, subject, index);
case JSRegExp::IRREGEXP: {
Handle<Object> result = IrregexpExec(regexp, subject, index);
- if (result.is_null()) ASSERT(Top::has_pending_exception());
+ ASSERT(!result.is_null() || Top::has_pending_exception());
return result;
}
case JSRegExp::JSCRE:
@@ -317,7 +317,7 @@
return AtomExecGlobal(regexp, subject);
case JSRegExp::IRREGEXP: {
Handle<Object> result = IrregexpExecGlobal(regexp, subject);
- if (result.is_null()) ASSERT(Top::has_pending_exception());
+ ASSERT(!result.is_null() || Top::has_pending_exception());
return result;
}
case JSRegExp::JSCRE:
@@ -823,6 +823,11 @@
offsets.vector(),
offsets.length());
+ if (matches.is_null()) {
+ ASSERT(Top::has_pending_exception());
+ return matches;
+ }
+
if (matches->IsJSArray()) {
SetElement(result, i, matches);
i++;
@@ -830,10 +835,9 @@
if (offsets.vector()[0] == offsets.vector()[1]) {
previous_index++;
}
- } else if (matches->IsNull()) {
- return result;
} else {
- return matches;
+ ASSERT(matches->IsNull());
+ return result;
}
}
}
Modified: branches/experimental/toiger/src/jsregexp.h
==============================================================================
--- branches/experimental/toiger/src/jsregexp.h (original)
+++ branches/experimental/toiger/src/jsregexp.h Thu Feb 19 03:42:34 2009
@@ -55,7 +55,6 @@
Handle<String> pattern,
Handle<String> flags);
- // Implements RegExp.prototype.exec(string) function.
// See ECMA-262 section 15.10.6.2.
// This function calls the garbage collector if necessary.
static Handle<Object> Exec(Handle<JSRegExp> regexp,
@@ -155,6 +154,9 @@
int* ovector,
int ovector_length);
+ // On a successful match, the result is a JSArray containing
+ // captured positions. On a failure, the result is the null value.
+ // Returns an empty handle in case of an exception.
static Handle<Object> IrregexpExecOnce(Handle<FixedArray> regexp,
int num_captures,
Handle<String> subject16,
Modified: branches/experimental/toiger/src/objects-debug.cc
==============================================================================
--- branches/experimental/toiger/src/objects-debug.cc (original)
+++ branches/experimental/toiger/src/objects-debug.cc Thu Feb 19 03:42:34
2009
@@ -552,11 +552,11 @@
PrintF(" - name: ");
name()->ShortPrint();
PrintF("\n - expected_nof_properties: %d", expected_nof_properties());
- PrintF("\n - instance class name =");
+ PrintF("\n - instance class name = ");
instance_class_name()->Print();
- PrintF("\n - code =");
+ PrintF("\n - code = ");
code()->ShortPrint();
- PrintF("\n - source code =");
+ PrintF("\n - source code = ");
GetSourceCode()->ShortPrint();
PrintF("\n - lazy load: %s",
lazy_load_data() == Heap::undefined_value() ? "no" : "yes");
@@ -568,7 +568,7 @@
PrintF("\n - end position = %d", end_position());
PrintF("\n - is expression = %d", is_expression());
PrintF("\n - debug info = ");
- debug_info()->Print();
+ debug_info()->ShortPrint();
PrintF("\n - length = %d", length());
PrintF("\n");
}
@@ -752,7 +752,7 @@
}
void AccessorInfo::AccessorInfoPrint() {
- PrintF("AccessorInfo");
+ HeapObject::PrintHeader("AccessorInfo");
PrintF("\n - getter: ");
getter()->ShortPrint();
PrintF("\n - setter: ");
@@ -773,7 +773,7 @@
}
void AccessCheckInfo::AccessCheckInfoPrint() {
- PrintF("AccessCheckInfo");
+ HeapObject::PrintHeader("AccessCheckInfo");
PrintF("\n - named_callback: ");
named_callback()->ShortPrint();
PrintF("\n - indexed_callback: ");
@@ -793,7 +793,7 @@
}
void InterceptorInfo::InterceptorInfoPrint() {
- PrintF("InterceptorInfo");
+ HeapObject::PrintHeader("InterceptorInfo");
PrintF("\n - getter: ");
getter()->ShortPrint();
PrintF("\n - setter: ");
@@ -815,7 +815,7 @@
}
void CallHandlerInfo::CallHandlerInfoPrint() {
- PrintF("CallHandlerInfo");
+ HeapObject::PrintHeader("CallHandlerInfo");
PrintF("\n - callback: ");
callback()->ShortPrint();
PrintF("\n - data: ");
@@ -843,7 +843,7 @@
}
void FunctionTemplateInfo::FunctionTemplateInfoPrint() {
- PrintF("FunctionTemplateInfo");
+ HeapObject::PrintHeader("FunctionTemplateInfo");
PrintF("\n - tag: ");
tag()->ShortPrint();
PrintF("\n - property_list: ");
@@ -881,7 +881,7 @@
}
void ObjectTemplateInfo::ObjectTemplateInfoPrint() {
- PrintF("ObjectTemplateInfo");
+ HeapObject::PrintHeader("ObjectTemplateInfo");
PrintF("\n - constructor: ");
constructor()->ShortPrint();
PrintF("\n - internal_field_count: ");
@@ -895,7 +895,7 @@
}
void SignatureInfo::SignatureInfoPrint() {
- PrintF("SignatureInfo");
+ HeapObject::PrintHeader("SignatureInfo");
PrintF("\n - receiver: ");
receiver()->ShortPrint();
PrintF("\n - args: ");
@@ -908,7 +908,7 @@
}
void TypeSwitchInfo::TypeSwitchInfoPrint() {
- PrintF("TypeSwitchInfo");
+ HeapObject::PrintHeader("TypeSwitchInfo");
PrintF("\n - types: ");
types()->ShortPrint();
}
@@ -950,15 +950,15 @@
void DebugInfo::DebugInfoPrint() {
- PrintF("DebugInfo");
- PrintF("\n - shared");
+ HeapObject::PrintHeader("DebugInfo");
+ PrintF("\n - shared: ");
shared()->ShortPrint();
- PrintF("\n - original_code");
+ PrintF("\n - original_code: ");
original_code()->ShortPrint();
- PrintF("\n - code");
+ PrintF("\n - code: ");
code()->ShortPrint();
- PrintF("\n - break_points");
- break_points()->ShortPrint();
+ PrintF("\n - break_points: ");
+ break_points()->Print();
}
@@ -972,11 +972,11 @@
void BreakPointInfo::BreakPointInfoPrint() {
- PrintF("BreakPointInfo");
- PrintF("\n - code_position %d", code_position());
- PrintF("\n - source_position %d", source_position());
- PrintF("\n - statement_position %d", statement_position());
- PrintF("\n - break_point_objects ");
+ HeapObject::PrintHeader("BreakPointInfo");
+ PrintF("\n - code_position: %d", code_position());
+ PrintF("\n - source_position: %d", source_position());
+ PrintF("\n - statement_position: %d", statement_position());
+ PrintF("\n - break_point_objects: ");
break_point_objects()->ShortPrint();
}
Modified: branches/experimental/toiger/src/objects.cc
==============================================================================
--- branches/experimental/toiger/src/objects.cc (original)
+++ branches/experimental/toiger/src/objects.cc Thu Feb 19 03:42:34 2009
@@ -926,7 +926,9 @@
break;
#define MAKE_STRUCT_CASE(NAME, Name, name) \
case NAME##_TYPE: \
+ accumulator->Put('<'); \
accumulator->Add(#Name); \
+ accumulator->Put('>'); \
break;
STRUCT_LIST(MAKE_STRUCT_CASE)
#undef MAKE_STRUCT_CASE
Modified: branches/experimental/toiger/test/cctest/test-debug.cc
==============================================================================
--- branches/experimental/toiger/test/cctest/test-debug.cc (original)
+++ branches/experimental/toiger/test/cctest/test-debug.cc Thu Feb 19
03:42:34 2009
@@ -363,8 +363,66 @@
Code);
}
+
+// Check that the debugger is loaded.
+static void CheckDebuggerLoaded() {
+ CHECK(Debug::debug_context().is_null());
+}
+
+
+// Check that the debugger has been fully unloaded.
+void CheckDebuggerUnloaded(bool check_functions) {
+ // Check that the debugger context is cleared and that there is no debug
+ // information stored for the debugger.
+ CHECK(Debug::debug_context().is_null());
+ CHECK_EQ(NULL, Debug::debug_info_list_);
+
+ // Collect garbage to ensure weak handles are cleared.
+ Heap::CollectAllGarbage();
+ Heap::CollectAllGarbage();
+
+ // Iterate the head and check that there are no debugger related objects
left.
+ HeapIterator iterator;
+ while (iterator.has_next()) {
+ HeapObject* obj = iterator.next();
+ CHECK(obj != NULL);
+ CHECK(!obj->IsDebugInfo());
+ CHECK(!obj->IsBreakPointInfo());
+
+ // If deep check of functions is requested check that no debug break
code
+ // is left in all functions.
+ if (check_functions) {
+ if (obj->IsJSFunction()) {
+ JSFunction* fun = JSFunction::cast(obj);
+ for (RelocIterator it(fun->shared()->code()); !it.done();
it.next()) {
+ RelocInfo::Mode rmode = it.rinfo()->rmode();
+ if (RelocInfo::IsCodeTarget(rmode)) {
+ CHECK(!Debug::IsDebugBreak(it.rinfo()->target_address()));
+ } else if (RelocInfo::IsJSReturn(rmode)) {
+ CHECK(!Debug::IsDebugBreakAtReturn(it.rinfo()));
+ }
+ }
+ }
+ }
+ }
+}
+
+
} } // namespace v8::internal
+
+// Check that the debugger is loaded.
+static void CheckDebuggerLoaded() {
+ v8::internal::CheckDebuggerLoaded();
+}
+
+
+// Check that the debugger has been fully unloaded.
+static void CheckDebuggerUnloaded(bool check_functions = false) {
+ v8::internal::CheckDebuggerUnloaded(check_functions);
+}
+
+
// Inherit from BreakLocationIterator to get access to protected parts for
// testing.
class TestBreakLocationIterator: public
v8::internal::BreakLocationIterator {
@@ -823,6 +881,7 @@
break_point_hit_count = 0;
v8::HandleScope scope;
DebugLocalContext env;
+
v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
v8::Undefined());
v8::Script::Compile(v8::String::New("function foo(){bar=0;}"))->Run();
@@ -846,6 +905,7 @@
CHECK_EQ(2, break_point_hit_count);
v8::Debug::SetDebugEventListener(NULL);
+ CheckDebuggerUnloaded();
}
@@ -878,6 +938,7 @@
CHECK_EQ(2, break_point_hit_count);
v8::Debug::SetDebugEventListener(NULL);
+ CheckDebuggerUnloaded();
}
@@ -910,6 +971,7 @@
CHECK_EQ(2, break_point_hit_count);
v8::Debug::SetDebugEventListener(NULL);
+ CheckDebuggerUnloaded();
}
@@ -941,6 +1003,7 @@
CHECK_EQ(2, break_point_hit_count);
v8::Debug::SetDebugEventListener(NULL);
+ CheckDebuggerUnloaded();
}
@@ -986,6 +1049,7 @@
CallWithBreakPoints(env->Global(), foo, 1, 25);
v8::Debug::SetDebugEventListener(NULL);
+ CheckDebuggerUnloaded();
}
@@ -1043,6 +1107,7 @@
CallAndGC(env->Global(), foo);
v8::Debug::SetDebugEventListener(NULL);
+ CheckDebuggerUnloaded();
}
@@ -1093,6 +1158,7 @@
CHECK_EQ(8, break_point_hit_count);
v8::Debug::SetDebugEventListener(NULL);
+ CheckDebuggerUnloaded();
// Make sure that the break point numbers are consecutive.
CHECK_EQ(1, bp1);
@@ -1207,6 +1273,7 @@
CHECK_EQ(2, break_point_hit_count);
v8::Debug::SetDebugEventListener(NULL);
+ CheckDebuggerUnloaded();
// Make sure that the break point numbers are consecutive.
CHECK_EQ(1, sbp1);
@@ -1272,6 +1339,7 @@
CHECK_EQ(3, break_point_hit_count);
v8::Debug::SetDebugEventListener(NULL);
+ CheckDebuggerUnloaded();
}
@@ -1333,6 +1401,7 @@
CHECK_EQ(5, break_point_hit_count);
v8::Debug::SetDebugEventListener(NULL);
+ CheckDebuggerUnloaded();
}
@@ -1387,6 +1456,7 @@
CHECK_EQ(5, break_point_hit_count);
v8::Debug::SetDebugEventListener(NULL);
+ CheckDebuggerUnloaded();
}
@@ -1445,6 +1515,7 @@
CHECK_EQ(1, break_point_hit_count);
v8::Debug::SetDebugEventListener(NULL);
+ CheckDebuggerUnloaded();
}
@@ -1510,6 +1581,7 @@
CHECK_EQ(2, break_point_hit_count);
v8::Debug::SetDebugEventListener(NULL);
+ CheckDebuggerUnloaded();
}
@@ -1565,6 +1637,7 @@
CHECK_EQ(1, break_point_hit_count);
v8::Debug::SetDebugEventListener(NULL);
+ CheckDebuggerUnloaded();
}
@@ -1670,6 +1743,7 @@
CHECK_EQ(0, break_point_hit_count);
v8::Debug::SetDebugEventListener(NULL);
+ CheckDebuggerUnloaded();
}
@@ -1695,6 +1769,7 @@
CHECK_EQ(0, break_point_hit_count);
v8::Debug::SetDebugEventListener(NULL);
+ CheckDebuggerUnloaded();
}
@@ -1722,6 +1797,7 @@
CHECK_EQ(3, break_point_hit_count);
v8::Debug::SetDebugEventListener(NULL);
+ CheckDebuggerUnloaded();
}
@@ -1836,6 +1912,7 @@
bar->Call(env->Global(), 2, argv_bar_3);
v8::Debug::SetDebugEventListener(NULL);
+ CheckDebuggerUnloaded();
}
@@ -1861,10 +1938,12 @@
CHECK_EQ(4, break_point_hit_count);
v8::Debug::SetDebugEventListener(NULL);
+ CheckDebuggerUnloaded();
// Register a debug event listener which just counts.
v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
+ SetBreakPoint(foo, 3);
break_point_hit_count = 0;
foo->Call(env->Global(), 0, NULL);
@@ -1872,6 +1951,7 @@
CHECK_EQ(1, break_point_hit_count);
v8::Debug::SetDebugEventListener(NULL);
+ CheckDebuggerUnloaded();
}
@@ -1906,10 +1986,12 @@
#endif
v8::Debug::SetDebugEventListener(NULL);
+ CheckDebuggerUnloaded();
// Register a debug event listener which just counts.
v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
+ SetBreakPoint(foo, 0);
break_point_hit_count = 0;
foo->Call(env->Global(), 0, NULL);
@@ -1917,6 +1999,7 @@
CHECK_EQ(1, break_point_hit_count);
v8::Debug::SetDebugEventListener(NULL);
+ CheckDebuggerUnloaded();
}
@@ -1957,6 +2040,7 @@
// Get rid of the debug event listener.
v8::Debug::SetDebugEventListener(NULL);
+ CheckDebuggerUnloaded();
}
@@ -2009,6 +2093,7 @@
// Get rid of the debug event listener.
v8::Debug::SetDebugEventListener(NULL);
+ CheckDebuggerUnloaded();
}
@@ -2046,6 +2131,7 @@
// Get rid of the debug event listener.
v8::Debug::SetDebugEventListener(NULL);
+ CheckDebuggerUnloaded();
}
@@ -2091,6 +2177,7 @@
// Get rid of the debug event listener.
v8::Debug::SetDebugEventListener(NULL);
+ CheckDebuggerUnloaded();
}
@@ -2137,6 +2224,7 @@
// Get rid of the debug event listener.
v8::Debug::SetDebugEventListener(NULL);
+ CheckDebuggerUnloaded(true);
}
@@ -2168,6 +2256,7 @@
// Get rid of the debug event listener.
v8::Debug::SetDebugEventListener(NULL);
+ CheckDebuggerUnloaded();
}
@@ -2193,6 +2282,7 @@
CHECK_EQ(3, break_point_hit_count);
v8::Debug::SetDebugEventListener(NULL);
+ CheckDebuggerUnloaded();
// Register a debug event listener which just counts.
v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
@@ -2204,6 +2294,7 @@
CHECK_EQ(1, break_point_hit_count);
v8::Debug::SetDebugEventListener(NULL);
+ CheckDebuggerUnloaded();
}
@@ -2350,6 +2441,7 @@
CHECK_EQ(1, message_callback_count);
v8::Debug::SetDebugEventListener(NULL);
+ CheckDebuggerUnloaded();
v8::V8::RemoveMessageListeners(MessageCallbackCount);
}
@@ -2486,6 +2578,7 @@
// Get rid of the debug event listener.
v8::Debug::SetDebugEventListener(NULL);
+ CheckDebuggerUnloaded();
}
@@ -2539,6 +2632,7 @@
// Get rid of the debug event listener.
v8::Debug::SetDebugEventListener(NULL);
+ CheckDebuggerUnloaded();
}
@@ -2575,6 +2669,7 @@
// Get rid of the debug event listener.
v8::Debug::SetDebugEventListener(NULL);
+ CheckDebuggerUnloaded();
}
@@ -3505,4 +3600,63 @@
// Test that a function with closure can be run in the debugger.
v8::Script::Compile(v8::String::New("CheckClosure()"))->Run();
+}
+
+
+// Test that clearing the debug event listener actually clears all break
points
+// and related information.
+TEST(DebuggerUnload) {
+ v8::HandleScope scope;
+ DebugLocalContext env;
+
+ // Check debugger is unloaded before it is used.
+ CheckDebuggerUnloaded();
+
+ // Add debug event listener.
+ v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
+ v8::Undefined());
+ CheckDebuggerLoaded();
+
+ // Create a couple of functions for the test.
+ v8::Local<v8::Function> foo =
+ CompileFunction(&env, "function foo(){x=1}", "foo");
+ v8::Local<v8::Function> bar =
+ CompileFunction(&env, "function bar(){y=2}", "bar");
+
+ // Set some break points.
+ SetBreakPoint(foo, 0);
+ SetBreakPoint(foo, 4);
+ SetBreakPoint(bar, 0);
+ SetBreakPoint(bar, 4);
+
+ // Make sure that the break points are there.
+ break_point_hit_count = 0;
+ foo->Call(env->Global(), 0, NULL);
+ CHECK_EQ(2, break_point_hit_count);
+ bar->Call(env->Global(), 0, NULL);
+ CHECK_EQ(4, break_point_hit_count);
+
+ // Remove the debug event listener without clearing breakpoints.
+ v8::Debug::SetDebugEventListener(NULL);
+ CheckDebuggerUnloaded(true);
+
+ // Set a new debug event listener.
+ v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
+ v8::Undefined());
+ CheckDebuggerLoaded();
+
+ // Check that the break points was actually cleared.
+ break_point_hit_count = 0;
+ foo->Call(env->Global(), 0, NULL);
+ CHECK_EQ(0, break_point_hit_count);
+
+ // Set break points and run again.
+ SetBreakPoint(foo, 0);
+ SetBreakPoint(foo, 4);
+ foo->Call(env->Global(), 0, NULL);
+ CHECK_EQ(2, break_point_hit_count);
+
+ // Remove the debug event listener without clearing breakpoints again.
+ v8::Debug::SetDebugEventListener(NULL);
+ CheckDebuggerUnloaded(true);
}
Modified:
branches/experimental/toiger/test/mjsunit/debug-evaluate-recursive.js
==============================================================================
--- branches/experimental/toiger/test/mjsunit/debug-evaluate-recursive.js
(original)
+++ branches/experimental/toiger/test/mjsunit/debug-evaluate-recursive.js
Thu Feb 19 03:42:34 2009
@@ -153,9 +153,11 @@
// Remove the debug event listener.
Debug.setListener(null);
-// Add debug event listener wich uses recursive breaks.
-listenerComplete = false;
+// Set debug event listener wich uses recursive breaks.
Debug.setListener(listener_recurse);
+listenerComplete = false;
+
+Debug.setBreakPoint(f, 2, 0);
debugger;
--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---