53
54
// Ignore return value from SetElement. It can only be a failure if there
54
55
// are element setters causing exceptions and the debugger context has none
56
Handle<Object> no_failure;
57
no_failure = SetElement(object, index, value, kNonStrictMode);
57
Handle<Object> no_failure =
58
JSObject::SetElement(object, index, value, NONE, kNonStrictMode);
58
59
ASSERT(!no_failure.is_null());
600
601
PostponeInterruptsScope postpone(isolate);
603
CompilationInfo info(script);
604
CompilationInfoWithZone info(script);
604
605
info.MarkAsGlobal();
605
if (ParserApi::Parse(&info)) {
606
// Parse and don't allow skipping lazy functions.
607
if (ParserApi::Parse(&info, kNoParsingFlags)) {
606
608
// Compile the code.
607
609
LiveEditFunctionTracker tracker(info.isolate(), info.function());
608
610
if (Compiler::MakeCodeForLiveEdit(&info)) {
638
static Handle<SharedFunctionInfo> UnwrapSharedFunctionInfoFromJSValue(
639
Handle<JSValue> jsValue) {
640
Object* shared = jsValue->value();
641
CHECK(shared->IsSharedFunctionInfo());
642
return Handle<SharedFunctionInfo>(SharedFunctionInfo::cast(shared));
646
static int GetArrayLength(Handle<JSArray> array) {
647
Object* length = array->length();
648
CHECK(length->IsSmi());
649
return Smi::cast(length)->value();
636
653
// Simple helper class that creates more or less typed structures over
637
654
// JSArray object. This is an adhoc method of passing structures from C++
638
655
// to JavaScript.
712
730
return this->GetSmiValueField(kParentIndexOffset_);
714
732
Handle<Code> GetFunctionCode() {
715
Handle<Object> raw_result = UnwrapJSValue(Handle<JSValue>(
716
JSValue::cast(this->GetField(kCodeOffset_))));
733
Object* element = this->GetField(kCodeOffset_);
734
CHECK(element->IsJSValue());
735
Handle<JSValue> value_wrapper(JSValue::cast(element));
736
Handle<Object> raw_result = UnwrapJSValue(value_wrapper);
737
CHECK(raw_result->IsCode());
717
738
return Handle<Code>::cast(raw_result);
719
740
Handle<Object> GetCodeScopeInfo() {
720
Handle<Object> raw_result = UnwrapJSValue(Handle<JSValue>(
721
JSValue::cast(this->GetField(kCodeScopeInfoOffset_))));
741
Object* element = this->GetField(kCodeScopeInfoOffset_);
742
CHECK(element->IsJSValue());
743
return UnwrapJSValue(Handle<JSValue>(JSValue::cast(element)));
724
745
int GetStartPosition() {
725
746
return this->GetSmiValueField(kStartPositionOffset_);
770
791
Handle<SharedFunctionInfo> GetInfo() {
771
792
Object* element = this->GetField(kSharedInfoOffset_);
793
CHECK(element->IsJSValue());
772
794
Handle<JSValue> value_wrapper(JSValue::cast(element));
773
Handle<Object> raw_result = UnwrapJSValue(value_wrapper);
774
return Handle<SharedFunctionInfo>::cast(raw_result);
795
return UnwrapSharedFunctionInfoFromJSValue(value_wrapper);
797
818
HandleScope scope;
798
819
FunctionInfoWrapper info = FunctionInfoWrapper::Create();
799
820
info.SetInitialProperties(fun->name(), fun->start_position(),
800
fun->end_position(), fun->num_parameters(),
821
fun->end_position(), fun->parameter_count(),
801
822
current_parent_index_);
802
823
current_parent_index_ = len_;
803
824
SetElementNonStrict(result_, len_, info.GetJSArray());
824
845
// Saves full information about a function: its code, its scope info
825
846
// and a SharedFunctionInfo object.
826
void FunctionInfo(Handle<SharedFunctionInfo> shared, Scope* scope) {
847
void FunctionInfo(Handle<SharedFunctionInfo> shared, Scope* scope,
827
849
if (!shared->IsSharedFunctionInfo()) {
834
856
Handle<Object>(shared->scope_info()));
835
857
info.SetSharedFunctionInfo(shared);
837
Handle<Object> scope_info_list(SerializeFunctionScope(scope));
859
Handle<Object> scope_info_list(SerializeFunctionScope(scope, zone));
838
860
info.SetOuterScopeInfo(scope_info_list);
841
863
Handle<JSArray> GetResult() { return result_; }
844
Object* SerializeFunctionScope(Scope* scope) {
866
Object* SerializeFunctionScope(Scope* scope, Zone* zone) {
845
867
HandleScope handle_scope;
847
869
Handle<JSArray> scope_info_list = FACTORY->NewJSArray(10);
855
877
return HEAP->undefined_value();
858
ZoneList<Variable*> list(10);
859
outer_scope->CollectUsedVariables(&list);
861
for (int i = 0; i < list.length(); i++) {
862
Variable* var1 = list[i];
863
if (var1->IsContextSlot()) {
880
ZoneList<Variable*> stack_list(outer_scope->StackLocalCount(), zone);
881
ZoneList<Variable*> context_list(outer_scope->ContextLocalCount(), zone);
882
outer_scope->CollectStackAndContextLocals(&stack_list, &context_list);
883
context_list.Sort(&Variable::CompareIndex);
872
for (int k = 1; k < j; k++) {
874
for (int m = k + 1; m < j; m++) {
875
if (list[l]->index() > list[m]->index()) {
881
for (int i = 0; i < j; i++) {
885
for (int i = 0; i < context_list.length(); i++) {
882
886
SetElementNonStrict(scope_info_list,
883
887
scope_info_length,
888
context_list[i]->name());
885
889
scope_info_length++;
886
890
SetElementNonStrict(
888
892
scope_info_length,
889
Handle<Smi>(Smi::FromInt(list[i]->index())));
893
Handle<Smi>(Smi::FromInt(context_list[i]->index())));
890
894
scope_info_length++;
892
896
SetElementNonStrict(scope_info_list,
941
// Visitor that collects all references to a particular code object,
942
// including "CODE_TARGET" references in other code objects.
943
// It works in context of ZoneScope.
944
class ReferenceCollectorVisitor : public ObjectVisitor {
944
// Visitor that finds all references to a particular code object,
945
// including "CODE_TARGET" references in other code objects and replaces
947
class ReplacingVisitor : public ObjectVisitor {
946
explicit ReferenceCollectorVisitor(Code* original)
947
: original_(original), rvalues_(10), reloc_infos_(10), code_entries_(10) {
949
explicit ReplacingVisitor(Code* original, Code* substitution)
950
: original_(original), substitution_(substitution) {
950
953
virtual void VisitPointers(Object** start, Object** end) {
951
954
for (Object** p = start; p < end; p++) {
952
955
if (*p == original_) {
958
961
virtual void VisitCodeEntry(Address entry) {
959
962
if (Code::GetObjectFromEntryAddress(entry) == original_) {
960
code_entries_.Add(entry);
963
Address substitution_entry = substitution_->instruction_start();
964
Memory::Address_at(entry) = substitution_entry;
964
968
virtual void VisitCodeTarget(RelocInfo* rinfo) {
965
969
if (RelocInfo::IsCodeTarget(rinfo->rmode()) &&
966
970
Code::GetCodeFromTargetAddress(rinfo->target_address()) == original_) {
967
reloc_infos_.Add(*rinfo);
971
Address substitution_entry = substitution_->instruction_start();
972
rinfo->set_target_address(substitution_entry);
972
977
VisitCodeTarget(rinfo);
975
// Post-visiting method that iterates over all collected references and
977
void Replace(Code* substitution) {
978
for (int i = 0; i < rvalues_.length(); i++) {
979
*(rvalues_[i]) = substitution;
981
Address substitution_entry = substitution->instruction_start();
982
for (int i = 0; i < reloc_infos_.length(); i++) {
983
reloc_infos_[i].set_target_address(substitution_entry);
985
for (int i = 0; i < code_entries_.length(); i++) {
986
Address entry = code_entries_[i];
987
Memory::Address_at(entry) = substitution_entry;
993
ZoneList<Object**> rvalues_;
994
ZoneList<RelocInfo> reloc_infos_;
995
ZoneList<Address> code_entries_;
999
986
// Finds all references to original and replaces them with substitution.
1000
static void ReplaceCodeObject(Code* original, Code* substitution) {
1001
ASSERT(!HEAP->InNewSpace(substitution));
987
static void ReplaceCodeObject(Handle<Code> original,
988
Handle<Code> substitution) {
989
// Perform a full GC in order to ensure that we are not in the middle of an
990
// incremental marking phase when we are replacing the code object.
991
// Since we are not in an incremental marking phase we can write pointers
992
// to code objects (that are never in new space) without worrying about
994
HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask,
995
"liveedit.cc ReplaceCodeObject");
997
ASSERT(!HEAP->InNewSpace(*substitution));
1003
999
AssertNoAllocation no_allocations_please;
1005
// A zone scope for ReferenceCollectorVisitor.
1006
ZoneScope scope(Isolate::Current(), DELETE_ON_EXIT);
1008
ReferenceCollectorVisitor visitor(original);
1001
ReplacingVisitor visitor(*original, *substitution);
1010
1003
// Iterate over all roots. Stack frames may have pointer into original code,
1011
1004
// so temporary replace the pointers with offset numbers
1012
1005
// in prologue/epilogue.
1014
HEAP->IterateStrongRoots(&visitor, VISIT_ALL);
1006
HEAP->IterateRoots(&visitor, VISIT_ALL);
1017
1008
// Now iterate over all pointers of all objects, including code_target
1018
1009
// implicit pointers.
1102
1091
Handle<SharedFunctionInfo> shared_info = shared_info_wrapper.GetInfo();
1093
HEAP->EnsureHeapIsIterable();
1104
1095
if (IsJSFunctionCode(shared_info->code())) {
1105
1096
Handle<Code> code = compile_info_wrapper.GetFunctionCode();
1106
ReplaceCodeObject(shared_info->code(), *code);
1107
Handle<Object> code_scope_info = compile_info_wrapper.GetCodeScopeInfo();
1097
ReplaceCodeObject(Handle<Code>(shared_info->code()), code);
1098
Handle<Object> code_scope_info = compile_info_wrapper.GetCodeScopeInfo();
1108
1099
if (code_scope_info->IsFixedArray()) {
1109
shared_info->set_scope_info(SerializedScopeInfo::cast(*code_scope_info));
1100
shared_info->set_scope_info(ScopeInfo::cast(*code_scope_info));
1154
1145
void LiveEdit::SetFunctionScript(Handle<JSValue> function_wrapper,
1155
1146
Handle<Object> script_handle) {
1156
1147
Handle<SharedFunctionInfo> shared_info =
1157
Handle<SharedFunctionInfo>::cast(UnwrapJSValue(function_wrapper));
1148
UnwrapSharedFunctionInfoFromJSValue(function_wrapper);
1149
CHECK(script_handle->IsScript() || script_handle->IsUndefined());
1158
1150
shared_info->set_script(*script_handle);
1160
1152
Isolate::Current()->compilation_cache()->Remove(shared_info);
1173
1165
static int TranslatePosition(int original_position,
1174
1166
Handle<JSArray> position_change_array) {
1175
1167
int position_diff = 0;
1176
int array_len = Smi::cast(position_change_array->length())->value();
1168
int array_len = GetArrayLength(position_change_array);
1177
1169
// TODO(635): binary search may be used here
1178
1170
for (int i = 0; i < array_len; i += 3) {
1179
1171
Object* element = position_change_array->GetElementNoExceptionThrown(i);
1172
CHECK(element->IsSmi());
1180
1173
int chunk_start = Smi::cast(element)->value();
1181
1174
if (original_position < chunk_start) {
1184
1177
element = position_change_array->GetElementNoExceptionThrown(i + 1);
1178
CHECK(element->IsSmi());
1185
1179
int chunk_end = Smi::cast(element)->value();
1186
1180
// Position mustn't be inside a chunk.
1187
1181
ASSERT(original_position >= chunk_end);
1188
1182
element = position_change_array->GetElementNoExceptionThrown(i + 2);
1183
CHECK(element->IsSmi());
1189
1184
int chunk_changed_end = Smi::cast(element)->value();
1190
1185
position_diff = chunk_changed_end - chunk_end;
1272
1267
// Patch positions in code (changes relocation info section) and possibly
1273
1268
// returns new instance of code.
1274
static Handle<Code> PatchPositionsInCode(Handle<Code> code,
1269
static Handle<Code> PatchPositionsInCode(
1275
1271
Handle<JSArray> position_change_array) {
1277
1273
RelocInfoBuffer buffer_writer(code->relocation_size(),
1286
1282
int new_position = TranslatePosition(position,
1287
1283
position_change_array);
1288
1284
if (position != new_position) {
1289
RelocInfo info_copy(rinfo->pc(), rinfo->rmode(), new_position);
1285
RelocInfo info_copy(rinfo->pc(), rinfo->rmode(), new_position, NULL);
1290
1286
buffer_writer.Write(&info_copy);
1401
1398
Handle<JSValue> subst_function_wrapper) {
1403
1400
Handle<SharedFunctionInfo> parent_shared =
1404
Handle<SharedFunctionInfo>::cast(UnwrapJSValue(parent_function_wrapper));
1401
UnwrapSharedFunctionInfoFromJSValue(parent_function_wrapper);
1405
1402
Handle<SharedFunctionInfo> orig_shared =
1406
Handle<SharedFunctionInfo>::cast(UnwrapJSValue(orig_function_wrapper));
1403
UnwrapSharedFunctionInfoFromJSValue(orig_function_wrapper);
1407
1404
Handle<SharedFunctionInfo> subst_shared =
1408
Handle<SharedFunctionInfo>::cast(UnwrapJSValue(subst_function_wrapper));
1405
UnwrapSharedFunctionInfoFromJSValue(subst_function_wrapper);
1410
1407
for (RelocIterator it(parent_shared->code()); !it.done(); it.next()) {
1411
1408
if (it.rinfo()->rmode() == RelocInfo::EMBEDDED_OBJECT) {
1428
1425
Handle<JSFunction> function(
1429
1426
JSFunction::cast(JavaScriptFrame::cast(frame)->function()));
1431
int len = Smi::cast(shared_info_array->length())->value();
1428
int len = GetArrayLength(shared_info_array);
1432
1429
for (int i = 0; i < len; i++) {
1434
JSValue::cast(shared_info_array->GetElementNoExceptionThrown(i));
1435
Handle<SharedFunctionInfo> shared(
1436
SharedFunctionInfo::cast(wrapper->value()));
1430
Object* element = shared_info_array->GetElementNoExceptionThrown(i);
1431
CHECK(element->IsJSValue());
1432
Handle<JSValue> jsvalue(JSValue::cast(element));
1433
Handle<SharedFunctionInfo> shared =
1434
UnwrapSharedFunctionInfoFromJSValue(jsvalue);
1438
1436
if (function->shared() == *shared || IsInlined(*function, *shared)) {
1439
1437
SetElementNonStrict(result, i, Handle<Smi>(Smi::FromInt(status)));
1487
1485
// Check the nature of the top frame.
1488
1486
Isolate* isolate = Isolate::Current();
1489
1487
Code* pre_top_frame_code = pre_top_frame->LookupCode();
1488
bool frame_has_padding;
1490
1489
if (pre_top_frame_code->is_inline_cache_stub() &&
1491
1490
pre_top_frame_code->ic_state() == DEBUG_BREAK) {
1492
1491
// OK, we can drop inline cache calls.
1493
1492
*mode = Debug::FRAME_DROPPED_IN_IC_CALL;
1493
frame_has_padding = Debug::FramePaddingLayout::kIsSupported;
1494
1494
} else if (pre_top_frame_code ==
1495
1495
isolate->debug()->debug_break_slot()) {
1496
1496
// OK, we can drop debug break slot.
1497
1497
*mode = Debug::FRAME_DROPPED_IN_DEBUG_SLOT_CALL;
1498
frame_has_padding = Debug::FramePaddingLayout::kIsSupported;
1498
1499
} else if (pre_top_frame_code ==
1499
1500
isolate->builtins()->builtin(
1500
1501
Builtins::kFrameDropper_LiveEdit)) {
1501
1502
// OK, we can drop our own code.
1502
*mode = Debug::FRAME_DROPPED_IN_DIRECT_CALL;
1503
pre_top_frame = frames[top_frame_index - 2];
1504
top_frame = frames[top_frame_index - 1];
1505
*mode = Debug::CURRENTLY_SET_MODE;
1506
frame_has_padding = false;
1503
1507
} else if (pre_top_frame_code ==
1504
1508
isolate->builtins()->builtin(Builtins::kReturn_DebugBreak)) {
1505
1509
*mode = Debug::FRAME_DROPPED_IN_RETURN_CALL;
1510
frame_has_padding = Debug::FramePaddingLayout::kIsSupported;
1506
1511
} else if (pre_top_frame_code->kind() == Code::STUB &&
1507
pre_top_frame_code->major_key()) {
1508
// Entry from our unit tests, it's fine, we support this case.
1512
pre_top_frame_code->major_key() == CodeStub::CEntry) {
1513
// Entry from our unit tests on 'debugger' statement.
1514
// It's fine, we support this case.
1509
1515
*mode = Debug::FRAME_DROPPED_IN_DIRECT_CALL;
1516
// We don't have a padding from 'debugger' statement call.
1517
// Here the stub is CEntry, it's not debug-only and can't be padded.
1518
// If anyone would complain, a proxy padded stub could be added.
1519
frame_has_padding = false;
1520
} else if (pre_top_frame->type() == StackFrame::ARGUMENTS_ADAPTOR) {
1521
// This must be adaptor that remain from the frame dropping that
1522
// is still on stack. A frame dropper frame must be above it.
1523
ASSERT(frames[top_frame_index - 2]->LookupCode() ==
1524
isolate->builtins()->builtin(Builtins::kFrameDropper_LiveEdit));
1525
pre_top_frame = frames[top_frame_index - 3];
1526
top_frame = frames[top_frame_index - 2];
1527
*mode = Debug::CURRENTLY_SET_MODE;
1528
frame_has_padding = false;
1511
1530
return "Unknown structure of stack above changing function";
1516
1535
- Debug::kFrameDropperFrameSize * kPointerSize // Size of the new frame.
1517
1536
+ kPointerSize; // Bigger address end is exclusive.
1538
Address* top_frame_pc_address = top_frame->pc_address();
1540
// top_frame may be damaged below this point. Do not used it.
1541
ASSERT(!(top_frame = NULL));
1519
1543
if (unused_stack_top > unused_stack_bottom) {
1520
return "Not enough space for frame dropper frame";
1544
if (frame_has_padding) {
1545
int shortage_bytes =
1546
static_cast<int>(unused_stack_top - unused_stack_bottom);
1548
Address padding_start = pre_top_frame->fp() -
1549
Debug::FramePaddingLayout::kFrameBaseSize * kPointerSize;
1551
Address padding_pointer = padding_start;
1552
Smi* padding_object =
1553
Smi::FromInt(Debug::FramePaddingLayout::kPaddingValue);
1554
while (Memory::Object_at(padding_pointer) == padding_object) {
1555
padding_pointer -= kPointerSize;
1557
int padding_counter =
1558
Smi::cast(Memory::Object_at(padding_pointer))->value();
1559
if (padding_counter * kPointerSize < shortage_bytes) {
1560
return "Not enough space for frame dropper frame "
1561
"(even with padding frame)";
1563
Memory::Object_at(padding_pointer) =
1564
Smi::FromInt(padding_counter - shortage_bytes / kPointerSize);
1566
StackFrame* pre_pre_frame = frames[top_frame_index - 2];
1568
memmove(padding_start + kPointerSize - shortage_bytes,
1569
padding_start + kPointerSize,
1570
Debug::FramePaddingLayout::kFrameBaseSize * kPointerSize);
1572
pre_top_frame->UpdateFp(pre_top_frame->fp() - shortage_bytes);
1573
pre_pre_frame->SetCallerFp(pre_top_frame->fp());
1574
unused_stack_top -= shortage_bytes;
1576
STATIC_ASSERT(sizeof(Address) == kPointerSize);
1577
top_frame_pc_address -= shortage_bytes / kPointerSize;
1579
return "Not enough space for frame dropper frame";
1523
1583
// Committing now. After this point we should return only NULL value.
1549
1609
return !frame->is_exit();
1552
// Fills result array with statuses of functions. Modifies the stack
1553
// removing all listed function if possible and if do_drop is true.
1554
static const char* DropActivationsInActiveThread(
1555
Handle<JSArray> shared_info_array, Handle<JSArray> result, bool do_drop) {
1613
// Describes a set of call frames that execute any of listed functions.
1614
// Finding no such frames does not mean error.
1615
class MultipleFunctionTarget {
1617
MultipleFunctionTarget(Handle<JSArray> shared_info_array,
1618
Handle<JSArray> result)
1619
: m_shared_info_array(shared_info_array),
1621
bool MatchActivation(StackFrame* frame,
1622
LiveEdit::FunctionPatchabilityStatus status) {
1623
return CheckActivation(m_shared_info_array, m_result, frame, status);
1625
const char* GetNotFoundMessage() {
1629
Handle<JSArray> m_shared_info_array;
1630
Handle<JSArray> m_result;
1633
// Drops all call frame matched by target and all frames above them.
1634
template<typename TARGET>
1635
static const char* DropActivationsInActiveThreadImpl(
1636
TARGET& target, bool do_drop, Zone* zone) {
1556
1637
Isolate* isolate = Isolate::Current();
1557
1638
Debug* debug = isolate->debug();
1558
ZoneScope scope(isolate, DELETE_ON_EXIT);
1559
Vector<StackFrame*> frames = CreateStackMap();
1639
ZoneScope scope(zone, DELETE_ON_EXIT);
1640
Vector<StackFrame*> frames = CreateStackMap(zone);
1561
int array_len = Smi::cast(shared_info_array->length())->value();
1563
1643
int top_frame_index = -1;
1564
1644
int frame_index = 0;
1568
1648
top_frame_index = frame_index;
1571
if (CheckActivation(shared_info_array, result, frame,
1572
LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE)) {
1651
if (target.MatchActivation(
1652
frame, LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE)) {
1573
1653
// We are still above break_frame. It is not a target frame,
1574
1654
// it is a problem.
1575
1655
return "Debugger mark-up on stack is not found";
1591
1671
c_code_found = true;
1594
if (CheckActivation(shared_info_array, result, frame,
1595
LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) {
1674
if (target.MatchActivation(
1675
frame, LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) {
1596
1676
target_frame_found = true;
1597
1677
bottom_js_frame_index = frame_index;
1604
1684
for (; frame_index < frames.length(); frame_index++) {
1605
1685
StackFrame* frame = frames[frame_index];
1606
1686
if (frame->is_java_script()) {
1607
if (CheckActivation(shared_info_array, result, frame,
1608
LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE)) {
1687
if (target.MatchActivation(
1688
frame, LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE)) {
1609
1689
// Cannot drop frame under C frames.
1644
1724
debug->FramesHaveBeenDropped(new_id, drop_mode,
1645
1725
restarter_frame_function_pointer);
1729
// Fills result array with statuses of functions. Modifies the stack
1730
// removing all listed function if possible and if do_drop is true.
1731
static const char* DropActivationsInActiveThread(
1732
Handle<JSArray> shared_info_array, Handle<JSArray> result, bool do_drop,
1734
MultipleFunctionTarget target(shared_info_array, result);
1736
const char* message =
1737
DropActivationsInActiveThreadImpl(target, do_drop, zone);
1742
int array_len = GetArrayLength(shared_info_array);
1647
1744
// Replace "blocked on active" with "replaced on active" status.
1648
1745
for (int i = 0; i < array_len; i++) {
1685
1782
Handle<JSArray> LiveEdit::CheckAndDropActivations(
1686
Handle<JSArray> shared_info_array, bool do_drop) {
1687
int len = Smi::cast(shared_info_array->length())->value();
1783
Handle<JSArray> shared_info_array, bool do_drop, Zone* zone) {
1784
int len = GetArrayLength(shared_info_array);
1689
1786
Handle<JSArray> result = FACTORY->NewJSArray(len);
1709
1806
// Try to drop activations from the current stack.
1710
1807
const char* error_message =
1711
DropActivationsInActiveThread(shared_info_array, result, do_drop);
1808
DropActivationsInActiveThread(shared_info_array, result, do_drop, zone);
1712
1809
if (error_message != NULL) {
1713
1810
// Add error message as an array extra element.
1714
1811
Vector<const char> vector_message(error_message, StrLength(error_message));
1819
// Describes a single callframe a target. Not finding this frame
1821
class SingleFrameTarget {
1823
explicit SingleFrameTarget(JavaScriptFrame* frame)
1825
m_saved_status(LiveEdit::FUNCTION_AVAILABLE_FOR_PATCH) {}
1827
bool MatchActivation(StackFrame* frame,
1828
LiveEdit::FunctionPatchabilityStatus status) {
1829
if (frame->fp() == m_frame->fp()) {
1830
m_saved_status = status;
1835
const char* GetNotFoundMessage() {
1836
return "Failed to found requested frame";
1838
LiveEdit::FunctionPatchabilityStatus saved_status() {
1839
return m_saved_status;
1842
JavaScriptFrame* m_frame;
1843
LiveEdit::FunctionPatchabilityStatus m_saved_status;
1847
// Finds a drops required frame and all frames above.
1848
// Returns error message or NULL.
1849
const char* LiveEdit::RestartFrame(JavaScriptFrame* frame, Zone* zone) {
1850
SingleFrameTarget target(frame);
1852
const char* result = DropActivationsInActiveThreadImpl(target, true, zone);
1853
if (result != NULL) {
1856
if (target.saved_status() == LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE) {
1857
return "Function is blocked under native code";
1722
1863
LiveEditFunctionTracker::LiveEditFunctionTracker(Isolate* isolate,
1723
1864
FunctionLiteral* fun)
1724
1865
: isolate_(isolate) {
1738
1879
void LiveEditFunctionTracker::RecordFunctionInfo(
1739
Handle<SharedFunctionInfo> info, FunctionLiteral* lit) {
1880
Handle<SharedFunctionInfo> info, FunctionLiteral* lit,
1740
1882
if (isolate_->active_function_info_listener() != NULL) {
1741
isolate_->active_function_info_listener()->FunctionInfo(info, lit->scope());
1883
isolate_->active_function_info_listener()->FunctionInfo(info, lit->scope(),