diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2017-11-20 15:06:40 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2017-11-22 11:48:58 +0000 |
commit | daa093eea7c773db06799a13bd7e4e2e2a9f8f14 (patch) | |
tree | 96cc5e7b9194c1b29eab927730bfa419e7111c25 /chromium/v8/src/debug | |
parent | be59a35641616a4cf23c4a13fa0632624b021c1b (diff) | |
download | qtwebengine-chromium-daa093eea7c773db06799a13bd7e4e2e2a9f8f14.tar.gz |
BASELINE: Update Chromium to 63.0.3239.58
Change-Id: Ia93b322a00ba4dd4004f3bcf1254063ba90e1605
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'chromium/v8/src/debug')
-rw-r--r-- | chromium/v8/src/debug/debug-coverage.cc | 31 | ||||
-rw-r--r-- | chromium/v8/src/debug/debug-coverage.h | 8 | ||||
-rw-r--r-- | chromium/v8/src/debug/debug-evaluate.cc | 86 | ||||
-rw-r--r-- | chromium/v8/src/debug/debug-evaluate.h | 9 | ||||
-rw-r--r-- | chromium/v8/src/debug/debug-frames.cc | 37 | ||||
-rw-r--r-- | chromium/v8/src/debug/debug-frames.h | 6 | ||||
-rw-r--r-- | chromium/v8/src/debug/debug-interface.h | 97 | ||||
-rw-r--r-- | chromium/v8/src/debug/debug-scope-iterator.cc | 13 | ||||
-rw-r--r-- | chromium/v8/src/debug/debug-scopes.cc | 25 | ||||
-rw-r--r-- | chromium/v8/src/debug/debug-scopes.h | 4 | ||||
-rw-r--r-- | chromium/v8/src/debug/debug-stack-trace-iterator.cc | 1 | ||||
-rw-r--r-- | chromium/v8/src/debug/debug-type-profile.cc | 102 | ||||
-rw-r--r-- | chromium/v8/src/debug/debug-type-profile.h | 45 | ||||
-rw-r--r-- | chromium/v8/src/debug/debug.cc | 106 | ||||
-rw-r--r-- | chromium/v8/src/debug/debug.h | 7 | ||||
-rw-r--r-- | chromium/v8/src/debug/liveedit.cc | 52 |
16 files changed, 430 insertions, 199 deletions
diff --git a/chromium/v8/src/debug/debug-coverage.cc b/chromium/v8/src/debug/debug-coverage.cc index e1ba0782efa..8fe2edc08a7 100644 --- a/chromium/v8/src/debug/debug-coverage.cc +++ b/chromium/v8/src/debug/debug-coverage.cc @@ -6,6 +6,7 @@ #include "src/ast/ast.h" #include "src/base/hashmap.h" +#include "src/debug/debug.h" #include "src/deoptimizer.h" #include "src/frames-inl.h" #include "src/isolate.h" @@ -60,15 +61,14 @@ bool CompareSharedFunctionInfo(SharedFunctionInfo* a, SharedFunctionInfo* b) { } bool CompareCoverageBlock(const CoverageBlock& a, const CoverageBlock& b) { - DCHECK(a.start != kNoSourcePosition); - DCHECK(b.start != kNoSourcePosition); + DCHECK_NE(kNoSourcePosition, a.start); + DCHECK_NE(kNoSourcePosition, b.start); if (a.start == b.start) return a.end > b.end; return a.start < b.start; } std::vector<CoverageBlock> GetSortedBlockData(Isolate* isolate, SharedFunctionInfo* shared) { - DCHECK(FLAG_block_coverage); DCHECK(shared->HasCoverageInfo()); CoverageInfo* coverage_info = @@ -82,7 +82,7 @@ std::vector<CoverageBlock> GetSortedBlockData(Isolate* isolate, const int until_pos = coverage_info->EndSourcePosition(i); const int count = coverage_info->BlockCount(i); - DCHECK(start_pos != kNoSourcePosition); + DCHECK_NE(kNoSourcePosition, start_pos); result.emplace_back(start_pos, until_pos, count); } @@ -324,7 +324,6 @@ void ClampToBinary(CoverageFunction* function) { } void ResetAllBlockCounts(SharedFunctionInfo* shared) { - DCHECK(FLAG_block_coverage); DCHECK(shared->HasCoverageInfo()); CoverageInfo* coverage_info = @@ -348,7 +347,6 @@ bool IsBlockMode(debug::Coverage::Mode mode) { void CollectBlockCoverage(Isolate* isolate, CoverageFunction* function, SharedFunctionInfo* info, debug::Coverage::Mode mode) { - DCHECK(FLAG_block_coverage); DCHECK(IsBlockMode(mode)); function->has_block_coverage = true; @@ -380,9 +378,10 @@ void CollectBlockCoverage(Isolate* isolate, CoverageFunction* function, } } // anonymous namespace -Coverage* Coverage::CollectPrecise(Isolate* isolate) { +std::unique_ptr<Coverage> Coverage::CollectPrecise(Isolate* isolate) { DCHECK(!isolate->is_best_effort_code_coverage()); - Coverage* result = Collect(isolate, isolate->code_coverage_mode()); + std::unique_ptr<Coverage> result = + Collect(isolate, isolate->code_coverage_mode()); if (isolate->is_precise_binary_code_coverage() || isolate->is_block_binary_code_coverage()) { // We do not have to hold onto feedback vectors for invocations we already @@ -392,12 +391,12 @@ Coverage* Coverage::CollectPrecise(Isolate* isolate) { return result; } -Coverage* Coverage::CollectBestEffort(Isolate* isolate) { +std::unique_ptr<Coverage> Coverage::CollectBestEffort(Isolate* isolate) { return Collect(isolate, v8::debug::Coverage::kBestEffort); } -Coverage* Coverage::Collect(Isolate* isolate, - v8::debug::Coverage::Mode collectionMode) { +std::unique_ptr<Coverage> Coverage::Collect( + Isolate* isolate, v8::debug::Coverage::Mode collectionMode) { SharedToCounterMap counter_map; const bool reset_count = collectionMode != v8::debug::Coverage::kBestEffort; @@ -439,7 +438,7 @@ Coverage* Coverage::Collect(Isolate* isolate, // Iterate shared function infos of every script and build a mapping // between source ranges and invocation counts. - Coverage* result = new Coverage(); + std::unique_ptr<Coverage> result(new Coverage()); Script::Iterator scripts(isolate); while (Script* script = scripts.Next()) { if (!script->IsUserJavaScript()) continue; @@ -491,8 +490,7 @@ Coverage* Coverage::Collect(Isolate* isolate, Handle<String> name(info->DebugName(), isolate); CoverageFunction function(start, end, count, name); - if (FLAG_block_coverage && IsBlockMode(collectionMode) && - info->HasCoverageInfo()) { + if (IsBlockMode(collectionMode) && info->HasCoverageInfo()) { CollectBlockCoverage(isolate, &function, info, collectionMode); } @@ -521,7 +519,7 @@ void Coverage::SelectMode(Isolate* isolate, debug::Coverage::Mode mode) { // recording is stopped. Since we delete coverage infos at that point, any // following coverage recording (without reloads) will be at function // granularity. - if (FLAG_block_coverage) isolate->debug()->RemoveAllCoverageInfos(); + isolate->debug()->RemoveAllCoverageInfos(); isolate->SetCodeCoverageList(isolate->heap()->undefined_value()); break; case debug::Coverage::kBlockBinary: @@ -546,6 +544,9 @@ void Coverage::SelectMode(Isolate* isolate, debug::Coverage::Mode mode) { if (!shared->IsSubjectToDebugging()) continue; vector->clear_invocation_count(); vectors.emplace_back(vector, isolate); + } else if (current_obj->IsJSFunction()) { + JSFunction* function = JSFunction::cast(current_obj); + function->set_code(function->shared()->code()); } } } diff --git a/chromium/v8/src/debug/debug-coverage.h b/chromium/v8/src/debug/debug-coverage.h index 49e3d60f21f..359a8133751 100644 --- a/chromium/v8/src/debug/debug-coverage.h +++ b/chromium/v8/src/debug/debug-coverage.h @@ -51,17 +51,17 @@ class Coverage : public std::vector<CoverageScript> { // In case of kPreciseCount, an updated count since last collection is // returned. In case of kPreciseBinary, a count of 1 is returned if a // function has been executed for the first time since last collection. - static Coverage* CollectPrecise(Isolate* isolate); + static std::unique_ptr<Coverage> CollectPrecise(Isolate* isolate); // Collecting best effort coverage always works, but may be imprecise // depending on selected mode. The invocation count is not reset. - static Coverage* CollectBestEffort(Isolate* isolate); + static std::unique_ptr<Coverage> CollectBestEffort(Isolate* isolate); // Select code coverage mode. static void SelectMode(Isolate* isolate, debug::Coverage::Mode mode); private: - static Coverage* Collect(Isolate* isolate, - v8::debug::Coverage::Mode collectionMode); + static std::unique_ptr<Coverage> Collect( + Isolate* isolate, v8::debug::Coverage::Mode collectionMode); Coverage() {} }; diff --git a/chromium/v8/src/debug/debug-evaluate.cc b/chromium/v8/src/debug/debug-evaluate.cc index 2cc0b25d8a0..3c898093563 100644 --- a/chromium/v8/src/debug/debug-evaluate.cc +++ b/chromium/v8/src/debug/debug-evaluate.cc @@ -5,6 +5,7 @@ #include "src/debug/debug-evaluate.h" #include "src/accessors.h" +#include "src/assembler-inl.h" #include "src/compiler.h" #include "src/contexts.h" #include "src/debug/debug-frames.h" @@ -157,8 +158,8 @@ DebugEvaluate::ContextBuilder::ContextBuilder(Isolate* isolate, Handle<StringSet> non_locals = it.GetNonLocals(); MaterializeReceiver(materialized, local_context, local_function, non_locals); - frame_inspector.MaterializeStackLocals(materialized, local_function); - MaterializeArgumentsObject(materialized, local_function); + frame_inspector.MaterializeStackLocals(materialized, local_function, + true); ContextChainElement context_chain_element; context_chain_element.scope_info = it.CurrentScopeInfo(); context_chain_element.materialized_object = materialized; @@ -168,7 +169,7 @@ DebugEvaluate::ContextBuilder::ContextBuilder(Isolate* isolate, if (it.HasContext()) { context_chain_element.wrapped_context = it.CurrentContext(); } - context_chain_.Add(context_chain_element); + context_chain_.push_back(context_chain_element); evaluation_context_ = outer_context; break; } else if (scope_type == ScopeIterator::ScopeTypeCatch || @@ -179,7 +180,7 @@ DebugEvaluate::ContextBuilder::ContextBuilder(Isolate* isolate, if (!current_context->IsDebugEvaluateContext()) { context_chain_element.wrapped_context = current_context; } - context_chain_.Add(context_chain_element); + context_chain_.push_back(context_chain_element); } else if (scope_type == ScopeIterator::ScopeTypeBlock || scope_type == ScopeIterator::ScopeTypeEval) { Handle<JSObject> materialized = factory->NewJSObjectWithNullProto(); @@ -191,28 +192,29 @@ DebugEvaluate::ContextBuilder::ContextBuilder(Isolate* isolate, if (it.HasContext()) { context_chain_element.wrapped_context = it.CurrentContext(); } - context_chain_.Add(context_chain_element); + context_chain_.push_back(context_chain_element); } else { break; } } - for (int i = context_chain_.length() - 1; i >= 0; i--) { + for (auto rit = context_chain_.rbegin(); rit != context_chain_.rend(); + rit++) { + ContextChainElement element = *rit; Handle<ScopeInfo> scope_info(ScopeInfo::CreateForWithScope( isolate, evaluation_context_->IsNativeContext() ? Handle<ScopeInfo>::null() : Handle<ScopeInfo>(evaluation_context_->scope_info()))); scope_info->SetIsDebugEvaluateScope(); evaluation_context_ = factory->NewDebugEvaluateContext( - evaluation_context_, scope_info, context_chain_[i].materialized_object, - context_chain_[i].wrapped_context, context_chain_[i].whitelist); + evaluation_context_, scope_info, element.materialized_object, + element.wrapped_context, element.whitelist); } } void DebugEvaluate::ContextBuilder::UpdateValues() { - for (int i = 0; i < context_chain_.length(); i++) { - ContextChainElement element = context_chain_[i]; + for (ContextChainElement& element : context_chain_) { if (!element.materialized_object.is_null()) { // Write back potential changes to materialized stack locals to the stack. FrameInspector(frame_, inlined_jsframe_index_, isolate_) @@ -223,24 +225,6 @@ void DebugEvaluate::ContextBuilder::UpdateValues() { } -void DebugEvaluate::ContextBuilder::MaterializeArgumentsObject( - Handle<JSObject> target, Handle<JSFunction> function) { - // Do not materialize the arguments object for eval or top-level code. - // Skip if "arguments" is already taken. - if (function->shared()->is_toplevel()) return; - Maybe<bool> maybe = JSReceiver::HasOwnProperty( - target, isolate_->factory()->arguments_string()); - DCHECK(maybe.IsJust()); - if (maybe.FromJust()) return; - - // FunctionGetArguments can't throw an exception. - Handle<JSObject> arguments = Accessors::FunctionGetArguments(function); - Handle<String> arguments_str = isolate_->factory()->arguments_string(); - JSObject::SetOwnPropertyIgnoreAttributes(target, arguments_str, arguments, - NONE) - .Check(); -} - void DebugEvaluate::ContextBuilder::MaterializeReceiver( Handle<JSObject> target, Handle<Context> local_context, Handle<JSFunction> local_function, Handle<StringSet> non_locals) { @@ -268,6 +252,7 @@ bool IntrinsicHasNoSideEffect(Runtime::FunctionId id) { V(ToString) \ V(ToLength) \ V(ToNumber) \ + V(NumberToString) \ /* Type checks */ \ V(IsJSReceiver) \ V(IsSmi) \ @@ -298,12 +283,16 @@ bool IntrinsicHasNoSideEffect(Runtime::FunctionId id) { V(NewTypeError) \ V(ThrowInvalidStringLength) \ /* Strings */ \ - V(StringCharCodeAt) \ V(StringIndexOf) \ V(StringIncludes) \ V(StringReplaceOneCharWithString) \ + V(StringToNumber) \ + V(StringTrim) \ V(SubString) \ V(RegExpInternalReplace) \ + /* BigInts */ \ + V(BigIntEqual) \ + V(BigIntToBoolean) \ /* Literals */ \ V(CreateArrayLiteral) \ V(CreateObjectLiteral) \ @@ -311,11 +300,13 @@ bool IntrinsicHasNoSideEffect(Runtime::FunctionId id) { /* Collections */ \ V(GenericHash) \ /* Called from builtins */ \ + V(StringAdd) \ V(StringParseFloat) \ V(StringParseInt) \ - V(StringCharCodeAtRT) \ + V(StringCharCodeAt) \ V(StringIndexOfUnchecked) \ V(StringEqual) \ + V(RegExpInitializeAndCompile) \ V(SymbolDescriptiveString) \ V(GenerateRandomNumbers) \ V(GlobalPrint) \ @@ -332,8 +323,10 @@ bool IntrinsicHasNoSideEffect(Runtime::FunctionId id) { V(ThrowIncompatibleMethodReceiver) \ V(ThrowInvalidHint) \ V(ThrowNotDateError) \ + V(ThrowRangeError) \ + V(ToName) \ + V(GetOwnPropertyDescriptor) \ /* Misc. */ \ - V(ForInPrepare) \ V(Call) \ V(MaxSmi) \ V(NewObject) \ @@ -385,8 +378,10 @@ bool BytecodeHasNoSideEffect(interpreter::Bytecode bytecode) { case Bytecode::kDivSmi: case Bytecode::kMod: case Bytecode::kModSmi: + case Bytecode::kNegate: case Bytecode::kBitwiseAnd: case Bytecode::kBitwiseAndSmi: + case Bytecode::kBitwiseNot: case Bytecode::kBitwiseOr: case Bytecode::kBitwiseOrSmi: case Bytecode::kBitwiseXor: @@ -437,6 +432,7 @@ bool BytecodeHasNoSideEffect(interpreter::Bytecode bytecode) { case Bytecode::kToNumber: case Bytecode::kToName: // Misc. + case Bytecode::kForInEnumerate: case Bytecode::kForInPrepare: case Bytecode::kForInContinue: case Bytecode::kForInNext: @@ -465,6 +461,7 @@ bool BuiltinHasNoSideEffect(Builtins::Name id) { switch (id) { // Whitelist for builtins. // Object builtins. + case Builtins::kObjectConstructor: case Builtins::kObjectCreate: case Builtins::kObjectEntries: case Builtins::kObjectGetOwnPropertyDescriptor: @@ -531,7 +528,7 @@ bool BuiltinHasNoSideEffect(Builtins::Name id) { case Builtins::kDatePrototypeValueOf: // Map builtins. case Builtins::kMapConstructor: - case Builtins::kMapGet: + case Builtins::kMapPrototypeGet: case Builtins::kMapPrototypeEntries: case Builtins::kMapPrototypeGetSize: case Builtins::kMapPrototypeKeys: @@ -594,18 +591,32 @@ bool BuiltinHasNoSideEffect(Builtins::Name id) { case Builtins::kStringFromCharCode: case Builtins::kStringFromCodePoint: case Builtins::kStringConstructor: + case Builtins::kStringPrototypeAnchor: + case Builtins::kStringPrototypeBig: + case Builtins::kStringPrototypeBlink: + case Builtins::kStringPrototypeBold: case Builtins::kStringPrototypeCharAt: case Builtins::kStringPrototypeCharCodeAt: case Builtins::kStringPrototypeCodePointAt: case Builtins::kStringPrototypeConcat: case Builtins::kStringPrototypeEndsWith: + case Builtins::kStringPrototypeFixed: + case Builtins::kStringPrototypeFontcolor: + case Builtins::kStringPrototypeFontsize: case Builtins::kStringPrototypeIncludes: case Builtins::kStringPrototypeIndexOf: + case Builtins::kStringPrototypeItalics: case Builtins::kStringPrototypeLastIndexOf: + case Builtins::kStringPrototypeLink: + case Builtins::kStringPrototypeRepeat: case Builtins::kStringPrototypeSlice: + case Builtins::kStringPrototypeSmall: case Builtins::kStringPrototypeStartsWith: + case Builtins::kStringPrototypeStrike: + case Builtins::kStringPrototypeSub: case Builtins::kStringPrototypeSubstr: case Builtins::kStringPrototypeSubstring: + case Builtins::kStringPrototypeSup: case Builtins::kStringPrototypeToString: #ifndef V8_INTL_SUPPORT case Builtins::kStringPrototypeToLowerCase: @@ -615,6 +626,7 @@ bool BuiltinHasNoSideEffect(Builtins::Name id) { case Builtins::kStringPrototypeTrimLeft: case Builtins::kStringPrototypeTrimRight: case Builtins::kStringPrototypeValueOf: + case Builtins::kStringToNumber: // Symbol builtins. case Builtins::kSymbolConstructor: case Builtins::kSymbolKeyFor: @@ -695,10 +707,16 @@ bool DebugEvaluate::FunctionHasNoSideEffect(Handle<SharedFunctionInfo> info) { return true; } else { // Check built-ins against whitelist. - int builtin_index = info->code()->builtin_index(); + int builtin_index = info->HasLazyDeserializationBuiltinId() + ? info->lazy_deserialization_builtin_id() + : info->code()->builtin_index(); + DCHECK_NE(Builtins::kDeserializeLazy, builtin_index); if (builtin_index >= 0 && builtin_index < Builtins::builtin_count && BuiltinHasNoSideEffect(static_cast<Builtins::Name>(builtin_index))) { #ifdef DEBUG + if (info->code()->builtin_index() == Builtins::kDeserializeLazy) { + return true; // Target builtin is not yet deserialized. + } // TODO(yangguo): Check builtin-to-builtin calls too. int mode = RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE); bool failed = false; @@ -712,7 +730,7 @@ bool DebugEvaluate::FunctionHasNoSideEffect(Handle<SharedFunctionInfo> info) { Builtins::name(builtin_index), function->name); failed = true; } - CHECK(!failed); + DCHECK(!failed); } #endif // DEBUG return true; diff --git a/chromium/v8/src/debug/debug-evaluate.h b/chromium/v8/src/debug/debug-evaluate.h index ba6ca7e4394..6327895d577 100644 --- a/chromium/v8/src/debug/debug-evaluate.h +++ b/chromium/v8/src/debug/debug-evaluate.h @@ -5,6 +5,8 @@ #ifndef V8_DEBUG_DEBUG_EVALUATE_H_ #define V8_DEBUG_DEBUG_EVALUATE_H_ +#include <vector> + #include "src/frames.h" #include "src/objects.h" #include "src/objects/string-table.h" @@ -66,11 +68,6 @@ class DebugEvaluate : public AllStatic { Handle<StringSet> whitelist; }; - // Helper function to find or create the arguments object for - // Runtime_DebugEvaluate. - void MaterializeArgumentsObject(Handle<JSObject> target, - Handle<JSFunction> function); - void MaterializeReceiver(Handle<JSObject> target, Handle<Context> local_context, Handle<JSFunction> local_function, @@ -78,7 +75,7 @@ class DebugEvaluate : public AllStatic { Handle<SharedFunctionInfo> outer_info_; Handle<Context> evaluation_context_; - List<ContextChainElement> context_chain_; + std::vector<ContextChainElement> context_chain_; Isolate* isolate_; JavaScriptFrame* frame_; int inlined_jsframe_index_; diff --git a/chromium/v8/src/debug/debug-frames.cc b/chromium/v8/src/debug/debug-frames.cc index 9017bcab0e3..b04f8fc1bc0 100644 --- a/chromium/v8/src/debug/debug-frames.cc +++ b/chromium/v8/src/debug/debug-frames.cc @@ -4,9 +4,10 @@ #include "src/debug/debug-frames.h" +#include "src/accessors.h" #include "src/frames-inl.h" #include "src/wasm/wasm-interpreter.h" -#include "src/wasm/wasm-objects.h" +#include "src/wasm/wasm-objects-inl.h" namespace v8 { namespace internal { @@ -37,7 +38,7 @@ FrameInspector::FrameInspector(StandardFrame* frame, int inlined_frame_index, // Calculate the deoptimized frame. if (is_optimized_) { - DCHECK(js_frame != nullptr); + DCHECK_NOT_NULL(js_frame); // TODO(turbofan): Deoptimization from AstGraphBuilder is not supported. if (js_frame->LookupCode()->is_turbofanned() && !js_frame->function()->shared()->HasBytecodeArray()) { @@ -108,7 +109,8 @@ void FrameInspector::SetArgumentsFrame(StandardFrame* frame) { // Create a plain JSObject which materializes the local scope for the specified // frame. void FrameInspector::MaterializeStackLocals(Handle<JSObject> target, - Handle<ScopeInfo> scope_info) { + Handle<ScopeInfo> scope_info, + bool materialize_arguments_object) { HandleScope scope(isolate_); // First fill all parameters. for (int i = 0; i < scope_info->ParameterCount(); ++i) { @@ -139,18 +141,41 @@ void FrameInspector::MaterializeStackLocals(Handle<JSObject> target, value = isolate_->factory()->undefined_value(); } if (value->IsOptimizedOut(isolate_)) { + if (materialize_arguments_object) { + Handle<String> arguments_str = isolate_->factory()->arguments_string(); + if (String::Equals(name, arguments_str)) continue; + } value = isolate_->factory()->undefined_value(); } JSObject::SetOwnPropertyIgnoreAttributes(target, name, value, NONE).Check(); } } - void FrameInspector::MaterializeStackLocals(Handle<JSObject> target, - Handle<JSFunction> function) { + Handle<JSFunction> function, + bool materialize_arguments_object) { + // Do not materialize the arguments object for eval or top-level code. + if (function->shared()->is_toplevel()) materialize_arguments_object = false; + Handle<SharedFunctionInfo> shared(function->shared()); Handle<ScopeInfo> scope_info(shared->scope_info()); - MaterializeStackLocals(target, scope_info); + MaterializeStackLocals(target, scope_info, materialize_arguments_object); + + // Third materialize the arguments object. + if (materialize_arguments_object) { + // Skip if "arguments" is already taken and wasn't optimized out (which + // causes {MaterializeStackLocals} above to skip the local variable). + Handle<String> arguments_str = isolate_->factory()->arguments_string(); + Maybe<bool> maybe = JSReceiver::HasOwnProperty(target, arguments_str); + DCHECK(maybe.IsJust()); + if (maybe.FromJust()) return; + + // FunctionGetArguments can't throw an exception. + Handle<JSObject> arguments = Accessors::FunctionGetArguments(function); + JSObject::SetOwnPropertyIgnoreAttributes(target, arguments_str, arguments, + NONE) + .Check(); + } } diff --git a/chromium/v8/src/debug/debug-frames.h b/chromium/v8/src/debug/debug-frames.h index 0a0d4329b98..96593b858d1 100644 --- a/chromium/v8/src/debug/debug-frames.h +++ b/chromium/v8/src/debug/debug-frames.h @@ -49,10 +49,12 @@ class FrameInspector { void SetArgumentsFrame(StandardFrame* frame); void MaterializeStackLocals(Handle<JSObject> target, - Handle<ScopeInfo> scope_info); + Handle<ScopeInfo> scope_info, + bool materialize_arguments_object = false); void MaterializeStackLocals(Handle<JSObject> target, - Handle<JSFunction> function); + Handle<JSFunction> function, + bool materialize_arguments_object = false); void UpdateStackLocalsFromMaterializedObject(Handle<JSObject> object, Handle<ScopeInfo> scope_info); diff --git a/chromium/v8/src/debug/debug-interface.h b/chromium/v8/src/debug/debug-interface.h index 78001524b2c..cc321ebfa23 100644 --- a/chromium/v8/src/debug/debug-interface.h +++ b/chromium/v8/src/debug/debug-interface.h @@ -18,9 +18,12 @@ namespace internal { struct CoverageBlock; struct CoverageFunction; struct CoverageScript; +struct TypeProfileEntry; +struct TypeProfileScript; class Coverage; class Script; -} +class TypeProfile; +} // namespace internal namespace debug { @@ -244,6 +247,8 @@ class GeneratorObject { */ class V8_EXPORT_PRIVATE Coverage { public: + MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(Coverage); + enum Mode { // Make use of existing information in feedback vectors on the heap. // Only return a yes/no result. Optimization and GC are not affected. @@ -269,19 +274,27 @@ class V8_EXPORT_PRIVATE Coverage { class V8_EXPORT_PRIVATE BlockData { public: + MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(BlockData); + int StartOffset() const; int EndOffset() const; uint32_t Count() const; private: - explicit BlockData(i::CoverageBlock* block) : block_(block) {} + explicit BlockData(i::CoverageBlock* block, + std::shared_ptr<i::Coverage> coverage) + : block_(block), coverage_(std::move(coverage)) {} + i::CoverageBlock* block_; + std::shared_ptr<i::Coverage> coverage_; friend class v8::debug::Coverage::FunctionData; }; class V8_EXPORT_PRIVATE FunctionData { public: + MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(FunctionData); + int StartOffset() const; int EndOffset() const; uint32_t Count() const; @@ -291,22 +304,29 @@ class V8_EXPORT_PRIVATE Coverage { BlockData GetBlockData(size_t i) const; private: - explicit FunctionData(i::CoverageFunction* function) - : function_(function) {} + explicit FunctionData(i::CoverageFunction* function, + std::shared_ptr<i::Coverage> coverage) + : function_(function), coverage_(std::move(coverage)) {} + i::CoverageFunction* function_; + std::shared_ptr<i::Coverage> coverage_; friend class v8::debug::Coverage::ScriptData; }; class V8_EXPORT_PRIVATE ScriptData { public: + MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(ScriptData); + Local<debug::Script> GetScript() const; size_t FunctionCount() const; FunctionData GetFunctionData(size_t i) const; private: - explicit ScriptData(i::CoverageScript* script) : script_(script) {} + explicit ScriptData(size_t index, std::shared_ptr<i::Coverage> c); + i::CoverageScript* script_; + std::shared_ptr<i::Coverage> coverage_; friend class v8::debug::Coverage; }; @@ -320,11 +340,72 @@ class V8_EXPORT_PRIVATE Coverage { ScriptData GetScriptData(size_t i) const; bool IsEmpty() const { return coverage_ == nullptr; } - ~Coverage(); + private: + explicit Coverage(std::shared_ptr<i::Coverage> coverage) + : coverage_(std::move(coverage)) {} + std::shared_ptr<i::Coverage> coverage_; +}; + +/* + * Provide API layer between inspector and type profile. + */ +class V8_EXPORT_PRIVATE TypeProfile { + public: + MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(TypeProfile); + + enum Mode { + kNone, + kCollect, + }; + class ScriptData; // Forward declaration. + + class V8_EXPORT_PRIVATE Entry { + public: + MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(Entry); + + int SourcePosition() const; + std::vector<MaybeLocal<String>> Types() const; + + private: + explicit Entry(const i::TypeProfileEntry* entry, + std::shared_ptr<i::TypeProfile> type_profile) + : entry_(entry), type_profile_(std::move(type_profile)) {} + + const i::TypeProfileEntry* entry_; + std::shared_ptr<i::TypeProfile> type_profile_; + + friend class v8::debug::TypeProfile::ScriptData; + }; + + class V8_EXPORT_PRIVATE ScriptData { + public: + MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(ScriptData); + + Local<debug::Script> GetScript() const; + std::vector<Entry> Entries() const; + + private: + explicit ScriptData(size_t index, + std::shared_ptr<i::TypeProfile> type_profile); + + i::TypeProfileScript* script_; + std::shared_ptr<i::TypeProfile> type_profile_; + + friend class v8::debug::TypeProfile; + }; + + static TypeProfile Collect(Isolate* isolate); + + static void SelectMode(Isolate* isolate, Mode mode); + + size_t ScriptCount() const; + ScriptData GetScriptData(size_t i) const; private: - explicit Coverage(i::Coverage* coverage) : coverage_(coverage) {} - i::Coverage* coverage_; + explicit TypeProfile(std::shared_ptr<i::TypeProfile> type_profile) + : type_profile_(std::move(type_profile)) {} + + std::shared_ptr<i::TypeProfile> type_profile_; }; class ScopeIterator { diff --git a/chromium/v8/src/debug/debug-scope-iterator.cc b/chromium/v8/src/debug/debug-scope-iterator.cc index 62c622853a0..5dc377375ee 100644 --- a/chromium/v8/src/debug/debug-scope-iterator.cc +++ b/chromium/v8/src/debug/debug-scope-iterator.cc @@ -4,20 +4,24 @@ #include "src/debug/debug-scope-iterator.h" +#include "src/api.h" #include "src/debug/debug.h" #include "src/debug/liveedit.h" #include "src/frames-inl.h" #include "src/isolate.h" -#include "src/wasm/wasm-objects.h" +#include "src/wasm/wasm-objects-inl.h" namespace v8 { std::unique_ptr<debug::ScopeIterator> debug::ScopeIterator::CreateForFunction( v8::Isolate* v8_isolate, v8::Local<v8::Function> v8_func) { + internal::Handle<internal::JSFunction> func = + internal::Handle<internal::JSFunction>::cast(Utils::OpenHandle(*v8_func)); + // Blink has function objects with callable map, JS_SPECIAL_API_OBJECT_TYPE + // but without context on heap. + if (!func->has_context()) return nullptr; return std::unique_ptr<debug::ScopeIterator>(new internal::DebugScopeIterator( - reinterpret_cast<internal::Isolate*>(v8_isolate), - internal::Handle<internal::JSFunction>::cast( - Utils::OpenHandle(*v8_func)))); + reinterpret_cast<internal::Isolate*>(v8_isolate), func)); } std::unique_ptr<debug::ScopeIterator> @@ -26,7 +30,6 @@ debug::ScopeIterator::CreateForGeneratorObject( internal::Handle<internal::Object> generator = Utils::OpenHandle(*v8_generator); DCHECK(generator->IsJSGeneratorObject()); - return std::unique_ptr<debug::ScopeIterator>(new internal::DebugScopeIterator( reinterpret_cast<internal::Isolate*>(v8_isolate), internal::Handle<internal::JSGeneratorObject>::cast(generator))); diff --git a/chromium/v8/src/debug/debug-scopes.cc b/chromium/v8/src/debug/debug-scopes.cc index 5c6775ccf98..0fcb20a6455 100644 --- a/chromium/v8/src/debug/debug-scopes.cc +++ b/chromium/v8/src/debug/debug-scopes.cc @@ -23,7 +23,6 @@ ScopeIterator::ScopeIterator(Isolate* isolate, FrameInspector* frame_inspector, ScopeIterator::Option option) : isolate_(isolate), frame_inspector_(frame_inspector), - nested_scope_chain_(4), seen_script_scope_(false) { if (!frame_inspector->GetContext()->IsContext()) { // Optimized frame, context or function cannot be materialized. Give up. @@ -83,9 +82,9 @@ void ScopeIterator::TryParseAndRetrieveScopes(ScopeIterator::Option option) { } } if (scope_info->scope_type() == FUNCTION_SCOPE) { - nested_scope_chain_.Add(ExtendedScopeInfo(scope_info, - shared_info->start_position(), - shared_info->end_position())); + nested_scope_chain_.emplace_back(scope_info, + shared_info->start_position(), + shared_info->end_position()); } if (!collect_non_locals) return; } @@ -245,7 +244,7 @@ void ScopeIterator::Next() { } if (HasNestedScopeChain()) { DCHECK_EQ(LastNestedScopeChain().scope_info->scope_type(), SCRIPT_SCOPE); - nested_scope_chain_.RemoveLast(); + nested_scope_chain_.pop_back(); DCHECK(!HasNestedScopeChain()); } CHECK(context_->IsNativeContext()); @@ -257,7 +256,7 @@ void ScopeIterator::Next() { DCHECK(context_->previous() != NULL); context_ = Handle<Context>(context_->previous(), isolate_); } - nested_scope_chain_.RemoveLast(); + nested_scope_chain_.pop_back(); if (!HasNestedScopeChain()) break; // Repeat to skip hidden scopes. } while (LastNestedScopeChain().is_hidden()); @@ -331,7 +330,7 @@ MaybeHandle<JSObject> ScopeIterator::ScopeObject() { return MaterializeScriptScope(); case ScopeIterator::ScopeTypeLocal: // Materialize the content of the local scope into a JSObject. - DCHECK(nested_scope_chain_.length() == 1); + DCHECK_EQ(1, nested_scope_chain_.size()); return MaterializeLocalScope(); case ScopeIterator::ScopeTypeWith: return WithContextExtension(); @@ -409,7 +408,7 @@ Handle<Context> ScopeIterator::CurrentContext() { } else if (LastNestedScopeChain().scope_info->HasContext()) { return context_; } else { - return Handle<Context>(); + return Handle<Context>::null(); } } @@ -965,10 +964,10 @@ void ScopeIterator::GetNestedScopeChain(Isolate* isolate, Scope* scope, if (scope->is_hidden()) { // We need to add this chain element in case the scope has a context // associated. We need to keep the scope chain and context chain in sync. - nested_scope_chain_.Add(ExtendedScopeInfo(scope->scope_info())); + nested_scope_chain_.emplace_back(scope->scope_info()); } else { - nested_scope_chain_.Add(ExtendedScopeInfo( - scope->scope_info(), scope->start_position(), scope->end_position())); + nested_scope_chain_.emplace_back( + scope->scope_info(), scope->start_position(), scope->end_position()); } for (Scope* inner_scope = scope->inner_scope(); inner_scope != nullptr; inner_scope = inner_scope->sibling()) { @@ -983,12 +982,12 @@ void ScopeIterator::GetNestedScopeChain(Isolate* isolate, Scope* scope, } bool ScopeIterator::HasNestedScopeChain() { - return !nested_scope_chain_.is_empty(); + return !nested_scope_chain_.empty(); } ScopeIterator::ExtendedScopeInfo& ScopeIterator::LastNestedScopeChain() { DCHECK(HasNestedScopeChain()); - return nested_scope_chain_.last(); + return nested_scope_chain_.back(); } } // namespace internal diff --git a/chromium/v8/src/debug/debug-scopes.h b/chromium/v8/src/debug/debug-scopes.h index 76e083fe872..9321b8f9954 100644 --- a/chromium/v8/src/debug/debug-scopes.h +++ b/chromium/v8/src/debug/debug-scopes.h @@ -5,6 +5,8 @@ #ifndef V8_DEBUG_DEBUG_SCOPES_H_ #define V8_DEBUG_DEBUG_SCOPES_H_ +#include <vector> + #include "src/debug/debug-frames.h" #include "src/frames.h" @@ -101,7 +103,7 @@ class ScopeIterator { FrameInspector* const frame_inspector_ = nullptr; Handle<JSGeneratorObject> generator_; Handle<Context> context_; - List<ExtendedScopeInfo> nested_scope_chain_; + std::vector<ExtendedScopeInfo> nested_scope_chain_; Handle<StringSet> non_locals_; bool seen_script_scope_; diff --git a/chromium/v8/src/debug/debug-stack-trace-iterator.cc b/chromium/v8/src/debug/debug-stack-trace-iterator.cc index 74ba3373d46..867436d1de5 100644 --- a/chromium/v8/src/debug/debug-stack-trace-iterator.cc +++ b/chromium/v8/src/debug/debug-stack-trace-iterator.cc @@ -4,6 +4,7 @@ #include "src/debug/debug-stack-trace-iterator.h" +#include "src/api.h" #include "src/debug/debug-evaluate.h" #include "src/debug/debug-scope-iterator.h" #include "src/debug/debug.h" diff --git a/chromium/v8/src/debug/debug-type-profile.cc b/chromium/v8/src/debug/debug-type-profile.cc new file mode 100644 index 00000000000..ef4f5ba3d78 --- /dev/null +++ b/chromium/v8/src/debug/debug-type-profile.cc @@ -0,0 +1,102 @@ +// 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/debug/debug-type-profile.h" + +#include "src/feedback-vector.h" +#include "src/isolate.h" +#include "src/objects-inl.h" +#include "src/objects.h" + +namespace v8 { +namespace internal { + +std::unique_ptr<TypeProfile> TypeProfile::Collect(Isolate* isolate) { + std::unique_ptr<TypeProfile> result(new TypeProfile()); + + // Collect existing feedback vectors. + std::vector<Handle<FeedbackVector>> feedback_vectors; + { + HeapIterator heap_iterator(isolate->heap()); + while (HeapObject* current_obj = heap_iterator.next()) { + if (current_obj->IsFeedbackVector()) { + FeedbackVector* vector = FeedbackVector::cast(current_obj); + SharedFunctionInfo* shared = vector->shared_function_info(); + if (!shared->IsSubjectToDebugging()) continue; + feedback_vectors.emplace_back(vector, isolate); + } + } + } + + Script::Iterator scripts(isolate); + + while (Script* script = scripts.Next()) { + if (!script->IsUserJavaScript()) { + continue; + } + + Handle<Script> script_handle(script, isolate); + + TypeProfileScript type_profile_script(script_handle); + std::vector<TypeProfileEntry>* entries = &type_profile_script.entries; + + for (const auto& vector : feedback_vectors) { + SharedFunctionInfo* info = vector->shared_function_info(); + DCHECK(info->IsSubjectToDebugging()); + + // Match vectors with script. + if (script != info->script()) { + continue; + } + if (info->feedback_metadata()->is_empty() || + !info->feedback_metadata()->HasTypeProfileSlot()) { + continue; + } + FeedbackSlot slot = vector->GetTypeProfileSlot(); + CollectTypeProfileNexus nexus(vector, slot); + Handle<String> name(info->DebugName(), isolate); + std::vector<int> source_positions = nexus.GetSourcePositions(); + for (int position : source_positions) { + DCHECK_GE(position, 0); + entries->emplace_back(position, nexus.GetTypesForSourcePositions( + static_cast<uint32_t>(position))); + } + + // Releases type profile data collected so far. + nexus.Clear(); + } + if (!entries->empty()) { + result->emplace_back(type_profile_script); + } + } + return result; +} + +void TypeProfile::SelectMode(Isolate* isolate, debug::TypeProfile::Mode mode) { + isolate->set_type_profile_mode(mode); + HandleScope handle_scope(isolate); + + if (mode == debug::TypeProfile::Mode::kNone) { + // Release type profile data collected so far. + { + HeapIterator heap_iterator(isolate->heap()); + while (HeapObject* current_obj = heap_iterator.next()) { + if (current_obj->IsFeedbackVector()) { + FeedbackVector* vector = FeedbackVector::cast(current_obj); + SharedFunctionInfo* info = vector->shared_function_info(); + if (!info->IsSubjectToDebugging() || + info->feedback_metadata()->is_empty() || + !info->feedback_metadata()->HasTypeProfileSlot()) + continue; + FeedbackSlot slot = vector->GetTypeProfileSlot(); + CollectTypeProfileNexus nexus(vector, slot); + nexus.Clear(); + } + } + } + } +} + +} // namespace internal +} // namespace v8 diff --git a/chromium/v8/src/debug/debug-type-profile.h b/chromium/v8/src/debug/debug-type-profile.h new file mode 100644 index 00000000000..de18951381a --- /dev/null +++ b/chromium/v8/src/debug/debug-type-profile.h @@ -0,0 +1,45 @@ +// 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_DEBUG_DEBUG_TYPE_PROFILE_H_ +#define V8_DEBUG_DEBUG_TYPE_PROFILE_H_ + +#include <vector> + +#include "src/debug/debug-interface.h" +#include "src/objects.h" + +namespace v8 { +namespace internal { + +// Forward declaration. +class Isolate; + +struct TypeProfileEntry { + explicit TypeProfileEntry( + int pos, std::vector<v8::internal::Handle<internal::String>> t) + : position(pos), types(std::move(t)) {} + int position; + std::vector<v8::internal::Handle<internal::String>> types; +}; + +struct TypeProfileScript { + explicit TypeProfileScript(Handle<Script> s) : script(s) {} + Handle<Script> script; + std::vector<TypeProfileEntry> entries; +}; + +class TypeProfile : public std::vector<TypeProfileScript> { + public: + static std::unique_ptr<TypeProfile> Collect(Isolate* isolate); + static void SelectMode(Isolate* isolate, debug::TypeProfile::Mode mode); + + private: + TypeProfile() {} +}; + +} // namespace internal +} // namespace v8 + +#endif // V8_DEBUG_DEBUG_TYPE_PROFILE_H_ diff --git a/chromium/v8/src/debug/debug.cc b/chromium/v8/src/debug/debug.cc index 8d5adfbaeac..1d50226e72d 100644 --- a/chromium/v8/src/debug/debug.cc +++ b/chromium/v8/src/debug/debug.cc @@ -24,13 +24,11 @@ #include "src/globals.h" #include "src/interpreter/interpreter.h" #include "src/isolate-inl.h" -#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" +#include "src/wasm/wasm-objects-inl.h" #include "include/v8-debug.h" @@ -64,9 +62,9 @@ BreakLocation BreakLocation::FromFrame(Handle<DebugInfo> debug_info, return it.GetBreakLocation(); } -void BreakLocation::AllAtCurrentStatement(Handle<DebugInfo> debug_info, - JavaScriptFrame* frame, - List<BreakLocation>* result_out) { +void BreakLocation::AllAtCurrentStatement( + Handle<DebugInfo> debug_info, JavaScriptFrame* frame, + std::vector<BreakLocation>* result_out) { auto summary = FrameSummary::GetTop(frame).AsJavaScript(); int offset = summary.code_offset(); Handle<AbstractCode> abstract_code = summary.abstract_code(); @@ -79,7 +77,7 @@ void BreakLocation::AllAtCurrentStatement(Handle<DebugInfo> debug_info, } for (BreakIterator it(debug_info); !it.Done(); it.Next()) { if (it.statement_position() == statement_position) { - result_out->Add(it.GetBreakLocation()); + result_out->push_back(it.GetBreakLocation()); } } } @@ -170,8 +168,8 @@ void BreakIterator::Next() { if (source_position_iterator_.is_statement()) { statement_position_ = position_; } - DCHECK(position_ >= 0); - DCHECK(statement_position_ >= 0); + DCHECK_LE(0, position_); + DCHECK_LE(0, statement_position_); DebugBreakType type = GetDebugBreakType(); if (type != NOT_DEBUG_BREAK) break; @@ -338,13 +336,12 @@ bool Debug::Load() { void Debug::Unload() { ClearAllBreakPoints(); ClearStepping(); + RemoveAllCoverageInfos(); RemoveDebugDelegate(); // Return debugger is not loaded. if (!is_loaded()) return; - if (FLAG_block_coverage) RemoveAllCoverageInfos(); - // Clear debugger context global handle. GlobalHandles::Destroy(Handle<Object>::cast(debug_context_).location()); debug_context_ = Handle<Context>(); @@ -470,10 +467,10 @@ bool Debug::IsMutedAtCurrentLocation(JavaScriptFrame* frame) { // Enter the debugger. DebugScope debug_scope(this); if (debug_scope.failed()) return false; - List<BreakLocation> break_locations; + std::vector<BreakLocation> break_locations; BreakLocation::AllAtCurrentStatement(debug_info, frame, &break_locations); bool has_break_points_at_all = false; - for (int i = 0; i < break_locations.length(); i++) { + for (size_t i = 0; i < break_locations.size(); i++) { bool has_break_points; MaybeHandle<FixedArray> check_result = CheckBreakPoints(debug_info, &break_locations[i], &has_break_points); @@ -558,16 +555,16 @@ bool Debug::SetBreakPoint(Handle<JSFunction> function, // Make sure the function is compiled and has set up the debug info. Handle<SharedFunctionInfo> shared(function->shared()); if (!EnsureBreakInfo(shared)) return true; - CHECK(PrepareFunctionForBreakPoints(shared)); + PrepareFunctionForBreakPoints(shared); Handle<DebugInfo> debug_info(shared->GetDebugInfo()); // Source positions starts with zero. - DCHECK(*source_position >= 0); + DCHECK_LE(0, *source_position); // Find the break point and change it. *source_position = FindBreakablePosition(debug_info, *source_position); DebugInfo::SetBreakPoint(debug_info, *source_position, break_point_object); // At least one active break point now. - DCHECK(debug_info->GetBreakPointCount() > 0); + DCHECK_LT(0, debug_info->GetBreakPointCount()); ClearBreakPoints(debug_info); ApplyBreakPoints(debug_info); @@ -596,7 +593,7 @@ bool Debug::SetBreakPointForScript(Handle<Script> script, // Make sure the function has set up the debug info. Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>::cast(result); if (!EnsureBreakInfo(shared)) return false; - CHECK(PrepareFunctionForBreakPoints(shared)); + PrepareFunctionForBreakPoints(shared); // Find position within function. The script position might be before the // source position of the first function. @@ -610,7 +607,7 @@ bool Debug::SetBreakPointForScript(Handle<Script> script, *source_position = FindBreakablePosition(debug_info, *source_position); DebugInfo::SetBreakPoint(debug_info, *source_position, break_point_object); // At least one active break point now. - DCHECK(debug_info->GetBreakPointCount() > 0); + DCHECK_LT(0, debug_info->GetBreakPointCount()); ClearBreakPoints(debug_info); ApplyBreakPoints(debug_info); @@ -643,8 +640,11 @@ void Debug::ApplyBreakPoints(Handle<DebugInfo> debug_info) { } void Debug::ClearBreakPoints(Handle<DebugInfo> debug_info) { + // If we attempt to clear breakpoints but none exist, simply return. This can + // happen e.g. CoverageInfos exit but no breakpoints are set. + if (!debug_info->HasDebugBytecodeArray()) return; + DisallowHeapAllocation no_gc; - DCHECK(debug_info->HasDebugBytecodeArray()); for (BreakIterator it(debug_info); !it.Done(); it.Next()) { it.ClearDebugBreak(); } @@ -698,7 +698,7 @@ void Debug::FloodWithOneShot(Handle<SharedFunctionInfo> shared, if (IsBlackboxed(shared)) return; // Make sure the function is compiled and has set up the debug info. if (!EnsureBreakInfo(shared)) return; - CHECK(PrepareFunctionForBreakPoints(shared)); + PrepareFunctionForBreakPoints(shared); Handle<DebugInfo> debug_info(shared->GetDebugInfo()); // Flood the function with break points. DCHECK(debug_info->HasDebugBytecodeArray()); @@ -1039,10 +1039,8 @@ class RedirectActiveFunctions : public ThreadVisitor { for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) { JavaScriptFrame* frame = it.frame(); JSFunction* function = frame->function(); - if (frame->is_optimized()) continue; - if (!function->Inlines(shared_)) continue; - - DCHECK(frame->is_interpreted()); + if (!frame->is_interpreted()) continue; + if (function->shared() != shared_) continue; InterpretedFrame* interpreted_frame = reinterpret_cast<InterpretedFrame*>(frame); BytecodeArray* debug_copy = shared_->GetDebugInfo()->DebugBytecodeArray(); @@ -1055,17 +1053,9 @@ class RedirectActiveFunctions : public ThreadVisitor { DisallowHeapAllocation no_gc_; }; - -bool Debug::PrepareFunctionForBreakPoints(Handle<SharedFunctionInfo> shared) { - // To prepare bytecode for debugging, we already need to have the debug - // info (containing the debug copy) upfront, but since we do not recompile, - // preparing for break points cannot fail. - DCHECK(shared->is_compiled()); - DCHECK(shared->HasDebugInfo()); - DCHECK(shared->HasBreakInfo()); - Handle<DebugInfo> debug_info = GetOrCreateDebugInfo(shared); - if (debug_info->IsPreparedForBreakpoints()) return true; - +void Debug::DeoptimizeFunction(Handle<SharedFunctionInfo> shared) { + // Deoptimize all code compiled from this shared function info including + // inlining. if (isolate_->concurrent_recompilation_enabled()) { isolate_->optimizing_compile_dispatcher()->Flush( OptimizingCompileDispatcher::BlockingBehavior::kBlock); @@ -1075,28 +1065,32 @@ bool Debug::PrepareFunctionForBreakPoints(Handle<SharedFunctionInfo> shared) { isolate_->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask, GarbageCollectionReason::kDebugger); - DCHECK(shared->is_compiled()); - { - // TODO(yangguo): with bytecode, we still walk the heap to find all - // optimized code for the function to deoptimize. We can probably be - // smarter here and avoid the heap walk. - HeapIterator iterator(isolate_->heap()); - HeapObject* obj; - - while ((obj = iterator.next()) != nullptr) { - if (obj->IsJSFunction()) { - JSFunction* function = JSFunction::cast(obj); - if (!function->Inlines(*shared)) continue; - if (function->has_feedback_vector()) { - function->ClearOptimizedCodeSlot("Prepare for breakpoints"); - } - if (function->code()->kind() == Code::OPTIMIZED_FUNCTION) { - Deoptimizer::DeoptimizeFunction(function); - } - } + bool found_something = false; + Code::OptimizedCodeIterator iterator(isolate_); + while (Code* code = iterator.Next()) { + if (code->Inlines(*shared)) { + code->set_marked_for_deoptimization(true); + found_something = true; } } + if (found_something) { + // Only go through with the deoptimization if something was found. + Deoptimizer::DeoptimizeMarkedCode(isolate_); + } +} + +void Debug::PrepareFunctionForBreakPoints(Handle<SharedFunctionInfo> shared) { + // To prepare bytecode for debugging, we already need to have the debug + // info (containing the debug copy) upfront, but since we do not recompile, + // preparing for break points cannot fail. + DCHECK(shared->is_compiled()); + DCHECK(shared->HasDebugInfo()); + DCHECK(shared->HasBreakInfo()); + Handle<DebugInfo> debug_info = GetOrCreateDebugInfo(shared); + if (debug_info->IsPreparedForBreakpoints()) return; + + DeoptimizeFunction(shared); // Update PCs on the stack to point to recompiled code. RedirectActiveFunctions redirect_visitor(*shared); redirect_visitor.VisitThread(isolate_, isolate_->thread_local_top()); @@ -1104,7 +1098,6 @@ bool Debug::PrepareFunctionForBreakPoints(Handle<SharedFunctionInfo> shared) { debug_info->set_flags(debug_info->flags() | DebugInfo::kPreparedForBreakpoints); - return true; } namespace { @@ -1351,7 +1344,6 @@ Handle<DebugInfo> Debug::GetOrCreateDebugInfo( void Debug::InstallCoverageInfo(Handle<SharedFunctionInfo> shared, Handle<CoverageInfo> coverage_info) { - DCHECK(FLAG_block_coverage); DCHECK(!coverage_info.is_null()); Handle<DebugInfo> debug_info = GetOrCreateDebugInfo(shared); @@ -1363,7 +1355,6 @@ void Debug::InstallCoverageInfo(Handle<SharedFunctionInfo> shared, } void Debug::RemoveAllCoverageInfos() { - DCHECK(FLAG_block_coverage); ClearAllDebugInfos( [=](Handle<DebugInfo> info) { return info->ClearCoverageInfo(); }); } @@ -1895,6 +1886,7 @@ void Debug::ProcessCompileEvent(v8::DebugEvent event, Handle<Script> script) { HandleScope scope(isolate_); PostponeInterruptsScope postpone(isolate_); DisableBreak no_recursive_break(this); + AllowJavascriptExecution allow_script(isolate_); debug_delegate_->ScriptCompiled(ToApiHandle<debug::Script>(script), live_edit_enabled(), event != v8::AfterCompile); diff --git a/chromium/v8/src/debug/debug.h b/chromium/v8/src/debug/debug.h index 9601fa7899f..154c3817294 100644 --- a/chromium/v8/src/debug/debug.h +++ b/chromium/v8/src/debug/debug.h @@ -5,6 +5,8 @@ #ifndef V8_DEBUG_DEBUG_H_ #define V8_DEBUG_DEBUG_H_ +#include <vector> + #include "src/allocation.h" #include "src/assembler.h" #include "src/base/atomicops.h" @@ -70,7 +72,7 @@ class BreakLocation { static void AllAtCurrentStatement(Handle<DebugInfo> debug_info, JavaScriptFrame* frame, - List<BreakLocation>* result_out); + std::vector<BreakLocation>* result_out); inline bool IsReturn() const { return type_ == DEBUG_BREAK_SLOT_AT_RETURN; } inline bool IsCall() const { return type_ == DEBUG_BREAK_SLOT_AT_CALL; } @@ -250,7 +252,8 @@ class Debug { void ClearStepping(); void ClearStepOut(); - bool PrepareFunctionForBreakPoints(Handle<SharedFunctionInfo> shared); + void DeoptimizeFunction(Handle<SharedFunctionInfo> shared); + void PrepareFunctionForBreakPoints(Handle<SharedFunctionInfo> shared); bool GetPossibleBreakpoints(Handle<Script> script, int start_position, int end_position, bool restrict_to_function, std::vector<BreakLocation>* locations); diff --git a/chromium/v8/src/debug/liveedit.cc b/chromium/v8/src/debug/liveedit.cc index ac5229b4197..e20e56cd75b 100644 --- a/chromium/v8/src/debug/liveedit.cc +++ b/chromium/v8/src/debug/liveedit.cc @@ -163,7 +163,7 @@ class Differencer { // Each cell keeps a value plus direction. Value is multiplied by 4. void set_value4_and_dir(int i1, int i2, int value4, Direction dir) { - DCHECK((value4 & kDirectionMask) == 0); + DCHECK_EQ(0, value4 & kDirectionMask); get_cell(i1, i2) = value4 | dir; } @@ -806,41 +806,6 @@ class FeedbackVectorFixer { }; -// Marks code that shares the same shared function info or has inlined -// code that shares the same function info. -class DependentFunctionMarker: public OptimizedFunctionVisitor { - public: - SharedFunctionInfo* shared_info_; - bool found_; - - explicit DependentFunctionMarker(SharedFunctionInfo* shared_info) - : shared_info_(shared_info), found_(false) { } - - virtual void VisitFunction(JSFunction* function) { - // It should be guaranteed by the iterator that everything is optimized. - DCHECK(function->code()->kind() == Code::OPTIMIZED_FUNCTION); - if (function->Inlines(shared_info_)) { - // Mark the code for deoptimization. - function->code()->set_marked_for_deoptimization(true); - found_ = true; - } - } -}; - - -static void DeoptimizeDependentFunctions(SharedFunctionInfo* function_info) { - DisallowHeapAllocation no_allocation; - DependentFunctionMarker marker(function_info); - // TODO(titzer): need to traverse all optimized code to find OSR code here. - Deoptimizer::VisitAllOptimizedFunctions(function_info->GetIsolate(), &marker); - - if (marker.found_) { - // Only go through with the deoptimization if something was found. - Deoptimizer::DeoptimizeMarkedCode(function_info->GetIsolate()); - } -} - - void LiveEdit::ReplaceFunctionCode( Handle<JSArray> new_compile_info_array, Handle<JSArray> shared_info_array) { @@ -889,8 +854,7 @@ void LiveEdit::ReplaceFunctionCode( FeedbackVectorFixer::PatchFeedbackVector(&compile_info_wrapper, shared_info, isolate); - DeoptimizeDependentFunctions(*shared_info); - isolate->compilation_cache()->Remove(shared_info); + isolate->debug()->DeoptimizeFunction(shared_info); } void LiveEdit::FunctionSourceUpdated(Handle<JSArray> shared_info_array, @@ -899,8 +863,7 @@ void LiveEdit::FunctionSourceUpdated(Handle<JSArray> shared_info_array, Handle<SharedFunctionInfo> shared_info = shared_info_wrapper.GetInfo(); shared_info->set_function_literal_id(new_function_literal_id); - DeoptimizeDependentFunctions(*shared_info); - shared_info_array->GetIsolate()->compilation_cache()->Remove(shared_info); + shared_info_array->GetIsolate()->debug()->DeoptimizeFunction(shared_info); } void LiveEdit::FixupScript(Handle<Script> script, int max_function_literal_id) { @@ -1022,11 +985,6 @@ void LiveEdit::PatchFunctionPositions(Handle<JSArray> shared_info_array, Handle<AbstractCode>(AbstractCode::cast(info->bytecode_array())), position_change_array); } - if (info->code()->kind() == Code::FUNCTION) { - TranslateSourcePositionTable( - Handle<AbstractCode>(AbstractCode::cast(info->code())), - position_change_array); - } if (info->HasBreakInfo()) { // Existing break points will be re-applied. Reset the debug info here. info->GetIsolate()->debug()->RemoveBreakInfoAndMaybeFree( @@ -1126,7 +1084,9 @@ static bool CheckActivation(Handle<JSArray> shared_info_array, Handle<SharedFunctionInfo> shared = UnwrapSharedFunctionInfoFromJSValue(jsvalue); - if (function->Inlines(*shared)) { + if (function->shared() == *shared || + (function->code()->is_optimized_code() && + function->code()->Inlines(*shared))) { SetElementSloppy(result, i, Handle<Smi>(Smi::FromInt(status), isolate)); return true; } |