| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/runtime/runtime-utils.h" | 5 #include "src/runtime/runtime-utils.h" |
| 6 | 6 |
| 7 #include "src/arguments.h" | 7 #include "src/arguments.h" |
| 8 #include "src/debug/debug.h" | 8 #include "src/debug/debug.h" |
| 9 #include "src/debug/debug-frames.h" | 9 #include "src/debug/debug-frames.h" |
| 10 #include "src/debug/liveedit.h" | 10 #include "src/debug/liveedit.h" |
| 11 #include "src/frames-inl.h" | 11 #include "src/frames-inl.h" |
| 12 #include "src/isolate-inl.h" | 12 #include "src/isolate-inl.h" |
| 13 #include "src/runtime/runtime.h" | 13 #include "src/runtime/runtime.h" |
| 14 | 14 |
| 15 namespace v8 { | 15 namespace v8 { |
| 16 namespace internal { | 16 namespace internal { |
| 17 | 17 |
| 18 // For a script finds all SharedFunctionInfo's in the heap that points | 18 // For a script finds all SharedFunctionInfo's in the heap that points |
| 19 // to this script. Returns JSArray of SharedFunctionInfo wrapped | 19 // to this script. Returns JSArray of SharedFunctionInfo wrapped |
| 20 // in OpaqueReferences. | 20 // in OpaqueReferences. |
| 21 RUNTIME_FUNCTION(Runtime_LiveEditFindSharedFunctionInfosForScript) { | 21 RUNTIME_FUNCTION(Runtime_LiveEditFindSharedFunctionInfosForScript) { |
| 22 HandleScope scope(isolate); | 22 HandleScope scope(isolate); |
| 23 CHECK(isolate->debug()->live_edit_enabled()); | 23 CHECK(isolate->debug()->live_edit_enabled()); |
| 24 DCHECK(args.length() == 1); | 24 DCHECK_EQ(1, args.length()); |
| 25 CONVERT_ARG_CHECKED(JSValue, script_value, 0); | 25 CONVERT_ARG_CHECKED(JSValue, script_value, 0); |
| 26 | 26 |
| 27 CHECK(script_value->value()->IsScript()); | 27 CHECK(script_value->value()->IsScript()); |
| 28 Handle<Script> script = Handle<Script>(Script::cast(script_value->value())); | 28 Handle<Script> script = Handle<Script>(Script::cast(script_value->value())); |
| 29 | 29 |
| 30 List<Handle<SharedFunctionInfo> > found; | 30 List<Handle<SharedFunctionInfo> > found; |
| 31 Heap* heap = isolate->heap(); | 31 Heap* heap = isolate->heap(); |
| 32 { | 32 { |
| 33 HeapIterator iterator(heap); | 33 HeapIterator iterator(heap); |
| 34 HeapObject* heap_obj; | 34 HeapObject* heap_obj; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 56 // For a script calculates compilation information about all its functions. | 56 // For a script calculates compilation information about all its functions. |
| 57 // The script source is explicitly specified by the second argument. | 57 // The script source is explicitly specified by the second argument. |
| 58 // The source of the actual script is not used, however it is important that | 58 // The source of the actual script is not used, however it is important that |
| 59 // all generated code keeps references to this particular instance of script. | 59 // all generated code keeps references to this particular instance of script. |
| 60 // Returns a JSArray of compilation infos. The array is ordered so that | 60 // Returns a JSArray of compilation infos. The array is ordered so that |
| 61 // each function with all its descendant is always stored in a continues range | 61 // each function with all its descendant is always stored in a continues range |
| 62 // with the function itself going first. The root function is a script function. | 62 // with the function itself going first. The root function is a script function. |
| 63 RUNTIME_FUNCTION(Runtime_LiveEditGatherCompileInfo) { | 63 RUNTIME_FUNCTION(Runtime_LiveEditGatherCompileInfo) { |
| 64 HandleScope scope(isolate); | 64 HandleScope scope(isolate); |
| 65 CHECK(isolate->debug()->live_edit_enabled()); | 65 CHECK(isolate->debug()->live_edit_enabled()); |
| 66 DCHECK(args.length() == 2); | 66 DCHECK_EQ(2, args.length()); |
| 67 CONVERT_ARG_CHECKED(JSValue, script, 0); | 67 CONVERT_ARG_CHECKED(JSValue, script, 0); |
| 68 CONVERT_ARG_HANDLE_CHECKED(String, source, 1); | 68 CONVERT_ARG_HANDLE_CHECKED(String, source, 1); |
| 69 | 69 |
| 70 CHECK(script->value()->IsScript()); | 70 CHECK(script->value()->IsScript()); |
| 71 Handle<Script> script_handle = Handle<Script>(Script::cast(script->value())); | 71 Handle<Script> script_handle = Handle<Script>(Script::cast(script->value())); |
| 72 | 72 |
| 73 RETURN_RESULT_OR_FAILURE(isolate, | 73 RETURN_RESULT_OR_FAILURE(isolate, |
| 74 LiveEdit::GatherCompileInfo(script_handle, source)); | 74 LiveEdit::GatherCompileInfo(script_handle, source)); |
| 75 } | 75 } |
| 76 | 76 |
| 77 | 77 |
| 78 // Changes the source of the script to a new_source. | 78 // Changes the source of the script to a new_source. |
| 79 // If old_script_name is provided (i.e. is a String), also creates a copy of | 79 // If old_script_name is provided (i.e. is a String), also creates a copy of |
| 80 // the script with its original source and sends notification to debugger. | 80 // the script with its original source and sends notification to debugger. |
| 81 RUNTIME_FUNCTION(Runtime_LiveEditReplaceScript) { | 81 RUNTIME_FUNCTION(Runtime_LiveEditReplaceScript) { |
| 82 HandleScope scope(isolate); | 82 HandleScope scope(isolate); |
| 83 CHECK(isolate->debug()->live_edit_enabled()); | 83 CHECK(isolate->debug()->live_edit_enabled()); |
| 84 DCHECK(args.length() == 3); | 84 DCHECK_EQ(3, args.length()); |
| 85 CONVERT_ARG_CHECKED(JSValue, original_script_value, 0); | 85 CONVERT_ARG_CHECKED(JSValue, original_script_value, 0); |
| 86 CONVERT_ARG_HANDLE_CHECKED(String, new_source, 1); | 86 CONVERT_ARG_HANDLE_CHECKED(String, new_source, 1); |
| 87 CONVERT_ARG_HANDLE_CHECKED(Object, old_script_name, 2); | 87 CONVERT_ARG_HANDLE_CHECKED(Object, old_script_name, 2); |
| 88 | 88 |
| 89 CHECK(original_script_value->value()->IsScript()); | 89 CHECK(original_script_value->value()->IsScript()); |
| 90 Handle<Script> original_script(Script::cast(original_script_value->value())); | 90 Handle<Script> original_script(Script::cast(original_script_value->value())); |
| 91 | 91 |
| 92 Handle<Object> old_script = LiveEdit::ChangeScriptSource( | 92 Handle<Object> old_script = LiveEdit::ChangeScriptSource( |
| 93 original_script, new_source, old_script_name); | 93 original_script, new_source, old_script_name); |
| 94 | 94 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 126 | 126 |
| 127 LiveEdit::FunctionSourceUpdated(shared_info, new_function_literal_id); | 127 LiveEdit::FunctionSourceUpdated(shared_info, new_function_literal_id); |
| 128 return isolate->heap()->undefined_value(); | 128 return isolate->heap()->undefined_value(); |
| 129 } | 129 } |
| 130 | 130 |
| 131 | 131 |
| 132 // Replaces code of SharedFunctionInfo with a new one. | 132 // Replaces code of SharedFunctionInfo with a new one. |
| 133 RUNTIME_FUNCTION(Runtime_LiveEditReplaceFunctionCode) { | 133 RUNTIME_FUNCTION(Runtime_LiveEditReplaceFunctionCode) { |
| 134 HandleScope scope(isolate); | 134 HandleScope scope(isolate); |
| 135 CHECK(isolate->debug()->live_edit_enabled()); | 135 CHECK(isolate->debug()->live_edit_enabled()); |
| 136 DCHECK(args.length() == 2); | 136 DCHECK_EQ(2, args.length()); |
| 137 CONVERT_ARG_HANDLE_CHECKED(JSArray, new_compile_info, 0); | 137 CONVERT_ARG_HANDLE_CHECKED(JSArray, new_compile_info, 0); |
| 138 CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_info, 1); | 138 CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_info, 1); |
| 139 CHECK(SharedInfoWrapper::IsInstance(shared_info)); | 139 CHECK(SharedInfoWrapper::IsInstance(shared_info)); |
| 140 | 140 |
| 141 LiveEdit::ReplaceFunctionCode(new_compile_info, shared_info); | 141 LiveEdit::ReplaceFunctionCode(new_compile_info, shared_info); |
| 142 return isolate->heap()->undefined_value(); | 142 return isolate->heap()->undefined_value(); |
| 143 } | 143 } |
| 144 | 144 |
| 145 | 145 |
| 146 // Connects SharedFunctionInfo to another script. | 146 // Connects SharedFunctionInfo to another script. |
| 147 RUNTIME_FUNCTION(Runtime_LiveEditFunctionSetScript) { | 147 RUNTIME_FUNCTION(Runtime_LiveEditFunctionSetScript) { |
| 148 HandleScope scope(isolate); | 148 HandleScope scope(isolate); |
| 149 CHECK(isolate->debug()->live_edit_enabled()); | 149 CHECK(isolate->debug()->live_edit_enabled()); |
| 150 DCHECK(args.length() == 2); | 150 DCHECK_EQ(2, args.length()); |
| 151 CONVERT_ARG_HANDLE_CHECKED(Object, function_object, 0); | 151 CONVERT_ARG_HANDLE_CHECKED(Object, function_object, 0); |
| 152 CONVERT_ARG_HANDLE_CHECKED(Object, script_object, 1); | 152 CONVERT_ARG_HANDLE_CHECKED(Object, script_object, 1); |
| 153 | 153 |
| 154 if (function_object->IsJSValue()) { | 154 if (function_object->IsJSValue()) { |
| 155 Handle<JSValue> function_wrapper = Handle<JSValue>::cast(function_object); | 155 Handle<JSValue> function_wrapper = Handle<JSValue>::cast(function_object); |
| 156 if (script_object->IsJSValue()) { | 156 if (script_object->IsJSValue()) { |
| 157 CHECK(JSValue::cast(*script_object)->value()->IsScript()); | 157 CHECK(JSValue::cast(*script_object)->value()->IsScript()); |
| 158 Script* script = Script::cast(JSValue::cast(*script_object)->value()); | 158 Script* script = Script::cast(JSValue::cast(*script_object)->value()); |
| 159 script_object = Handle<Object>(script, isolate); | 159 script_object = Handle<Object>(script, isolate); |
| 160 } | 160 } |
| 161 CHECK(function_wrapper->value()->IsSharedFunctionInfo()); | 161 CHECK(function_wrapper->value()->IsSharedFunctionInfo()); |
| 162 LiveEdit::SetFunctionScript(function_wrapper, script_object); | 162 LiveEdit::SetFunctionScript(function_wrapper, script_object); |
| 163 } else { | 163 } else { |
| 164 // Just ignore this. We may not have a SharedFunctionInfo for some functions | 164 // Just ignore this. We may not have a SharedFunctionInfo for some functions |
| 165 // and we check it in this function. | 165 // and we check it in this function. |
| 166 } | 166 } |
| 167 | 167 |
| 168 return isolate->heap()->undefined_value(); | 168 return isolate->heap()->undefined_value(); |
| 169 } | 169 } |
| 170 | 170 |
| 171 | 171 |
| 172 // In a code of a parent function replaces original function as embedded object | 172 // In a code of a parent function replaces original function as embedded object |
| 173 // with a substitution one. | 173 // with a substitution one. |
| 174 RUNTIME_FUNCTION(Runtime_LiveEditReplaceRefToNestedFunction) { | 174 RUNTIME_FUNCTION(Runtime_LiveEditReplaceRefToNestedFunction) { |
| 175 HandleScope scope(isolate); | 175 HandleScope scope(isolate); |
| 176 CHECK(isolate->debug()->live_edit_enabled()); | 176 CHECK(isolate->debug()->live_edit_enabled()); |
| 177 DCHECK(args.length() == 3); | 177 DCHECK_EQ(3, args.length()); |
| 178 | 178 |
| 179 CONVERT_ARG_HANDLE_CHECKED(JSValue, parent_wrapper, 0); | 179 CONVERT_ARG_HANDLE_CHECKED(JSValue, parent_wrapper, 0); |
| 180 CONVERT_ARG_HANDLE_CHECKED(JSValue, orig_wrapper, 1); | 180 CONVERT_ARG_HANDLE_CHECKED(JSValue, orig_wrapper, 1); |
| 181 CONVERT_ARG_HANDLE_CHECKED(JSValue, subst_wrapper, 2); | 181 CONVERT_ARG_HANDLE_CHECKED(JSValue, subst_wrapper, 2); |
| 182 CHECK(parent_wrapper->value()->IsSharedFunctionInfo()); | 182 CHECK(parent_wrapper->value()->IsSharedFunctionInfo()); |
| 183 CHECK(orig_wrapper->value()->IsSharedFunctionInfo()); | 183 CHECK(orig_wrapper->value()->IsSharedFunctionInfo()); |
| 184 CHECK(subst_wrapper->value()->IsSharedFunctionInfo()); | 184 CHECK(subst_wrapper->value()->IsSharedFunctionInfo()); |
| 185 | 185 |
| 186 LiveEdit::ReplaceRefToNestedFunction(parent_wrapper, orig_wrapper, | 186 LiveEdit::ReplaceRefToNestedFunction(parent_wrapper, orig_wrapper, |
| 187 subst_wrapper); | 187 subst_wrapper); |
| 188 return isolate->heap()->undefined_value(); | 188 return isolate->heap()->undefined_value(); |
| 189 } | 189 } |
| 190 | 190 |
| 191 | 191 |
| 192 // Updates positions of a shared function info (first parameter) according | 192 // Updates positions of a shared function info (first parameter) according |
| 193 // to script source change. Text change is described in second parameter as | 193 // to script source change. Text change is described in second parameter as |
| 194 // array of groups of 3 numbers: | 194 // array of groups of 3 numbers: |
| 195 // (change_begin, change_end, change_end_new_position). | 195 // (change_begin, change_end, change_end_new_position). |
| 196 // Each group describes a change in text; groups are sorted by change_begin. | 196 // Each group describes a change in text; groups are sorted by change_begin. |
| 197 RUNTIME_FUNCTION(Runtime_LiveEditPatchFunctionPositions) { | 197 RUNTIME_FUNCTION(Runtime_LiveEditPatchFunctionPositions) { |
| 198 HandleScope scope(isolate); | 198 HandleScope scope(isolate); |
| 199 CHECK(isolate->debug()->live_edit_enabled()); | 199 CHECK(isolate->debug()->live_edit_enabled()); |
| 200 DCHECK(args.length() == 2); | 200 DCHECK_EQ(2, args.length()); |
| 201 CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_array, 0); | 201 CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_array, 0); |
| 202 CONVERT_ARG_HANDLE_CHECKED(JSArray, position_change_array, 1); | 202 CONVERT_ARG_HANDLE_CHECKED(JSArray, position_change_array, 1); |
| 203 CHECK(SharedInfoWrapper::IsInstance(shared_array)); | 203 CHECK(SharedInfoWrapper::IsInstance(shared_array)); |
| 204 | 204 |
| 205 LiveEdit::PatchFunctionPositions(shared_array, position_change_array); | 205 LiveEdit::PatchFunctionPositions(shared_array, position_change_array); |
| 206 return isolate->heap()->undefined_value(); | 206 return isolate->heap()->undefined_value(); |
| 207 } | 207 } |
| 208 | 208 |
| 209 | 209 |
| 210 // For array of SharedFunctionInfo's (each wrapped in JSValue) | 210 // For array of SharedFunctionInfo's (each wrapped in JSValue) |
| 211 // checks that none of them have activations on stacks (of any thread). | 211 // checks that none of them have activations on stacks (of any thread). |
| 212 // Returns array of the same length with corresponding results of | 212 // Returns array of the same length with corresponding results of |
| 213 // LiveEdit::FunctionPatchabilityStatus type. | 213 // LiveEdit::FunctionPatchabilityStatus type. |
| 214 RUNTIME_FUNCTION(Runtime_LiveEditCheckAndDropActivations) { | 214 RUNTIME_FUNCTION(Runtime_LiveEditCheckAndDropActivations) { |
| 215 HandleScope scope(isolate); | 215 HandleScope scope(isolate); |
| 216 CHECK(isolate->debug()->live_edit_enabled()); | 216 CHECK(isolate->debug()->live_edit_enabled()); |
| 217 DCHECK(args.length() == 3); | 217 DCHECK_EQ(3, args.length()); |
| 218 CONVERT_ARG_HANDLE_CHECKED(JSArray, old_shared_array, 0); | 218 CONVERT_ARG_HANDLE_CHECKED(JSArray, old_shared_array, 0); |
| 219 CONVERT_ARG_HANDLE_CHECKED(JSArray, new_shared_array, 1); | 219 CONVERT_ARG_HANDLE_CHECKED(JSArray, new_shared_array, 1); |
| 220 CONVERT_BOOLEAN_ARG_CHECKED(do_drop, 2); | 220 CONVERT_BOOLEAN_ARG_CHECKED(do_drop, 2); |
| 221 USE(new_shared_array); | 221 USE(new_shared_array); |
| 222 CHECK(old_shared_array->length()->IsSmi()); | 222 CHECK(old_shared_array->length()->IsSmi()); |
| 223 CHECK(new_shared_array->length() == old_shared_array->length()); | 223 CHECK(new_shared_array->length() == old_shared_array->length()); |
| 224 CHECK(old_shared_array->HasFastElements()); | 224 CHECK(old_shared_array->HasFastElements()); |
| 225 CHECK(new_shared_array->HasFastElements()); | 225 CHECK(new_shared_array->HasFastElements()); |
| 226 int array_length = Smi::cast(old_shared_array->length())->value(); | 226 int array_length = Smi::cast(old_shared_array->length())->value(); |
| 227 for (int i = 0; i < array_length; i++) { | 227 for (int i = 0; i < array_length; i++) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 245 do_drop); | 245 do_drop); |
| 246 } | 246 } |
| 247 | 247 |
| 248 | 248 |
| 249 // Compares 2 strings line-by-line, then token-wise and returns diff in form | 249 // Compares 2 strings line-by-line, then token-wise and returns diff in form |
| 250 // of JSArray of triplets (pos1, pos1_end, pos2_end) describing list | 250 // of JSArray of triplets (pos1, pos1_end, pos2_end) describing list |
| 251 // of diff chunks. | 251 // of diff chunks. |
| 252 RUNTIME_FUNCTION(Runtime_LiveEditCompareStrings) { | 252 RUNTIME_FUNCTION(Runtime_LiveEditCompareStrings) { |
| 253 HandleScope scope(isolate); | 253 HandleScope scope(isolate); |
| 254 CHECK(isolate->debug()->live_edit_enabled()); | 254 CHECK(isolate->debug()->live_edit_enabled()); |
| 255 DCHECK(args.length() == 2); | 255 DCHECK_EQ(2, args.length()); |
| 256 CONVERT_ARG_HANDLE_CHECKED(String, s1, 0); | 256 CONVERT_ARG_HANDLE_CHECKED(String, s1, 0); |
| 257 CONVERT_ARG_HANDLE_CHECKED(String, s2, 1); | 257 CONVERT_ARG_HANDLE_CHECKED(String, s2, 1); |
| 258 | 258 |
| 259 Handle<JSArray> result = LiveEdit::CompareStrings(s1, s2); | 259 Handle<JSArray> result = LiveEdit::CompareStrings(s1, s2); |
| 260 uint32_t array_length = 0; | 260 uint32_t array_length = 0; |
| 261 CHECK(result->length()->ToArrayLength(&array_length)); | 261 CHECK(result->length()->ToArrayLength(&array_length)); |
| 262 if (array_length > 0) { | 262 if (array_length > 0) { |
| 263 isolate->debug()->feature_tracker()->Track(DebugFeatureTracker::kLiveEdit); | 263 isolate->debug()->feature_tracker()->Track(DebugFeatureTracker::kLiveEdit); |
| 264 } | 264 } |
| 265 | 265 |
| 266 return *result; | 266 return *result; |
| 267 } | 267 } |
| 268 | 268 |
| 269 | 269 |
| 270 // Restarts a call frame and completely drops all frames above. | 270 // Restarts a call frame and completely drops all frames above. |
| 271 // Returns true if successful. Otherwise returns undefined or an error message. | 271 // Returns true if successful. Otherwise returns undefined or an error message. |
| 272 RUNTIME_FUNCTION(Runtime_LiveEditRestartFrame) { | 272 RUNTIME_FUNCTION(Runtime_LiveEditRestartFrame) { |
| 273 HandleScope scope(isolate); | 273 HandleScope scope(isolate); |
| 274 CHECK(isolate->debug()->live_edit_enabled()); | 274 CHECK(isolate->debug()->live_edit_enabled()); |
| 275 DCHECK(args.length() == 2); | 275 DCHECK_EQ(2, args.length()); |
| 276 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]); | 276 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]); |
| 277 CHECK(isolate->debug()->CheckExecutionState(break_id)); | 277 CHECK(isolate->debug()->CheckExecutionState(break_id)); |
| 278 | 278 |
| 279 CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]); | 279 CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]); |
| 280 Heap* heap = isolate->heap(); | 280 Heap* heap = isolate->heap(); |
| 281 | 281 |
| 282 // Find the relevant frame with the requested index. | 282 // Find the relevant frame with the requested index. |
| 283 StackFrame::Id id = isolate->debug()->break_frame_id(); | 283 StackFrame::Id id = isolate->debug()->break_frame_id(); |
| 284 if (id == StackFrame::NO_ID) { | 284 if (id == StackFrame::NO_ID) { |
| 285 // If there are no JavaScript stack frames return undefined. | 285 // If there are no JavaScript stack frames return undefined. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 296 // We don't really care what the inlined frame index is, since we are | 296 // We don't really care what the inlined frame index is, since we are |
| 297 // throwing away the entire frame anyways. | 297 // throwing away the entire frame anyways. |
| 298 const char* error_message = LiveEdit::RestartFrame(it.javascript_frame()); | 298 const char* error_message = LiveEdit::RestartFrame(it.javascript_frame()); |
| 299 if (error_message) { | 299 if (error_message) { |
| 300 return *(isolate->factory()->InternalizeUtf8String(error_message)); | 300 return *(isolate->factory()->InternalizeUtf8String(error_message)); |
| 301 } | 301 } |
| 302 return heap->true_value(); | 302 return heap->true_value(); |
| 303 } | 303 } |
| 304 } // namespace internal | 304 } // namespace internal |
| 305 } // namespace v8 | 305 } // namespace v8 |
| OLD | NEW |