Commit 54271c21 authored by kozyatinskiy's avatar kozyatinskiy Committed by Commit bot

[inspector] move console to builtins

What will we get:
- console would be included into snapshot and allow us to reduce time that we spent in contextCreated function (~5 times faster),
- it allows us to make further small improvement of console methods, e.g. we can implement super quick return from console.assert if first argument is true,
- console calls are ~ 15% faster.

CQ_INCLUDE_TRYBOTS=master.tryserver.blink:linux_trusty_blink_rel;master.tryserver.chromium.linux:linux_chromium_rel_ng

BUG=v8:6175
R=dgozman@chromium.org

Review-Url: https://codereview.chromium.org/2785293002
Cr-Original-Original-Original-Commit-Position: refs/heads/master@{#44353}
Committed: https://chromium.googlesource.com/v8/v8/+/55905f85d63d75aaa9313e51eb7bede754a8e41c
Review-Url: https://codereview.chromium.org/2785293002
Cr-Original-Original-Commit-Position: refs/heads/master@{#44355}
Committed: https://chromium.googlesource.com/v8/v8/+/cc74ea0bc4fe4a71fa53d08b62cc18d15e01fbb3
Review-Url: https://codereview.chromium.org/2785293002
Cr-Original-Commit-Position: refs/heads/master@{#44416}
Committed: https://chromium.googlesource.com/v8/v8/+/f5dc738cda0336929dcb8eb73b87fdcd01b7c685
Review-Url: https://codereview.chromium.org/2785293002
Cr-Commit-Position: refs/heads/master@{#44702}
parent 59710233
......@@ -1115,6 +1115,7 @@ v8_source_set("v8_base") {
"src/builtins/builtins-boolean.cc",
"src/builtins/builtins-call.cc",
"src/builtins/builtins-callsite.cc",
"src/builtins/builtins-console.cc",
"src/builtins/builtins-constructor.h",
"src/builtins/builtins-dataview.cc",
"src/builtins/builtins-date.cc",
......
......@@ -150,6 +150,9 @@ class FunctionCallbackArguments;
class GlobalHandles;
} // namespace internal
namespace debug {
class ConsoleCallArguments;
} // namespace debug
// --- Handles ---
......@@ -3602,6 +3605,7 @@ class FunctionCallbackInfo {
protected:
friend class internal::FunctionCallbackArguments;
friend class internal::CustomArguments<FunctionCallbackInfo>;
friend class debug::ConsoleCallArguments;
static const int kHolderIndex = 0;
static const int kIsolateIndex = 1;
static const int kReturnValueDefaultValueIndex = 2;
......
......@@ -25,6 +25,7 @@
#include "src/base/safe_conversions.h"
#include "src/base/utils/random-number-generator.h"
#include "src/bootstrapper.h"
#include "src/builtins/builtins-utils.h"
#include "src/char-predicates-inl.h"
#include "src/code-stubs.h"
#include "src/compiler-dispatcher/compiler-dispatcher.h"
......@@ -9671,6 +9672,22 @@ Local<Function> debug::GetBuiltin(Isolate* v8_isolate, Builtin builtin) {
return Utils::ToLocal(handle_scope.CloseAndEscape(fun));
}
void debug::SetConsoleDelegate(Isolate* v8_isolate, ConsoleDelegate* delegate) {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
ENTER_V8(isolate);
isolate->set_console_delegate(delegate);
}
debug::ConsoleCallArguments::ConsoleCallArguments(
const v8::FunctionCallbackInfo<v8::Value>& info)
: v8::FunctionCallbackInfo<v8::Value>(nullptr, info.values_, info.length_) {
}
debug::ConsoleCallArguments::ConsoleCallArguments(
internal::BuiltinArguments& args)
: v8::FunctionCallbackInfo<v8::Value>(nullptr, &args[0] - 1,
args.length() - 1) {}
MaybeLocal<debug::Script> debug::GeneratorObject::Script() {
i::Handle<i::JSGeneratorObject> obj = Utils::OpenHandle(this);
i::Object* maybe_script = obj->function()->shared()->script();
......
......@@ -2558,6 +2558,54 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY));
}
{ // -- C o n s o l e
Handle<String> name = factory->InternalizeUtf8String("console");
Handle<JSFunction> cons = factory->NewFunction(name);
Handle<JSObject> empty = factory->NewJSObject(isolate->object_function());
JSFunction::SetInstancePrototype(cons, empty);
Handle<JSObject> console = factory->NewJSObject(cons, TENURED);
DCHECK(console->IsJSObject());
JSObject::AddProperty(global, name, console, DONT_ENUM);
SimpleInstallFunction(console, "debug", Builtins::kConsoleDebug, 1, false);
SimpleInstallFunction(console, "error", Builtins::kConsoleError, 1, false);
SimpleInstallFunction(console, "info", Builtins::kConsoleInfo, 1, false);
SimpleInstallFunction(console, "log", Builtins::kConsoleLog, 1, false);
SimpleInstallFunction(console, "warn", Builtins::kConsoleWarn, 1, false);
SimpleInstallFunction(console, "dir", Builtins::kConsoleDir, 1, false);
SimpleInstallFunction(console, "dirxml", Builtins::kConsoleDirXml, 1,
false);
SimpleInstallFunction(console, "table", Builtins::kConsoleTable, 1, false);
SimpleInstallFunction(console, "trace", Builtins::kConsoleTrace, 1, false);
SimpleInstallFunction(console, "group", Builtins::kConsoleGroup, 1, false);
SimpleInstallFunction(console, "groupCollapsed",
Builtins::kConsoleGroupCollapsed, 1, false);
SimpleInstallFunction(console, "groupEnd", Builtins::kConsoleGroupEnd, 1,
false);
SimpleInstallFunction(console, "clear", Builtins::kConsoleClear, 1, false);
SimpleInstallFunction(console, "count", Builtins::kConsoleCount, 1, false);
SimpleInstallFunction(console, "assert", Builtins::kConsoleAssert, 1,
false);
SimpleInstallFunction(console, "markTimeline",
Builtins::kConsoleMarkTimeline, 1, false);
SimpleInstallFunction(console, "profile", Builtins::kConsoleProfile, 1,
false);
SimpleInstallFunction(console, "profileEnd", Builtins::kConsoleProfileEnd,
1, false);
SimpleInstallFunction(console, "timeline", Builtins::kConsoleTimeline, 1,
false);
SimpleInstallFunction(console, "timelineEnd", Builtins::kConsoleTimelineEnd,
1, false);
SimpleInstallFunction(console, "time", Builtins::kConsoleTime, 1, false);
SimpleInstallFunction(console, "timeEnd", Builtins::kConsoleTimeEnd, 1,
false);
SimpleInstallFunction(console, "timeStamp", Builtins::kConsoleTimeStamp, 1,
false);
JSObject::AddProperty(
console, factory->to_string_tag_symbol(),
factory->NewStringFromAsciiChecked("Object"),
static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY));
}
#ifdef V8_I18N_SUPPORT
{ // -- I n t l
Handle<String> name = factory->InternalizeUtf8String("Intl");
......
// 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/builtins/builtins-utils.h"
#include "src/builtins/builtins.h"
#include "src/debug/interface-types.h"
#include "src/objects-inl.h"
namespace v8 {
namespace internal {
// -----------------------------------------------------------------------------
// Console
#define CONSOLE_METHOD_LIST(V) \
V(Debug) \
V(Error) \
V(Info) \
V(Log) \
V(Warn) \
V(Dir) \
V(DirXml) \
V(Table) \
V(Trace) \
V(Group) \
V(GroupCollapsed) \
V(GroupEnd) \
V(Clear) \
V(Count) \
V(Assert) \
V(MarkTimeline) \
V(Profile) \
V(ProfileEnd) \
V(Timeline) \
V(TimelineEnd) \
V(Time) \
V(TimeEnd) \
V(TimeStamp)
#define CONSOLE_BUILTIN_IMPLEMENTATION(name) \
BUILTIN(Console##name) { \
HandleScope scope(isolate); \
if (isolate->console_delegate()) { \
debug::ConsoleCallArguments wrapper(args); \
isolate->console_delegate()->name(wrapper); \
} \
return isolate->heap()->undefined_value(); \
}
CONSOLE_METHOD_LIST(CONSOLE_BUILTIN_IMPLEMENTATION)
#undef CONSOLE_BUILTIN_IMPLEMENTATION
#undef CONSOLE_METHOD_LIST
} // namespace internal
} // namespace v8
......@@ -345,6 +345,31 @@ namespace internal {
CPP(CallSitePrototypeIsToplevel) \
CPP(CallSitePrototypeToString) \
\
/* Console */ \
CPP(ConsoleDebug) \
CPP(ConsoleError) \
CPP(ConsoleInfo) \
CPP(ConsoleLog) \
CPP(ConsoleWarn) \
CPP(ConsoleDir) \
CPP(ConsoleDirXml) \
CPP(ConsoleTable) \
CPP(ConsoleTrace) \
CPP(ConsoleGroup) \
CPP(ConsoleGroupCollapsed) \
CPP(ConsoleGroupEnd) \
CPP(ConsoleClear) \
CPP(ConsoleCount) \
CPP(ConsoleAssert) \
CPP(ConsoleMarkTimeline) \
CPP(ConsoleProfile) \
CPP(ConsoleProfileEnd) \
CPP(ConsoleTimeline) \
CPP(ConsoleTimelineEnd) \
CPP(ConsoleTime) \
CPP(ConsoleTimeEnd) \
CPP(ConsoleTimeStamp) \
\
/* DataView */ \
CPP(DataViewConstructor) \
CPP(DataViewConstructor_ConstructStub) \
......
......@@ -209,6 +209,8 @@ enum Builtin {
Local<Function> GetBuiltin(Isolate* isolate, Builtin builtin);
void SetConsoleDelegate(Isolate* isolate, ConsoleDelegate* delegate);
/**
* Native wrapper around v8::internal::JSGeneratorObject object.
*/
......
......@@ -9,9 +9,15 @@
#include <string>
#include <vector>
#include "include/v8.h"
#include "src/globals.h"
namespace v8 {
namespace internal {
class BuiltinArguments;
} // internal
namespace debug {
/**
......@@ -90,6 +96,47 @@ class V8_EXPORT_PRIVATE BreakLocation : public Location {
BreakLocationType type_;
};
class ConsoleCallArguments : private v8::FunctionCallbackInfo<v8::Value> {
public:
int Length() const { return v8::FunctionCallbackInfo<v8::Value>::Length(); }
V8_INLINE Local<Value> operator[](int i) const {
return v8::FunctionCallbackInfo<v8::Value>::operator[](i);
}
explicit ConsoleCallArguments(const v8::FunctionCallbackInfo<v8::Value>&);
explicit ConsoleCallArguments(internal::BuiltinArguments&);
};
// v8::FunctionCallbackInfo could be used for getting arguments only. Calling
// of any other getter will produce a crash.
class ConsoleDelegate {
public:
virtual void Debug(const ConsoleCallArguments& args) {}
virtual void Error(const ConsoleCallArguments& args) {}
virtual void Info(const ConsoleCallArguments& args) {}
virtual void Log(const ConsoleCallArguments& args) {}
virtual void Warn(const ConsoleCallArguments& args) {}
virtual void Dir(const ConsoleCallArguments& args) {}
virtual void DirXml(const ConsoleCallArguments& args) {}
virtual void Table(const ConsoleCallArguments& args) {}
virtual void Trace(const ConsoleCallArguments& args) {}
virtual void Group(const ConsoleCallArguments& args) {}
virtual void GroupCollapsed(const ConsoleCallArguments& args) {}
virtual void GroupEnd(const ConsoleCallArguments& args) {}
virtual void Clear(const ConsoleCallArguments& args) {}
virtual void Count(const ConsoleCallArguments& args) {}
virtual void Assert(const ConsoleCallArguments& args) {}
virtual void MarkTimeline(const ConsoleCallArguments& args) {}
virtual void Profile(const ConsoleCallArguments& args) {}
virtual void ProfileEnd(const ConsoleCallArguments& args) {}
virtual void Timeline(const ConsoleCallArguments& args) {}
virtual void TimelineEnd(const ConsoleCallArguments& args) {}
virtual void Time(const ConsoleCallArguments& args) {}
virtual void TimeEnd(const ConsoleCallArguments& args) {}
virtual void TimeStamp(const ConsoleCallArguments& args) {}
virtual ~ConsoleDelegate() = default;
};
} // namespace debug
} // namespace v8
......
......@@ -25,19 +25,16 @@ InspectedContext::InspectedContext(V8InspectorImpl* inspector,
m_humanReadableName(toString16(info.humanReadableName)),
m_auxData(toString16(info.auxData)),
m_reported(false) {
v8::Isolate* isolate = m_inspector->isolate();
v8::debug::SetContextId(info.context, contextId);
if (!info.hasMemoryOnConsole) return;
v8::Context::Scope contextScope(info.context);
v8::Local<v8::Object> global = info.context->Global();
v8::Local<v8::Object> console =
m_inspector->console()->createConsole(info.context);
if (info.hasMemoryOnConsole) {
m_inspector->console()->installMemoryGetter(info.context, console);
}
if (!global
->Set(info.context, toV8StringInternalized(isolate, "console"),
console)
.FromMaybe(false)) {
return;
v8::Local<v8::Value> console;
if (global->Get(info.context, toV8String(m_inspector->isolate(), "console"))
.ToLocal(&console) &&
console->IsObject()) {
m_inspector->console()->installMemoryGetter(
info.context, v8::Local<v8::Object>::Cast(console));
}
}
......
This diff is collapsed.
......@@ -8,6 +8,7 @@
#include "src/base/macros.h"
#include "include/v8.h"
#include "src/debug/interface-types.h"
namespace v8_inspector {
......@@ -16,9 +17,8 @@ class V8InspectorImpl;
// Console API
// https://console.spec.whatwg.org/#console-interface
class V8Console {
class V8Console : public v8::debug::ConsoleDelegate {
public:
v8::Local<v8::Object> createConsole(v8::Local<v8::Context> context);
v8::Local<v8::Object> createCommandLineAPI(v8::Local<v8::Context> context);
void installMemoryGetter(v8::Local<v8::Context> context,
v8::Local<v8::Object> console);
......@@ -49,29 +49,29 @@ class V8Console {
explicit V8Console(V8InspectorImpl* inspector);
private:
void debugCallback(const v8::FunctionCallbackInfo<v8::Value>&);
void errorCallback(const v8::FunctionCallbackInfo<v8::Value>&);
void infoCallback(const v8::FunctionCallbackInfo<v8::Value>&);
void logCallback(const v8::FunctionCallbackInfo<v8::Value>&);
void warnCallback(const v8::FunctionCallbackInfo<v8::Value>&);
void dirCallback(const v8::FunctionCallbackInfo<v8::Value>&);
void dirxmlCallback(const v8::FunctionCallbackInfo<v8::Value>&);
void tableCallback(const v8::FunctionCallbackInfo<v8::Value>&);
void traceCallback(const v8::FunctionCallbackInfo<v8::Value>&);
void groupCallback(const v8::FunctionCallbackInfo<v8::Value>&);
void groupCollapsedCallback(const v8::FunctionCallbackInfo<v8::Value>&);
void groupEndCallback(const v8::FunctionCallbackInfo<v8::Value>&);
void clearCallback(const v8::FunctionCallbackInfo<v8::Value>&);
void countCallback(const v8::FunctionCallbackInfo<v8::Value>&);
void assertCallback(const v8::FunctionCallbackInfo<v8::Value>&);
void markTimelineCallback(const v8::FunctionCallbackInfo<v8::Value>&);
void profileCallback(const v8::FunctionCallbackInfo<v8::Value>&);
void profileEndCallback(const v8::FunctionCallbackInfo<v8::Value>&);
void timelineCallback(const v8::FunctionCallbackInfo<v8::Value>&);
void timelineEndCallback(const v8::FunctionCallbackInfo<v8::Value>&);
void timeCallback(const v8::FunctionCallbackInfo<v8::Value>&);
void timeEndCallback(const v8::FunctionCallbackInfo<v8::Value>&);
void timeStampCallback(const v8::FunctionCallbackInfo<v8::Value>&);
void Debug(const v8::debug::ConsoleCallArguments&) override;
void Error(const v8::debug::ConsoleCallArguments&) override;
void Info(const v8::debug::ConsoleCallArguments&) override;
void Log(const v8::debug::ConsoleCallArguments&) override;
void Warn(const v8::debug::ConsoleCallArguments&) override;
void Dir(const v8::debug::ConsoleCallArguments&) override;
void DirXml(const v8::debug::ConsoleCallArguments&) override;
void Table(const v8::debug::ConsoleCallArguments&) override;
void Trace(const v8::debug::ConsoleCallArguments&) override;
void Group(const v8::debug::ConsoleCallArguments&) override;
void GroupCollapsed(const v8::debug::ConsoleCallArguments&) override;
void GroupEnd(const v8::debug::ConsoleCallArguments&) override;
void Clear(const v8::debug::ConsoleCallArguments&) override;
void Count(const v8::debug::ConsoleCallArguments&) override;
void Assert(const v8::debug::ConsoleCallArguments&) override;
void MarkTimeline(const v8::debug::ConsoleCallArguments&) override;
void Profile(const v8::debug::ConsoleCallArguments&) override;
void ProfileEnd(const v8::debug::ConsoleCallArguments&) override;
void Timeline(const v8::debug::ConsoleCallArguments&) override;
void TimelineEnd(const v8::debug::ConsoleCallArguments&) override;
void Time(const v8::debug::ConsoleCallArguments&) override;
void TimeEnd(const v8::debug::ConsoleCallArguments&) override;
void TimeStamp(const v8::debug::ConsoleCallArguments&) override;
template <void (V8Console::*func)(const v8::FunctionCallbackInfo<v8::Value>&)>
static void call(const v8::FunctionCallbackInfo<v8::Value>& info) {
......@@ -79,6 +79,13 @@ class V8Console {
static_cast<V8Console*>(info.Data().As<v8::External>()->Value());
(console->*func)(info);
}
template <void (V8Console::*func)(const v8::debug::ConsoleCallArguments&)>
static void call(const v8::FunctionCallbackInfo<v8::Value>& info) {
V8Console* console =
static_cast<V8Console*>(info.Data().As<v8::External>()->Value());
v8::debug::ConsoleCallArguments args(info);
(console->*func)(args);
}
// TODO(foolip): There is no spec for the Memory Info API, see blink-dev:
// https://groups.google.com/a/chromium.org/d/msg/blink-dev/g5YRCGpC9vs/b4OJz71NmPwJ
......
......@@ -56,9 +56,13 @@ V8InspectorImpl::V8InspectorImpl(v8::Isolate* isolate,
m_debugger(new V8Debugger(isolate, this)),
m_capturingStackTracesCount(0),
m_lastExceptionId(0),
m_lastContextId(0) {}
m_lastContextId(0) {
v8::debug::SetConsoleDelegate(m_isolate, console());
}
V8InspectorImpl::~V8InspectorImpl() {}
V8InspectorImpl::~V8InspectorImpl() {
v8::debug::SetConsoleDelegate(m_isolate, nullptr);
}
int V8InspectorImpl::contextGroupId(v8::Local<v8::Context> context) {
return contextGroupId(InspectedContext::contextId(context));
......
......@@ -34,6 +34,10 @@ namespace base {
class RandomNumberGenerator;
}
namespace debug {
class ConsoleDelegate;
}
namespace internal {
class AccessCompilerData;
......@@ -749,6 +753,11 @@ class Isolate {
return MaybeHandle<T>();
}
void set_console_delegate(debug::ConsoleDelegate* delegate) {
console_delegate_ = delegate;
}
debug::ConsoleDelegate* console_delegate() { return console_delegate_; }
// Re-throw an exception. This involves no error reporting since error
// reporting was handled when the exception was thrown originally.
Object* ReThrow(Object* exception);
......@@ -1552,6 +1561,8 @@ class Isolate {
CancelableTaskManager* cancelable_task_manager_;
debug::ConsoleDelegate* console_delegate_ = nullptr;
v8::Isolate::AbortOnUncaughtExceptionCallback
abort_on_uncaught_exception_callback_;
......
......@@ -486,6 +486,7 @@
'builtins/builtins-call.cc',
'builtins/builtins-call-gen.cc',
'builtins/builtins-callsite.cc',
'builtins/builtins-console.cc',
'builtins/builtins-constructor-gen.cc',
'builtins/builtins-constructor-gen.h',
'builtins/builtins-constructor.h',
......
......@@ -226,6 +226,7 @@ void InspectorClientImpl::disconnect() {
states_[it.first] = it.second->stateJSON();
}
sessions_.clear();
inspector_.reset();
}
void InspectorClientImpl::scheduleCreateContextGroup(
......
Running test: consoleExistsOnGlobal
true
Running test: consoleHasRightPropertyDescriptor
{
configurable : true
enumerable : false
value : <value>
writable : true
}
Running test: ConsoleNotExistsOnGlobal
false
Running test: prototypeChainMustBeCorrect
true
Running test: consoleToString
[object Object]
// 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.
InspectorTest.addScript(`
var self = this;
function checkPrototype() {
const prototype1 = Object.getPrototypeOf(console);
const prototype2 = Object.getPrototypeOf(prototype1);
if (Object.getOwnPropertyNames(prototype1).length !== 0)
return "false: The [[Prototype]] must have no properties";
if (prototype2 !== Object.prototype)
return "false: The [[Prototype]]'s [[Prototype]] must be %ObjectPrototype%";
return "true";
}
`);
InspectorTest.runAsyncTestSuite([
async function consoleExistsOnGlobal() {
let message = await Protocol.Runtime.evaluate({
expression: 'self.hasOwnProperty(\'console\')', returnByValue: true});
InspectorTest.log(message.result.result.value);
},
async function consoleHasRightPropertyDescriptor() {
let message = await Protocol.Runtime.evaluate({
expression: 'Object.getOwnPropertyDescriptor(self, \'console\')',
returnByValue: true});
let result = message.result.result.value;
result.value = '<value>';
InspectorTest.logObject(result);
},
async function ConsoleNotExistsOnGlobal() {
let message = await Protocol.Runtime.evaluate({
expression: '\'Console\' in self', returnByValue: true})
InspectorTest.log(message.result.result.value);
},
async function prototypeChainMustBeCorrect() {
let message = await Protocol.Runtime.evaluate({
expression: "checkPrototype()", returnByValue: true });
InspectorTest.log(message.result.result.value);
},
async function consoleToString() {
let message = await Protocol.Runtime.evaluate({
expression: 'console.toString()', returnByValue: true})
InspectorTest.log(message.result.result.value);
}
]);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment