Commit 5df7d689 authored by yangguo's avatar yangguo Committed by Commit bot

Debugger: load debugger builtins as normal native JS.

R=jkummerow@chromium.org

Review URL: https://codereview.chromium.org/1282793002

Cr-Commit-Position: refs/heads/master@{#30136}
parent 88f90680
......@@ -230,8 +230,8 @@ action("js2c") {
"src/templates.js",
"src/harmony-array.js",
"src/harmony-typedarray.js",
"src/debug/debug.js",
"src/debug/mirrors.js",
"src/debug/debug.js",
"src/debug/liveedit.js",
]
......
......@@ -239,6 +239,7 @@ class Genesis BASE_EMBEDDED {
Handle<JSFunction>* fun);
bool InstallExperimentalNatives();
bool InstallExtraNatives();
bool InstallDebuggerNatives();
void InstallBuiltinFunctionIds();
void InstallExperimentalBuiltinFunctionIds();
void InitializeNormalizedMapCaches();
......@@ -354,7 +355,7 @@ Handle<Context> Bootstrapper::CreateEnvironment(
extensions, context_type);
Handle<Context> env = genesis.result();
if (env.is_null() ||
(context_type == FULL_CONTEXT && !InstallExtensions(env, extensions))) {
(context_type != THIN_CONTEXT && !InstallExtensions(env, extensions))) {
return Handle<Context>();
}
return scope.CloseAndEscape(env);
......@@ -2622,6 +2623,14 @@ bool Genesis::InstallExtraNatives() {
}
bool Genesis::InstallDebuggerNatives() {
for (int i = 0; i < Natives::GetDebuggerCount(); ++i) {
if (!Bootstrapper::CompileBuiltin(isolate(), i)) return false;
}
return CallUtilsFunction(isolate(), "PostDebug");
}
bool Bootstrapper::InstallCodeStubNatives(Isolate* isolate) {
for (int i = CodeStubNatives::GetDebuggerCount();
i < CodeStubNatives::GetBuiltinsCount(); i++) {
......@@ -2723,9 +2732,6 @@ bool Genesis::InstallSpecialObjects(Handle<Context> native_context) {
Handle<Smi> stack_trace_limit(Smi::FromInt(FLAG_stack_trace_limit), isolate);
JSObject::AddProperty(Error, name, stack_trace_limit, NONE);
// By now the utils object is useless and can be removed.
native_context->set_natives_utils_object(*factory->undefined_value());
// Expose the natives in global if a name for it is specified.
if (FLAG_expose_natives_as != NULL && strlen(FLAG_expose_natives_as) != 0) {
Handle<String> natives_key =
......@@ -3215,7 +3221,7 @@ Genesis::Genesis(Isolate* isolate,
MakeFunctionInstancePrototypeWritable();
if (context_type == FULL_CONTEXT) {
if (context_type != THIN_CONTEXT) {
if (!ConfigureGlobalObjects(global_proxy_template)) return;
}
isolate->counters()->contexts_created_from_scratch()->Increment();
......@@ -3229,11 +3235,18 @@ Genesis::Genesis(Isolate* isolate,
InitializeExperimentalGlobal();
if (!InstallExperimentalNatives()) return;
if (!InstallExtraNatives()) return;
// By now the utils object is useless and can be removed.
native_context()->set_natives_utils_object(
isolate->heap()->undefined_value());
}
// The serializer cannot serialize typed arrays. Reset those typed arrays
// for each new context.
InitializeBuiltinTypedArrays();
} else if (context_type == DEBUG_CONTEXT) {
DCHECK(!isolate->serializer_enabled());
InitializeExperimentalGlobal();
if (!InstallDebuggerNatives()) return;
}
result_ = native_context();
......
......@@ -61,7 +61,7 @@ class SourceCodeCache final BASE_EMBEDDED {
DISALLOW_COPY_AND_ASSIGN(SourceCodeCache);
};
enum ContextType { FULL_CONTEXT, THIN_CONTEXT };
enum ContextType { FULL_CONTEXT, THIN_CONTEXT, DEBUG_CONTEXT };
// The Boostrapper is the public interface for creating a JavaScript global
// context.
......
......@@ -15,12 +15,8 @@
namespace v8 {
namespace internal {
static inline bool IsDebugContext(Isolate* isolate, Context* context) {
// Try to unwrap script context if it exist.
if (context->IsScriptContext()) context = context->previous();
DCHECK_NOT_NULL(context);
return context == *isolate->debug()->debug_context();
return context->native_context() == *isolate->debug()->debug_context();
}
......
......@@ -429,62 +429,6 @@ DebugInfoListNode::~DebugInfoListNode() {
}
bool Debug::CompileDebuggerScript(Isolate* isolate, int index) {
Factory* factory = isolate->factory();
HandleScope scope(isolate);
// Bail out if the index is invalid.
if (index == -1) return false;
// Find source and name for the requested script.
Handle<String> source_code =
isolate->bootstrapper()->SourceLookup<Natives>(index);
Vector<const char> name = Natives::GetScriptName(index);
Handle<String> script_name =
factory->NewStringFromAscii(name).ToHandleChecked();
Handle<Context> context = isolate->native_context();
// Compile the script.
Handle<SharedFunctionInfo> function_info;
function_info = Compiler::CompileScript(
source_code, script_name, 0, 0, ScriptOriginOptions(), Handle<Object>(),
context, NULL, NULL, ScriptCompiler::kNoCompileOptions, NATIVES_CODE,
false);
if (function_info.is_null()) return false;
// Execute the shared function in the debugger context.
Handle<JSFunction> function =
factory->NewFunctionFromSharedFunctionInfo(function_info, context);
MaybeHandle<Object> maybe_exception;
MaybeHandle<Object> result = Execution::TryCall(
function, handle(context->global_proxy()), 0, NULL, &maybe_exception);
// Check for caught exceptions.
if (result.is_null()) {
DCHECK(!isolate->has_pending_exception());
MessageLocation computed_location;
isolate->ComputeLocation(&computed_location);
Handle<JSMessageObject> message = MessageHandler::MakeMessageObject(
isolate, MessageTemplate::kDebuggerLoading, &computed_location,
isolate->factory()->undefined_value(), Handle<JSArray>());
DCHECK(!isolate->has_pending_exception());
Handle<Object> exception;
if (maybe_exception.ToHandle(&exception)) {
isolate->set_pending_exception(*exception);
MessageHandler::ReportMessage(isolate, NULL, message);
}
DCHECK(!maybe_exception.is_null());
return false;
}
// Mark this script as native and return successfully.
Handle<Script> script(Script::cast(function->shared()->script()));
script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
return true;
}
bool Debug::Load() {
// Return if debugger is already loaded.
if (is_loaded()) return true;
......@@ -503,38 +447,12 @@ bool Debug::Load() {
HandleScope scope(isolate_);
ExtensionConfiguration no_extensions;
Handle<Context> context = isolate_->bootstrapper()->CreateEnvironment(
MaybeHandle<JSGlobalProxy>(), v8::Local<ObjectTemplate>(),
&no_extensions);
MaybeHandle<JSGlobalProxy>(), v8::Local<ObjectTemplate>(), &no_extensions,
DEBUG_CONTEXT);
// Fail if no context could be created.
if (context.is_null()) return false;
// Use the debugger context.
SaveContext save(isolate_);
isolate_->set_context(*context);
// Expose the builtins object in the debugger context.
Handle<String> key = isolate_->factory()->InternalizeOneByteString(
STATIC_CHAR_VECTOR("builtins"));
Handle<GlobalObject> global =
Handle<GlobalObject>(context->global_object(), isolate_);
Handle<JSBuiltinsObject> builtin =
Handle<JSBuiltinsObject>(global->builtins(), isolate_);
RETURN_ON_EXCEPTION_VALUE(
isolate_, Object::SetProperty(global, key, builtin, SLOPPY), false);
// Compile the JavaScript for the debugger in the debugger context.
bool caught_exception =
!CompileDebuggerScript(isolate_, Natives::GetIndex("mirrors")) ||
!CompileDebuggerScript(isolate_, Natives::GetIndex("debug"));
if (FLAG_enable_liveedit) {
caught_exception = caught_exception ||
!CompileDebuggerScript(isolate_, Natives::GetIndex("liveedit"));
}
// Check for caught exceptions.
if (caught_exception) return false;
debug_context_ = Handle<Context>::cast(
isolate_->global_handles()->Create(*context));
return true;
......@@ -727,9 +645,9 @@ bool Debug::CheckBreakPoint(Handle<Object> break_point_object) {
factory->InternalizeOneByteString(
STATIC_CHAR_VECTOR("IsBreakPointTriggered"));
Handle<GlobalObject> debug_global(debug_context()->global_object());
Handle<JSFunction> check_break_point =
Handle<JSFunction>::cast(Object::GetProperty(
debug_global, is_break_point_triggered_string).ToHandleChecked());
Handle<JSFunction> check_break_point = Handle<JSFunction>::cast(
Object::GetProperty(debug_utils(), is_break_point_triggered_string)
.ToHandleChecked());
// Get the break id as an object.
Handle<Object> break_id = factory->NewNumberFromInt(Debug::break_id());
......@@ -1752,14 +1670,12 @@ void Debug::ClearMirrorCache() {
PostponeInterruptsScope postpone(isolate_);
HandleScope scope(isolate_);
AssertDebugContext();
Factory* factory = isolate_->factory();
Handle<GlobalObject> global(isolate_->global_object());
JSObject::SetProperty(global,
factory->NewStringFromAsciiChecked("next_handle_"),
handle(Smi::FromInt(0), isolate_), SLOPPY).Check();
JSObject::SetProperty(global,
factory->NewStringFromAsciiChecked("mirror_cache_"),
factory->NewJSArray(0, FAST_ELEMENTS), SLOPPY).Check();
Handle<Object> fun =
Object::GetProperty(isolate_, debug_utils(), "ClearMirrorCache")
.ToHandleChecked();
Handle<Object> undefined = isolate_->factory()->undefined_value();
Execution::TryCall(Handle<JSFunction>::cast(fun), undefined, 0, NULL);
}
......@@ -1836,9 +1752,9 @@ MaybeHandle<Object> Debug::MakeJSObject(const char* constructor_name,
Handle<Object> argv[]) {
AssertDebugContext();
// Create the execution state object.
Handle<GlobalObject> global(isolate_->global_object());
Handle<Object> constructor = Object::GetProperty(
isolate_, global, constructor_name).ToHandleChecked();
Handle<Object> constructor =
Object::GetProperty(isolate_, debug_utils(), constructor_name)
.ToHandleChecked();
DCHECK(constructor->IsJSFunction());
if (!constructor->IsJSFunction()) return MaybeHandle<Object>();
// We do not handle interrupts here. In particular, termination interrupts.
......@@ -2066,13 +1982,9 @@ void Debug::OnAfterCompile(Handle<Script> script) {
// script. Make sure that these break points are set.
// Get the function UpdateScriptBreakPoints (defined in debug.js).
Handle<String> update_script_break_points_string =
isolate_->factory()->InternalizeOneByteString(
STATIC_CHAR_VECTOR("UpdateScriptBreakPoints"));
Handle<GlobalObject> debug_global(debug_context()->global_object());
Handle<Object> update_script_break_points =
Object::GetProperty(
debug_global, update_script_break_points_string).ToHandleChecked();
Object::GetProperty(isolate_, debug_utils(), "UpdateScriptBreakPoints")
.ToHandleChecked();
if (!update_script_break_points->IsJSFunction()) {
return;
}
......
......@@ -494,6 +494,11 @@ class Debug {
base::NoBarrier_Load(&thread_local_.current_debug_scope_));
}
inline Handle<Context> debug_context() { return debug_context_; }
inline Handle<Object> debug_utils() {
AssertDebugContext();
return isolate_->natives_utils_object();
}
void set_live_edit_enabled(bool v) { live_edit_enabled_ = v; }
bool live_edit_enabled() const {
return FLAG_enable_liveedit && live_edit_enabled_ ;
......@@ -587,7 +592,6 @@ class Debug {
bool auto_continue);
void InvokeMessageHandler(MessageImpl message);
static bool CompileDebuggerScript(Isolate* isolate, int index);
void ClearOneShot();
void ActivateStepIn(StackFrame* frame);
void ClearStepIn();
......
This diff is collapsed.
......@@ -20,9 +20,23 @@
//
// LiveEdit namespace is declared inside a single function constructor.
"use strict";
(function(global, utils) {
"use strict";
Debug.LiveEdit = new function() {
// -------------------------------------------------------------------
// Imports
var FindScriptSourcePosition = global.Debug.findScriptSourcePosition;
var GetScriptBreakPoints;
var GlobalArray = global.Array;
var MathFloor = global.Math.floor;
var SyntaxError = global.SyntaxError;
utils.Import(function(from) {
GetScriptBreakPoints = from.GetScriptBreakPoints;
});
// -------------------------------------------------------------------
// Forward declaration for minifier.
var FunctionStatus;
......@@ -72,10 +86,10 @@ Debug.LiveEdit = new function() {
FindCorrespondingFunctions(root_old_node, root_new_node);
// Prepare to-do lists.
var replace_code_list = new Array();
var link_to_old_script_list = new Array();
var link_to_original_script_list = new Array();
var update_positions_list = new Array();
var replace_code_list = new GlobalArray();
var link_to_old_script_list = new GlobalArray();
var link_to_original_script_list = new GlobalArray();
var update_positions_list = new GlobalArray();
function HarvestTodo(old_node) {
function CollectDamaged(node) {
......@@ -128,7 +142,7 @@ Debug.LiveEdit = new function() {
HarvestTodo(root_old_node);
// Collect shared infos for functions whose code need to be patched.
var replaced_function_infos = new Array();
var replaced_function_infos = new GlobalArray();
for (var i = 0; i < replace_code_list.length; i++) {
var live_shared_function_infos =
replace_code_list[i].live_shared_function_infos;
......@@ -170,7 +184,7 @@ Debug.LiveEdit = new function() {
old_script = %LiveEditReplaceScript(script, new_source,
old_script_name);
var link_to_old_script_report = new Array();
var link_to_old_script_report = new GlobalArray();
change_log.push( { linked_to_old_script: link_to_old_script_report } );
// We need to link to old script all former nested functions.
......@@ -192,7 +206,7 @@ Debug.LiveEdit = new function() {
PatchFunctionCode(replace_code_list[i], change_log);
}
var position_patch_report = new Array();
var position_patch_report = new GlobalArray();
change_log.push( {position_patched: position_patch_report} );
for (var i = 0; i < update_positions_list.length; i++) {
......@@ -214,9 +228,6 @@ Debug.LiveEdit = new function() {
preview_description.updated = true;
return preview_description;
}
// Function is public.
this.ApplyPatchMultiChunk = ApplyPatchMultiChunk;
// Fully compiles source string as a script. Returns Array of
// FunctionCompileInfo -- a descriptions of all functions of the script.
......@@ -233,8 +244,8 @@ Debug.LiveEdit = new function() {
var raw_compile_info = %LiveEditGatherCompileInfo(script, source);
// Sort function infos by start position field.
var compile_info = new Array();
var old_index_map = new Array();
var compile_info = new GlobalArray();
var old_index_map = new GlobalArray();
for (var i = 0; i < raw_compile_info.length; i++) {
var info = new FunctionCompileInfo(raw_compile_info[i]);
// Remove all links to the actual script. Breakpoints system and
......@@ -367,7 +378,7 @@ Debug.LiveEdit = new function() {
break_point.clear();
// TODO(LiveEdit): be careful with resource offset here.
var break_point_position = Debug.findScriptSourcePosition(original_script,
var break_point_position = FindScriptSourcePosition(original_script,
break_point.line(), break_point.column());
var old_position_description = {
......@@ -443,7 +454,7 @@ Debug.LiveEdit = new function() {
}
function PosTranslator(diff_array) {
var chunks = new Array();
var chunks = new GlobalArray();
var current_diff = 0;
for (var i = 0; i < diff_array.length; i += 3) {
var pos1_begin = diff_array[i];
......@@ -469,7 +480,7 @@ Debug.LiveEdit = new function() {
var chunk_index2 = array.length - 1;
while (chunk_index1 < chunk_index2) {
var middle_index = Math.floor((chunk_index1 + chunk_index2) / 2);
var middle_index = MathFloor((chunk_index1 + chunk_index2) / 2);
if (pos < array[middle_index + 1].pos1) {
chunk_index2 = middle_index;
} else {
......@@ -550,7 +561,7 @@ Debug.LiveEdit = new function() {
function BuildNode() {
var my_index = index;
index++;
var child_array = new Array();
var child_array = new GlobalArray();
while (index < code_info_array.length &&
code_info_array[index].outer_index == my_index) {
child_array.push(BuildNode());
......@@ -682,7 +693,7 @@ Debug.LiveEdit = new function() {
var scope_change_description =
IsFunctionContextLocalsChanged(old_node.info, new_node.info);
if (scope_change_description) {
old_node.status = FunctionStatus.CHANGED;
old_node.status = FunctionStatus.CHANGED;
}
var old_children = old_node.children;
......@@ -783,7 +794,7 @@ Debug.LiveEdit = new function() {
function FindLiveSharedInfos(old_code_tree, script) {
var shared_raw_list = %LiveEditFindSharedFunctionInfosForScript(script);
var shared_infos = new Array();
var shared_infos = new GlobalArray();
for (var i = 0; i < shared_raw_list.length; i++) {
shared_infos.push(new SharedInfoWrapper(shared_raw_list[i]));
......@@ -900,7 +911,7 @@ Debug.LiveEdit = new function() {
// have activations on stack (of any thread). Throws a Failure exception
// if this proves to be false.
function CheckStackActivations(shared_wrapper_list, change_log) {
var shared_list = new Array();
var shared_list = new GlobalArray();
for (var i = 0; i < shared_wrapper_list.length; i++) {
shared_list[i] = shared_wrapper_list[i].info;
}
......@@ -910,8 +921,8 @@ Debug.LiveEdit = new function() {
throw new Failure(result[shared_list.length]);
}
var problems = new Array();
var dropped = new Array();
var problems = new GlobalArray();
var dropped = new GlobalArray();
for (var i = 0; i < shared_list.length; i++) {
var shared = shared_wrapper_list[i];
if (result[i] == FunctionPatchabilityStatus.REPLACED_ON_ACTIVE_STACK) {
......@@ -964,8 +975,6 @@ Debug.LiveEdit = new function() {
function Failure(message) {
this.message = message;
}
// Function (constructor) is public.
this.Failure = Failure;
Failure.prototype.toString = function() {
return "LiveEdit Failure: " + this.message;
......@@ -1000,8 +1009,6 @@ Debug.LiveEdit = new function() {
function GetPcFromSourcePos(func, source_pos) {
return %GetFunctionCodePositionFromSource(func, source_pos);
}
// Function is public.
this.GetPcFromSourcePos = GetPcFromSourcePos;
// LiveEdit main entry point: changes a script text to a new string.
function SetScriptSource(script, new_source, preview_only, change_log) {
......@@ -1010,8 +1017,6 @@ Debug.LiveEdit = new function() {
return ApplyPatchMultiChunk(script, diff, new_source, preview_only,
change_log);
}
// Function is public.
this.SetScriptSource = SetScriptSource;
function CompareStrings(s1, s2) {
return %LiveEditCompareStrings(s1, s2);
......@@ -1098,10 +1103,21 @@ Debug.LiveEdit = new function() {
return ProcessOldNode(old_code_tree);
}
// Functions are public for tests.
this.TestApi = {
// -------------------------------------------------------------------
// Exports
var LiveEdit = {};
LiveEdit.SetScriptSource = SetScriptSource;
LiveEdit.ApplyPatchMultiChunk = ApplyPatchMultiChunk;
LiveEdit.Failure = Failure;
LiveEdit.GetPcFromSourcePos = GetPcFromSourcePos;
LiveEdit.TestApi = {
PosTranslator: PosTranslator,
CompareStrings: CompareStrings,
ApplySingleChunkPatch: ApplySingleChunkPatch
};
};
global.Debug.LiveEdit = LiveEdit;
})
This diff is collapsed.
......@@ -73,6 +73,7 @@ class CallSite {
/* Error */ \
T(None, "") \
T(CyclicProto, "Cyclic __proto__ value") \
T(Debugger, "Debugger: %") \
T(DebuggerLoading, "Error loading debugger") \
T(DefaultOptionsMissing, "Internal % error. Default options are missing.") \
T(UncaughtException, "Uncaught %") \
......@@ -101,6 +102,8 @@ class CallSite {
T(DataViewNotArrayBuffer, \
"First argument to DataView constructor must be an ArrayBuffer") \
T(DateType, "this is not a Date object.") \
T(DebuggerFrame, "Debugger: Invalid frame index.") \
T(DebuggerType, "Debugger: Parameters have wrong types.") \
T(DefineDisallowed, "Cannot define property:%, object is not extensible.") \
T(DuplicateTemplateProperty, "Object template has duplicate property '%'") \
T(ExtendsValueGenerator, \
......
......@@ -208,6 +208,22 @@ function PostExperimentals(utils) {
experimental_exports = UNDEFINED;
utils.PostExperimentals = UNDEFINED;
utils.PostDebug = UNDEFINED;
utils.Import = UNDEFINED;
utils.Export = UNDEFINED;
};
function PostDebug(utils) {
for ( ; !IS_UNDEFINED(exports); exports = exports.next) {
exports(experimental_exports);
}
for ( ; !IS_UNDEFINED(imports); imports = imports.next) {
imports(experimental_exports);
}
utils.PostDebug = UNDEFINED;
utils.PostExperimentals = UNDEFINED;
utils.Import = UNDEFINED;
utils.Export = UNDEFINED;
......@@ -227,6 +243,7 @@ InstallFunctions(utils, NONE, [
"SetUpLockedPrototype", SetUpLockedPrototype,
"PostNatives", PostNatives,
"PostExperimentals", PostExperimentals,
"PostDebug", PostDebug,
]);
})
......@@ -1201,6 +1201,7 @@ utils.Export(function(to) {
to.StringLastIndexOf = StringLastIndexOfJS;
to.StringMatch = StringMatchJS;
to.StringReplace = StringReplace;
to.StringSlice = StringSlice;
to.StringSplit = StringSplitJS;
to.StringSubstr = StringSubstr;
to.StringSubstring = StringSubstring;
......
......@@ -51,8 +51,7 @@ function listener(event, exec_state, event_data, data) {
listenerCallCount++;
// Check that mirror cache is cleared when entering debugger.
assertEquals(0, debug.next_handle_, "Mirror cache not cleared");
assertEquals(0, debug.mirror_cache_.length, "Mirror cache not cleared");
assertTrue(debug.MirrorCacheIsEmpty(), "Mirror cache not cleared");
// Get the debug command processor in paused state.
var dcp = exec_state.debugCommandProcessor(false);
......@@ -66,8 +65,7 @@ function listener(event, exec_state, event_data, data) {
Debug.scripts();
// Some mirrors where cached.
assertFalse(debug.next_handle_ == 0, "Mirror cache not used");
assertFalse(debug.mirror_cache_.length == 0, "Mirror cache not used");
assertFalse(debug.MirrorCacheIsEmpty(), "Mirror cache not used");
}
} catch (e) {
print(e);
......
......@@ -1796,8 +1796,8 @@
'../../src/templates.js',
'../../src/harmony-array.js',
'../../src/harmony-typedarray.js',
'../../src/debug/debug.js',
'../../src/debug/mirrors.js',
'../../src/debug/debug.js',
'../../src/debug/liveedit.js',
],
'experimental_library_files': [
......
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