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 |