Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(782)

Unified Diff: src/runtime/runtime-liveedit.cc

Issue 612023002: Split even more runtime functions into separate files. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/runtime/runtime-generator.cc ('k') | src/runtime/runtime-test.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/runtime/runtime-liveedit.cc
diff --git a/src/runtime/runtime-liveedit.cc b/src/runtime/runtime-liveedit.cc
new file mode 100644
index 0000000000000000000000000000000000000000..a121d8f1698c8e1dc7359b8f4dd05b2f362903da
--- /dev/null
+++ b/src/runtime/runtime-liveedit.cc
@@ -0,0 +1,293 @@
+// Copyright 2014 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/v8.h"
+
+#include "src/arguments.h"
+#include "src/debug.h"
+#include "src/liveedit.h"
+#include "src/runtime/runtime.h"
+#include "src/runtime/runtime-utils.h"
+
+namespace v8 {
+namespace internal {
+
+
+static int FindSharedFunctionInfosForScript(HeapIterator* iterator,
+ Script* script,
+ FixedArray* buffer) {
+ DisallowHeapAllocation no_allocation;
+ int counter = 0;
+ int buffer_size = buffer->length();
+ for (HeapObject* obj = iterator->next(); obj != NULL;
+ obj = iterator->next()) {
+ DCHECK(obj != NULL);
+ if (!obj->IsSharedFunctionInfo()) {
+ continue;
+ }
+ SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj);
+ if (shared->script() != script) {
+ continue;
+ }
+ if (counter < buffer_size) {
+ buffer->set(counter, shared);
+ }
+ counter++;
+ }
+ return counter;
+}
+
+
+// For a script finds all SharedFunctionInfo's in the heap that points
+// to this script. Returns JSArray of SharedFunctionInfo wrapped
+// in OpaqueReferences.
+RUNTIME_FUNCTION(Runtime_LiveEditFindSharedFunctionInfosForScript) {
+ HandleScope scope(isolate);
+ CHECK(isolate->debug()->live_edit_enabled());
+ DCHECK(args.length() == 1);
+ CONVERT_ARG_CHECKED(JSValue, script_value, 0);
+
+ RUNTIME_ASSERT(script_value->value()->IsScript());
+ Handle<Script> script = Handle<Script>(Script::cast(script_value->value()));
+
+ const int kBufferSize = 32;
+
+ Handle<FixedArray> array;
+ array = isolate->factory()->NewFixedArray(kBufferSize);
+ int number;
+ Heap* heap = isolate->heap();
+ {
+ HeapIterator heap_iterator(heap);
+ Script* scr = *script;
+ FixedArray* arr = *array;
+ number = FindSharedFunctionInfosForScript(&heap_iterator, scr, arr);
+ }
+ if (number > kBufferSize) {
+ array = isolate->factory()->NewFixedArray(number);
+ HeapIterator heap_iterator(heap);
+ Script* scr = *script;
+ FixedArray* arr = *array;
+ FindSharedFunctionInfosForScript(&heap_iterator, scr, arr);
+ }
+
+ Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(array);
+ result->set_length(Smi::FromInt(number));
+
+ LiveEdit::WrapSharedFunctionInfos(result);
+
+ return *result;
+}
+
+
+// For a script calculates compilation information about all its functions.
+// The script source is explicitly specified by the second argument.
+// The source of the actual script is not used, however it is important that
+// all generated code keeps references to this particular instance of script.
+// Returns a JSArray of compilation infos. The array is ordered so that
+// each function with all its descendant is always stored in a continues range
+// with the function itself going first. The root function is a script function.
+RUNTIME_FUNCTION(Runtime_LiveEditGatherCompileInfo) {
+ HandleScope scope(isolate);
+ CHECK(isolate->debug()->live_edit_enabled());
+ DCHECK(args.length() == 2);
+ CONVERT_ARG_CHECKED(JSValue, script, 0);
+ CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
+
+ RUNTIME_ASSERT(script->value()->IsScript());
+ Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
+
+ Handle<JSArray> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result, LiveEdit::GatherCompileInfo(script_handle, source));
+ return *result;
+}
+
+
+// Changes the source of the script to a new_source.
+// If old_script_name is provided (i.e. is a String), also creates a copy of
+// the script with its original source and sends notification to debugger.
+RUNTIME_FUNCTION(Runtime_LiveEditReplaceScript) {
+ HandleScope scope(isolate);
+ CHECK(isolate->debug()->live_edit_enabled());
+ DCHECK(args.length() == 3);
+ CONVERT_ARG_CHECKED(JSValue, original_script_value, 0);
+ CONVERT_ARG_HANDLE_CHECKED(String, new_source, 1);
+ CONVERT_ARG_HANDLE_CHECKED(Object, old_script_name, 2);
+
+ RUNTIME_ASSERT(original_script_value->value()->IsScript());
+ Handle<Script> original_script(Script::cast(original_script_value->value()));
+
+ Handle<Object> old_script = LiveEdit::ChangeScriptSource(
+ original_script, new_source, old_script_name);
+
+ if (old_script->IsScript()) {
+ Handle<Script> script_handle = Handle<Script>::cast(old_script);
+ return *Script::GetWrapper(script_handle);
+ } else {
+ return isolate->heap()->null_value();
+ }
+}
+
+
+RUNTIME_FUNCTION(Runtime_LiveEditFunctionSourceUpdated) {
+ HandleScope scope(isolate);
+ CHECK(isolate->debug()->live_edit_enabled());
+ DCHECK(args.length() == 1);
+ CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_info, 0);
+ RUNTIME_ASSERT(SharedInfoWrapper::IsInstance(shared_info));
+
+ LiveEdit::FunctionSourceUpdated(shared_info);
+ return isolate->heap()->undefined_value();
+}
+
+
+// Replaces code of SharedFunctionInfo with a new one.
+RUNTIME_FUNCTION(Runtime_LiveEditReplaceFunctionCode) {
+ HandleScope scope(isolate);
+ CHECK(isolate->debug()->live_edit_enabled());
+ DCHECK(args.length() == 2);
+ CONVERT_ARG_HANDLE_CHECKED(JSArray, new_compile_info, 0);
+ CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_info, 1);
+ RUNTIME_ASSERT(SharedInfoWrapper::IsInstance(shared_info));
+
+ LiveEdit::ReplaceFunctionCode(new_compile_info, shared_info);
+ return isolate->heap()->undefined_value();
+}
+
+
+// Connects SharedFunctionInfo to another script.
+RUNTIME_FUNCTION(Runtime_LiveEditFunctionSetScript) {
+ HandleScope scope(isolate);
+ CHECK(isolate->debug()->live_edit_enabled());
+ DCHECK(args.length() == 2);
+ CONVERT_ARG_HANDLE_CHECKED(Object, function_object, 0);
+ CONVERT_ARG_HANDLE_CHECKED(Object, script_object, 1);
+
+ if (function_object->IsJSValue()) {
+ Handle<JSValue> function_wrapper = Handle<JSValue>::cast(function_object);
+ if (script_object->IsJSValue()) {
+ RUNTIME_ASSERT(JSValue::cast(*script_object)->value()->IsScript());
+ Script* script = Script::cast(JSValue::cast(*script_object)->value());
+ script_object = Handle<Object>(script, isolate);
+ }
+ RUNTIME_ASSERT(function_wrapper->value()->IsSharedFunctionInfo());
+ LiveEdit::SetFunctionScript(function_wrapper, script_object);
+ } else {
+ // Just ignore this. We may not have a SharedFunctionInfo for some functions
+ // and we check it in this function.
+ }
+
+ return isolate->heap()->undefined_value();
+}
+
+
+// In a code of a parent function replaces original function as embedded object
+// with a substitution one.
+RUNTIME_FUNCTION(Runtime_LiveEditReplaceRefToNestedFunction) {
+ HandleScope scope(isolate);
+ CHECK(isolate->debug()->live_edit_enabled());
+ DCHECK(args.length() == 3);
+
+ CONVERT_ARG_HANDLE_CHECKED(JSValue, parent_wrapper, 0);
+ CONVERT_ARG_HANDLE_CHECKED(JSValue, orig_wrapper, 1);
+ CONVERT_ARG_HANDLE_CHECKED(JSValue, subst_wrapper, 2);
+ RUNTIME_ASSERT(parent_wrapper->value()->IsSharedFunctionInfo());
+ RUNTIME_ASSERT(orig_wrapper->value()->IsSharedFunctionInfo());
+ RUNTIME_ASSERT(subst_wrapper->value()->IsSharedFunctionInfo());
+
+ LiveEdit::ReplaceRefToNestedFunction(parent_wrapper, orig_wrapper,
+ subst_wrapper);
+ return isolate->heap()->undefined_value();
+}
+
+
+// Updates positions of a shared function info (first parameter) according
+// to script source change. Text change is described in second parameter as
+// array of groups of 3 numbers:
+// (change_begin, change_end, change_end_new_position).
+// Each group describes a change in text; groups are sorted by change_begin.
+RUNTIME_FUNCTION(Runtime_LiveEditPatchFunctionPositions) {
+ HandleScope scope(isolate);
+ CHECK(isolate->debug()->live_edit_enabled());
+ DCHECK(args.length() == 2);
+ CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_array, 0);
+ CONVERT_ARG_HANDLE_CHECKED(JSArray, position_change_array, 1);
+ RUNTIME_ASSERT(SharedInfoWrapper::IsInstance(shared_array))
+
+ LiveEdit::PatchFunctionPositions(shared_array, position_change_array);
+ return isolate->heap()->undefined_value();
+}
+
+
+// For array of SharedFunctionInfo's (each wrapped in JSValue)
+// checks that none of them have activations on stacks (of any thread).
+// Returns array of the same length with corresponding results of
+// LiveEdit::FunctionPatchabilityStatus type.
+RUNTIME_FUNCTION(Runtime_LiveEditCheckAndDropActivations) {
+ HandleScope scope(isolate);
+ CHECK(isolate->debug()->live_edit_enabled());
+ DCHECK(args.length() == 2);
+ CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_array, 0);
+ CONVERT_BOOLEAN_ARG_CHECKED(do_drop, 1);
+ RUNTIME_ASSERT(shared_array->length()->IsSmi());
+ RUNTIME_ASSERT(shared_array->HasFastElements())
+ int array_length = Smi::cast(shared_array->length())->value();
+ for (int i = 0; i < array_length; i++) {
+ Handle<Object> element =
+ Object::GetElement(isolate, shared_array, i).ToHandleChecked();
+ RUNTIME_ASSERT(
+ element->IsJSValue() &&
+ Handle<JSValue>::cast(element)->value()->IsSharedFunctionInfo());
+ }
+
+ return *LiveEdit::CheckAndDropActivations(shared_array, do_drop);
+}
+
+
+// Compares 2 strings line-by-line, then token-wise and returns diff in form
+// of JSArray of triplets (pos1, pos1_end, pos2_end) describing list
+// of diff chunks.
+RUNTIME_FUNCTION(Runtime_LiveEditCompareStrings) {
+ HandleScope scope(isolate);
+ CHECK(isolate->debug()->live_edit_enabled());
+ DCHECK(args.length() == 2);
+ CONVERT_ARG_HANDLE_CHECKED(String, s1, 0);
+ CONVERT_ARG_HANDLE_CHECKED(String, s2, 1);
+
+ return *LiveEdit::CompareStrings(s1, s2);
+}
+
+
+// Restarts a call frame and completely drops all frames above.
+// Returns true if successful. Otherwise returns undefined or an error message.
+RUNTIME_FUNCTION(Runtime_LiveEditRestartFrame) {
+ HandleScope scope(isolate);
+ CHECK(isolate->debug()->live_edit_enabled());
+ DCHECK(args.length() == 2);
+ CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
+ RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
+
+ CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
+ Heap* heap = isolate->heap();
+
+ // Find the relevant frame with the requested index.
+ StackFrame::Id id = isolate->debug()->break_frame_id();
+ if (id == StackFrame::NO_ID) {
+ // If there are no JavaScript stack frames return undefined.
+ return heap->undefined_value();
+ }
+
+ JavaScriptFrameIterator it(isolate, id);
+ int inlined_jsframe_index = FindIndexedNonNativeFrame(&it, index);
+ if (inlined_jsframe_index == -1) return heap->undefined_value();
+ // We don't really care what the inlined frame index is, since we are
+ // throwing away the entire frame anyways.
+ const char* error_message = LiveEdit::RestartFrame(it.frame());
+ if (error_message) {
+ return *(isolate->factory()->InternalizeUtf8String(error_message));
+ }
+ return heap->true_value();
+}
+}
+} // namespace v8::internal
« no previous file with comments | « src/runtime/runtime-generator.cc ('k') | src/runtime/runtime-test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698