BLOCKED_ON_ACTIVE_STACK: 2,
BLOCKED_ON_OTHER_STACK: 3,
BLOCKED_UNDER_NATIVE_CODE: 4,
- REPLACED_ON_ACTIVE_STACK: 5,
- BLOCKED_UNDER_GENERATOR: 6,
- BLOCKED_ACTIVE_GENERATOR: 7
+ REPLACED_ON_ACTIVE_STACK: 5
};
FunctionPatchabilityStatus.SymbolName = function(code) {
}
+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 {
bool target_frame_found = false;
int bottom_js_frame_index = top_frame_index;
- bool non_droppable_frame_found = false;
- LiveEdit::FunctionPatchabilityStatus non_droppable_reason;
+ bool c_code_found = false;
for (; frame_index < frames.length(); frame_index++) {
StackFrame* frame = frames[frame_index];
- 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;
+ if (!IsDropableFrame(frame)) {
+ c_code_found = true;
break;
}
if (target.MatchActivation(
}
}
- 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.
+ if (c_code_found) {
+ // There is a C frames on stack. 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, non_droppable_reason)) {
- // Fail.
+ if (target.MatchActivation(
+ frame, LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE)) {
+ // Cannot drop frame under C frames.
return NULL;
}
}
}
-bool LiveEdit::FindActiveGenerators(Handle<FixedArray> shared_info_array,
- Handle<FixedArray> result,
- int len) {
- 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) {
- 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,
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++) {
- FunctionPatchabilityStatus status = FUNCTION_AVAILABLE_FOR_PATCH;
- result_elements->set(i, Smi::FromInt(status));
+ SetElementSloppy(
+ result,
+ i,
+ Handle<Smi>(Smi::FromInt(FUNCTION_AVAILABLE_FOR_PATCH), isolate));
}
- // 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)) {
- return result;
- }
- // Check inactive threads. Fail if some functions are blocked there.
+ // First check inactive threads. Fail if some functions are blocked there.
InactiveThreadActivationsChecker inactive_threads_checker(shared_info_array,
result);
isolate->thread_manager()->IterateArchivedThreads(
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;
}
Handle<JSValue> orig_function_shared,
Handle<JSValue> subst_function_shared);
- // Find open generator activations, and set corresponding "result" elements to
- // FUNCTION_BLOCKED_ACTIVE_GENERATOR.
- static bool FindActiveGenerators(Handle<FixedArray> shared_info_array,
- Handle<FixedArray> result, int len);
-
// Checks listed functions on stack and return array with corresponding
// FunctionPatchabilityStatus statuses; extra array element may
// contain general error message. Modifies the current stack and
FUNCTION_BLOCKED_ON_ACTIVE_STACK = 2,
FUNCTION_BLOCKED_ON_OTHER_STACK = 3,
FUNCTION_BLOCKED_UNDER_NATIVE_CODE = 4,
- FUNCTION_REPLACED_ON_ACTIVE_STACK = 5,
- FUNCTION_BLOCKED_UNDER_GENERATOR = 6,
- FUNCTION_BLOCKED_ACTIVE_GENERATOR = 7
+ FUNCTION_REPLACED_ON_ACTIVE_STACK = 5
};
// Compares 2 strings line-by-line, then token-wise and returns diff in form
return continuation() > 0;
}
-bool JSGeneratorObject::is_closed() {
- return continuation() == kGeneratorClosed;
-}
-
-bool JSGeneratorObject::is_executing() {
- return continuation() == kGeneratorExecuting;
-}
-
JSGeneratorObject* JSGeneratorObject::cast(Object* obj) {
ASSERT(obj->IsJSGeneratorObject());
ASSERT(HeapObject::cast(obj)->Size() == JSGeneratorObject::kSize);
// cannot be resumed.
inline int continuation();
inline void set_continuation(int continuation);
- inline bool is_closed();
- inline bool is_executing();
inline bool is_suspended();
// [operand_stack]: Saved operand stack.
+++ /dev/null
-// 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.
-
-// Flags: --expose-debug-as debug --harmony-generators
-
-var Debug = debug.Debug;
-var LiveEdit = Debug.LiveEdit;
-
-unique_id = 0;
-
-var Generator = (function*(){}).constructor;
-
-function assertIteratorResult(value, done, result) {
- assertEquals({value: value, done: done}, result);
-}
-
-function MakeGenerator() {
- // Prevents eval script caching.
- unique_id++;
- return Generator('callback',
- "/* " + unique_id + "*/\n" +
- "yield callback();\n" +
- "return 'Cat';\n");
-}
-
-function MakeFunction() {
- // Prevents eval script caching.
- unique_id++;
- return Function('callback',
- "/* " + unique_id + "*/\n" +
- "callback();\n" +
- "return 'Cat';\n");
-}
-
-// First, try MakeGenerator with no perturbations.
-(function(){
- var generator = MakeGenerator();
- function callback() {};
- var iter = generator(callback);
- assertIteratorResult(undefined, false, iter.next());
- assertIteratorResult("Cat", true, iter.next());
-})();
-
-function patch(fun, from, to) {
- function debug() {
- var log = new Array();
- var script = Debug.findScript(fun);
- var pos = script.source.indexOf(from);
- try {
- LiveEdit.TestApi.ApplySingleChunkPatch(script, pos, from.length, to,
- log);
- } finally {
- print("Change log: " + JSON.stringify(log) + "\n");
- }
- }
- Debug.ExecuteInDebugContext(debug, false);
-}
-
-// Try to edit a MakeGenerator while it's running, then again while it's
-// stopped.
-(function(){
- var generator = MakeGenerator();
-
- var gen_patch_attempted = false;
- function attempt_gen_patch() {
- assertFalse(gen_patch_attempted);
- gen_patch_attempted = true;
- assertThrows(function() { patch(generator, "'Cat'", "'Capybara'") },
- LiveEdit.Failure);
- };
- var iter = generator(attempt_gen_patch);
- assertIteratorResult(undefined, false, iter.next());
- // Patch should not succeed because there is a live generator activation on
- // the stack.
- assertIteratorResult("Cat", true, iter.next());
- assertTrue(gen_patch_attempted);
-
- // At this point one iterator is live, but closed, so the patch will succeed.
- patch(generator, "'Cat'", "'Capybara'");
- iter = generator(function(){});
- assertIteratorResult(undefined, false, iter.next());
- // Patch successful.
- assertIteratorResult("Capybara", true, iter.next());
-
- // Patching will fail however when a live iterator is suspended.
- iter = generator(function(){});
- assertIteratorResult(undefined, false, iter.next());
- assertThrows(function() { patch(generator, "'Capybara'", "'Tapir'") },
- LiveEdit.Failure);
- assertIteratorResult("Capybara", true, iter.next());
-
- // Try to patch functions with activations inside and outside generator
- // function activations. We should succeed in the former case, but not in the
- // latter.
- var fun_outside = MakeFunction();
- var fun_inside = MakeFunction();
- var fun_patch_attempted = false;
- var fun_patch_restarted = false;
- function attempt_fun_patches() {
- if (fun_patch_attempted) {
- assertFalse(fun_patch_restarted);
- fun_patch_restarted = true;
- return;
- }
- fun_patch_attempted = true;
- // Patching outside a generator activation must fail.
- assertThrows(function() { patch(fun_outside, "'Cat'", "'Cobra'") },
- LiveEdit.Failure);
- // Patching inside a generator activation may succeed.
- patch(fun_inside, "'Cat'", "'Koala'");
- }
- iter = generator(function() { return fun_inside(attempt_fun_patches) });
- assertEquals('Cat',
- fun_outside(function () {
- assertIteratorResult('Koala', false, iter.next());
- assertTrue(fun_patch_restarted);
- }));
-})();
'debug-liveedit-stack-padding': [SKIP],
'debug-liveedit-restart-frame': [SKIP],
'debug-liveedit-double-call': [SKIP],
- 'harmony/generators-debug-liveedit': [SKIP],
# BUG(v8:3147). It works on other architectures by accident.
'regress/regress-conditional-position': [FAIL],
'debug-liveedit-stack-padding': [SKIP],
'debug-liveedit-restart-frame': [SKIP],
'debug-liveedit-double-call': [SKIP],
- 'harmony/generators-debug-liveedit': [SKIP],
# Currently always deopt on minus zero
'math-floor-of-div-minus-zero': [SKIP],
'debug-liveedit-stack-padding': [SKIP],
'debug-liveedit-restart-frame': [SKIP],
'debug-liveedit-double-call': [SKIP],
- 'harmony/generators-debug-liveedit': [SKIP],
# Currently always deopt on minus zero
'math-floor-of-div-minus-zero': [SKIP],
'debug-liveedit-stack-padding': [SKIP],
'debug-liveedit-restart-frame': [SKIP],
'debug-liveedit-double-call': [SKIP],
- 'harmony/generators-debug-liveedit': [SKIP],
# This test dumps core for arm.debug, so no reason to expect it to work
# for NaCl. The other three fuzz-natives tests seem to run fine.