Fix debugger's eval when close to stack overflow.
R=verwaest@chromium.org BUG=v8:2318 Review URL: https://chromiumcodereview.appspot.com/10914290 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12518 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
fb506e0864
commit
cb72bf5735
@ -2826,6 +2826,7 @@ void Debugger::OnScriptCollected(int id) {
|
||||
HandleScope scope(isolate_);
|
||||
|
||||
// No more to do if not debugging.
|
||||
if (isolate_->debug()->InDebugger()) return;
|
||||
if (!IsDebuggerActive()) return;
|
||||
if (!Debugger::EventActive(v8::ScriptCollected)) return;
|
||||
|
||||
|
@ -793,7 +793,6 @@ class Debugger {
|
||||
};
|
||||
void OnAfterCompile(Handle<Script> script,
|
||||
AfterCompileFlags after_compile_flags);
|
||||
void OnNewFunction(Handle<JSFunction> fun);
|
||||
void OnScriptCollected(int id);
|
||||
void ProcessDebugEvent(v8::DebugEvent event,
|
||||
Handle<JSObject> event_data,
|
||||
|
@ -10843,7 +10843,8 @@ class ScopeIterator {
|
||||
inlined_jsframe_index_(inlined_jsframe_index),
|
||||
function_(JSFunction::cast(frame->function())),
|
||||
context_(Context::cast(frame->context())),
|
||||
nested_scope_chain_(4) {
|
||||
nested_scope_chain_(4),
|
||||
failed_(false) {
|
||||
|
||||
// Catch the case when the debugger stops in an internal function.
|
||||
Handle<SharedFunctionInfo> shared_info(function_->shared());
|
||||
@ -10917,17 +10918,24 @@ class ScopeIterator {
|
||||
frame_(NULL),
|
||||
inlined_jsframe_index_(0),
|
||||
function_(function),
|
||||
context_(function->context()) {
|
||||
context_(function->context()),
|
||||
failed_(false) {
|
||||
if (function->IsBuiltin()) {
|
||||
context_ = Handle<Context>();
|
||||
}
|
||||
}
|
||||
|
||||
// More scopes?
|
||||
bool Done() { return context_.is_null(); }
|
||||
bool Done() {
|
||||
ASSERT(!failed_);
|
||||
return context_.is_null();
|
||||
}
|
||||
|
||||
bool Failed() { return failed_; }
|
||||
|
||||
// Move to the next scope.
|
||||
void Next() {
|
||||
ASSERT(!failed_);
|
||||
ScopeType scope_type = Type();
|
||||
if (scope_type == ScopeTypeGlobal) {
|
||||
// The global scope is always the last in the chain.
|
||||
@ -10948,6 +10956,7 @@ class ScopeIterator {
|
||||
|
||||
// Return the type of the current scope.
|
||||
ScopeType Type() {
|
||||
ASSERT(!failed_);
|
||||
if (!nested_scope_chain_.is_empty()) {
|
||||
Handle<ScopeInfo> scope_info = nested_scope_chain_.last();
|
||||
switch (scope_info->Type()) {
|
||||
@ -10997,6 +11006,7 @@ class ScopeIterator {
|
||||
|
||||
// Return the JavaScript object with the content of the current scope.
|
||||
Handle<JSObject> ScopeObject() {
|
||||
ASSERT(!failed_);
|
||||
switch (Type()) {
|
||||
case ScopeIterator::ScopeTypeGlobal:
|
||||
return Handle<JSObject>(CurrentContext()->global_object());
|
||||
@ -11022,6 +11032,7 @@ class ScopeIterator {
|
||||
}
|
||||
|
||||
Handle<ScopeInfo> CurrentScopeInfo() {
|
||||
ASSERT(!failed_);
|
||||
if (!nested_scope_chain_.is_empty()) {
|
||||
return nested_scope_chain_.last();
|
||||
} else if (context_->IsBlockContext()) {
|
||||
@ -11035,6 +11046,7 @@ class ScopeIterator {
|
||||
// Return the context for this scope. For the local context there might not
|
||||
// be an actual context.
|
||||
Handle<Context> CurrentContext() {
|
||||
ASSERT(!failed_);
|
||||
if (Type() == ScopeTypeGlobal ||
|
||||
nested_scope_chain_.is_empty()) {
|
||||
return context_;
|
||||
@ -11048,6 +11060,7 @@ class ScopeIterator {
|
||||
#ifdef DEBUG
|
||||
// Debug print of the content of the current scope.
|
||||
void DebugPrint() {
|
||||
ASSERT(!failed_);
|
||||
switch (Type()) {
|
||||
case ScopeIterator::ScopeTypeGlobal:
|
||||
PrintF("Global:\n");
|
||||
@ -11105,6 +11118,7 @@ class ScopeIterator {
|
||||
Handle<JSFunction> function_;
|
||||
Handle<Context> context_;
|
||||
List<Handle<ScopeInfo> > nested_scope_chain_;
|
||||
bool failed_;
|
||||
|
||||
void RetrieveScopeChain(Scope* scope,
|
||||
Handle<SharedFunctionInfo> shared_info) {
|
||||
@ -11117,7 +11131,9 @@ class ScopeIterator {
|
||||
// faulty. We fail in debug mode but in release mode we only provide the
|
||||
// information we get from the context chain but nothing about
|
||||
// completely stack allocated scopes or stack allocated locals.
|
||||
UNREACHABLE();
|
||||
// Or it could be due to stack overflow.
|
||||
ASSERT(isolate_->has_pending_exception());
|
||||
failed_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -11542,6 +11558,8 @@ static Handle<Context> CopyNestedScopeContextChain(Isolate* isolate,
|
||||
List<Handle<Context> > context_chain;
|
||||
|
||||
ScopeIterator it(isolate, frame, inlined_jsframe_index);
|
||||
if (it.Failed()) return Handle<Context>::null();
|
||||
|
||||
for (; it.Type() != ScopeIterator::ScopeTypeGlobal &&
|
||||
it.Type() != ScopeIterator::ScopeTypeLocal ; it.Next()) {
|
||||
ASSERT(!it.Done());
|
||||
@ -11570,9 +11588,7 @@ static Handle<Context> CopyNestedScopeContextChain(Isolate* isolate,
|
||||
// Materialize the contents of the block scope into a JSObject.
|
||||
Handle<JSObject> block_scope_object =
|
||||
MaterializeBlockScope(isolate, current);
|
||||
if (block_scope_object.is_null()) {
|
||||
return Handle<Context>::null();
|
||||
}
|
||||
CHECK(!block_scope_object.is_null());
|
||||
// Allocate a new function context for the debug evaluation and set the
|
||||
// extension object.
|
||||
Handle<Context> new_context =
|
||||
@ -11733,6 +11749,12 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
|
||||
context,
|
||||
frame,
|
||||
inlined_jsframe_index);
|
||||
if (context.is_null()) {
|
||||
ASSERT(isolate->has_pending_exception());
|
||||
MaybeObject* exception = isolate->pending_exception();
|
||||
isolate->clear_pending_exception();
|
||||
return exception;
|
||||
}
|
||||
|
||||
if (additional_context->IsJSObject()) {
|
||||
Handle<JSObject> extension = Handle<JSObject>::cast(additional_context);
|
||||
|
44
test/mjsunit/regress/regress-2318.js
Normal file
44
test/mjsunit/regress/regress-2318.js
Normal file
@ -0,0 +1,44 @@
|
||||
// Copyright 2012 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Flags: --expose-debug-as debug
|
||||
|
||||
function f() {
|
||||
var i = 0;
|
||||
f(1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0);
|
||||
};
|
||||
|
||||
Debug = debug.Debug;
|
||||
var bp = Debug.setBreakPoint(f, 0);
|
||||
|
||||
function listener(event, exec_state, event_data, data) {
|
||||
result = exec_state.frame().evaluate("i").value();
|
||||
};
|
||||
|
||||
Debug.setListener(listener);
|
||||
assertThrows(function() { f(); }, RangeError);
|
||||
|
Loading…
Reference in New Issue
Block a user