diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-10-24 11:30:15 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-10-30 12:56:19 +0000 |
commit | 6036726eb981b6c4b42047513b9d3f4ac865daac (patch) | |
tree | 673593e70678e7789766d1f732eb51f613a2703b /chromium/v8/src/debug | |
parent | 466052c4e7c052268fd931888cd58961da94c586 (diff) | |
download | qtwebengine-chromium-6036726eb981b6c4b42047513b9d3f4ac865daac.tar.gz |
BASELINE: Update Chromium to 70.0.3538.78
Change-Id: Ie634710bf039e26c1957f4ae45e101bd4c434ae7
Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/v8/src/debug')
-rw-r--r-- | chromium/v8/src/debug/arm/OWNERS | 1 | ||||
-rw-r--r-- | chromium/v8/src/debug/arm64/OWNERS | 1 | ||||
-rw-r--r-- | chromium/v8/src/debug/debug-coverage.cc | 49 | ||||
-rw-r--r-- | chromium/v8/src/debug/debug-evaluate.cc | 227 | ||||
-rw-r--r-- | chromium/v8/src/debug/debug-scope-iterator.cc | 3 | ||||
-rw-r--r-- | chromium/v8/src/debug/debug-scopes.cc | 1 | ||||
-rw-r--r-- | chromium/v8/src/debug/debug-stack-trace-iterator.cc | 5 | ||||
-rw-r--r-- | chromium/v8/src/debug/debug.cc | 77 | ||||
-rw-r--r-- | chromium/v8/src/debug/debug.h | 29 | ||||
-rw-r--r-- | chromium/v8/src/debug/liveedit.cc | 197 | ||||
-rw-r--r-- | chromium/v8/src/debug/mips/OWNERS | 5 | ||||
-rw-r--r-- | chromium/v8/src/debug/mips64/OWNERS | 5 |
12 files changed, 335 insertions, 265 deletions
diff --git a/chromium/v8/src/debug/arm/OWNERS b/chromium/v8/src/debug/arm/OWNERS deleted file mode 100644 index 906a5ce6418..00000000000 --- a/chromium/v8/src/debug/arm/OWNERS +++ /dev/null @@ -1 +0,0 @@ -rmcilroy@chromium.org diff --git a/chromium/v8/src/debug/arm64/OWNERS b/chromium/v8/src/debug/arm64/OWNERS deleted file mode 100644 index 906a5ce6418..00000000000 --- a/chromium/v8/src/debug/arm64/OWNERS +++ /dev/null @@ -1 +0,0 @@ -rmcilroy@chromium.org diff --git a/chromium/v8/src/debug/debug-coverage.cc b/chromium/v8/src/debug/debug-coverage.cc index 9e7195b1f3e..f8b716f7c91 100644 --- a/chromium/v8/src/debug/debug-coverage.cc +++ b/chromium/v8/src/debug/debug-coverage.cc @@ -72,8 +72,7 @@ void SortBlockData(std::vector<CoverageBlock>& v) { std::sort(v.begin(), v.end(), CompareCoverageBlock); } -std::vector<CoverageBlock> GetSortedBlockData(Isolate* isolate, - SharedFunctionInfo* shared) { +std::vector<CoverageBlock> GetSortedBlockData(SharedFunctionInfo* shared) { DCHECK(shared->HasCoverageInfo()); CoverageInfo* coverage_info = @@ -172,6 +171,12 @@ class CoverageBlockIterator final { return function_->blocks[read_index_ + 1]; } + CoverageBlock& GetPreviousBlock() { + DCHECK(IsActive()); + DCHECK_GT(read_index_, 0); + return function_->blocks[read_index_ - 1]; + } + CoverageBlock& GetParent() { DCHECK(IsActive()); return nesting_stack_.back(); @@ -326,6 +331,30 @@ void MergeNestedRanges(CoverageFunction* function) { } } +void FilterAliasedSingletons(CoverageFunction* function) { + CoverageBlockIterator iter(function); + + iter.Next(); // Advance once since we reference the previous block later. + + while (iter.Next()) { + CoverageBlock& previous_block = iter.GetPreviousBlock(); + CoverageBlock& block = iter.GetBlock(); + + bool is_singleton = block.end == kNoSourcePosition; + bool aliases_start = block.start == previous_block.start; + + if (is_singleton && aliases_start) { + // The previous block must have a full range since duplicate singletons + // have already been merged. + DCHECK_NE(previous_block.end, kNoSourcePosition); + // Likewise, the next block must have another start position since + // singletons are sorted to the end. + DCHECK_IMPLIES(iter.HasNext(), iter.GetNextBlock().start != block.start); + iter.DeleteBlock(); + } + } +} + void FilterUncoveredRanges(CoverageFunction* function) { CoverageBlockIterator iter(function); @@ -385,13 +414,12 @@ bool IsBinaryMode(debug::Coverage::Mode mode) { } } -void CollectBlockCoverage(Isolate* isolate, CoverageFunction* function, - SharedFunctionInfo* info, +void CollectBlockCoverage(CoverageFunction* function, SharedFunctionInfo* info, debug::Coverage::Mode mode) { DCHECK(IsBlockMode(mode)); function->has_block_coverage = true; - function->blocks = GetSortedBlockData(isolate, info); + function->blocks = GetSortedBlockData(info); // If in binary mode, only report counts of 0/1. if (mode == debug::Coverage::kBlockBinary) ClampToBinary(function); @@ -399,6 +427,15 @@ void CollectBlockCoverage(Isolate* isolate, CoverageFunction* function, // Remove duplicate singleton ranges, keeping the max count. MergeDuplicateSingletons(function); + // Remove singleton ranges with the same start position as a full range and + // throw away their counts. + // Singleton ranges are only intended to split existing full ranges and should + // never expand into a full range. Consider 'if (cond) { ... } else { ... }' + // as a problematic example; if the then-block produces a continuation + // singleton, it would incorrectly expand into the else range. + // For more context, see https://crbug.com/v8/8237. + FilterAliasedSingletons(function); + // Rewrite all singletons (created e.g. by continuations and unconditional // control flow) to ranges. RewritePositionSingletonsToRanges(function); @@ -544,7 +581,7 @@ std::unique_ptr<Coverage> Coverage::Collect( CoverageFunction function(start, end, count, name); if (IsBlockMode(collectionMode) && info->HasCoverageInfo()) { - CollectBlockCoverage(isolate, &function, info, collectionMode); + CollectBlockCoverage(&function, info, collectionMode); } // Only include a function range if itself or its parent function is diff --git a/chromium/v8/src/debug/debug-evaluate.cc b/chromium/v8/src/debug/debug-evaluate.cc index 0dd23037723..583b41f1b28 100644 --- a/chromium/v8/src/debug/debug-evaluate.cc +++ b/chromium/v8/src/debug/debug-evaluate.cc @@ -32,7 +32,8 @@ MaybeHandle<Object> DebugEvaluate::Global(Isolate* isolate, ScriptOriginOptions origin_options(false, true); MaybeHandle<SharedFunctionInfo> maybe_function_info = Compiler::GetSharedFunctionInfoForScript( - source, Compiler::ScriptDetails(isolate->factory()->empty_string()), + isolate, source, + Compiler::ScriptDetails(isolate->factory()->empty_string()), origin_options, nullptr, nullptr, ScriptCompiler::kNoCompileOptions, ScriptCompiler::kNoCacheNoReason, NOT_NATIVES_CODE); @@ -254,111 +255,112 @@ namespace { bool IntrinsicHasNoSideEffect(Runtime::FunctionId id) { // Use macro to include both inlined and non-inlined version of an intrinsic. -#define INTRINSIC_WHITELIST(V) \ - /* Conversions */ \ - V(NumberToStringSkipCache) \ - V(ToBigInt) \ - V(ToInteger) \ - V(ToLength) \ - V(ToNumber) \ - V(ToObject) \ - V(ToString) \ - /* Type checks */ \ - V(IsArray) \ - V(IsDate) \ - V(IsFunction) \ - V(IsJSProxy) \ - V(IsJSReceiver) \ - V(IsJSWeakMap) \ - V(IsJSWeakSet) \ - V(IsRegExp) \ - V(IsSmi) \ - V(IsTypedArray) \ - /* Loads */ \ - V(LoadLookupSlotForCall) \ - /* Arrays */ \ - V(ArraySpeciesConstructor) \ - V(EstimateNumberOfElements) \ - V(GetArrayKeys) \ - V(HasComplexElements) \ - V(HasFastPackedElements) \ - V(NewArray) \ - V(NormalizeElements) \ - V(PrepareElementsForSort) \ - V(TrySliceSimpleNonFastElements) \ - V(TypedArrayGetBuffer) \ - /* Errors */ \ - V(NewTypeError) \ - V(ReThrow) \ - V(ThrowCalledNonCallable) \ - V(ThrowInvalidStringLength) \ - V(ThrowIteratorResultNotAnObject) \ - V(ThrowReferenceError) \ - V(ThrowSymbolIteratorInvalid) \ - /* Strings */ \ - V(RegExpInternalReplace) \ - V(StringIncludes) \ - V(StringIndexOf) \ - V(StringReplaceOneCharWithString) \ - V(StringSubstring) \ - V(StringToNumber) \ - V(StringTrim) \ - /* BigInts */ \ - V(BigIntEqualToBigInt) \ - V(BigIntToBoolean) \ - V(BigIntToNumber) \ - /* Literals */ \ - V(CreateArrayLiteral) \ - V(CreateObjectLiteral) \ - V(CreateRegExpLiteral) \ - /* Called from builtins */ \ - V(AllocateInNewSpace) \ - V(AllocateInTargetSpace) \ - V(AllocateSeqOneByteString) \ - V(AllocateSeqTwoByteString) \ - V(ArrayIncludes_Slow) \ - V(ArrayIndexOf) \ - V(ArrayIsArray) \ - V(ClassOf) \ - V(GenerateRandomNumbers) \ - V(GetFunctionName) \ - V(GetOwnPropertyDescriptor) \ - V(GlobalPrint) \ - V(HasProperty) \ - V(ObjectCreate) \ - V(ObjectEntries) \ - V(ObjectEntriesSkipFastPath) \ - V(ObjectHasOwnProperty) \ - V(ObjectValues) \ - V(ObjectValuesSkipFastPath) \ - V(ObjectGetOwnPropertyNames) \ - V(ObjectGetOwnPropertyNamesTryFast) \ - V(RegExpInitializeAndCompile) \ - V(StackGuard) \ - V(StringAdd) \ - V(StringCharCodeAt) \ - V(StringEqual) \ - V(StringIndexOfUnchecked) \ - V(StringParseFloat) \ - V(StringParseInt) \ - V(SymbolDescriptiveString) \ - V(ThrowRangeError) \ - V(ThrowTypeError) \ - V(ToName) \ - V(TransitionElementsKind) \ - /* Misc. */ \ - V(Call) \ - V(CompleteInobjectSlackTrackingForMap) \ - V(HasInPrototypeChain) \ - V(MaxSmi) \ - V(NewObject) \ - V(SmiLexicographicCompare) \ - V(StringMaxLength) \ - V(StringToArray) \ - /* Test */ \ - V(GetOptimizationStatus) \ - V(OptimizeFunctionOnNextCall) \ - V(OptimizeOsr) \ +#define INTRINSIC_WHITELIST(V) \ + /* Conversions */ \ + V(NumberToString) \ + V(ToBigInt) \ + V(ToInteger) \ + V(ToLength) \ + V(ToNumber) \ + V(ToObject) \ + V(ToString) \ + /* Type checks */ \ + V(IsArray) \ + V(IsDate) \ + V(IsFunction) \ + V(IsJSProxy) \ + V(IsJSReceiver) \ + V(IsRegExp) \ + V(IsSmi) \ + V(IsTypedArray) \ + /* Loads */ \ + V(LoadLookupSlotForCall) \ + V(GetProperty) \ + /* Arrays */ \ + V(ArraySpeciesConstructor) \ + V(EstimateNumberOfElements) \ + V(GetArrayKeys) \ + V(HasComplexElements) \ + V(HasFastPackedElements) \ + V(NewArray) \ + V(NormalizeElements) \ + V(PrepareElementsForSort) \ + V(TrySliceSimpleNonFastElements) \ + V(TypedArrayGetBuffer) \ + /* Errors */ \ + V(NewTypeError) \ + V(ReThrow) \ + V(ThrowCalledNonCallable) \ + V(ThrowInvalidStringLength) \ + V(ThrowIteratorResultNotAnObject) \ + V(ThrowReferenceError) \ + V(ThrowSymbolIteratorInvalid) \ + /* Strings */ \ + V(RegExpInternalReplace) \ + V(StringIncludes) \ + V(StringIndexOf) \ + V(StringReplaceOneCharWithString) \ + V(StringSubstring) \ + V(StringToNumber) \ + V(StringTrim) \ + /* BigInts */ \ + V(BigIntEqualToBigInt) \ + V(BigIntToBoolean) \ + V(BigIntToNumber) \ + /* Literals */ \ + V(CreateArrayLiteral) \ + V(CreateArrayLiteralWithoutAllocationSite) \ + V(CreateObjectLiteral) \ + V(CreateObjectLiteralWithoutAllocationSite) \ + V(CreateRegExpLiteral) \ + /* Called from builtins */ \ + V(AllocateInNewSpace) \ + V(AllocateInTargetSpace) \ + V(AllocateSeqOneByteString) \ + V(AllocateSeqTwoByteString) \ + V(ArrayIncludes_Slow) \ + V(ArrayIndexOf) \ + V(ArrayIsArray) \ + V(ClassOf) \ + V(GenerateRandomNumbers) \ + V(GetFunctionName) \ + V(GetOwnPropertyDescriptor) \ + V(GlobalPrint) \ + V(HasProperty) \ + V(ObjectCreate) \ + V(ObjectEntries) \ + V(ObjectEntriesSkipFastPath) \ + V(ObjectHasOwnProperty) \ + V(ObjectValues) \ + V(ObjectValuesSkipFastPath) \ + V(ObjectGetOwnPropertyNames) \ + V(ObjectGetOwnPropertyNamesTryFast) \ + V(RegExpInitializeAndCompile) \ + V(StackGuard) \ + V(StringAdd) \ + V(StringCharCodeAt) \ + V(StringEqual) \ + V(StringIndexOfUnchecked) \ + V(StringParseFloat) \ + V(StringParseInt) \ + V(SymbolDescriptiveString) \ + V(ThrowRangeError) \ + V(ThrowTypeError) \ + V(ToName) \ + V(TransitionElementsKind) \ + /* Misc. */ \ + V(Call) \ + V(CompleteInobjectSlackTrackingForMap) \ + V(HasInPrototypeChain) \ + V(MaxSmi) \ + V(NewObject) \ + V(SmiLexicographicCompare) \ + V(StringMaxLength) \ + V(StringToArray) \ + /* Test */ \ + V(GetOptimizationStatus) \ + V(OptimizeFunctionOnNextCall) \ + V(OptimizeOsr) \ V(UnblockConcurrentRecompilation) #define CASE(Name) \ @@ -553,12 +555,14 @@ DebugInfo::SideEffectState BuiltinGetSideEffectState(Builtins::Name id) { case Builtins::kArrayPrototypeValues: case Builtins::kArrayIncludes: case Builtins::kArrayPrototypeEntries: + case Builtins::kArrayPrototypeFill: case Builtins::kArrayPrototypeFind: case Builtins::kArrayPrototypeFindIndex: case Builtins::kArrayPrototypeFlat: case Builtins::kArrayPrototypeFlatMap: case Builtins::kArrayPrototypeKeys: case Builtins::kArrayPrototypeSlice: + case Builtins::kArrayPrototypeSort: case Builtins::kArrayForEach: case Builtins::kArrayEvery: case Builtins::kArraySome: @@ -567,6 +571,9 @@ DebugInfo::SideEffectState BuiltinGetSideEffectState(Builtins::Name id) { case Builtins::kArrayMap: case Builtins::kArrayReduce: case Builtins::kArrayReduceRight: + // Trace builtins. + case Builtins::kIsTraceCategoryEnabled: + case Builtins::kTrace: // TypedArray builtins. case Builtins::kTypedArrayConstructor: case Builtins::kTypedArrayPrototypeBuffer: @@ -810,6 +817,7 @@ DebugInfo::SideEffectState BuiltinGetSideEffectState(Builtins::Name id) { case Builtins::kArrayIteratorPrototypeNext: case Builtins::kArrayPrototypePop: case Builtins::kArrayPrototypePush: + case Builtins::kArrayPrototypeReverse: case Builtins::kArrayPrototypeShift: case Builtins::kArraySplice: case Builtins::kArrayUnshift: @@ -987,12 +995,7 @@ void DebugEvaluate::ApplySideEffectChecks( for (interpreter::BytecodeArrayIterator it(bytecode_array); !it.done(); it.Advance()) { interpreter::Bytecode bytecode = it.current_bytecode(); - if (BytecodeRequiresRuntimeCheck(bytecode)) { - interpreter::Bytecode debugbreak = - interpreter::Bytecodes::GetDebugBreak(bytecode); - bytecode_array->set(it.current_offset(), - interpreter::Bytecodes::ToByte(debugbreak)); - } + if (BytecodeRequiresRuntimeCheck(bytecode)) it.ApplyDebugBreak(); } } diff --git a/chromium/v8/src/debug/debug-scope-iterator.cc b/chromium/v8/src/debug/debug-scope-iterator.cc index dbade081cbb..e71c1c07b3c 100644 --- a/chromium/v8/src/debug/debug-scope-iterator.cc +++ b/chromium/v8/src/debug/debug-scope-iterator.cc @@ -4,11 +4,12 @@ #include "src/debug/debug-scope-iterator.h" -#include "src/api.h" +#include "src/api-inl.h" #include "src/debug/debug.h" #include "src/debug/liveedit.h" #include "src/frames-inl.h" #include "src/isolate.h" +#include "src/objects/js-generator-inl.h" #include "src/wasm/wasm-objects-inl.h" namespace v8 { diff --git a/chromium/v8/src/debug/debug-scopes.cc b/chromium/v8/src/debug/debug-scopes.cc index 8c6fae1d9fc..01cd017eb22 100644 --- a/chromium/v8/src/debug/debug-scopes.cc +++ b/chromium/v8/src/debug/debug-scopes.cc @@ -12,6 +12,7 @@ #include "src/frames-inl.h" #include "src/globals.h" #include "src/isolate-inl.h" +#include "src/objects/js-generator-inl.h" #include "src/objects/module.h" #include "src/parsing/parse-info.h" #include "src/parsing/parsing.h" diff --git a/chromium/v8/src/debug/debug-stack-trace-iterator.cc b/chromium/v8/src/debug/debug-stack-trace-iterator.cc index bf1e1b623b4..14d2850b69c 100644 --- a/chromium/v8/src/debug/debug-stack-trace-iterator.cc +++ b/chromium/v8/src/debug/debug-stack-trace-iterator.cc @@ -4,7 +4,7 @@ #include "src/debug/debug-stack-trace-iterator.h" -#include "src/api.h" +#include "src/api-inl.h" #include "src/debug/debug-evaluate.h" #include "src/debug/debug-scope-iterator.h" #include "src/debug/debug.h" @@ -173,8 +173,7 @@ v8::MaybeLocal<v8::Value> DebugStackTraceIterator::Evaluate( v8::Local<v8::String> source, bool throw_on_side_effect) { DCHECK(!Done()); Handle<Object> value; - i::SafeForInterruptsScope safe_for_interrupt_scope( - isolate_, i::StackGuard::TERMINATE_EXECUTION); + i::SafeForInterruptsScope safe_for_interrupt_scope(isolate_); if (!DebugEvaluate::Local(isolate_, iterator_.frame()->id(), inlined_frame_index_, Utils::OpenHandle(*source), throw_on_side_effect) diff --git a/chromium/v8/src/debug/debug.cc b/chromium/v8/src/debug/debug.cc index 47de9523a50..3a3a48b699a 100644 --- a/chromium/v8/src/debug/debug.cc +++ b/chromium/v8/src/debug/debug.cc @@ -7,7 +7,7 @@ #include <memory> #include <unordered_set> -#include "src/api.h" +#include "src/api-inl.h" #include "src/arguments.h" #include "src/assembler-inl.h" #include "src/base/platform/mutex.h" @@ -30,6 +30,7 @@ #include "src/log.h" #include "src/messages.h" #include "src/objects/debug-objects-inl.h" +#include "src/objects/js-generator-inl.h" #include "src/objects/js-promise-inl.h" #include "src/snapshot/natives.h" #include "src/snapshot/snapshot.h" @@ -278,15 +279,12 @@ void BreakIterator::SkipToPosition(int position) { void BreakIterator::SetDebugBreak() { DebugBreakType debug_break_type = GetDebugBreakType(); if (debug_break_type == DEBUGGER_STATEMENT) return; + HandleScope scope(isolate()); DCHECK(debug_break_type >= DEBUG_BREAK_SLOT); - BytecodeArray* bytecode_array = debug_info_->DebugBytecodeArray(); - interpreter::Bytecode bytecode = - interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset())); - if (interpreter::Bytecodes::IsDebugBreak(bytecode)) return; - interpreter::Bytecode debugbreak = - interpreter::Bytecodes::GetDebugBreak(bytecode); - bytecode_array->set(code_offset(), - interpreter::Bytecodes::ToByte(debugbreak)); + Handle<BytecodeArray> bytecode_array(debug_info_->DebugBytecodeArray(), + isolate()); + interpreter::BytecodeArrayAccessor(bytecode_array, code_offset()) + .ApplyDebugBreak(); } void BreakIterator::ClearDebugBreak() { @@ -322,6 +320,7 @@ BreakLocation BreakIterator::GetBreakLocation() { generator_object_reg_index); } +Isolate* BreakIterator::isolate() { return debug_info_->GetIsolate(); } void DebugFeatureTracker::Track(DebugFeatureTracker::Feature feature) { uint32_t mask = 1 << feature; @@ -334,8 +333,6 @@ void DebugFeatureTracker::Track(DebugFeatureTracker::Feature feature) { // Threading support. void Debug::ThreadInit() { - thread_local_.break_count_ = 0; - thread_local_.break_id_ = 0; thread_local_.break_frame_id_ = StackFrame::NO_ID; thread_local_.last_step_action_ = StepNone; thread_local_.last_statement_position_ = kNoSourcePosition; @@ -355,19 +352,31 @@ void Debug::ThreadInit() { char* Debug::ArchiveDebug(char* storage) { - // Simply reset state. Don't archive anything. - ThreadInit(); + MemCopy(storage, reinterpret_cast<char*>(&thread_local_), + ArchiveSpacePerThread()); return storage + ArchiveSpacePerThread(); } - char* Debug::RestoreDebug(char* storage) { - // Simply reset state. Don't restore anything. - ThreadInit(); + MemCopy(reinterpret_cast<char*>(&thread_local_), storage, + ArchiveSpacePerThread()); + + // Enter the debugger. + DebugScope debug_scope(this); + + // Clear any one-shot breakpoints that may have been set by the other + // thread, and reapply breakpoints for this thread. + ClearOneShot(); + + if (thread_local_.last_step_action_ != StepNone) { + // Reset the previous step action for this thread. + PrepareStep(thread_local_.last_step_action_); + } + return storage + ArchiveSpacePerThread(); } -int Debug::ArchiveSpacePerThread() { return 0; } +int Debug::ArchiveSpacePerThread() { return sizeof(ThreadLocal); } void Debug::Iterate(RootVisitor* v) { v->VisitRootPointer(Root::kDebug, nullptr, &thread_local_.return_value_); @@ -1571,11 +1580,10 @@ void Debug::FreeDebugInfoListNode(DebugInfoListNode* prev, prev->set_next(node->next()); } - // Pack function_identifier back into the - // SFI::function_identifier_or_debug_info field. + // Pack script back into the + // SFI::script_or_debug_info field. Handle<DebugInfo> debug_info(node->debug_info()); - debug_info->shared()->set_function_identifier_or_debug_info( - debug_info->function_identifier()); + debug_info->shared()->set_script_or_debug_info(debug_info->script()); delete node; } @@ -1620,12 +1628,12 @@ Handle<FixedArray> Debug::GetLoadedScripts() { isolate_->heap()->CollectAllGarbage(Heap::kFinalizeIncrementalMarkingMask, GarbageCollectionReason::kDebugger); Factory* factory = isolate_->factory(); - if (!factory->script_list()->IsFixedArrayOfWeakCells()) { + if (!factory->script_list()->IsWeakArrayList()) { return factory->empty_fixed_array(); } - Handle<FixedArrayOfWeakCells> array = - Handle<FixedArrayOfWeakCells>::cast(factory->script_list()); - Handle<FixedArray> results = factory->NewFixedArray(array->Length()); + Handle<WeakArrayList> array = + Handle<WeakArrayList>::cast(factory->script_list()); + Handle<FixedArray> results = factory->NewFixedArray(array->length()); int length = 0; { Script::Iterator iterator(isolate_); @@ -1730,7 +1738,6 @@ void Debug::OnException(Handle<Object> exception, Handle<Object> promise) { DebugScope debug_scope(this); HandleScope scope(isolate_); - PostponeInterruptsScope postpone(isolate_); DisableBreak no_recursive_break(this); Handle<Context> native_context(isolate_->native_context()); @@ -1858,7 +1865,6 @@ void Debug::ProcessCompileEvent(bool has_compile_error, Handle<Script> script) { SuppressDebug while_processing(this); DebugScope debug_scope(this); HandleScope scope(isolate_); - PostponeInterruptsScope postpone(isolate_); DisableBreak no_recursive_break(this); AllowJavascriptExecution allow_script(isolate_); debug_delegate_->ScriptCompiled(ToApiHandle<debug::Script>(script), @@ -1999,15 +2005,14 @@ void Debug::PrintBreakLocation() { DebugScope::DebugScope(Debug* debug) : debug_(debug), - prev_(debug->debugger_entry()), - no_termination_exceptons_(debug_->isolate_, - StackGuard::TERMINATE_EXECUTION) { + prev_(reinterpret_cast<DebugScope*>( + base::Relaxed_Load(&debug->thread_local_.current_debug_scope_))), + no_interrupts_(debug_->isolate_) { // Link recursive debugger entry. base::Relaxed_Store(&debug_->thread_local_.current_debug_scope_, reinterpret_cast<base::AtomicWord>(this)); - // Store the previous break id, frame id and return value. - break_id_ = debug_->break_id(); + // Store the previous frame id and return value. break_frame_id_ = debug_->break_frame_id(); // Create the new break info. If there is no proper frames there is no break @@ -2016,7 +2021,6 @@ DebugScope::DebugScope(Debug* debug) bool has_frames = !it.done(); debug_->thread_local_.break_frame_id_ = has_frames ? it.frame()->id() : StackFrame::NO_ID; - debug_->SetNextBreakId(); debug_->UpdateState(); } @@ -2029,7 +2033,6 @@ DebugScope::~DebugScope() { // Restore to the previous break state. debug_->thread_local_.break_frame_id_ = break_frame_id_; - debug_->thread_local_.break_id_ = break_id_; debug_->UpdateState(); } @@ -2121,6 +2124,8 @@ void Debug::ClearSideEffectChecks(Handle<DebugInfo> debug_info) { Handle<BytecodeArray> original(debug_info->OriginalBytecodeArray(), isolate_); for (interpreter::BytecodeArrayIterator it(debug_bytecode); !it.done(); it.Advance()) { + // Restore from original. This may copy only the scaling prefix, which is + // correct, since we patch scaling prefixes to debug breaks if exists. debug_bytecode->set(it.current_offset(), original->get(it.current_offset())); } @@ -2173,6 +2178,10 @@ bool Debug::PerformSideEffectCheck(Handle<JSFunction> function, return false; } +Handle<Object> Debug::return_value_handle() { + return handle(thread_local_.return_value_, isolate_); +} + bool Debug::PerformSideEffectCheckForCallback(Handle<Object> callback_info) { DCHECK_EQ(isolate_->debug_execution_mode(), DebugInfo::kSideEffects); if (!callback_info.is_null() && callback_info->IsCallHandlerInfo() && diff --git a/chromium/v8/src/debug/debug.h b/chromium/v8/src/debug/debug.h index 31881fe1069..a6ad7bd4daa 100644 --- a/chromium/v8/src/debug/debug.h +++ b/chromium/v8/src/debug/debug.h @@ -8,7 +8,6 @@ #include <vector> #include "src/allocation.h" -#include "src/assembler.h" #include "src/base/atomicops.h" #include "src/base/hashmap.h" #include "src/base/platform/platform.h" @@ -30,6 +29,7 @@ namespace internal { // Forward declarations. class DebugScope; +class JSGeneratorObject; // Step actions. NOTE: These values are in macros.py as well. enum StepAction : int8_t { @@ -152,7 +152,7 @@ class BreakIterator { private: int BreakIndexFromPosition(int position); - Isolate* isolate() { return debug_info_->GetIsolate(); } + Isolate* isolate(); DebugBreakType GetDebugBreakType(); @@ -314,8 +314,9 @@ class Debug { static int ArchiveSpacePerThread(); void FreeThreadResources() { } void Iterate(RootVisitor* v); + void InitThread(const ExecutionAccess& lock) { ThreadInit(); } - bool CheckExecutionState() { return is_active() && break_id() != 0; } + bool CheckExecutionState() { return is_active(); } void StartSideEffectCheckMode(); void StopSideEffectCheckMode(); @@ -330,11 +331,6 @@ class Debug { bool PerformSideEffectCheckForObject(Handle<Object> object); // Flags and states. - DebugScope* debugger_entry() { - return reinterpret_cast<DebugScope*>( - base::Relaxed_Load(&thread_local_.current_debug_scope_)); - } - inline bool is_active() const { return is_active_; } inline bool in_debug_scope() const { return !!base::Relaxed_Load(&thread_local_.current_debug_scope_); @@ -347,11 +343,8 @@ class Debug { bool break_points_active() const { return break_points_active_; } StackFrame::Id break_frame_id() { return thread_local_.break_frame_id_; } - int break_id() { return thread_local_.break_id_; } - Handle<Object> return_value_handle() { - return handle(thread_local_.return_value_, isolate_); - } + Handle<Object> return_value_handle(); Object* return_value() { return thread_local_.return_value_; } void set_return_value(Object* value) { thread_local_.return_value_ = value; } @@ -393,9 +386,6 @@ class Debug { void UpdateState(); void UpdateHookOnFunctionCall(); void Unload(); - void SetNextBreakId() { - thread_local_.break_id_ = ++thread_local_.break_count_; - } // Return the number of virtual frames below debugger entry. int CurrentFrameCount(); @@ -503,12 +493,6 @@ class Debug { // Top debugger entry. base::AtomicWord current_debug_scope_; - // Counter for generating next break id. - int break_count_; - - // Current break id. - int break_id_; - // Frame id for the frame of the current break. StackFrame::Id break_frame_id_; @@ -578,8 +562,7 @@ class DebugScope BASE_EMBEDDED { Debug* debug_; DebugScope* prev_; // Previous scope if entered recursively. StackFrame::Id break_frame_id_; // Previous break frame id. - int break_id_; // Previous break id. - PostponeInterruptsScope no_termination_exceptons_; + PostponeInterruptsScope no_interrupts_; }; // This scope is used to handle return values in nested debug break points. diff --git a/chromium/v8/src/debug/liveedit.cc b/chromium/v8/src/debug/liveedit.cc index 7193d0abd1e..371d1d55754 100644 --- a/chromium/v8/src/debug/liveedit.cc +++ b/chromium/v8/src/debug/liveedit.cc @@ -4,7 +4,7 @@ #include "src/debug/liveedit.h" -#include "src/api.h" +#include "src/api-inl.h" #include "src/ast/ast-traversal-visitor.h" #include "src/ast/ast.h" #include "src/ast/scopes.h" @@ -17,6 +17,7 @@ #include "src/messages.h" #include "src/objects-inl.h" #include "src/objects/hash-table-inl.h" +#include "src/objects/js-generator-inl.h" #include "src/parsing/parse-info.h" #include "src/parsing/parsing.h" #include "src/source-position-table.h" @@ -542,9 +543,25 @@ struct SourcePositionEvent { if (a.position != b.position) return a.position < b.position; if (a.type != b.type) return a.type < b.type; if (a.type == LITERAL_STARTS && b.type == LITERAL_STARTS) { - return a.literal->end_position() < b.literal->end_position(); + // If the literals start in the same position, we want the one with the + // furthest (i.e. largest) end position to be first. + if (a.literal->end_position() != b.literal->end_position()) { + return a.literal->end_position() > b.literal->end_position(); + } + // If they also end in the same position, we want the first in order of + // literal ids to be first. + return a.literal->function_literal_id() < + b.literal->function_literal_id(); } else if (a.type == LITERAL_ENDS && b.type == LITERAL_ENDS) { - return a.literal->start_position() > b.literal->start_position(); + // If the literals end in the same position, we want the one with the + // nearest (i.e. largest) start position to be first. + if (a.literal->start_position() != b.literal->start_position()) { + return a.literal->start_position() > b.literal->start_position(); + } + // If they also end in the same position, we want the last in order of + // literal ids to be first. + return a.literal->function_literal_id() > + b.literal->function_literal_id(); } else { return a.pos_diff < b.pos_diff; } @@ -658,20 +675,33 @@ using LiteralMap = std::unordered_map<FunctionLiteral*, FunctionLiteral*>; void MapLiterals(const FunctionLiteralChanges& changes, const std::vector<FunctionLiteral*>& new_literals, LiteralMap* unchanged, LiteralMap* changed) { + // Track the top-level script function separately as it can overlap fully with + // another function, e.g. the script "()=>42". + const std::pair<int, int> kTopLevelMarker = std::make_pair(-1, -1); std::map<std::pair<int, int>, FunctionLiteral*> position_to_new_literal; for (FunctionLiteral* literal : new_literals) { DCHECK(literal->start_position() != kNoSourcePosition); DCHECK(literal->end_position() != kNoSourcePosition); - position_to_new_literal[std::make_pair(literal->start_position(), - literal->end_position())] = literal; + std::pair<int, int> key = + literal->function_literal_id() == FunctionLiteral::kIdTypeTopLevel + ? kTopLevelMarker + : std::make_pair(literal->start_position(), + literal->end_position()); + // Make sure there are no duplicate keys. + DCHECK_EQ(position_to_new_literal.find(key), position_to_new_literal.end()); + position_to_new_literal[key] = literal; } LiteralMap mappings; std::unordered_map<FunctionLiteral*, ChangeState> change_state; for (const auto& change_pair : changes) { FunctionLiteral* literal = change_pair.first; const FunctionLiteralChange& change = change_pair.second; - auto it = position_to_new_literal.find( - std::make_pair(change.new_start_position, change.new_end_position)); + std::pair<int, int> key = + literal->function_literal_id() == FunctionLiteral::kIdTypeTopLevel + ? kTopLevelMarker + : std::make_pair(change.new_start_position, + change.new_end_position); + auto it = position_to_new_literal.find(key); if (it == position_to_new_literal.end() || HasChangedScope(literal, it->second)) { change_state[literal] = ChangeState::DAMAGED; @@ -775,22 +805,22 @@ class FunctionDataMap : public ThreadVisitor { public: void AddInterestingLiteral(int script_id, FunctionLiteral* literal, bool should_restart) { - map_.emplace(std::make_pair(script_id, literal->function_literal_id()), + map_.emplace(GetFuncId(script_id, literal), FunctionData{literal, should_restart}); } - bool Lookup(Isolate* isolate, SharedFunctionInfo* sfi, FunctionData** data) { - int function_literal_id = sfi->FunctionLiteralId(isolate); - if (!sfi->script()->IsScript() || function_literal_id == -1) { + bool Lookup(SharedFunctionInfo* sfi, FunctionData** data) { + int start_position = sfi->StartPosition(); + if (!sfi->script()->IsScript() || start_position == -1) { return false; } Script* script = Script::cast(sfi->script()); - return Lookup(script->id(), function_literal_id, data); + return Lookup(GetFuncId(script->id(), sfi), data); } bool Lookup(Handle<Script> script, FunctionLiteral* literal, FunctionData** data) { - return Lookup(script->id(), literal->function_literal_id(), data); + return Lookup(GetFuncId(script->id(), literal), data); } void Fill(Isolate* isolate, Address* restart_frame_fp) { @@ -800,20 +830,20 @@ class FunctionDataMap : public ThreadVisitor { if (obj->IsSharedFunctionInfo()) { SharedFunctionInfo* sfi = SharedFunctionInfo::cast(obj); FunctionData* data = nullptr; - if (!Lookup(isolate, sfi, &data)) continue; + if (!Lookup(sfi, &data)) continue; data->shared = handle(sfi, isolate); } else if (obj->IsJSFunction()) { JSFunction* js_function = JSFunction::cast(obj); SharedFunctionInfo* sfi = js_function->shared(); FunctionData* data = nullptr; - if (!Lookup(isolate, sfi, &data)) continue; + if (!Lookup(sfi, &data)) continue; data->js_functions.emplace_back(js_function, isolate); } else if (obj->IsJSGeneratorObject()) { JSGeneratorObject* gen = JSGeneratorObject::cast(obj); if (gen->is_closed()) continue; SharedFunctionInfo* sfi = gen->function()->shared(); FunctionData* data = nullptr; - if (!Lookup(isolate, sfi, &data)) continue; + if (!Lookup(sfi, &data)) continue; data->running_generators.emplace_back(gen, isolate); } } @@ -843,7 +873,7 @@ class FunctionDataMap : public ThreadVisitor { stack_position = FunctionData::BELOW_NON_DROPPABLE_FRAME; } FunctionData* data = nullptr; - if (!Lookup(isolate, *sfi, &data)) continue; + if (!Lookup(*sfi, &data)) continue; if (!data->should_restart) continue; data->stack_position = stack_position; *restart_frame_fp = frame->fp(); @@ -854,8 +884,36 @@ class FunctionDataMap : public ThreadVisitor { } private: - bool Lookup(int script_id, int function_literal_id, FunctionData** data) { - auto it = map_.find(std::make_pair(script_id, function_literal_id)); + // Unique id for a function: script_id + start_position, where start_position + // is special cased to -1 for top-level so that it does not overlap with a + // function whose start position is 0. + using FuncId = std::pair<int, int>; + + FuncId GetFuncId(int script_id, FunctionLiteral* literal) { + int start_position = literal->start_position(); + if (literal->function_literal_id() == 0) { + // This is the top-level script function literal, so special case its + // start position + DCHECK_EQ(start_position, 0); + start_position = -1; + } + return FuncId(script_id, start_position); + } + + FuncId GetFuncId(int script_id, SharedFunctionInfo* sfi) { + DCHECK_EQ(script_id, Script::cast(sfi->script())->id()); + int start_position = sfi->StartPosition(); + DCHECK_NE(start_position, -1); + if (sfi->is_toplevel()) { + // This is the top-level function, so special case its start position + DCHECK_EQ(start_position, 0); + start_position = -1; + } + return FuncId(script_id, start_position); + } + + bool Lookup(FuncId id, FunctionData** data) { + auto it = map_.find(id); if (it == map_.end()) return false; *data = &it->second; return true; @@ -867,14 +925,13 @@ class FunctionDataMap : public ThreadVisitor { it.frame()->GetFunctions(&sfis); for (auto& sfi : sfis) { FunctionData* data = nullptr; - if (!Lookup(isolate, *sfi, &data)) continue; + if (!Lookup(*sfi, &data)) continue; data->stack_position = FunctionData::ARCHIVED_THREAD; } } } - using UniqueLiteralId = std::pair<int, int>; // script_id + literal_id - std::map<UniqueLiteralId, FunctionData> map_; + std::map<FuncId, FunctionData> map_; }; bool CanPatchScript(const LiteralMap& changed, Handle<Script> script, @@ -932,7 +989,7 @@ bool CanRestartFrame(Isolate* isolate, Address fp, JavaScriptFrame::cast(restart_frame)->GetFunctions(&sfis); for (auto& sfi : sfis) { FunctionData* data = nullptr; - if (!function_data_map.Lookup(isolate, *sfi, &data)) continue; + if (!function_data_map.Lookup(*sfi, &data)) continue; auto new_literal_it = changed.find(data->literal); if (new_literal_it == changed.end()) continue; if (new_literal_it->second->scope()->new_target_var()) { @@ -944,9 +1001,8 @@ bool CanRestartFrame(Isolate* isolate, Address fp, return true; } -void TranslateSourcePositionTable(Handle<BytecodeArray> code, +void TranslateSourcePositionTable(Isolate* isolate, Handle<BytecodeArray> code, const std::vector<SourceChangeRange>& diffs) { - Isolate* isolate = code->GetIsolate(); SourcePositionTableBuilder builder; Handle<ByteArray> source_position_table(code->SourcePositionTable(), isolate); @@ -979,8 +1035,8 @@ void UpdatePositions(Isolate* isolate, Handle<SharedFunctionInfo> sfi, sfi->SetFunctionTokenPosition(new_function_token_position, new_start_position); if (sfi->HasBytecodeArray()) { - TranslateSourcePositionTable(handle(sfi->GetBytecodeArray(), isolate), - diffs); + TranslateSourcePositionTable( + isolate, handle(sfi->GetBytecodeArray(), isolate), diffs); } } } // anonymous namespace @@ -1042,6 +1098,7 @@ void LiveEdit::PatchScript(Isolate* isolate, Handle<Script> script, return; } + std::map<int, int> start_position_to_unchanged_id; for (const auto& mapping : unchanged) { FunctionData* data = nullptr; if (!function_data_map.Lookup(script, mapping.first, &data)) continue; @@ -1057,10 +1114,6 @@ void LiveEdit::PatchScript(Isolate* isolate, Handle<Script> script, } UpdatePositions(isolate, sfi, diffs); - MaybeObject* weak_redundant_new_sfi = - new_script->shared_function_infos()->Get( - mapping.second->function_literal_id()); - sfi->set_script(*new_script); if (sfi->HasUncompiledData()) { sfi->uncompiled_data()->set_function_literal_id( @@ -1071,26 +1124,10 @@ void LiveEdit::PatchScript(Isolate* isolate, Handle<Script> script, DCHECK_EQ(sfi->FunctionLiteralId(isolate), mapping.second->function_literal_id()); - // Swap the now-redundant, newly compiled SFI into the old script, so that - // we can look up the old function_literal_id using the new SFI when - // processing changed functions. - HeapObject* redundant_new_sfi_obj; - if (weak_redundant_new_sfi->ToStrongOrWeakHeapObject( - &redundant_new_sfi_obj)) { - SharedFunctionInfo* redundant_new_sfi = - SharedFunctionInfo::cast(redundant_new_sfi_obj); - - redundant_new_sfi->set_script(*script); - if (redundant_new_sfi->HasUncompiledData()) { - redundant_new_sfi->uncompiled_data()->set_function_literal_id( - mapping.first->function_literal_id()); - } - script->shared_function_infos()->Set( - mapping.first->function_literal_id(), - HeapObjectReference::Weak(redundant_new_sfi)); - DCHECK_EQ(redundant_new_sfi->FunctionLiteralId(isolate), - mapping.first->function_literal_id()); - } + // Save the new start_position -> id mapping, so that we can recover it when + // iterating over changed functions' constant pools. + start_position_to_unchanged_id[mapping.second->start_position()] = + mapping.second->function_literal_id(); if (sfi->HasUncompiledDataWithPreParsedScope()) { sfi->ClearPreParsedScopeData(); @@ -1107,8 +1144,8 @@ void LiveEdit::PatchScript(Isolate* isolate, Handle<Script> script, for (int i = 0; i < constants->length(); ++i) { if (!constants->get(i)->IsSharedFunctionInfo()) continue; FunctionData* data = nullptr; - if (!function_data_map.Lookup( - isolate, SharedFunctionInfo::cast(constants->get(i)), &data)) { + if (!function_data_map.Lookup(SharedFunctionInfo::cast(constants->get(i)), + &data)) { continue; } auto change_it = changed.find(data->literal); @@ -1148,44 +1185,48 @@ void LiveEdit::PatchScript(Isolate* isolate, Handle<Script> script, if (!constants->get(i)->IsSharedFunctionInfo()) continue; SharedFunctionInfo* inner_sfi = SharedFunctionInfo::cast(constants->get(i)); - if (inner_sfi->script() != *script) continue; - - // If the inner SFI's script is the old script, then this is actually a - // redundant new_script SFI where the old script SFI was unchanged, so we - // swapped their scripts in the unchanged iteration. This means that we - // have to update this changed SFI's inner SFI constant to point at the - // old inner SFI, which has already been patched to be on the new script. - // - // So, we look up FunctionData using the current, newly compiled - // inner_sfi, but the resulting FunctionData will still be referring to - // the old, unchanged SFI. - FunctionData* data = nullptr; - if (!function_data_map.Lookup(isolate, inner_sfi, &data)) continue; - Handle<SharedFunctionInfo> old_unchanged_inner_sfi = - data->shared.ToHandleChecked(); + + // See if there is a mapping from this function's start position to a + // unchanged function's id. + auto unchanged_it = + start_position_to_unchanged_id.find(inner_sfi->StartPosition()); + if (unchanged_it == start_position_to_unchanged_id.end()) continue; + + // Grab that function id from the new script's SFI list, which should have + // already been updated in in the unchanged pass. + SharedFunctionInfo* old_unchanged_inner_sfi = + SharedFunctionInfo::cast(new_script->shared_function_infos() + ->Get(unchanged_it->second) + ->GetHeapObject()); // Now some sanity checks. Make sure that this inner_sfi is not the // unchanged SFI yet... - DCHECK_NE(*old_unchanged_inner_sfi, inner_sfi); - // ... that the unchanged SFI has already been processed and patched to be - // on the new script ... + DCHECK_NE(old_unchanged_inner_sfi, inner_sfi); + // ... and that the unchanged SFI has already been processed and patched + // to be on the new script ... DCHECK_EQ(old_unchanged_inner_sfi->script(), *new_script); - // ... and that the id of the unchanged SFI matches the unchanged target - // literal's id. - DCHECK_EQ(old_unchanged_inner_sfi->FunctionLiteralId(isolate), - unchanged[data->literal]->function_literal_id()); - constants->set(i, *old_unchanged_inner_sfi); + + constants->set(i, old_unchanged_inner_sfi); } } #ifdef DEBUG { - // Check that all the functions in the new script are valid and that their - // function literals match what is expected. + // Check that all the functions in the new script are valid, that their + // function literals match what is expected, and that start positions are + // unique. DisallowHeapAllocation no_gc; SharedFunctionInfo::ScriptIterator it(isolate, *new_script); + std::set<int> start_positions; while (SharedFunctionInfo* sfi = it.Next()) { DCHECK_EQ(sfi->script(), *new_script); DCHECK_EQ(sfi->FunctionLiteralId(isolate), it.CurrentIndex()); + // Don't check the start position of the top-level function, as it can + // overlap with a function in the script. + if (sfi->is_toplevel()) { + DCHECK_EQ(start_positions.find(sfi->StartPosition()), + start_positions.end()); + start_positions.insert(sfi->StartPosition()); + } if (!sfi->HasBytecodeArray()) continue; // Check that all the functions in this function's constant pool are also diff --git a/chromium/v8/src/debug/mips/OWNERS b/chromium/v8/src/debug/mips/OWNERS index 4ce9d7f91da..8bbcab4c2d0 100644 --- a/chromium/v8/src/debug/mips/OWNERS +++ b/chromium/v8/src/debug/mips/OWNERS @@ -1,3 +1,2 @@ -ivica.bogosavljevic@mips.com -Miran.Karic@mips.com -sreten.kovacevic@mips.com
\ No newline at end of file +ibogosavljevic@wavecomp.com +skovacevic@wavecomp.com
\ No newline at end of file diff --git a/chromium/v8/src/debug/mips64/OWNERS b/chromium/v8/src/debug/mips64/OWNERS index 4ce9d7f91da..8bbcab4c2d0 100644 --- a/chromium/v8/src/debug/mips64/OWNERS +++ b/chromium/v8/src/debug/mips64/OWNERS @@ -1,3 +1,2 @@ -ivica.bogosavljevic@mips.com -Miran.Karic@mips.com -sreten.kovacevic@mips.com
\ No newline at end of file +ibogosavljevic@wavecomp.com +skovacevic@wavecomp.com
\ No newline at end of file |