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

Unified Diff: src/liveedit.cc

Issue 266983004: Prevent liveedit on or under generators with open activations (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 8 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
Index: src/liveedit.cc
diff --git a/src/liveedit.cc b/src/liveedit.cc
index e4d35d650fc285feac9eef2f4cfaf8b3aef21e1e..1df4729e69515ff04fe55bb002f6b06442940bde 100644
--- a/src/liveedit.cc
+++ b/src/liveedit.cc
@@ -1655,11 +1655,6 @@ static const char* DropFrames(Vector<StackFrame*> frames,
}
-static bool IsDropableFrame(StackFrame* frame) {
- return !frame->is_exit();
-}
-
-
// Describes a set of call frames that execute any of listed functions.
// Finding no such frames does not mean error.
class MultipleFunctionTarget {
@@ -1713,12 +1708,20 @@ static const char* DropActivationsInActiveThreadImpl(
bool target_frame_found = false;
int bottom_js_frame_index = top_frame_index;
- bool c_code_found = false;
+ bool non_droppable_frame_found = false;
+ LiveEdit::FunctionPatchabilityStatus non_droppable_reason;
for (; frame_index < frames.length(); frame_index++) {
StackFrame* frame = frames[frame_index];
- if (!IsDropableFrame(frame)) {
- c_code_found = true;
+ if (frame->is_exit()) {
+ non_droppable_frame_found = true;
+ non_droppable_reason = LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE;
+ break;
+ }
+ if (!frame->is_java_script()) continue;
+ if (JavaScriptFrame::cast(frame)->function()->shared()->is_generator()) {
+ non_droppable_frame_found = true;
+ non_droppable_reason = LiveEdit::FUNCTION_BLOCKED_UNDER_GENERATOR;
break;
}
if (target.MatchActivation(
@@ -1728,15 +1731,15 @@ static const char* DropActivationsInActiveThreadImpl(
}
}
- if (c_code_found) {
- // There is a C frames on stack. Check that there are no target frames
- // below them.
+ if (non_droppable_frame_found) {
+ // There is a C or generator frame on stack. We can't drop C frames, and we
+ // can't restart generators. Check that there are no target frames below
+ // them.
for (; frame_index < frames.length(); frame_index++) {
StackFrame* frame = frames[frame_index];
if (frame->is_java_script()) {
- if (target.MatchActivation(
- frame, LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE)) {
- // Cannot drop frame under C frames.
+ if (target.MatchActivation(frame, non_droppable_reason)) {
+ // Fail.
return NULL;
}
}
@@ -1806,6 +1809,46 @@ static const char* DropActivationsInActiveThread(
}
+bool LiveEdit::FindActiveGenerators(Handle<FixedArray> shared_info_array,
+ Handle<FixedArray> result, int len) {
Yang 2014/05/06 13:05:03 one argument per line is easier on the eye.
+ Isolate* isolate = shared_info_array->GetIsolate();
+ Heap* heap = isolate->heap();
+ heap->EnsureHeapIsIterable();
+ bool found_suspended_activations = false;
+
+ ASSERT_LE(len, result->length());
+
+ DisallowHeapAllocation no_allocation;
+
+ FunctionPatchabilityStatus active = FUNCTION_BLOCKED_ACTIVE_GENERATOR;
+
+ HeapIterator iterator(heap);
+ HeapObject* obj = NULL;
+ while (((obj = iterator.next()) != NULL)) {
Yang 2014/05/06 13:05:03 I think we can remove one set of brackets here.
+ if (!obj->IsJSGeneratorObject()) continue;
+
+ JSGeneratorObject* gen = JSGeneratorObject::cast(obj);
+ if (gen->is_closed()) continue;
+
+ HandleScope scope(isolate);
+
+ for (int i = 0; i < len; i++) {
+ Handle<JSValue> jsvalue =
+ Handle<JSValue>::cast(FixedArray::get(shared_info_array, i));
+ Handle<SharedFunctionInfo> shared =
+ UnwrapSharedFunctionInfoFromJSValue(jsvalue);
+
+ if (gen->function()->shared() == *shared) {
+ result->set(i, Smi::FromInt(active));
+ found_suspended_activations = true;
+ }
+ }
+ }
+
+ return found_suspended_activations;
+}
+
+
class InactiveThreadActivationsChecker : public ThreadVisitor {
public:
InactiveThreadActivationsChecker(Handle<JSArray> shared_info_array,
@@ -1836,18 +1879,28 @@ Handle<JSArray> LiveEdit::CheckAndDropActivations(
Isolate* isolate = shared_info_array->GetIsolate();
int len = GetArrayLength(shared_info_array);
+ CHECK(shared_info_array->HasFastElements());
+ Handle<FixedArray> shared_info_array_elements(
+ FixedArray::cast(shared_info_array->elements()));
+
Handle<JSArray> result = isolate->factory()->NewJSArray(len);
+ Handle<FixedArray> result_elements =
+ JSObject::EnsureWritableFastElements(result);
// Fill the default values.
for (int i = 0; i < len; i++) {
- SetElementSloppy(
- result,
- i,
- Handle<Smi>(Smi::FromInt(FUNCTION_AVAILABLE_FOR_PATCH), isolate));
+ FunctionPatchabilityStatus status = FUNCTION_AVAILABLE_FOR_PATCH;
+ result_elements->set(i, Smi::FromInt(status));
}
+ // Scan the heap for active generators -- those that are either currently
+ // running (as we wouldn't want to restart them, because we don't know where
+ // to restart them from) or suspended. Fail if any one corresponds to the set
+ // of functions being edited.
+ if (FindActiveGenerators(shared_info_array_elements, result_elements, len))
Yang 2014/05/06 13:05:03 please use curly brackets if the if-statement cont
+ return result;
- // First check inactive threads. Fail if some functions are blocked there.
+ // Check inactive threads. Fail if some functions are blocked there.
InactiveThreadActivationsChecker inactive_threads_checker(shared_info_array,
result);
isolate->thread_manager()->IterateArchivedThreads(
@@ -1910,6 +1963,9 @@ const char* LiveEdit::RestartFrame(JavaScriptFrame* frame) {
if (target.saved_status() == LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE) {
return "Function is blocked under native code";
}
+ if (target.saved_status() == LiveEdit::FUNCTION_BLOCKED_UNDER_GENERATOR) {
+ return "Function is blocked under a generator activation";
+ }
return NULL;
}

Powered by Google App Engine
This is Rietveld 408576698