summaryrefslogtreecommitdiff
path: root/chromium/v8/src/debug
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2017-11-20 15:06:40 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2017-11-22 11:48:58 +0000
commitdaa093eea7c773db06799a13bd7e4e2e2a9f8f14 (patch)
tree96cc5e7b9194c1b29eab927730bfa419e7111c25 /chromium/v8/src/debug
parentbe59a35641616a4cf23c4a13fa0632624b021c1b (diff)
downloadqtwebengine-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.cc31
-rw-r--r--chromium/v8/src/debug/debug-coverage.h8
-rw-r--r--chromium/v8/src/debug/debug-evaluate.cc86
-rw-r--r--chromium/v8/src/debug/debug-evaluate.h9
-rw-r--r--chromium/v8/src/debug/debug-frames.cc37
-rw-r--r--chromium/v8/src/debug/debug-frames.h6
-rw-r--r--chromium/v8/src/debug/debug-interface.h97
-rw-r--r--chromium/v8/src/debug/debug-scope-iterator.cc13
-rw-r--r--chromium/v8/src/debug/debug-scopes.cc25
-rw-r--r--chromium/v8/src/debug/debug-scopes.h4
-rw-r--r--chromium/v8/src/debug/debug-stack-trace-iterator.cc1
-rw-r--r--chromium/v8/src/debug/debug-type-profile.cc102
-rw-r--r--chromium/v8/src/debug/debug-type-profile.h45
-rw-r--r--chromium/v8/src/debug/debug.cc106
-rw-r--r--chromium/v8/src/debug/debug.h7
-rw-r--r--chromium/v8/src/debug/liveedit.cc52
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;
}