From d74ece41800063f92a3bc02963a0aa83be2288c7 Mon Sep 17 00:00:00 2001 From: jgruber Date: Tue, 23 May 2017 05:17:09 -0700 Subject: [PATCH] [objects] Extract DebugInfo and BreakPointInfo to own file BUG=v8:5402 Review-Url: https://codereview.chromium.org/2900713004 Cr-Commit-Position: refs/heads/master@{#45486} --- BUILD.gn | 3 + src/debug/debug.cc | 6 + src/debug/debug.h | 6 +- src/deoptimizer.cc | 1 + src/factory.cc | 1 + src/factory.h | 2 + src/heap/heap.h | 6 + src/objects-debug.cc | 1 + src/objects-inl.h | 359 +++--------------------------- src/objects-printer.cc | 1 + src/objects.cc | 262 ++-------------------- src/objects.h | 102 +-------- src/objects/debug-objects-inl.h | 60 +++++ src/objects/debug-objects.cc | 246 ++++++++++++++++++++ src/objects/debug-objects.h | 115 ++++++++++ src/objects/object-macros-undef.h | 51 ++++- src/objects/object-macros.h | 206 +++++++++++++++++ src/v8.gyp | 3 + src/wasm/wasm-objects.cc | 1 + 19 files changed, 753 insertions(+), 679 deletions(-) create mode 100644 src/objects/debug-objects-inl.h create mode 100644 src/objects/debug-objects.cc create mode 100644 src/objects/debug-objects.h diff --git a/BUILD.gn b/BUILD.gn index 697fe07b43..91eea94c44 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -1748,6 +1748,9 @@ v8_source_set("v8_base") { "src/objects/code-cache.h", "src/objects/compilation-cache-inl.h", "src/objects/compilation-cache.h", + "src/objects/debug-objects-inl.h", + "src/objects/debug-objects.cc", + "src/objects/debug-objects.h", "src/objects/descriptor-array.h", "src/objects/dictionary.h", "src/objects/frame-array-inl.h", diff --git a/src/debug/debug.cc b/src/debug/debug.cc index 83613ef2bc..f257f67e29 100644 --- a/src/debug/debug.cc +++ b/src/debug/debug.cc @@ -28,6 +28,7 @@ #include "src/list.h" #include "src/log.h" #include "src/messages.h" +#include "src/objects/debug-objects-inl.h" #include "src/snapshot/natives.h" #include "src/wasm/wasm-module.h" #include "src/wasm/wasm-objects.h" @@ -248,6 +249,11 @@ void CodeBreakIterator::SkipToPosition(int position, SkipTo(it.BreakIndexFromPosition(position, alignment)); } +int CodeBreakIterator::code_offset() { + return static_cast(rinfo()->pc() - + debug_info_->DebugCode()->instruction_start()); +} + void CodeBreakIterator::SetDebugBreak() { DebugBreakType debug_break_type = GetDebugBreakType(); DCHECK(debug_break_type >= DEBUG_BREAK_SLOT); diff --git a/src/debug/debug.h b/src/debug/debug.h index 5dad8a8ceb..ae2a26d41a 100644 --- a/src/debug/debug.h +++ b/src/debug/debug.h @@ -17,6 +17,7 @@ #include "src/flags.h" #include "src/frames.h" #include "src/globals.h" +#include "src/objects/debug-objects.h" #include "src/runtime/runtime.h" #include "src/source-position-table.h" #include "src/string-stream.h" @@ -177,10 +178,7 @@ class CodeBreakIterator : public BreakIterator { void SkipToPosition(int position, BreakPositionAlignment alignment); - int code_offset() override { - return static_cast(rinfo()->pc() - - debug_info_->DebugCode()->instruction_start()); - } + int code_offset() override; private: int GetModeMask(); diff --git a/src/deoptimizer.cc b/src/deoptimizer.cc index 02aef7c7a5..f69ac22210 100644 --- a/src/deoptimizer.cc +++ b/src/deoptimizer.cc @@ -16,6 +16,7 @@ #include "src/global-handles.h" #include "src/interpreter/interpreter.h" #include "src/macro-assembler.h" +#include "src/objects/debug-objects-inl.h" #include "src/tracing/trace-event.h" #include "src/v8.h" diff --git a/src/factory.cc b/src/factory.cc index 067f8f82fc..80066cfe22 100644 --- a/src/factory.cc +++ b/src/factory.cc @@ -13,6 +13,7 @@ #include "src/conversions.h" #include "src/isolate-inl.h" #include "src/macro-assembler.h" +#include "src/objects/debug-objects-inl.h" #include "src/objects/frame-array-inl.h" #include "src/objects/module-info.h" #include "src/objects/scope-info.h" diff --git a/src/factory.h b/src/factory.h index 8146205559..779e397ce9 100644 --- a/src/factory.h +++ b/src/factory.h @@ -17,8 +17,10 @@ namespace v8 { namespace internal { +class BreakPointInfo; class BoilerplateDescription; class ConstantElementsPair; +class DebugInfo; enum FunctionMode { // With prototype. diff --git a/src/heap/heap.h b/src/heap/heap.h index 13473c2498..3c9414e434 100644 --- a/src/heap/heap.h +++ b/src/heap/heap.h @@ -338,6 +338,12 @@ using v8::MemoryPressureLevel; V(WithContextMap) \ PRIVATE_SYMBOL_LIST(V) +#define FIXED_ARRAY_ELEMENTS_WRITE_BARRIER(heap, array, start, length) \ + do { \ + heap->RecordFixedArrayElements(array, start, length); \ + heap->incremental_marking()->IterateBlackObject(array); \ + } while (false) + // Forward declarations. class AllocationObserver; class ArrayBufferTracker; diff --git a/src/objects-debug.cc b/src/objects-debug.cc index 8bab9289d6..ae10ccddfc 100644 --- a/src/objects-debug.cc +++ b/src/objects-debug.cc @@ -13,6 +13,7 @@ #include "src/layout-descriptor.h" #include "src/macro-assembler.h" #include "src/objects-inl.h" +#include "src/objects/debug-objects-inl.h" #include "src/objects/literal-objects.h" #include "src/objects/module-info.h" #include "src/ostreams.h" diff --git a/src/objects-inl.h b/src/objects-inl.h index 1414dfa233..df3acff039 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -67,79 +67,6 @@ int PropertyDetails::field_width_in_words() const { return representation().IsDouble() ? kDoubleSize / kPointerSize : 1; } -#define INT_ACCESSORS(holder, name, offset) \ - int holder::name() const { return READ_INT_FIELD(this, offset); } \ - void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); } - -#define ACCESSORS_CHECKED2(holder, name, type, offset, get_condition, \ - set_condition) \ - type* holder::name() const { \ - DCHECK(get_condition); \ - return type::cast(READ_FIELD(this, offset)); \ - } \ - void holder::set_##name(type* value, WriteBarrierMode mode) { \ - DCHECK(set_condition); \ - WRITE_FIELD(this, offset, value); \ - CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode); \ - } -#define ACCESSORS_CHECKED(holder, name, type, offset, condition) \ - ACCESSORS_CHECKED2(holder, name, type, offset, condition, condition) - -#define ACCESSORS(holder, name, type, offset) \ - ACCESSORS_CHECKED(holder, name, type, offset, true) - -// Getter that returns a Smi as an int and writes an int as a Smi. -#define SMI_ACCESSORS_CHECKED(holder, name, offset, condition) \ - int holder::name() const { \ - DCHECK(condition); \ - Object* value = READ_FIELD(this, offset); \ - return Smi::cast(value)->value(); \ - } \ - void holder::set_##name(int value) { \ - DCHECK(condition); \ - WRITE_FIELD(this, offset, Smi::FromInt(value)); \ - } - -#define SMI_ACCESSORS(holder, name, offset) \ - SMI_ACCESSORS_CHECKED(holder, name, offset, true) - -#define SYNCHRONIZED_SMI_ACCESSORS(holder, name, offset) \ - int holder::synchronized_##name() const { \ - Object* value = ACQUIRE_READ_FIELD(this, offset); \ - return Smi::cast(value)->value(); \ - } \ - void holder::synchronized_set_##name(int value) { \ - RELEASE_WRITE_FIELD(this, offset, Smi::FromInt(value)); \ - } - -#define NOBARRIER_SMI_ACCESSORS(holder, name, offset) \ - int holder::nobarrier_##name() const { \ - Object* value = NOBARRIER_READ_FIELD(this, offset); \ - return Smi::cast(value)->value(); \ - } \ - void holder::nobarrier_set_##name(int value) { \ - NOBARRIER_WRITE_FIELD(this, offset, Smi::FromInt(value)); \ - } - -#define BOOL_GETTER(holder, field, name, offset) \ - bool holder::name() const { \ - return BooleanBit::get(field(), offset); \ - } \ - - -#define BOOL_ACCESSORS(holder, field, name, offset) \ - bool holder::name() const { \ - return BooleanBit::get(field(), offset); \ - } \ - void holder::set_##name(bool value) { \ - set_##field(BooleanBit::set(field(), offset, value)); \ - } - -#define TYPE_CHECKER(type, instancetype) \ - bool HeapObject::Is##type() const { \ - return map()->instance_type() == instancetype; \ - } - TYPE_CHECKER(BreakPointInfo, TUPLE2_TYPE) TYPE_CHECKER(ByteArray, BYTE_ARRAY_TYPE) TYPE_CHECKER(BytecodeArray, BYTECODE_ARRAY_TYPE) @@ -602,9 +529,15 @@ bool Object::IsMinusZero() const { // Cast operations CAST_ACCESSOR(AbstractCode) +CAST_ACCESSOR(AccessCheckInfo) +CAST_ACCESSOR(AccessorInfo) +CAST_ACCESSOR(AccessorPair) +CAST_ACCESSOR(AliasedArgumentsEntry) +CAST_ACCESSOR(AllocationMemento) +CAST_ACCESSOR(AllocationSite) CAST_ACCESSOR(ArrayList) +CAST_ACCESSOR(AsyncGeneratorRequest) CAST_ACCESSOR(BoilerplateDescription) -CAST_ACCESSOR(BreakPointInfo) CAST_ACCESSOR(ByteArray) CAST_ACCESSOR(BytecodeArray) CAST_ACCESSOR(CallHandlerInfo) @@ -612,6 +545,7 @@ CAST_ACCESSOR(Cell) CAST_ACCESSOR(Code) CAST_ACCESSOR(ConsString) CAST_ACCESSOR(ConstantElementsPair) +CAST_ACCESSOR(ContextExtension) CAST_ACCESSOR(DeoptimizationInputData) CAST_ACCESSOR(DeoptimizationOutputData) CAST_ACCESSOR(DependentCode) @@ -624,19 +558,23 @@ CAST_ACCESSOR(FixedArrayBase) CAST_ACCESSOR(FixedDoubleArray) CAST_ACCESSOR(FixedTypedArrayBase) CAST_ACCESSOR(Foreign) +CAST_ACCESSOR(FunctionTemplateInfo) CAST_ACCESSOR(GlobalDictionary) CAST_ACCESSOR(HandlerTable) CAST_ACCESSOR(HeapObject) +CAST_ACCESSOR(InterceptorInfo) CAST_ACCESSOR(JSArgumentsObject); CAST_ACCESSOR(JSArray) CAST_ACCESSOR(JSArrayBuffer) CAST_ACCESSOR(JSArrayBufferView) +CAST_ACCESSOR(JSArrayIterator) +CAST_ACCESSOR(JSAsyncFromSyncIterator) +CAST_ACCESSOR(JSAsyncGeneratorObject) CAST_ACCESSOR(JSBoundFunction) CAST_ACCESSOR(JSDataView) CAST_ACCESSOR(JSDate) CAST_ACCESSOR(JSFunction) CAST_ACCESSOR(JSGeneratorObject) -CAST_ACCESSOR(JSAsyncGeneratorObject) CAST_ACCESSOR(JSGlobalObject) CAST_ACCESSOR(JSGlobalProxy) CAST_ACCESSOR(JSMap) @@ -644,65 +582,67 @@ CAST_ACCESSOR(JSMapIterator) CAST_ACCESSOR(JSMessageObject) CAST_ACCESSOR(JSModuleNamespace) CAST_ACCESSOR(JSObject) +CAST_ACCESSOR(JSPromise) +CAST_ACCESSOR(JSPromiseCapability) CAST_ACCESSOR(JSProxy) CAST_ACCESSOR(JSReceiver) CAST_ACCESSOR(JSRegExp) -CAST_ACCESSOR(JSPromiseCapability) -CAST_ACCESSOR(JSPromise) CAST_ACCESSOR(JSSet) CAST_ACCESSOR(JSSetIterator) CAST_ACCESSOR(JSSloppyArgumentsObject) -CAST_ACCESSOR(JSAsyncFromSyncIterator) CAST_ACCESSOR(JSStringIterator) -CAST_ACCESSOR(JSArrayIterator) CAST_ACCESSOR(JSTypedArray) CAST_ACCESSOR(JSValue) CAST_ACCESSOR(JSWeakCollection) CAST_ACCESSOR(JSWeakMap) CAST_ACCESSOR(JSWeakSet) CAST_ACCESSOR(LayoutDescriptor) +CAST_ACCESSOR(Module) CAST_ACCESSOR(ModuleInfo) +CAST_ACCESSOR(ModuleInfoEntry) CAST_ACCESSOR(Name) CAST_ACCESSOR(NameDictionary) CAST_ACCESSOR(NormalizedMapCache) CAST_ACCESSOR(Object) -CAST_ACCESSOR(ObjectHashTable) CAST_ACCESSOR(ObjectHashSet) +CAST_ACCESSOR(ObjectHashTable) +CAST_ACCESSOR(ObjectTemplateInfo) CAST_ACCESSOR(Oddball) CAST_ACCESSOR(OrderedHashMap) CAST_ACCESSOR(OrderedHashSet) +CAST_ACCESSOR(PromiseReactionJobInfo) +CAST_ACCESSOR(PromiseResolveThenableJobInfo) CAST_ACCESSOR(PropertyCell) -CAST_ACCESSOR(TemplateList) +CAST_ACCESSOR(PrototypeInfo) CAST_ACCESSOR(RegExpMatchInfo) CAST_ACCESSOR(ScopeInfo) +CAST_ACCESSOR(Script) CAST_ACCESSOR(SeededNumberDictionary) CAST_ACCESSOR(SeqOneByteString) CAST_ACCESSOR(SeqString) CAST_ACCESSOR(SeqTwoByteString) CAST_ACCESSOR(SharedFunctionInfo) -CAST_ACCESSOR(SourcePositionTableWithFrameCache) CAST_ACCESSOR(SlicedString) CAST_ACCESSOR(SloppyArgumentsElements) CAST_ACCESSOR(Smi) +CAST_ACCESSOR(SourcePositionTableWithFrameCache) +CAST_ACCESSOR(StackFrameInfo) CAST_ACCESSOR(String) CAST_ACCESSOR(StringSet) CAST_ACCESSOR(StringTable) CAST_ACCESSOR(Struct) CAST_ACCESSOR(Symbol) CAST_ACCESSOR(TemplateInfo) +CAST_ACCESSOR(TemplateList) CAST_ACCESSOR(ThinString) +CAST_ACCESSOR(Tuple2) +CAST_ACCESSOR(Tuple3) CAST_ACCESSOR(TypeFeedbackInfo) CAST_ACCESSOR(UnseededNumberDictionary) CAST_ACCESSOR(WeakCell) CAST_ACCESSOR(WeakFixedArray) CAST_ACCESSOR(WeakHashTable) -#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name) -STRUCT_LIST(MAKE_STRUCT_CAST) -#undef MAKE_STRUCT_CAST - -#undef CAST_ACCESSOR - bool Object::HasValidElements() { // Dictionary is covered under FixedArray. return IsFixedArray() || IsFixedDoubleArray() || IsFixedTypedArrayBase(); @@ -1267,150 +1207,6 @@ bool JSObject::PrototypeHasNoElements(Isolate* isolate, JSObject* object) { return true; } -#define FIELD_ADDR(p, offset) \ - (reinterpret_cast(p) + offset - kHeapObjectTag) - -#define FIELD_ADDR_CONST(p, offset) \ - (reinterpret_cast(p) + offset - kHeapObjectTag) - -#define READ_FIELD(p, offset) \ - (*reinterpret_cast(FIELD_ADDR_CONST(p, offset))) - -#define ACQUIRE_READ_FIELD(p, offset) \ - reinterpret_cast(base::Acquire_Load( \ - reinterpret_cast(FIELD_ADDR_CONST(p, offset)))) - -#define NOBARRIER_READ_FIELD(p, offset) \ - reinterpret_cast(base::NoBarrier_Load( \ - reinterpret_cast(FIELD_ADDR_CONST(p, offset)))) - -#ifdef V8_CONCURRENT_MARKING -#define WRITE_FIELD(p, offset, value) \ - base::NoBarrier_Store( \ - reinterpret_cast(FIELD_ADDR(p, offset)), \ - reinterpret_cast(value)); -#else -#define WRITE_FIELD(p, offset, value) \ - (*reinterpret_cast(FIELD_ADDR(p, offset)) = value) -#endif - -#define RELEASE_WRITE_FIELD(p, offset, value) \ - base::Release_Store( \ - reinterpret_cast(FIELD_ADDR(p, offset)), \ - reinterpret_cast(value)); - -#define NOBARRIER_WRITE_FIELD(p, offset, value) \ - base::NoBarrier_Store( \ - reinterpret_cast(FIELD_ADDR(p, offset)), \ - reinterpret_cast(value)); - -#define WRITE_BARRIER(heap, object, offset, value) \ - heap->incremental_marking()->RecordWrite( \ - object, HeapObject::RawField(object, offset), value); \ - heap->RecordWrite(object, offset, value); - -#define FIXED_ARRAY_ELEMENTS_WRITE_BARRIER(heap, array, start, length) \ - do { \ - heap->RecordFixedArrayElements(array, start, length); \ - heap->incremental_marking()->IterateBlackObject(array); \ - } while (false) - -#define CONDITIONAL_WRITE_BARRIER(heap, object, offset, value, mode) \ - if (mode != SKIP_WRITE_BARRIER) { \ - if (mode == UPDATE_WRITE_BARRIER) { \ - heap->incremental_marking()->RecordWrite( \ - object, HeapObject::RawField(object, offset), value); \ - } \ - heap->RecordWrite(object, offset, value); \ - } - -#define READ_DOUBLE_FIELD(p, offset) \ - ReadDoubleValue(FIELD_ADDR_CONST(p, offset)) - -#define WRITE_DOUBLE_FIELD(p, offset, value) \ - WriteDoubleValue(FIELD_ADDR(p, offset), value) - -#define READ_INT_FIELD(p, offset) \ - (*reinterpret_cast(FIELD_ADDR_CONST(p, offset))) - -#define WRITE_INT_FIELD(p, offset, value) \ - (*reinterpret_cast(FIELD_ADDR(p, offset)) = value) - -#define READ_INTPTR_FIELD(p, offset) \ - (*reinterpret_cast(FIELD_ADDR_CONST(p, offset))) - -#define WRITE_INTPTR_FIELD(p, offset, value) \ - (*reinterpret_cast(FIELD_ADDR(p, offset)) = value) - -#define READ_UINT8_FIELD(p, offset) \ - (*reinterpret_cast(FIELD_ADDR_CONST(p, offset))) - -#define WRITE_UINT8_FIELD(p, offset, value) \ - (*reinterpret_cast(FIELD_ADDR(p, offset)) = value) - -#define READ_INT8_FIELD(p, offset) \ - (*reinterpret_cast(FIELD_ADDR_CONST(p, offset))) - -#define WRITE_INT8_FIELD(p, offset, value) \ - (*reinterpret_cast(FIELD_ADDR(p, offset)) = value) - -#define READ_UINT16_FIELD(p, offset) \ - (*reinterpret_cast(FIELD_ADDR_CONST(p, offset))) - -#define WRITE_UINT16_FIELD(p, offset, value) \ - (*reinterpret_cast(FIELD_ADDR(p, offset)) = value) - -#define READ_INT16_FIELD(p, offset) \ - (*reinterpret_cast(FIELD_ADDR_CONST(p, offset))) - -#define WRITE_INT16_FIELD(p, offset, value) \ - (*reinterpret_cast(FIELD_ADDR(p, offset)) = value) - -#define READ_UINT32_FIELD(p, offset) \ - (*reinterpret_cast(FIELD_ADDR_CONST(p, offset))) - -#define WRITE_UINT32_FIELD(p, offset, value) \ - (*reinterpret_cast(FIELD_ADDR(p, offset)) = value) - -#define READ_INT32_FIELD(p, offset) \ - (*reinterpret_cast(FIELD_ADDR_CONST(p, offset))) - -#define WRITE_INT32_FIELD(p, offset, value) \ - (*reinterpret_cast(FIELD_ADDR(p, offset)) = value) - -#define READ_FLOAT_FIELD(p, offset) \ - (*reinterpret_cast(FIELD_ADDR_CONST(p, offset))) - -#define WRITE_FLOAT_FIELD(p, offset, value) \ - (*reinterpret_cast(FIELD_ADDR(p, offset)) = value) - -#define READ_UINT64_FIELD(p, offset) \ - (*reinterpret_cast(FIELD_ADDR_CONST(p, offset))) - -#define WRITE_UINT64_FIELD(p, offset, value) \ - (*reinterpret_cast(FIELD_ADDR(p, offset)) = value) - -#define READ_INT64_FIELD(p, offset) \ - (*reinterpret_cast(FIELD_ADDR_CONST(p, offset))) - -#define WRITE_INT64_FIELD(p, offset, value) \ - (*reinterpret_cast(FIELD_ADDR(p, offset)) = value) - -#define READ_BYTE_FIELD(p, offset) \ - (*reinterpret_cast(FIELD_ADDR_CONST(p, offset))) - -#define NOBARRIER_READ_BYTE_FIELD(p, offset) \ - static_cast(base::NoBarrier_Load( \ - reinterpret_cast(FIELD_ADDR(p, offset)))) - -#define WRITE_BYTE_FIELD(p, offset, value) \ - (*reinterpret_cast(FIELD_ADDR(p, offset)) = value) - -#define NOBARRIER_WRITE_BYTE_FIELD(p, offset, value) \ - base::NoBarrier_Store( \ - reinterpret_cast(FIELD_ADDR(p, offset)), \ - static_cast(value)); - Object** HeapObject::RawField(HeapObject* obj, int byte_offset) { return reinterpret_cast(FIELD_ADDR(obj, byte_offset)); } @@ -5841,41 +5637,6 @@ void Script::set_origin_options(ScriptOriginOptions origin_options) { (origin_options.Flags() << kOriginOptionsShift)); } - -ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex) -SMI_ACCESSORS(DebugInfo, debugger_hints, kDebuggerHintsIndex) -ACCESSORS(DebugInfo, debug_bytecode_array, Object, kDebugBytecodeArrayIndex) -ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex) - -bool DebugInfo::HasDebugBytecodeArray() { - return debug_bytecode_array()->IsBytecodeArray(); -} - -bool DebugInfo::HasDebugCode() { - Code* code = shared()->code(); - bool has = code->kind() == Code::FUNCTION; - DCHECK(!has || code->has_debug_break_slots()); - return has; -} - -BytecodeArray* DebugInfo::OriginalBytecodeArray() { - DCHECK(HasDebugBytecodeArray()); - return shared()->bytecode_array(); -} - -BytecodeArray* DebugInfo::DebugBytecodeArray() { - DCHECK(HasDebugBytecodeArray()); - return BytecodeArray::cast(debug_bytecode_array()); -} - -Code* DebugInfo::DebugCode() { - DCHECK(HasDebugCode()); - return shared()->code(); -} - -SMI_ACCESSORS(BreakPointInfo, source_position, kSourcePositionIndex) -ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex) - SMI_ACCESSORS(StackFrameInfo, line_number, kLineNumberIndex) SMI_ACCESSORS(StackFrameInfo, column_number, kColumnNumberIndex) SMI_ACCESSORS(StackFrameInfo, script_id, kScriptIdIndex) @@ -6204,29 +5965,11 @@ bool SharedFunctionInfo::HasDebugInfo() const { return has_debug_info; } -DebugInfo* SharedFunctionInfo::GetDebugInfo() const { - DCHECK(HasDebugInfo()); - return DebugInfo::cast(debug_info()); -} - bool SharedFunctionInfo::HasDebugCode() const { if (HasBaselineCode()) return code()->has_debug_break_slots(); return HasBytecodeArray(); } -int SharedFunctionInfo::debugger_hints() const { - if (HasDebugInfo()) return GetDebugInfo()->debugger_hints(); - return Smi::cast(debug_info())->value(); -} - -void SharedFunctionInfo::set_debugger_hints(int value) { - if (HasDebugInfo()) { - GetDebugInfo()->set_debugger_hints(value); - } else { - set_debug_info(Smi::FromInt(value)); - } -} - bool SharedFunctionInfo::IsApiFunction() { return function_data()->IsFunctionTemplateInfo(); } @@ -8206,52 +7949,6 @@ ACCESSORS(JSAsyncFromSyncIterator, sync_iterator, JSReceiver, ACCESSORS(JSStringIterator, string, String, kStringOffset) SMI_ACCESSORS(JSStringIterator, index, kNextIndexOffset) -#undef INT_ACCESSORS -#undef ACCESSORS -#undef ACCESSORS_CHECKED -#undef ACCESSORS_CHECKED2 -#undef SMI_ACCESSORS -#undef SYNCHRONIZED_SMI_ACCESSORS -#undef NOBARRIER_SMI_ACCESSORS -#undef BOOL_GETTER -#undef BOOL_ACCESSORS -#undef FIELD_ADDR -#undef FIELD_ADDR_CONST -#undef READ_FIELD -#undef NOBARRIER_READ_FIELD -#undef WRITE_FIELD -#undef NOBARRIER_WRITE_FIELD -#undef WRITE_BARRIER -#undef CONDITIONAL_WRITE_BARRIER -#undef READ_DOUBLE_FIELD -#undef WRITE_DOUBLE_FIELD -#undef READ_INT_FIELD -#undef WRITE_INT_FIELD -#undef READ_INTPTR_FIELD -#undef WRITE_INTPTR_FIELD -#undef READ_UINT8_FIELD -#undef WRITE_UINT8_FIELD -#undef READ_INT8_FIELD -#undef WRITE_INT8_FIELD -#undef READ_UINT16_FIELD -#undef WRITE_UINT16_FIELD -#undef READ_INT16_FIELD -#undef WRITE_INT16_FIELD -#undef READ_UINT32_FIELD -#undef WRITE_UINT32_FIELD -#undef READ_INT32_FIELD -#undef WRITE_INT32_FIELD -#undef READ_FLOAT_FIELD -#undef WRITE_FLOAT_FIELD -#undef READ_UINT64_FIELD -#undef WRITE_UINT64_FIELD -#undef READ_INT64_FIELD -#undef WRITE_INT64_FIELD -#undef READ_BYTE_FIELD -#undef WRITE_BYTE_FIELD -#undef NOBARRIER_READ_BYTE_FIELD -#undef NOBARRIER_WRITE_BYTE_FIELD - } // namespace internal } // namespace v8 diff --git a/src/objects-printer.cc b/src/objects-printer.cc index 2ea68863cf..e8d6b49768 100644 --- a/src/objects-printer.cc +++ b/src/objects-printer.cc @@ -12,6 +12,7 @@ #include "src/disassembler.h" #include "src/interpreter/bytecodes.h" #include "src/objects-inl.h" +#include "src/objects/debug-objects-inl.h" #include "src/ostreams.h" #include "src/regexp/jsregexp.h" diff --git a/src/objects.cc b/src/objects.cc index a181edf76e..ce840e228d 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -57,6 +57,7 @@ #include "src/objects-body-descriptors-inl.h" #include "src/objects/code-cache-inl.h" #include "src/objects/compilation-cache-inl.h" +#include "src/objects/debug-objects-inl.h" #include "src/objects/frame-array-inl.h" #include "src/objects/map.h" #include "src/property-descriptor.h" @@ -13417,6 +13418,23 @@ void SharedFunctionInfo::SetScript(Handle shared, shared->set_script(*script_object); } +DebugInfo* SharedFunctionInfo::GetDebugInfo() const { + DCHECK(HasDebugInfo()); + return DebugInfo::cast(debug_info()); +} + +int SharedFunctionInfo::debugger_hints() const { + if (HasDebugInfo()) return GetDebugInfo()->debugger_hints(); + return Smi::cast(debug_info())->value(); +} + +void SharedFunctionInfo::set_debugger_hints(int value) { + if (HasDebugInfo()) { + GetDebugInfo()->set_debugger_hints(value); + } else { + set_debug_info(Smi::FromInt(value)); + } +} String* SharedFunctionInfo::DebugName() { Object* n = name(); @@ -19107,250 +19125,6 @@ Handle JSWeakCollection::GetEntries(Handle holder, return isolate->factory()->NewJSArrayWithElements(entries); } -// Check if there is a break point at this source position. -bool DebugInfo::HasBreakPoint(int source_position) { - // Get the break point info object for this code offset. - Object* break_point_info = GetBreakPointInfo(source_position); - - // If there is no break point info object or no break points in the break - // point info object there is no break point at this code offset. - if (break_point_info->IsUndefined(GetIsolate())) return false; - return BreakPointInfo::cast(break_point_info)->GetBreakPointCount() > 0; -} - -// Get the break point info object for this source position. -Object* DebugInfo::GetBreakPointInfo(int source_position) { - Isolate* isolate = GetIsolate(); - if (!break_points()->IsUndefined(isolate)) { - for (int i = 0; i < break_points()->length(); i++) { - if (!break_points()->get(i)->IsUndefined(isolate)) { - BreakPointInfo* break_point_info = - BreakPointInfo::cast(break_points()->get(i)); - if (break_point_info->source_position() == source_position) { - return break_point_info; - } - } - } - } - return isolate->heap()->undefined_value(); -} - -bool DebugInfo::ClearBreakPoint(Handle debug_info, - Handle break_point_object) { - Isolate* isolate = debug_info->GetIsolate(); - if (debug_info->break_points()->IsUndefined(isolate)) return false; - - for (int i = 0; i < debug_info->break_points()->length(); i++) { - if (debug_info->break_points()->get(i)->IsUndefined(isolate)) continue; - Handle break_point_info = Handle( - BreakPointInfo::cast(debug_info->break_points()->get(i)), isolate); - if (BreakPointInfo::HasBreakPointObject(break_point_info, - break_point_object)) { - BreakPointInfo::ClearBreakPoint(break_point_info, break_point_object); - return true; - } - } - return false; -} - -void DebugInfo::SetBreakPoint(Handle debug_info, int source_position, - Handle break_point_object) { - Isolate* isolate = debug_info->GetIsolate(); - Handle break_point_info( - debug_info->GetBreakPointInfo(source_position), isolate); - if (!break_point_info->IsUndefined(isolate)) { - BreakPointInfo::SetBreakPoint( - Handle::cast(break_point_info), - break_point_object); - return; - } - - // Adding a new break point for a code offset which did not have any - // break points before. Try to find a free slot. - static const int kNoBreakPointInfo = -1; - int index = kNoBreakPointInfo; - for (int i = 0; i < debug_info->break_points()->length(); i++) { - if (debug_info->break_points()->get(i)->IsUndefined(isolate)) { - index = i; - break; - } - } - if (index == kNoBreakPointInfo) { - // No free slot - extend break point info array. - Handle old_break_points = Handle( - FixedArray::cast(debug_info->break_points()), isolate); - Handle new_break_points = - isolate->factory()->NewFixedArray( - old_break_points->length() + - DebugInfo::kEstimatedNofBreakPointsInFunction); - - debug_info->set_break_points(*new_break_points); - for (int i = 0; i < old_break_points->length(); i++) { - new_break_points->set(i, old_break_points->get(i)); - } - index = old_break_points->length(); - } - DCHECK(index != kNoBreakPointInfo); - - // Allocate new BreakPointInfo object and set the break point. - Handle new_break_point_info = - isolate->factory()->NewBreakPointInfo(source_position); - BreakPointInfo::SetBreakPoint(new_break_point_info, break_point_object); - debug_info->break_points()->set(index, *new_break_point_info); -} - -// Get the break point objects for a source position. -Handle DebugInfo::GetBreakPointObjects(int source_position) { - Object* break_point_info = GetBreakPointInfo(source_position); - Isolate* isolate = GetIsolate(); - if (break_point_info->IsUndefined(isolate)) { - return isolate->factory()->undefined_value(); - } - return Handle( - BreakPointInfo::cast(break_point_info)->break_point_objects(), isolate); -} - - -// Get the total number of break points. -int DebugInfo::GetBreakPointCount() { - Isolate* isolate = GetIsolate(); - if (break_points()->IsUndefined(isolate)) return 0; - int count = 0; - for (int i = 0; i < break_points()->length(); i++) { - if (!break_points()->get(i)->IsUndefined(isolate)) { - BreakPointInfo* break_point_info = - BreakPointInfo::cast(break_points()->get(i)); - count += break_point_info->GetBreakPointCount(); - } - } - return count; -} - - -Handle DebugInfo::FindBreakPointInfo( - Handle debug_info, Handle break_point_object) { - Isolate* isolate = debug_info->GetIsolate(); - if (!debug_info->break_points()->IsUndefined(isolate)) { - for (int i = 0; i < debug_info->break_points()->length(); i++) { - if (!debug_info->break_points()->get(i)->IsUndefined(isolate)) { - Handle break_point_info = Handle( - BreakPointInfo::cast(debug_info->break_points()->get(i)), isolate); - if (BreakPointInfo::HasBreakPointObject(break_point_info, - break_point_object)) { - return break_point_info; - } - } - } - } - return isolate->factory()->undefined_value(); -} - -// Remove the specified break point object. -void BreakPointInfo::ClearBreakPoint(Handle break_point_info, - Handle break_point_object) { - Isolate* isolate = break_point_info->GetIsolate(); - // If there are no break points just ignore. - if (break_point_info->break_point_objects()->IsUndefined(isolate)) return; - // If there is a single break point clear it if it is the same. - if (!break_point_info->break_point_objects()->IsFixedArray()) { - if (break_point_info->break_point_objects() == *break_point_object) { - break_point_info->set_break_point_objects( - isolate->heap()->undefined_value()); - } - return; - } - // If there are multiple break points shrink the array - DCHECK(break_point_info->break_point_objects()->IsFixedArray()); - Handle old_array = - Handle( - FixedArray::cast(break_point_info->break_point_objects())); - Handle new_array = - isolate->factory()->NewFixedArray(old_array->length() - 1); - int found_count = 0; - for (int i = 0; i < old_array->length(); i++) { - if (old_array->get(i) == *break_point_object) { - DCHECK(found_count == 0); - found_count++; - } else { - new_array->set(i - found_count, old_array->get(i)); - } - } - // If the break point was found in the list change it. - if (found_count > 0) break_point_info->set_break_point_objects(*new_array); -} - - -// Add the specified break point object. -void BreakPointInfo::SetBreakPoint(Handle break_point_info, - Handle break_point_object) { - Isolate* isolate = break_point_info->GetIsolate(); - - // If there was no break point objects before just set it. - if (break_point_info->break_point_objects()->IsUndefined(isolate)) { - break_point_info->set_break_point_objects(*break_point_object); - return; - } - // If the break point object is the same as before just ignore. - if (break_point_info->break_point_objects() == *break_point_object) return; - // If there was one break point object before replace with array. - if (!break_point_info->break_point_objects()->IsFixedArray()) { - Handle array = isolate->factory()->NewFixedArray(2); - array->set(0, break_point_info->break_point_objects()); - array->set(1, *break_point_object); - break_point_info->set_break_point_objects(*array); - return; - } - // If there was more than one break point before extend array. - Handle old_array = - Handle( - FixedArray::cast(break_point_info->break_point_objects())); - Handle new_array = - isolate->factory()->NewFixedArray(old_array->length() + 1); - for (int i = 0; i < old_array->length(); i++) { - // If the break point was there before just ignore. - if (old_array->get(i) == *break_point_object) return; - new_array->set(i, old_array->get(i)); - } - // Add the new break point. - new_array->set(old_array->length(), *break_point_object); - break_point_info->set_break_point_objects(*new_array); -} - - -bool BreakPointInfo::HasBreakPointObject( - Handle break_point_info, - Handle break_point_object) { - // No break point. - Isolate* isolate = break_point_info->GetIsolate(); - if (break_point_info->break_point_objects()->IsUndefined(isolate)) { - return false; - } - // Single break point. - if (!break_point_info->break_point_objects()->IsFixedArray()) { - return break_point_info->break_point_objects() == *break_point_object; - } - // Multiple break points. - FixedArray* array = FixedArray::cast(break_point_info->break_point_objects()); - for (int i = 0; i < array->length(); i++) { - if (array->get(i) == *break_point_object) { - return true; - } - } - return false; -} - - -// Get the number of break points. -int BreakPointInfo::GetBreakPointCount() { - // No break point. - if (break_point_objects()->IsUndefined(GetIsolate())) return 0; - // Single break point. - if (!break_point_objects()->IsFixedArray()) return 1; - // Multiple break points. - return FixedArray::cast(break_point_objects())->length(); -} - - // static MaybeHandle JSDate::New(Handle constructor, Handle new_target, double tv) { diff --git a/src/objects.h b/src/objects.h index c75891b633..68247821ca 100644 --- a/src/objects.h +++ b/src/objects.h @@ -5181,7 +5181,7 @@ class SharedFunctionInfo: public HeapObject { // The function is subject to debugging if a debug info is attached. inline bool HasDebugInfo() const; - inline DebugInfo* GetDebugInfo() const; + DebugInfo* GetDebugInfo() const; // A function has debug code if the compiled code has debug break slots. inline bool HasDebugCode() const; @@ -5192,8 +5192,8 @@ class SharedFunctionInfo: public HeapObject { // Bit field containing various information collected for debugging. // This field is either stored on the kDebugInfo slot or inside the // debug info struct. - inline int debugger_hints() const; - inline void set_debugger_hints(int value); + int debugger_hints() const; + void set_debugger_hints(int value); // Indicates that the function was created by the Function function. // Though it's anonymous, toString should treat it as if it had the name @@ -9204,102 +9204,6 @@ class ObjectTemplateInfo: public TemplateInfo { : public BitField {}; }; - -// The DebugInfo class holds additional information for a function being -// debugged. -class DebugInfo: public Struct { - public: - // The shared function info for the source being debugged. - DECL_ACCESSORS(shared, SharedFunctionInfo) - - // Bit field containing various information collected for debugging. - DECL_INT_ACCESSORS(debugger_hints) - - DECL_ACCESSORS(debug_bytecode_array, Object) - // Fixed array holding status information for each active break point. - DECL_ACCESSORS(break_points, FixedArray) - - // Check if there is a break point at a source position. - bool HasBreakPoint(int source_position); - // Attempt to clear a break point. Return true if successful. - static bool ClearBreakPoint(Handle debug_info, - Handle break_point_object); - // Set a break point. - static void SetBreakPoint(Handle debug_info, int source_position, - Handle break_point_object); - // Get the break point objects for a source position. - Handle GetBreakPointObjects(int source_position); - // Find the break point info holding this break point object. - static Handle FindBreakPointInfo(Handle debug_info, - Handle break_point_object); - // Get the number of break points for this function. - int GetBreakPointCount(); - - inline bool HasDebugBytecodeArray(); - inline bool HasDebugCode(); - - inline BytecodeArray* OriginalBytecodeArray(); - inline BytecodeArray* DebugBytecodeArray(); - inline Code* DebugCode(); - - DECLARE_CAST(DebugInfo) - - // Dispatched behavior. - DECLARE_PRINTER(DebugInfo) - DECLARE_VERIFIER(DebugInfo) - - static const int kSharedFunctionInfoIndex = Struct::kHeaderSize; - static const int kDebuggerHintsIndex = - kSharedFunctionInfoIndex + kPointerSize; - static const int kDebugBytecodeArrayIndex = - kDebuggerHintsIndex + kPointerSize; - static const int kBreakPointsStateIndex = - kDebugBytecodeArrayIndex + kPointerSize; - static const int kSize = kBreakPointsStateIndex + kPointerSize; - - static const int kEstimatedNofBreakPointsInFunction = 4; - - private: - // Get the break point info object for a source position. - Object* GetBreakPointInfo(int source_position); - - DISALLOW_IMPLICIT_CONSTRUCTORS(DebugInfo); -}; - - -// The BreakPointInfo class holds information for break points set in a -// function. The DebugInfo object holds a BreakPointInfo object for each code -// position with one or more break points. -class BreakPointInfo : public Tuple2 { - public: - // The position in the source for the break position. - DECL_INT_ACCESSORS(source_position) - // List of related JavaScript break points. - DECL_ACCESSORS(break_point_objects, Object) - - // Removes a break point. - static void ClearBreakPoint(Handle info, - Handle break_point_object); - // Set a break point. - static void SetBreakPoint(Handle info, - Handle break_point_object); - // Check if break point info has this break point object. - static bool HasBreakPointObject(Handle info, - Handle break_point_object); - // Get the number of break points for this code offset. - int GetBreakPointCount(); - - int GetStatementPosition(Handle debug_info); - - DECLARE_CAST(BreakPointInfo) - - static const int kSourcePositionIndex = kValue1Offset; - static const int kBreakPointObjectsIndex = kValue2Offset; - - private: - DISALLOW_IMPLICIT_CONSTRUCTORS(BreakPointInfo); -}; - class StackFrameInfo : public Struct { public: DECL_INT_ACCESSORS(line_number) diff --git a/src/objects/debug-objects-inl.h b/src/objects/debug-objects-inl.h new file mode 100644 index 0000000000..b71c4c0f56 --- /dev/null +++ b/src/objects/debug-objects-inl.h @@ -0,0 +1,60 @@ +// Copyright 2017 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef V8_OBJECTS_DEBUG_OBJECTS_INL_H_ +#define V8_OBJECTS_DEBUG_OBJECTS_INL_H_ + +#include "src/objects/debug-objects.h" + +#include "src/heap/heap-inl.h" + +// Has to be the last include (doesn't have include guards): +#include "src/objects/object-macros.h" + +namespace v8 { +namespace internal { + +CAST_ACCESSOR(BreakPointInfo) +CAST_ACCESSOR(DebugInfo) + +ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex) +SMI_ACCESSORS(DebugInfo, debugger_hints, kDebuggerHintsIndex) +ACCESSORS(DebugInfo, debug_bytecode_array, Object, kDebugBytecodeArrayIndex) +ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex) + +SMI_ACCESSORS(BreakPointInfo, source_position, kSourcePositionIndex) +ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex) + +bool DebugInfo::HasDebugBytecodeArray() { + return debug_bytecode_array()->IsBytecodeArray(); +} + +bool DebugInfo::HasDebugCode() { + Code* code = shared()->code(); + bool has = code->kind() == Code::FUNCTION; + DCHECK(!has || code->has_debug_break_slots()); + return has; +} + +BytecodeArray* DebugInfo::OriginalBytecodeArray() { + DCHECK(HasDebugBytecodeArray()); + return shared()->bytecode_array(); +} + +BytecodeArray* DebugInfo::DebugBytecodeArray() { + DCHECK(HasDebugBytecodeArray()); + return BytecodeArray::cast(debug_bytecode_array()); +} + +Code* DebugInfo::DebugCode() { + DCHECK(HasDebugCode()); + return shared()->code(); +} + +} // namespace internal +} // namespace v8 + +#include "src/objects/object-macros-undef.h" + +#endif // V8_OBJECTS_DEBUG_OBJECTS_INL_H_ diff --git a/src/objects/debug-objects.cc b/src/objects/debug-objects.cc new file mode 100644 index 0000000000..1100df3980 --- /dev/null +++ b/src/objects/debug-objects.cc @@ -0,0 +1,246 @@ +// Copyright 2017 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "src/objects/debug-objects.h" +#include "src/objects/debug-objects-inl.h" + +namespace v8 { +namespace internal { + +// Check if there is a break point at this source position. +bool DebugInfo::HasBreakPoint(int source_position) { + // Get the break point info object for this code offset. + Object* break_point_info = GetBreakPointInfo(source_position); + + // If there is no break point info object or no break points in the break + // point info object there is no break point at this code offset. + if (break_point_info->IsUndefined(GetIsolate())) return false; + return BreakPointInfo::cast(break_point_info)->GetBreakPointCount() > 0; +} + +// Get the break point info object for this source position. +Object* DebugInfo::GetBreakPointInfo(int source_position) { + Isolate* isolate = GetIsolate(); + if (!break_points()->IsUndefined(isolate)) { + for (int i = 0; i < break_points()->length(); i++) { + if (!break_points()->get(i)->IsUndefined(isolate)) { + BreakPointInfo* break_point_info = + BreakPointInfo::cast(break_points()->get(i)); + if (break_point_info->source_position() == source_position) { + return break_point_info; + } + } + } + } + return isolate->heap()->undefined_value(); +} + +bool DebugInfo::ClearBreakPoint(Handle debug_info, + Handle break_point_object) { + Isolate* isolate = debug_info->GetIsolate(); + if (debug_info->break_points()->IsUndefined(isolate)) return false; + + for (int i = 0; i < debug_info->break_points()->length(); i++) { + if (debug_info->break_points()->get(i)->IsUndefined(isolate)) continue; + Handle break_point_info = Handle( + BreakPointInfo::cast(debug_info->break_points()->get(i)), isolate); + if (BreakPointInfo::HasBreakPointObject(break_point_info, + break_point_object)) { + BreakPointInfo::ClearBreakPoint(break_point_info, break_point_object); + return true; + } + } + return false; +} + +void DebugInfo::SetBreakPoint(Handle debug_info, int source_position, + Handle break_point_object) { + Isolate* isolate = debug_info->GetIsolate(); + Handle break_point_info( + debug_info->GetBreakPointInfo(source_position), isolate); + if (!break_point_info->IsUndefined(isolate)) { + BreakPointInfo::SetBreakPoint( + Handle::cast(break_point_info), break_point_object); + return; + } + + // Adding a new break point for a code offset which did not have any + // break points before. Try to find a free slot. + static const int kNoBreakPointInfo = -1; + int index = kNoBreakPointInfo; + for (int i = 0; i < debug_info->break_points()->length(); i++) { + if (debug_info->break_points()->get(i)->IsUndefined(isolate)) { + index = i; + break; + } + } + if (index == kNoBreakPointInfo) { + // No free slot - extend break point info array. + Handle old_break_points = Handle( + FixedArray::cast(debug_info->break_points()), isolate); + Handle new_break_points = isolate->factory()->NewFixedArray( + old_break_points->length() + + DebugInfo::kEstimatedNofBreakPointsInFunction); + + debug_info->set_break_points(*new_break_points); + for (int i = 0; i < old_break_points->length(); i++) { + new_break_points->set(i, old_break_points->get(i)); + } + index = old_break_points->length(); + } + DCHECK(index != kNoBreakPointInfo); + + // Allocate new BreakPointInfo object and set the break point. + Handle new_break_point_info = + isolate->factory()->NewBreakPointInfo(source_position); + BreakPointInfo::SetBreakPoint(new_break_point_info, break_point_object); + debug_info->break_points()->set(index, *new_break_point_info); +} + +// Get the break point objects for a source position. +Handle DebugInfo::GetBreakPointObjects(int source_position) { + Object* break_point_info = GetBreakPointInfo(source_position); + Isolate* isolate = GetIsolate(); + if (break_point_info->IsUndefined(isolate)) { + return isolate->factory()->undefined_value(); + } + return Handle( + BreakPointInfo::cast(break_point_info)->break_point_objects(), isolate); +} + +// Get the total number of break points. +int DebugInfo::GetBreakPointCount() { + Isolate* isolate = GetIsolate(); + if (break_points()->IsUndefined(isolate)) return 0; + int count = 0; + for (int i = 0; i < break_points()->length(); i++) { + if (!break_points()->get(i)->IsUndefined(isolate)) { + BreakPointInfo* break_point_info = + BreakPointInfo::cast(break_points()->get(i)); + count += break_point_info->GetBreakPointCount(); + } + } + return count; +} + +Handle DebugInfo::FindBreakPointInfo( + Handle debug_info, Handle break_point_object) { + Isolate* isolate = debug_info->GetIsolate(); + if (!debug_info->break_points()->IsUndefined(isolate)) { + for (int i = 0; i < debug_info->break_points()->length(); i++) { + if (!debug_info->break_points()->get(i)->IsUndefined(isolate)) { + Handle break_point_info = Handle( + BreakPointInfo::cast(debug_info->break_points()->get(i)), isolate); + if (BreakPointInfo::HasBreakPointObject(break_point_info, + break_point_object)) { + return break_point_info; + } + } + } + } + return isolate->factory()->undefined_value(); +} + +// Remove the specified break point object. +void BreakPointInfo::ClearBreakPoint(Handle break_point_info, + Handle break_point_object) { + Isolate* isolate = break_point_info->GetIsolate(); + // If there are no break points just ignore. + if (break_point_info->break_point_objects()->IsUndefined(isolate)) return; + // If there is a single break point clear it if it is the same. + if (!break_point_info->break_point_objects()->IsFixedArray()) { + if (break_point_info->break_point_objects() == *break_point_object) { + break_point_info->set_break_point_objects( + isolate->heap()->undefined_value()); + } + return; + } + // If there are multiple break points shrink the array + DCHECK(break_point_info->break_point_objects()->IsFixedArray()); + Handle old_array = Handle( + FixedArray::cast(break_point_info->break_point_objects())); + Handle new_array = + isolate->factory()->NewFixedArray(old_array->length() - 1); + int found_count = 0; + for (int i = 0; i < old_array->length(); i++) { + if (old_array->get(i) == *break_point_object) { + DCHECK(found_count == 0); + found_count++; + } else { + new_array->set(i - found_count, old_array->get(i)); + } + } + // If the break point was found in the list change it. + if (found_count > 0) break_point_info->set_break_point_objects(*new_array); +} + +// Add the specified break point object. +void BreakPointInfo::SetBreakPoint(Handle break_point_info, + Handle break_point_object) { + Isolate* isolate = break_point_info->GetIsolate(); + + // If there was no break point objects before just set it. + if (break_point_info->break_point_objects()->IsUndefined(isolate)) { + break_point_info->set_break_point_objects(*break_point_object); + return; + } + // If the break point object is the same as before just ignore. + if (break_point_info->break_point_objects() == *break_point_object) return; + // If there was one break point object before replace with array. + if (!break_point_info->break_point_objects()->IsFixedArray()) { + Handle array = isolate->factory()->NewFixedArray(2); + array->set(0, break_point_info->break_point_objects()); + array->set(1, *break_point_object); + break_point_info->set_break_point_objects(*array); + return; + } + // If there was more than one break point before extend array. + Handle old_array = Handle( + FixedArray::cast(break_point_info->break_point_objects())); + Handle new_array = + isolate->factory()->NewFixedArray(old_array->length() + 1); + for (int i = 0; i < old_array->length(); i++) { + // If the break point was there before just ignore. + if (old_array->get(i) == *break_point_object) return; + new_array->set(i, old_array->get(i)); + } + // Add the new break point. + new_array->set(old_array->length(), *break_point_object); + break_point_info->set_break_point_objects(*new_array); +} + +bool BreakPointInfo::HasBreakPointObject( + Handle break_point_info, + Handle break_point_object) { + // No break point. + Isolate* isolate = break_point_info->GetIsolate(); + if (break_point_info->break_point_objects()->IsUndefined(isolate)) { + return false; + } + // Single break point. + if (!break_point_info->break_point_objects()->IsFixedArray()) { + return break_point_info->break_point_objects() == *break_point_object; + } + // Multiple break points. + FixedArray* array = FixedArray::cast(break_point_info->break_point_objects()); + for (int i = 0; i < array->length(); i++) { + if (array->get(i) == *break_point_object) { + return true; + } + } + return false; +} + +// Get the number of break points. +int BreakPointInfo::GetBreakPointCount() { + // No break point. + if (break_point_objects()->IsUndefined(GetIsolate())) return 0; + // Single break point. + if (!break_point_objects()->IsFixedArray()) return 1; + // Multiple break points. + return FixedArray::cast(break_point_objects())->length(); +} + +} // namespace internal +} // namespace v8 diff --git a/src/objects/debug-objects.h b/src/objects/debug-objects.h new file mode 100644 index 0000000000..dfb529c87d --- /dev/null +++ b/src/objects/debug-objects.h @@ -0,0 +1,115 @@ +// Copyright 2017 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef V8_OBJECTS_DEBUG_OBJECTS_H_ +#define V8_OBJECTS_DEBUG_OBJECTS_H_ + +#include "src/objects.h" + +// Has to be the last include (doesn't have include guards): +#include "src/objects/object-macros.h" + +namespace v8 { +namespace internal { + +// The DebugInfo class holds additional information for a function being +// debugged. +class DebugInfo : public Struct { + public: + // The shared function info for the source being debugged. + DECL_ACCESSORS(shared, SharedFunctionInfo) + + // Bit field containing various information collected for debugging. + DECL_INT_ACCESSORS(debugger_hints) + + DECL_ACCESSORS(debug_bytecode_array, Object) + // Fixed array holding status information for each active break point. + DECL_ACCESSORS(break_points, FixedArray) + + // Check if there is a break point at a source position. + bool HasBreakPoint(int source_position); + // Attempt to clear a break point. Return true if successful. + static bool ClearBreakPoint(Handle debug_info, + Handle break_point_object); + // Set a break point. + static void SetBreakPoint(Handle debug_info, int source_position, + Handle break_point_object); + // Get the break point objects for a source position. + Handle GetBreakPointObjects(int source_position); + // Find the break point info holding this break point object. + static Handle FindBreakPointInfo(Handle debug_info, + Handle break_point_object); + // Get the number of break points for this function. + int GetBreakPointCount(); + + inline bool HasDebugBytecodeArray(); + inline bool HasDebugCode(); + + inline BytecodeArray* OriginalBytecodeArray(); + inline BytecodeArray* DebugBytecodeArray(); + inline Code* DebugCode(); + + DECLARE_CAST(DebugInfo) + + // Dispatched behavior. + DECLARE_PRINTER(DebugInfo) + DECLARE_VERIFIER(DebugInfo) + + static const int kSharedFunctionInfoIndex = Struct::kHeaderSize; + static const int kDebuggerHintsIndex = + kSharedFunctionInfoIndex + kPointerSize; + static const int kDebugBytecodeArrayIndex = + kDebuggerHintsIndex + kPointerSize; + static const int kBreakPointsStateIndex = + kDebugBytecodeArrayIndex + kPointerSize; + static const int kSize = kBreakPointsStateIndex + kPointerSize; + + static const int kEstimatedNofBreakPointsInFunction = 4; + + private: + // Get the break point info object for a source position. + Object* GetBreakPointInfo(int source_position); + + DISALLOW_IMPLICIT_CONSTRUCTORS(DebugInfo); +}; + +// The BreakPointInfo class holds information for break points set in a +// function. The DebugInfo object holds a BreakPointInfo object for each code +// position with one or more break points. +class BreakPointInfo : public Tuple2 { + public: + // The position in the source for the break position. + DECL_INT_ACCESSORS(source_position) + // List of related JavaScript break points. + DECL_ACCESSORS(break_point_objects, Object) + + // Removes a break point. + static void ClearBreakPoint(Handle info, + Handle break_point_object); + // Set a break point. + static void SetBreakPoint(Handle info, + Handle break_point_object); + // Check if break point info has this break point object. + static bool HasBreakPointObject(Handle info, + Handle break_point_object); + // Get the number of break points for this code offset. + int GetBreakPointCount(); + + int GetStatementPosition(Handle debug_info); + + DECLARE_CAST(BreakPointInfo) + + static const int kSourcePositionIndex = kValue1Offset; + static const int kBreakPointObjectsIndex = kValue2Offset; + + private: + DISALLOW_IMPLICIT_CONSTRUCTORS(BreakPointInfo); +}; + +} // namespace internal +} // namespace v8 + +#include "src/objects/object-macros-undef.h" + +#endif // V8_OBJECTS_DEBUG_OBJECTS_H_ diff --git a/src/objects/object-macros-undef.h b/src/objects/object-macros-undef.h index 571e84a3e9..cbcbfac458 100644 --- a/src/objects/object-macros-undef.h +++ b/src/objects/object-macros-undef.h @@ -2,9 +2,58 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#undef CAST_ACCESSOR #undef DECL_BOOLEAN_ACCESSORS #undef DECL_INT_ACCESSORS #undef DECL_ACCESSORS #undef DECLARE_CAST +#undef CAST_ACCESSOR +#undef INT_ACCESSORS +#undef ACCESSORS_CHECKED2 +#undef ACCESSORS_CHECKED +#undef ACCESSORS +#undef SMI_ACCESSORS_CHECKED +#undef SMI_ACCESSORS +#undef SYNCHRONIZED_SMI_ACCESSORS +#undef NOBARRIER_SMI_ACCESSORS +#undef BOOL_GETTER +#undef BOOL_ACCESSORS +#undef TYPE_CHECKER +#undef FIELD_ADDR +#undef FIELD_ADDR_CONST +#undef READ_FIELD +#undef ACQUIRE_READ_FIELD +#undef NOBARRIER_READ_FIELD +#undef WRITE_FIELD +#undef RELEASE_WRITE_FIELD +#undef NOBARRIER_WRITE_FIELD +#undef WRITE_BARRIER +#undef CONDITIONAL_WRITE_BARRIER +#undef READ_DOUBLE_FIELD +#undef WRITE_DOUBLE_FIELD +#undef READ_INT_FIELD +#undef WRITE_INT_FIELD +#undef READ_INTPTR_FIELD +#undef WRITE_INTPTR_FIELD +#undef READ_UINT8_FIELD +#undef WRITE_UINT8_FIELD +#undef READ_INT8_FIELD +#undef WRITE_INT8_FIELD +#undef READ_UINT16_FIELD +#undef WRITE_UINT16_FIELD +#undef READ_INT16_FIELD +#undef WRITE_INT16_FIELD +#undef READ_UINT32_FIELD +#undef WRITE_UINT32_FIELD +#undef READ_INT32_FIELD +#undef WRITE_INT32_FIELD +#undef READ_FLOAT_FIELD +#undef WRITE_FLOAT_FIELD +#undef READ_UINT64_FIELD +#undef WRITE_UINT64_FIELD +#undef READ_INT64_FIELD +#undef WRITE_INT64_FIELD +#undef READ_BYTE_FIELD +#undef NOBARRIER_READ_BYTE_FIELD +#undef WRITE_BYTE_FIELD +#undef NOBARRIER_WRITE_BYTE_FIELD #undef DECLARE_VERIFIER diff --git a/src/objects/object-macros.h b/src/objects/object-macros.h index c03026d51b..127223b86d 100644 --- a/src/objects/object-macros.h +++ b/src/objects/object-macros.h @@ -35,6 +35,212 @@ return reinterpret_cast(object); \ } +#define INT_ACCESSORS(holder, name, offset) \ + int holder::name() const { return READ_INT_FIELD(this, offset); } \ + void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); } + +#define ACCESSORS_CHECKED2(holder, name, type, offset, get_condition, \ + set_condition) \ + type* holder::name() const { \ + DCHECK(get_condition); \ + return type::cast(READ_FIELD(this, offset)); \ + } \ + void holder::set_##name(type* value, WriteBarrierMode mode) { \ + DCHECK(set_condition); \ + WRITE_FIELD(this, offset, value); \ + CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode); \ + } +#define ACCESSORS_CHECKED(holder, name, type, offset, condition) \ + ACCESSORS_CHECKED2(holder, name, type, offset, condition, condition) + +#define ACCESSORS(holder, name, type, offset) \ + ACCESSORS_CHECKED(holder, name, type, offset, true) + +// Getter that returns a Smi as an int and writes an int as a Smi. +#define SMI_ACCESSORS_CHECKED(holder, name, offset, condition) \ + int holder::name() const { \ + DCHECK(condition); \ + Object* value = READ_FIELD(this, offset); \ + return Smi::cast(value)->value(); \ + } \ + void holder::set_##name(int value) { \ + DCHECK(condition); \ + WRITE_FIELD(this, offset, Smi::FromInt(value)); \ + } + +#define SMI_ACCESSORS(holder, name, offset) \ + SMI_ACCESSORS_CHECKED(holder, name, offset, true) + +#define SYNCHRONIZED_SMI_ACCESSORS(holder, name, offset) \ + int holder::synchronized_##name() const { \ + Object* value = ACQUIRE_READ_FIELD(this, offset); \ + return Smi::cast(value)->value(); \ + } \ + void holder::synchronized_set_##name(int value) { \ + RELEASE_WRITE_FIELD(this, offset, Smi::FromInt(value)); \ + } + +#define NOBARRIER_SMI_ACCESSORS(holder, name, offset) \ + int holder::nobarrier_##name() const { \ + Object* value = NOBARRIER_READ_FIELD(this, offset); \ + return Smi::cast(value)->value(); \ + } \ + void holder::nobarrier_set_##name(int value) { \ + NOBARRIER_WRITE_FIELD(this, offset, Smi::FromInt(value)); \ + } + +#define BOOL_GETTER(holder, field, name, offset) \ + bool holder::name() const { return BooleanBit::get(field(), offset); } + +#define BOOL_ACCESSORS(holder, field, name, offset) \ + bool holder::name() const { return BooleanBit::get(field(), offset); } \ + void holder::set_##name(bool value) { \ + set_##field(BooleanBit::set(field(), offset, value)); \ + } + +#define TYPE_CHECKER(type, instancetype) \ + bool HeapObject::Is##type() const { \ + return map()->instance_type() == instancetype; \ + } + +#define FIELD_ADDR(p, offset) \ + (reinterpret_cast(p) + offset - kHeapObjectTag) + +#define FIELD_ADDR_CONST(p, offset) \ + (reinterpret_cast(p) + offset - kHeapObjectTag) + +#define READ_FIELD(p, offset) \ + (*reinterpret_cast(FIELD_ADDR_CONST(p, offset))) + +#define ACQUIRE_READ_FIELD(p, offset) \ + reinterpret_cast(base::Acquire_Load( \ + reinterpret_cast(FIELD_ADDR_CONST(p, offset)))) + +#define NOBARRIER_READ_FIELD(p, offset) \ + reinterpret_cast(base::NoBarrier_Load( \ + reinterpret_cast(FIELD_ADDR_CONST(p, offset)))) + +#ifdef V8_CONCURRENT_MARKING +#define WRITE_FIELD(p, offset, value) \ + base::NoBarrier_Store( \ + reinterpret_cast(FIELD_ADDR(p, offset)), \ + reinterpret_cast(value)); +#else +#define WRITE_FIELD(p, offset, value) \ + (*reinterpret_cast(FIELD_ADDR(p, offset)) = value) +#endif + +#define RELEASE_WRITE_FIELD(p, offset, value) \ + base::Release_Store( \ + reinterpret_cast(FIELD_ADDR(p, offset)), \ + reinterpret_cast(value)); + +#define NOBARRIER_WRITE_FIELD(p, offset, value) \ + base::NoBarrier_Store( \ + reinterpret_cast(FIELD_ADDR(p, offset)), \ + reinterpret_cast(value)); + +#define WRITE_BARRIER(heap, object, offset, value) \ + heap->incremental_marking()->RecordWrite( \ + object, HeapObject::RawField(object, offset), value); \ + heap->RecordWrite(object, offset, value); + +#define CONDITIONAL_WRITE_BARRIER(heap, object, offset, value, mode) \ + if (mode != SKIP_WRITE_BARRIER) { \ + if (mode == UPDATE_WRITE_BARRIER) { \ + heap->incremental_marking()->RecordWrite( \ + object, HeapObject::RawField(object, offset), value); \ + } \ + heap->RecordWrite(object, offset, value); \ + } + +#define READ_DOUBLE_FIELD(p, offset) \ + ReadDoubleValue(FIELD_ADDR_CONST(p, offset)) + +#define WRITE_DOUBLE_FIELD(p, offset, value) \ + WriteDoubleValue(FIELD_ADDR(p, offset), value) + +#define READ_INT_FIELD(p, offset) \ + (*reinterpret_cast(FIELD_ADDR_CONST(p, offset))) + +#define WRITE_INT_FIELD(p, offset, value) \ + (*reinterpret_cast(FIELD_ADDR(p, offset)) = value) + +#define READ_INTPTR_FIELD(p, offset) \ + (*reinterpret_cast(FIELD_ADDR_CONST(p, offset))) + +#define WRITE_INTPTR_FIELD(p, offset, value) \ + (*reinterpret_cast(FIELD_ADDR(p, offset)) = value) + +#define READ_UINT8_FIELD(p, offset) \ + (*reinterpret_cast(FIELD_ADDR_CONST(p, offset))) + +#define WRITE_UINT8_FIELD(p, offset, value) \ + (*reinterpret_cast(FIELD_ADDR(p, offset)) = value) + +#define READ_INT8_FIELD(p, offset) \ + (*reinterpret_cast(FIELD_ADDR_CONST(p, offset))) + +#define WRITE_INT8_FIELD(p, offset, value) \ + (*reinterpret_cast(FIELD_ADDR(p, offset)) = value) + +#define READ_UINT16_FIELD(p, offset) \ + (*reinterpret_cast(FIELD_ADDR_CONST(p, offset))) + +#define WRITE_UINT16_FIELD(p, offset, value) \ + (*reinterpret_cast(FIELD_ADDR(p, offset)) = value) + +#define READ_INT16_FIELD(p, offset) \ + (*reinterpret_cast(FIELD_ADDR_CONST(p, offset))) + +#define WRITE_INT16_FIELD(p, offset, value) \ + (*reinterpret_cast(FIELD_ADDR(p, offset)) = value) + +#define READ_UINT32_FIELD(p, offset) \ + (*reinterpret_cast(FIELD_ADDR_CONST(p, offset))) + +#define WRITE_UINT32_FIELD(p, offset, value) \ + (*reinterpret_cast(FIELD_ADDR(p, offset)) = value) + +#define READ_INT32_FIELD(p, offset) \ + (*reinterpret_cast(FIELD_ADDR_CONST(p, offset))) + +#define WRITE_INT32_FIELD(p, offset, value) \ + (*reinterpret_cast(FIELD_ADDR(p, offset)) = value) + +#define READ_FLOAT_FIELD(p, offset) \ + (*reinterpret_cast(FIELD_ADDR_CONST(p, offset))) + +#define WRITE_FLOAT_FIELD(p, offset, value) \ + (*reinterpret_cast(FIELD_ADDR(p, offset)) = value) + +#define READ_UINT64_FIELD(p, offset) \ + (*reinterpret_cast(FIELD_ADDR_CONST(p, offset))) + +#define WRITE_UINT64_FIELD(p, offset, value) \ + (*reinterpret_cast(FIELD_ADDR(p, offset)) = value) + +#define READ_INT64_FIELD(p, offset) \ + (*reinterpret_cast(FIELD_ADDR_CONST(p, offset))) + +#define WRITE_INT64_FIELD(p, offset, value) \ + (*reinterpret_cast(FIELD_ADDR(p, offset)) = value) + +#define READ_BYTE_FIELD(p, offset) \ + (*reinterpret_cast(FIELD_ADDR_CONST(p, offset))) + +#define NOBARRIER_READ_BYTE_FIELD(p, offset) \ + static_cast(base::NoBarrier_Load( \ + reinterpret_cast(FIELD_ADDR(p, offset)))) + +#define WRITE_BYTE_FIELD(p, offset, value) \ + (*reinterpret_cast(FIELD_ADDR(p, offset)) = value) + +#define NOBARRIER_WRITE_BYTE_FIELD(p, offset, value) \ + base::NoBarrier_Store( \ + reinterpret_cast(FIELD_ADDR(p, offset)), \ + static_cast(value)); + #ifdef VERIFY_HEAP #define DECLARE_VERIFIER(Name) void Name##Verify(); #else diff --git a/src/v8.gyp b/src/v8.gyp index 6d88d19b6d..85d6b998c8 100644 --- a/src/v8.gyp +++ b/src/v8.gyp @@ -1224,6 +1224,9 @@ 'objects/code-cache-inl.h', 'objects/compilation-cache.h', 'objects/compilation-cache-inl.h', + 'objects/debug-objects-inl.h', + 'objects/debug-objects.cc', + 'objects/debug-objects.h', 'objects/descriptor-array.h', 'objects/dictionary.h', 'objects/frame-array.h', diff --git a/src/wasm/wasm-objects.cc b/src/wasm/wasm-objects.cc index ea09bf01fc..901e302f7e 100644 --- a/src/wasm/wasm-objects.cc +++ b/src/wasm/wasm-objects.cc @@ -10,6 +10,7 @@ #include "src/compiler/wasm-compiler.h" #include "src/debug/debug-interface.h" #include "src/objects-inl.h" +#include "src/objects/debug-objects-inl.h" #include "src/wasm/module-decoder.h" #include "src/wasm/wasm-code-specialization.h" #include "src/wasm/wasm-module.h"