#include "src/ic-inl.h"
#include "src/isolate-inl.h"
#include "src/list.h"
+#include "src/log.h"
#include "src/messages.h"
#include "src/natives.h"
#include "src/stub-cache.h"
-#include "src/log.h"
#include "include/v8-debug.h"
BreakLocationIterator::~BreakLocationIterator() {
- ASSERT(reloc_iterator_ != NULL);
- ASSERT(reloc_iterator_original_ != NULL);
+ DCHECK(reloc_iterator_ != NULL);
+ DCHECK(reloc_iterator_original_ != NULL);
delete reloc_iterator_;
delete reloc_iterator_original_;
}
void BreakLocationIterator::Next() {
DisallowHeapAllocation no_gc;
- ASSERT(!RinfoDone());
+ DCHECK(!RinfoDone());
// Iterate through reloc info for code and original code stopping at each
// breakable code target.
// statement position.
position_ = static_cast<int>(
rinfo()->data() - debug_info_->shared()->start_position());
- ASSERT(position_ >= 0);
- ASSERT(statement_position_ >= 0);
+ DCHECK(position_ >= 0);
+ DCHECK(statement_position_ >= 0);
}
if (IsDebugBreakSlot()) {
return;
}
} else {
- ASSERT(type_ == SOURCE_BREAK_LOCATIONS);
+ DCHECK(type_ == SOURCE_BREAK_LOCATIONS);
if (IsSourceBreakStub(code)) {
break_point_++;
return;
// If there is not already a real break point here patch code with debug
// break.
if (!HasBreakPoint()) SetDebugBreak();
- ASSERT(IsDebugBreak() || IsDebuggerStatement());
+ DCHECK(IsDebugBreak() || IsDebuggerStatement());
// Set the break point information.
DebugInfo::SetBreakPoint(debug_info_, code_position(),
position(), statement_position(),
// If there are no more break points here remove the debug break.
if (!HasBreakPoint()) {
ClearDebugBreak();
- ASSERT(!IsDebugBreak());
+ DCHECK(!IsDebugBreak());
}
}
// If there is a real break point here no more to do.
if (HasBreakPoint()) {
- ASSERT(IsDebugBreak());
+ DCHECK(IsDebugBreak());
return;
}
// If there is a real break point here no more to do.
if (HasBreakPoint()) {
- ASSERT(IsDebugBreak());
+ DCHECK(IsDebugBreak());
return;
}
// Patch code removing debug break.
ClearDebugBreak();
- ASSERT(!IsDebugBreak());
+ DCHECK(!IsDebugBreak());
}
// Patch the IC call.
SetDebugBreakAtIC();
}
- ASSERT(IsDebugBreak());
+ DCHECK(IsDebugBreak());
}
// Patch the IC call.
ClearDebugBreakAtIC();
}
- ASSERT(!IsDebugBreak());
+ DCHECK(!IsDebugBreak());
}
Address target = original_rinfo()->target_address();
Handle<Code> target_code(Code::GetCodeFromTargetAddress(target));
if (target_code->kind() == Code::STUB) {
- return target_code->major_key() == CodeStub::CallFunction;
+ return CodeStub::GetMajorKey(*target_code) == CodeStub::CallFunction;
}
return target_code->is_call_stub();
}
}
bool is_call_function_stub =
(maybe_call_function_stub->kind() == Code::STUB &&
- maybe_call_function_stub->major_key() == CodeStub::CallFunction);
+ CodeStub::GetMajorKey(*maybe_call_function_stub) ==
+ CodeStub::CallFunction);
// Step in through construct call requires no changes to the running code.
// Step in through getters/setters should already be prepared as well
// Step in through CallFunction stub should also be prepared by caller of
// this function (Debug::PrepareStep) which should flood target function
// with breakpoints.
- ASSERT(RelocInfo::IsConstructCall(rmode()) ||
+ DCHECK(RelocInfo::IsConstructCall(rmode()) ||
target_code->is_inline_cache_stub() ||
is_call_function_stub);
#endif
}
}
if (code->kind() == Code::STUB) {
- ASSERT(code->major_key() == CodeStub::CallFunction);
+ DCHECK(CodeStub::GetMajorKey(*code) == CodeStub::CallFunction);
return isolate->builtins()->CallFunctionStub_DebugBreak();
}
bool BreakLocationIterator::RinfoDone() const {
- ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done());
+ DCHECK(reloc_iterator_->done() == reloc_iterator_original_->done());
return reloc_iterator_->done();
}
reloc_iterator_->next();
reloc_iterator_original_->next();
#ifdef DEBUG
- ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done());
+ DCHECK(reloc_iterator_->done() == reloc_iterator_original_->done());
if (!reloc_iterator_->done()) {
- ASSERT(rmode() == original_rmode());
+ DCHECK(rmode() == original_rmode());
}
#endif
}
ScriptCache::ScriptCache(Isolate* isolate) : HashMap(HashMap::PointersMatch),
- isolate_(isolate),
- collected_scripts_(10) {
+ isolate_(isolate) {
Heap* heap = isolate_->heap();
HandleScope scope(isolate_);
HashMap::Entry* entry =
HashMap::Lookup(reinterpret_cast<void*>(id), Hash(id), true);
if (entry->value != NULL) {
- ASSERT(*script == *reinterpret_cast<Script**>(entry->value));
+#ifdef DEBUG
+ // The code deserializer may introduce duplicate Script objects.
+ // Assert that the Script objects with the same id have the same name.
+ Handle<Script> found(reinterpret_cast<Script**>(entry->value));
+ DCHECK(script->id() == found->id());
+ DCHECK(!script->name()->IsString() ||
+ String::cast(script->name())->Equals(String::cast(found->name())));
+#endif
return;
}
// Globalize the script object, make it weak and use the location of the
Handle<FixedArray> instances = factory->NewFixedArray(occupancy());
int count = 0;
for (HashMap::Entry* entry = Start(); entry != NULL; entry = Next(entry)) {
- ASSERT(entry->value != NULL);
+ DCHECK(entry->value != NULL);
if (entry->value != NULL) {
instances->set(count, *reinterpret_cast<Script**>(entry->value));
count++;
}
-void ScriptCache::ProcessCollectedScripts() {
- Debug* debug = isolate_->debug();
- for (int i = 0; i < collected_scripts_.length(); i++) {
- debug->OnScriptCollected(collected_scripts_[i]);
- }
- collected_scripts_.Clear();
-}
-
-
void ScriptCache::Clear() {
// Iterate the script cache to get rid of all the weak handles.
for (HashMap::Entry* entry = Start(); entry != NULL; entry = Next(entry)) {
- ASSERT(entry != NULL);
+ DCHECK(entry != NULL);
Object** location = reinterpret_cast<Object**>(entry->value);
- ASSERT((*location)->IsScript());
+ DCHECK((*location)->IsScript());
GlobalHandles::ClearWeakness(location);
GlobalHandles::Destroy(location);
}
HashMap::Entry* entry = script_cache->Lookup(key, hash, false);
Object** location = reinterpret_cast<Object**>(entry->value);
script_cache->Remove(key, hash);
- script_cache->collected_scripts_.Add(id);
// Clear the weak handle.
GlobalHandles::Destroy(location);
for (DebugInfoListNode* n = debug->debug_info_list_;
n != NULL;
n = n->next()) {
- ASSERT(n != node);
+ DCHECK(n != node);
}
#endif
}
// Compile the script.
Handle<SharedFunctionInfo> function_info;
- function_info = Compiler::CompileScript(source_code,
- script_name, 0, 0,
- false,
- context,
- NULL, NULL, NO_CACHED_DATA,
- NATIVES_CODE);
+ function_info = Compiler::CompileScript(
+ source_code, script_name, 0, 0, false, context, NULL, NULL,
+ ScriptCompiler::kNoCompileOptions, NATIVES_CODE);
// Silently ignore stack overflows during compilation.
if (function_info.is_null()) {
- ASSERT(isolate->has_pending_exception());
+ DCHECK(isolate->has_pending_exception());
isolate->clear_pending_exception();
return false;
}
Handle<Object> exception;
MaybeHandle<Object> result =
Execution::TryCall(function,
- Handle<Object>(context->global_object(), isolate),
+ handle(context->global_proxy()),
0,
NULL,
&exception);
// Check for caught exceptions.
if (result.is_null()) {
- ASSERT(!isolate->has_pending_exception());
+ DCHECK(!isolate->has_pending_exception());
MessageLocation computed_location;
isolate->ComputeLocation(&computed_location);
Handle<Object> message = MessageHandler::MakeMessageObject(
isolate, "error_loading_debugger", &computed_location,
Vector<Handle<Object> >::empty(), Handle<JSArray>());
- ASSERT(!isolate->has_pending_exception());
+ DCHECK(!isolate->has_pending_exception());
if (!exception.is_null()) {
isolate->set_pending_exception(*exception);
MessageHandler::ReportMessage(isolate, NULL, message);
ExtensionConfiguration no_extensions;
Handle<Context> context =
isolate_->bootstrapper()->CreateEnvironment(
- Handle<Object>::null(),
+ MaybeHandle<JSGlobalProxy>(),
v8::Handle<ObjectTemplate>(),
&no_extensions);
Handle<JSBuiltinsObject> builtin =
Handle<JSBuiltinsObject>(global->builtins(), isolate_);
RETURN_ON_EXCEPTION_VALUE(
- isolate_,
- JSReceiver::SetProperty(global, key, builtin, NONE, SLOPPY),
- false);
+ isolate_, Object::SetProperty(global, key, builtin, SLOPPY), false);
// Compile the JavaScript for the debugger in the debugger context.
bool caught_exception =
ClearAllBreakPoints();
ClearStepping();
- // Match unmatched PromiseHandlePrologue calls.
- while (thread_local_.promise_on_stack_) PromiseHandleEpilogue();
+ // Match unmatched PopPromise calls.
+ while (thread_local_.promise_on_stack_) PopPromise();
// Return debugger is not loaded.
if (!is_loaded()) return;
void Debug::Break(Arguments args, JavaScriptFrame* frame) {
Heap* heap = isolate_->heap();
HandleScope scope(isolate_);
- ASSERT(args.length() == 0);
+ DCHECK(args.length() == 0);
// Initialize LiveEdit.
LiveEdit::InitializeThreadLocal(this);
frame->fp() != thread_local_.step_out_fp_ &&
break_points_hit->IsUndefined() ) {
// Step count should always be 0 for StepOut.
- ASSERT(thread_local_.step_count_ == 0);
+ DCHECK(thread_local_.step_count_ == 0);
} else if (!break_points_hit->IsUndefined() ||
(thread_local_.last_step_action_ != StepNone &&
thread_local_.step_count_ == 0)) {
// they are in a FixedArray.
Handle<FixedArray> break_points_hit;
int break_points_hit_count = 0;
- ASSERT(!break_point_objects->IsUndefined());
+ DCHECK(!break_point_objects->IsUndefined());
if (break_point_objects->IsFixedArray()) {
Handle<FixedArray> array(FixedArray::cast(*break_point_objects));
break_points_hit = factory->NewFixedArray(array->length());
// Return the debug info for this function. EnsureDebugInfo must be called
// prior to ensure the debug info has been generated for shared.
Handle<DebugInfo> Debug::GetDebugInfo(Handle<SharedFunctionInfo> shared) {
- ASSERT(HasDebugInfo(shared));
+ DCHECK(HasDebugInfo(shared));
return Handle<DebugInfo>(DebugInfo::cast(shared->debug_info()));
}
Handle<DebugInfo> debug_info = GetDebugInfo(shared);
// Source positions starts with zero.
- ASSERT(*source_position >= 0);
+ DCHECK(*source_position >= 0);
// Find the break point and change it.
BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
Handle<DebugInfo> debug_info = GetDebugInfo(shared);
// Source positions starts with zero.
- ASSERT(position >= 0);
+ DCHECK(position >= 0);
// Find the break point and change it.
BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
*source_position = it.position() + shared->start_position();
// At least one active break point now.
- ASSERT(debug_info->GetBreakPointCount() > 0);
+ DCHECK(debug_info->GetBreakPointCount() > 0);
return true;
}
isolate_);
if (!bindee.is_null() && bindee->IsJSFunction() &&
- !JSFunction::cast(*bindee)->IsNative()) {
+ !JSFunction::cast(*bindee)->IsFromNativeScript()) {
Handle<JSFunction> bindee_function(JSFunction::cast(*bindee));
Debug::FloodWithOneShot(bindee_function);
}
}
-PromiseOnStack::PromiseOnStack(Isolate* isolate,
- PromiseOnStack* prev,
- Handle<JSFunction> getter)
+PromiseOnStack::PromiseOnStack(Isolate* isolate, PromiseOnStack* prev,
+ Handle<JSObject> promise)
: isolate_(isolate), prev_(prev) {
handler_ = StackHandler::FromAddress(
Isolate::handler(isolate->thread_local_top()));
- getter_ = Handle<JSFunction>::cast(
- isolate->global_handles()->Create(*getter));
+ promise_ =
+ Handle<JSObject>::cast(isolate->global_handles()->Create(*promise));
}
PromiseOnStack::~PromiseOnStack() {
- isolate_->global_handles()->Destroy(Handle<Object>::cast(getter_).location());
+ isolate_->global_handles()->Destroy(
+ Handle<Object>::cast(promise_).location());
}
-void Debug::PromiseHandlePrologue(Handle<JSFunction> promise_getter) {
+void Debug::PushPromise(Handle<JSObject> promise) {
PromiseOnStack* prev = thread_local_.promise_on_stack_;
- thread_local_.promise_on_stack_ =
- new PromiseOnStack(isolate_, prev, promise_getter);
+ thread_local_.promise_on_stack_ = new PromiseOnStack(isolate_, prev, promise);
}
-void Debug::PromiseHandleEpilogue() {
+void Debug::PopPromise() {
if (thread_local_.promise_on_stack_ == NULL) return;
PromiseOnStack* prev = thread_local_.promise_on_stack_->prev();
delete thread_local_.promise_on_stack_;
}
-Handle<Object> Debug::GetPromiseForUncaughtException() {
+Handle<Object> Debug::GetPromiseOnStackOnThrow() {
Handle<Object> undefined = isolate_->factory()->undefined_value();
if (thread_local_.promise_on_stack_ == NULL) return undefined;
- Handle<JSFunction> promise_getter = thread_local_.promise_on_stack_->getter();
- StackHandler* promise_catch = thread_local_.promise_on_stack_->handler();
+ StackHandler* promise_try = thread_local_.promise_on_stack_->handler();
// Find the top-most try-catch handler.
StackHandler* handler = StackHandler::FromAddress(
Isolate::handler(isolate_->thread_local_top()));
- while (handler != NULL && !handler->is_catch()) {
+ do {
+ if (handler == promise_try) {
+ // Mark the pushed try-catch handler to prevent a later duplicate event
+ // triggered with the following reject.
+ return thread_local_.promise_on_stack_->promise();
+ }
handler = handler->next();
- }
-#ifdef DEBUG
- // Make sure that our promise catch handler is in the list of handlers,
- // even if it's not the top-most try-catch handler.
- StackHandler* temp = handler;
- while (temp != promise_catch && !temp->is_catch()) {
- temp = temp->next();
- CHECK(temp != NULL);
- }
-#endif // DEBUG
-
- if (handler == promise_catch) {
- return Execution::Call(
- isolate_, promise_getter, undefined, 0, NULL).ToHandleChecked();
- }
+ // Throwing inside a Promise can be intercepted by an inner try-catch, so
+ // we stop at the first try-catch handler.
+ } while (handler != NULL && !handler->is_catch());
return undefined;
}
+bool Debug::PromiseHasRejectHandler(Handle<JSObject> promise) {
+ Handle<JSFunction> fun = Handle<JSFunction>::cast(
+ JSObject::GetDataProperty(isolate_->js_builtins_object(),
+ isolate_->factory()->NewStringFromStaticAscii(
+ "PromiseHasRejectHandler")));
+ Handle<Object> result =
+ Execution::Call(isolate_, fun, promise, 0, NULL).ToHandleChecked();
+ return result->IsTrue();
+}
+
+
void Debug::PrepareStep(StepAction step_action,
int step_count,
StackFrame::Id frame_id) {
PrepareForBreakPoints();
- ASSERT(in_debug_scope());
+ DCHECK(in_debug_scope());
// Remember this step action and count.
thread_local_.last_step_action_ = step_action;
Code::GetCodeFromTargetAddress(original_target);
}
if ((maybe_call_function_stub->kind() == Code::STUB &&
- maybe_call_function_stub->major_key() == CodeStub::CallFunction) ||
+ CodeStub::GetMajorKey(maybe_call_function_stub) ==
+ CodeStub::CallFunction) ||
maybe_call_function_stub->kind() == Code::CALL_IC) {
// Save reference to the code as we may need it to find out arguments
// count for 'step in' later.
frames_it.Advance();
}
} else {
- ASSERT(it.IsExit());
+ DCHECK(it.IsExit());
frames_it.Advance();
}
// Skip builtin functions on the stack.
- while (!frames_it.done() && frames_it.frame()->function()->IsNative()) {
+ while (!frames_it.done() &&
+ frames_it.frame()->function()->IsFromNativeScript()) {
frames_it.Advance();
}
// Step out: If there is a JavaScript caller frame, we need to
bool is_call_ic = call_function_stub->kind() == Code::CALL_IC;
// Find out number of arguments from the stub minor key.
- // Reverse lookup required as the minor key cannot be retrieved
- // from the code object.
- Handle<Object> obj(
- isolate_->heap()->code_stubs()->SlowReverseLookup(
- *call_function_stub),
- isolate_);
- ASSERT(!obj.is_null());
- ASSERT(!(*obj)->IsUndefined());
- ASSERT(obj->IsSmi());
- // Get the STUB key and extract major and minor key.
- uint32_t key = Smi::cast(*obj)->value();
+ uint32_t key = call_function_stub->stub_key();
// Argc in the stub is the number of arguments passed - not the
// expected arguments of the called function.
int call_function_arg_count = is_call_ic
: CallFunctionStub::ExtractArgcFromMinorKey(
CodeStub::MinorKeyFromKey(key));
- ASSERT(is_call_ic ||
- call_function_stub->major_key() == CodeStub::MajorKeyFromKey(key));
+ DCHECK(is_call_ic ||
+ CodeStub::GetMajorKey(*call_function_stub) ==
+ CodeStub::MajorKeyFromKey(key));
// Find target function on the expression stack.
// Expression stack looks like this (top to bottom):
// Receiver
// Function to call
int expressions_count = frame->ComputeExpressionsCount();
- ASSERT(expressions_count - 2 - call_function_arg_count >= 0);
+ DCHECK(expressions_count - 2 - call_function_arg_count >= 0);
Object* fun = frame->GetExpression(
expressions_count - 2 - call_function_arg_count);
Handle<JSFunction> js_function(JSFunction::cast(fun));
if (js_function->shared()->bound()) {
Debug::FloodBoundFunctionWithOneShot(js_function);
- } else if (!js_function->IsNative()) {
+ } else if (!js_function->IsFromNativeScript()) {
// Don't step into builtins.
// It will also compile target function if it's not compiled yet.
FloodWithOneShot(js_function);
if (is_load_or_store) {
// Remember source position and frame to handle step in getter/setter. If
// there is a custom getter/setter it will be handled in
- // Object::Get/SetPropertyWithCallback, otherwise the step action will be
+ // Object::Get/SetPropertyWithAccessor, otherwise the step action will be
// propagated on the next Debug::Break.
thread_local_.last_statement_position_ =
debug_info->code()->SourceStatementPosition(frame->pc());
it.Advance();
// For constructor functions skip another frame.
if (is_constructor) {
- ASSERT(it.frame()->is_construct());
+ DCHECK(it.frame()->is_construct());
it.Advance();
}
fp = it.frame()->fp();
if (function->shared()->bound()) {
// Handle Function.prototype.bind
Debug::FloodBoundFunctionWithOneShot(function);
- } else if (!function->IsNative()) {
+ } else if (!function->IsFromNativeScript()) {
// Don't allow step into functions in the native context.
if (function->shared()->code() ==
isolate->builtins()->builtin(Builtins::kFunctionApply) ||
// function.
if (!holder.is_null() && holder->IsJSFunction()) {
Handle<JSFunction> js_function = Handle<JSFunction>::cast(holder);
- if (!js_function->IsNative()) {
+ if (!js_function->IsFromNativeScript()) {
Debug::FloodWithOneShot(js_function);
} else if (js_function->shared()->bound()) {
// Handle Function.prototype.bind
void Debug::ActivateStepIn(StackFrame* frame) {
- ASSERT(!StepOutActive());
+ DCHECK(!StepOutActive());
thread_local_.step_into_fp_ = frame->UnpaddedFP();
}
void Debug::ActivateStepOut(StackFrame* frame) {
- ASSERT(!StepInActive());
+ DCHECK(!StepInActive());
thread_local_.step_out_fp_ = frame->UnpaddedFP();
}
}
} else if (frame->function()->IsJSFunction()) {
JSFunction* function = frame->function();
- ASSERT(frame->LookupCode()->kind() == Code::FUNCTION);
+ DCHECK(frame->LookupCode()->kind() == Code::FUNCTION);
active_functions->Add(Handle<JSFunction>(function));
function->shared()->code()->set_gc_metadata(active_code_marker);
}
// Assembler::CheckConstPool() and Assembler::CheckVeneerPool(). Note that this
// is only useful for architectures using constant pools or veneer pools.
static int ComputeCodeOffsetFromPcOffset(Code *code, int pc_offset) {
- ASSERT_EQ(code->kind(), Code::FUNCTION);
- ASSERT(!code->has_debug_break_slots());
- ASSERT_LE(0, pc_offset);
- ASSERT_LT(pc_offset, code->instruction_end() - code->instruction_start());
+ DCHECK_EQ(code->kind(), Code::FUNCTION);
+ DCHECK(!code->has_debug_break_slots());
+ DCHECK_LE(0, pc_offset);
+ DCHECK_LT(pc_offset, code->instruction_end() - code->instruction_start());
int mask = RelocInfo::ModeMask(RelocInfo::CONST_POOL) |
RelocInfo::ModeMask(RelocInfo::VENEER_POOL);
for (RelocIterator it(code, mask); !it.done(); it.next()) {
RelocInfo* info = it.rinfo();
if (info->pc() >= pc) break;
- ASSERT(RelocInfo::IsConstPool(info->rmode()));
+ DCHECK(RelocInfo::IsConstPool(info->rmode()));
code_offset -= static_cast<int>(info->data());
- ASSERT_LE(0, code_offset);
+ DCHECK_LE(0, code_offset);
}
return code_offset;
// The inverse of ComputeCodeOffsetFromPcOffset.
static int ComputePcOffsetFromCodeOffset(Code *code, int code_offset) {
- ASSERT_EQ(code->kind(), Code::FUNCTION);
+ DCHECK_EQ(code->kind(), Code::FUNCTION);
int mask = RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) |
RelocInfo::ModeMask(RelocInfo::CONST_POOL) |
if (RelocInfo::IsDebugBreakSlot(info->rmode())) {
reloc += Assembler::kDebugBreakSlotLength;
} else {
- ASSERT(RelocInfo::IsConstPool(info->rmode()));
+ DCHECK(RelocInfo::IsConstPool(info->rmode()));
reloc += static_cast<int>(info->data());
}
}
int pc_offset = code_offset + reloc;
- ASSERT_LT(code->instruction_start() + pc_offset, code->instruction_end());
+ DCHECK_LT(code->instruction_start() + pc_offset, code->instruction_end());
return pc_offset;
}
JSFunction* function = frame->function();
- ASSERT(frame->LookupCode()->kind() == Code::FUNCTION);
+ DCHECK(frame->LookupCode()->kind() == Code::FUNCTION);
Handle<Code> frame_code(frame->LookupCode());
if (frame_code->has_debug_break_slots()) continue;
reinterpret_cast<intptr_t>(new_pc));
}
+ if (FLAG_enable_ool_constant_pool) {
+ // Update constant pool pointer for new code.
+ frame->set_constant_pool(new_code->constant_pool());
+ }
+
// Patch the return address to return into the code with
// debug break slots.
frame->set_pc(new_pc);
if (!shared->allows_lazy_compilation()) continue;
if (!shared->script()->IsScript()) continue;
- if (function->IsNative()) continue;
+ if (function->IsFromNativeScript()) continue;
if (shared->code()->gc_metadata() == active_code_marker) continue;
if (shared->is_generator()) {
if (!gen->is_suspended()) continue;
JSFunction* fun = gen->function();
- ASSERT_EQ(fun->code()->kind(), Code::FUNCTION);
+ DCHECK_EQ(fun->code()->kind(), Code::FUNCTION);
if (fun->code()->has_debug_break_slots()) continue;
int pc_offset = gen->continuation();
- ASSERT_LT(0, pc_offset);
+ DCHECK_LT(0, pc_offset);
int code_offset =
ComputeCodeOffsetFromPcOffset(fun->code(), pc_offset);
if (obj->IsJSFunction()) {
function = Handle<JSFunction>(JSFunction::cast(obj));
shared = Handle<SharedFunctionInfo>(function->shared());
- ASSERT(shared->allows_lazy_compilation() || shared->is_compiled());
+ DCHECK(shared->allows_lazy_compilation() || shared->is_compiled());
found_next_candidate = true;
} else if (obj->IsSharedFunctionInfo()) {
shared = Handle<SharedFunctionInfo>(SharedFunctionInfo::cast(obj));
// Return if we already have the debug info for shared.
if (HasDebugInfo(shared)) {
- ASSERT(shared->is_compiled());
+ DCHECK(shared->is_compiled());
return true;
}
void Debug::RemoveDebugInfo(Handle<DebugInfo> debug_info) {
- ASSERT(debug_info_list_ != NULL);
+ DCHECK(debug_info_list_ != NULL);
// Run through the debug info objects to find this one and remove it.
DebugInfoListNode* prev = NULL;
DebugInfoListNode* current = debug_info_list_;
#ifdef DEBUG
// Get the code which is actually executing.
Handle<Code> frame_code(frame->LookupCode());
- ASSERT(frame_code.is_identical_to(code));
+ DCHECK(frame_code.is_identical_to(code));
#endif
// Find the call address in the running code. This address holds the call to
// either a DebugBreakXXX or to the debug break return entry code if the
// break point is still active after processing the break point.
- Address addr = frame->pc() - Assembler::kPatchDebugBreakSlotReturnOffset;
+ Address addr = Assembler::break_address_from_return_address(frame->pc());
// Check if the location is at JS exit or debug break slot.
bool at_js_return = false;
// Continue just after the slot.
after_break_target_ = addr + Assembler::kDebugBreakSlotLength;
- } else if (IsDebugBreak(Assembler::target_address_at(addr, *code))) {
- // We now know that there is still a debug break call at the target address,
- // so the break point is still there and the original code will hold the
- // address to jump to in order to complete the call which is replaced by a
- // call to DebugBreakXXX.
-
- // Find the corresponding address in the original code.
- addr += original_code->instruction_start() - code->instruction_start();
-
- // Install jump to the call address in the original code. This will be the
- // call which was overwritten by the call to DebugBreakXXX.
- after_break_target_ = Assembler::target_address_at(addr, *original_code);
} else {
- // There is no longer a break point present. Don't try to look in the
- // original code as the running code will have the right address. This takes
- // care of the case where the last break point is removed from the function
- // and therefore no "original code" is available.
- after_break_target_ = Assembler::target_address_at(addr, *code);
+ addr = Assembler::target_address_from_return_address(frame->pc());
+ if (IsDebugBreak(Assembler::target_address_at(addr, *code))) {
+ // We now know that there is still a debug break call at the target
+ // address, so the break point is still there and the original code will
+ // hold the address to jump to in order to complete the call which is
+ // replaced by a call to DebugBreakXXX.
+
+ // Find the corresponding address in the original code.
+ addr += original_code->instruction_start() - code->instruction_start();
+
+ // Install jump to the call address in the original code. This will be the
+ // call which was overwritten by the call to DebugBreakXXX.
+ after_break_target_ = Assembler::target_address_at(addr, *original_code);
+ } else {
+ // There is no longer a break point present. Don't try to look in the
+ // original code as the running code will have the right address. This
+ // takes care of the case where the last break point is removed from the
+ // function and therefore no "original code" is available.
+ after_break_target_ = Assembler::target_address_at(addr, *code);
+ }
}
}
#ifdef DEBUG
// Get the code which is actually executing.
Handle<Code> frame_code(frame->LookupCode());
- ASSERT(frame_code.is_identical_to(code));
+ DCHECK(frame_code.is_identical_to(code));
#endif
// Find the call address in the running code.
- Address addr = frame->pc() - Assembler::kPatchDebugBreakSlotReturnOffset;
+ Address addr = Assembler::break_address_from_return_address(frame->pc());
// Check if the location is at JS return.
RelocIterator it(debug_info->code());
HandleScope scope(isolate_);
AssertDebugContext();
Factory* factory = isolate_->factory();
- JSObject::SetProperty(isolate_->global_object(),
+ Handle<GlobalObject> global(isolate_->global_object());
+ JSObject::SetProperty(global,
factory->NewStringFromAsciiChecked("next_handle_"),
handle(Smi::FromInt(0), isolate_),
- NONE,
SLOPPY).Check();
- JSObject::SetProperty(isolate_->global_object(),
+ JSObject::SetProperty(global,
factory->NewStringFromAsciiChecked("mirror_cache_"),
factory->NewJSArray(0, FAST_ELEMENTS),
- NONE,
SLOPPY).Check();
}
}
-void Debug::AfterGarbageCollection() {
- // Generate events for collected scripts.
- if (script_cache_ != NULL) {
- script_cache_->ProcessCollectedScripts();
- }
-}
-
-
MaybeHandle<Object> Debug::MakeJSObject(const char* constructor_name,
int argc,
Handle<Object> argv[]) {
AssertDebugContext();
// Create the execution state object.
+ Handle<GlobalObject> global(isolate_->global_object());
Handle<Object> constructor = Object::GetProperty(
- isolate_, isolate_->global_object(), constructor_name).ToHandleChecked();
- ASSERT(constructor->IsJSFunction());
+ isolate_, global, constructor_name).ToHandleChecked();
+ DCHECK(constructor->IsJSFunction());
if (!constructor->IsJSFunction()) return MaybeHandle<Object>();
// We do not handle interrupts here. In particular, termination interrupts.
PostponeInterruptsScope no_interrupts(isolate_);
return Execution::TryCall(Handle<JSFunction>::cast(constructor),
- Handle<JSObject>(debug_context()->global_object()),
+ handle(debug_context()->global_proxy()),
argc,
argv);
}
MaybeHandle<Object> Debug::MakeBreakEvent(Handle<Object> break_points_hit) {
- Handle<Object> exec_state;
- if (!MakeExecutionState().ToHandle(&exec_state)) return MaybeHandle<Object>();
// Create the new break event object.
- Handle<Object> argv[] = { exec_state, break_points_hit };
+ Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()),
+ break_points_hit };
return MakeJSObject("MakeBreakEvent", ARRAY_SIZE(argv), argv);
}
MaybeHandle<Object> Debug::MakeExceptionEvent(Handle<Object> exception,
bool uncaught,
Handle<Object> promise) {
- Handle<Object> exec_state;
- if (!MakeExecutionState().ToHandle(&exec_state)) return MaybeHandle<Object>();
// Create the new exception event object.
- Handle<Object> argv[] = { exec_state,
+ Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()),
exception,
isolate_->factory()->ToBoolean(uncaught),
promise };
MaybeHandle<Object> Debug::MakeCompileEvent(Handle<Script> script,
- bool before) {
- Handle<Object> exec_state;
- if (!MakeExecutionState().ToHandle(&exec_state)) return MaybeHandle<Object>();
+ v8::DebugEvent type) {
// Create the compile event object.
Handle<Object> script_wrapper = Script::GetWrapper(script);
- Handle<Object> argv[] = { exec_state,
- script_wrapper,
- isolate_->factory()->ToBoolean(before) };
+ Handle<Object> argv[] = { script_wrapper,
+ isolate_->factory()->NewNumberFromInt(type) };
return MakeJSObject("MakeCompileEvent", ARRAY_SIZE(argv), argv);
}
-MaybeHandle<Object> Debug::MakeScriptCollectedEvent(int id) {
- Handle<Object> exec_state;
- if (!MakeExecutionState().ToHandle(&exec_state)) return MaybeHandle<Object>();
- // Create the script collected event object.
- Handle<Object> id_object = Handle<Smi>(Smi::FromInt(id), isolate_);
- Handle<Object> argv[] = { exec_state, id_object };
- return MakeJSObject("MakeScriptCollectedEvent", ARRAY_SIZE(argv), argv);
+MaybeHandle<Object> Debug::MakePromiseEvent(Handle<JSObject> event_data) {
+ // Create the promise event object.
+ Handle<Object> argv[] = { event_data };
+ return MakeJSObject("MakePromiseEvent", ARRAY_SIZE(argv), argv);
+}
+
+
+MaybeHandle<Object> Debug::MakeAsyncTaskEvent(Handle<JSObject> task_event) {
+ // Create the async task event object.
+ Handle<Object> argv[] = { task_event };
+ return MakeJSObject("MakeAsyncTaskEvent", ARRAY_SIZE(argv), argv);
}
-void Debug::OnException(Handle<Object> exception, bool uncaught) {
+void Debug::OnThrow(Handle<Object> exception, bool uncaught) {
if (in_debug_scope() || ignore_events()) return;
+ HandleScope scope(isolate_);
+ OnException(exception, uncaught, GetPromiseOnStackOnThrow());
+}
+
+void Debug::OnPromiseReject(Handle<JSObject> promise, Handle<Object> value) {
+ if (in_debug_scope() || ignore_events()) return;
HandleScope scope(isolate_);
- Handle<Object> promise = GetPromiseForUncaughtException();
- uncaught |= !promise->IsUndefined();
+ OnException(value, false, promise);
+}
+
+void Debug::OnException(Handle<Object> exception, bool uncaught,
+ Handle<Object> promise) {
+ if (promise->IsJSObject()) {
+ uncaught |= !PromiseHasRejectHandler(Handle<JSObject>::cast(promise));
+ }
// Bail out if exception breaks are not active
if (uncaught) {
// Uncaught exceptions are reported by either flags.
}
+void Debug::OnCompileError(Handle<Script> script) {
+ // No more to do if not debugging.
+ if (in_debug_scope() || ignore_events()) return;
+
+ HandleScope scope(isolate_);
+ DebugScope debug_scope(this);
+ if (debug_scope.failed()) return;
+
+ // Create the compile state object.
+ Handle<Object> event_data;
+ // Bail out and don't call debugger if exception.
+ if (!MakeCompileEvent(script, v8::CompileError).ToHandle(&event_data)) return;
+
+ // Process debug event.
+ ProcessDebugEvent(v8::CompileError, Handle<JSObject>::cast(event_data), true);
+}
+
+
void Debug::OnDebugBreak(Handle<Object> break_points_hit,
bool auto_continue) {
// The caller provided for DebugScope.
// Create the event data object.
Handle<Object> event_data;
// Bail out and don't call debugger if exception.
- if (!MakeCompileEvent(script, true).ToHandle(&event_data)) return;
+ if (!MakeCompileEvent(script, v8::BeforeCompile).ToHandle(&event_data))
+ return;
// Process debug event.
ProcessDebugEvent(v8::BeforeCompile,
// Handle debugger actions when a new script is compiled.
-void Debug::OnAfterCompile(Handle<Script> script,
- AfterCompileFlags after_compile_flags) {
+void Debug::OnAfterCompile(Handle<Script> script) {
// Add the newly compiled script to the script cache.
if (script_cache_ != NULL) script_cache_->Add(script);
if (in_debug_scope() || ignore_events()) return;
HandleScope scope(isolate_);
- // Store whether in debugger before entering debugger.
- bool was_in_scope = in_debug_scope();
-
DebugScope debug_scope(this);
if (debug_scope.failed()) return;
if (!update_script_break_points->IsJSFunction()) {
return;
}
- ASSERT(update_script_break_points->IsJSFunction());
+ DCHECK(update_script_break_points->IsJSFunction());
// Wrap the script object in a proper JS object before passing it
// to JavaScript.
argv).is_null()) {
return;
}
- // Bail out based on state or if there is no listener for this event
- if (was_in_scope && (after_compile_flags & SEND_WHEN_DEBUGGING) == 0) return;
// Create the compile state object.
Handle<Object> event_data;
// Bail out and don't call debugger if exception.
- if (!MakeCompileEvent(script, false).ToHandle(&event_data)) return;
+ if (!MakeCompileEvent(script, v8::AfterCompile).ToHandle(&event_data)) return;
// Process debug event.
ProcessDebugEvent(v8::AfterCompile, Handle<JSObject>::cast(event_data), true);
}
-void Debug::OnScriptCollected(int id) {
+void Debug::OnPromiseEvent(Handle<JSObject> data) {
if (in_debug_scope() || ignore_events()) return;
HandleScope scope(isolate_);
// Create the script collected state object.
Handle<Object> event_data;
// Bail out and don't call debugger if exception.
- if (!MakeScriptCollectedEvent(id).ToHandle(&event_data)) return;
+ if (!MakePromiseEvent(data).ToHandle(&event_data)) return;
// Process debug event.
- ProcessDebugEvent(v8::ScriptCollected,
+ ProcessDebugEvent(v8::PromiseEvent,
+ Handle<JSObject>::cast(event_data),
+ true);
+}
+
+
+void Debug::OnAsyncTaskEvent(Handle<JSObject> data) {
+ if (in_debug_scope() || ignore_events()) return;
+
+ HandleScope scope(isolate_);
+ DebugScope debug_scope(this);
+ if (debug_scope.failed()) return;
+
+ // Create the script collected state object.
+ Handle<Object> event_data;
+ // Bail out and don't call debugger if exception.
+ if (!MakeAsyncTaskEvent(data).ToHandle(&event_data)) return;
+
+ // Process debug event.
+ ProcessDebugEvent(v8::AsyncTaskEvent,
Handle<JSObject>::cast(event_data),
true);
}
event_listener_data_,
client_data);
callback(event_details);
- ASSERT(!isolate_->has_scheduled_exception());
+ DCHECK(!isolate_->has_scheduled_exception());
} else {
// Invoke the JavaScript debug event listener.
- ASSERT(event_listener_->IsJSFunction());
+ DCHECK(event_listener_->IsJSFunction());
Handle<Object> argv[] = { Handle<Object>(Smi::FromInt(event), isolate_),
exec_state,
event_data,
event_listener_data_ };
+ Handle<JSReceiver> global(isolate_->global_proxy());
Execution::TryCall(Handle<JSFunction>::cast(event_listener_),
- isolate_->global_object(),
- ARRAY_SIZE(argv),
- argv);
+ global, ARRAY_SIZE(argv), argv);
}
}
// Prevent other interrupts from triggering, for example API callbacks,
// while dispatching message handler callbacks.
PostponeInterruptsScope no_interrupts(isolate_);
- ASSERT(is_active_);
+ DCHECK(is_active_);
HandleScope scope(isolate_);
// Process the individual events.
bool sendEventMessage = false;
case v8::AfterCompile:
sendEventMessage = true;
break;
- case v8::ScriptCollected:
- sendEventMessage = true;
- break;
case v8::NewFunction:
break;
default:
// The debug command interrupt flag might have been set when the command was
// added. It should be enough to clear the flag only once while we are in the
// debugger.
- ASSERT(in_debug_scope());
+ DCHECK(in_debug_scope());
isolate_->stack_guard()->ClearDebugCommand();
// Notify the debugger that a debug event has occurred unless auto continue is
// in the queue if any. For script collected events don't even process
// messages in the queue as the execution state might not be what is expected
// by the client.
- if ((auto_continue && !has_commands()) || event == v8::ScriptCollected) {
- return;
- }
+ if (auto_continue && !has_commands()) return;
// DebugCommandProcessor goes here.
bool running = auto_continue;
if (check.HasOverflowed()) return;
{ JavaScriptFrameIterator it(isolate_);
- ASSERT(!it.done());
+ DCHECK(!it.done());
Object* fun = it.frame()->function();
if (fun && fun->IsJSFunction()) {
// Don't stop in builtin functions.
}
-DebugScope::DebugScope(Debug* debug) : debug_(debug),
- prev_(debug->debugger_entry()),
- save_(debug_->isolate_) {
+DebugScope::DebugScope(Debug* debug)
+ : debug_(debug),
+ prev_(debug->debugger_entry()),
+ save_(debug_->isolate_),
+ no_termination_exceptons_(debug_->isolate_,
+ StackGuard::TERMINATE_EXECUTION) {
// Link recursive debugger entry.
debug_->thread_local_.current_debug_scope_ = this;
Isolate* isolate = event_data_->GetIsolate();
v8::Handle<v8::Context> context = GetDebugEventContext(isolate);
// Isolate::context() may be NULL when "script collected" event occures.
- ASSERT(!context.IsEmpty() || event_ == v8::ScriptCollected);
+ DCHECK(!context.IsEmpty());
return context;
}
CommandMessage CommandMessageQueue::Get() {
- ASSERT(!IsEmpty());
+ DCHECK(!IsEmpty());
int result = start_;
start_ = (start_ + 1) % size_;
return messages_[result];
bool LockingCommandMessageQueue::IsEmpty() const {
- LockGuard<Mutex> lock_guard(&mutex_);
+ base::LockGuard<base::Mutex> lock_guard(&mutex_);
return queue_.IsEmpty();
}
CommandMessage LockingCommandMessageQueue::Get() {
- LockGuard<Mutex> lock_guard(&mutex_);
+ base::LockGuard<base::Mutex> lock_guard(&mutex_);
CommandMessage result = queue_.Get();
logger_->DebugEvent("Get", result.text());
return result;
void LockingCommandMessageQueue::Put(const CommandMessage& message) {
- LockGuard<Mutex> lock_guard(&mutex_);
+ base::LockGuard<base::Mutex> lock_guard(&mutex_);
queue_.Put(message);
logger_->DebugEvent("Put", message.text());
}
void LockingCommandMessageQueue::Clear() {
- LockGuard<Mutex> lock_guard(&mutex_);
+ base::LockGuard<base::Mutex> lock_guard(&mutex_);
queue_.Clear();
}