OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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/debug/liveedit.h" | 5 #include "src/debug/liveedit.h" |
6 | 6 |
7 #include "src/ast/scopes.h" | 7 #include "src/ast/scopes.h" |
8 #include "src/code-stubs.h" | 8 #include "src/code-stubs.h" |
9 #include "src/compilation-cache.h" | 9 #include "src/compilation-cache.h" |
10 #include "src/compiler.h" | 10 #include "src/compiler.h" |
(...skipping 634 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
645 | 645 |
646 | 646 |
647 Handle<SharedFunctionInfo> SharedInfoWrapper::GetInfo() { | 647 Handle<SharedFunctionInfo> SharedInfoWrapper::GetInfo() { |
648 Handle<Object> element = this->GetField(kSharedInfoOffset_); | 648 Handle<Object> element = this->GetField(kSharedInfoOffset_); |
649 Handle<JSValue> value_wrapper = Handle<JSValue>::cast(element); | 649 Handle<JSValue> value_wrapper = Handle<JSValue>::cast(element); |
650 return UnwrapSharedFunctionInfoFromJSValue(value_wrapper); | 650 return UnwrapSharedFunctionInfoFromJSValue(value_wrapper); |
651 } | 651 } |
652 | 652 |
653 | 653 |
654 void LiveEdit::InitializeThreadLocal(Debug* debug) { | 654 void LiveEdit::InitializeThreadLocal(Debug* debug) { |
655 debug->thread_local_.frame_drop_mode_ = LIVE_EDIT_FRAMES_UNTOUCHED; | 655 debug->thread_local_.restart_fp_ = 0; |
656 } | 656 } |
657 | 657 |
658 | 658 |
659 bool LiveEdit::SetAfterBreakTarget(Debug* debug) { | |
660 Code* code = NULL; | |
661 Isolate* isolate = debug->isolate_; | |
662 switch (debug->thread_local_.frame_drop_mode_) { | |
663 case LIVE_EDIT_FRAMES_UNTOUCHED: | |
664 return false; | |
665 case LIVE_EDIT_FRAME_DROPPED_IN_DEBUG_SLOT_CALL: | |
666 // Debug break slot stub does not return normally, instead it manually | |
667 // cleans the stack and jumps. We should patch the jump address. | |
668 code = isolate->builtins()->builtin(Builtins::kFrameDropper_LiveEdit); | |
669 break; | |
670 case LIVE_EDIT_FRAME_DROPPED_IN_DIRECT_CALL: | |
671 // Nothing to do, after_break_target is not used here. | |
672 return true; | |
673 case LIVE_EDIT_FRAME_DROPPED_IN_RETURN_CALL: | |
674 code = isolate->builtins()->builtin(Builtins::kFrameDropper_LiveEdit); | |
675 break; | |
676 case LIVE_EDIT_CURRENTLY_SET_MODE: | |
677 UNREACHABLE(); | |
678 break; | |
679 } | |
680 debug->after_break_target_ = code->entry(); | |
681 return true; | |
682 } | |
683 | |
684 | |
685 MaybeHandle<JSArray> LiveEdit::GatherCompileInfo(Handle<Script> script, | 659 MaybeHandle<JSArray> LiveEdit::GatherCompileInfo(Handle<Script> script, |
686 Handle<String> source) { | 660 Handle<String> source) { |
687 Isolate* isolate = script->GetIsolate(); | 661 Isolate* isolate = script->GetIsolate(); |
688 | 662 |
689 MaybeHandle<JSArray> infos; | 663 MaybeHandle<JSArray> infos; |
690 Handle<Object> original_source = | 664 Handle<Object> original_source = |
691 Handle<Object>(script->source(), isolate); | 665 Handle<Object>(script->source(), isolate); |
692 script->set_source(*source); | 666 script->set_source(*source); |
693 | 667 |
694 { | 668 { |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
738 // A logical 'finally' section. | 712 // A logical 'finally' section. |
739 script->set_source(*original_source); | 713 script->set_source(*original_source); |
740 | 714 |
741 if (rethrow_exception.is_null()) { | 715 if (rethrow_exception.is_null()) { |
742 return infos.ToHandleChecked(); | 716 return infos.ToHandleChecked(); |
743 } else { | 717 } else { |
744 return isolate->Throw<JSArray>(rethrow_exception); | 718 return isolate->Throw<JSArray>(rethrow_exception); |
745 } | 719 } |
746 } | 720 } |
747 | 721 |
748 | |
749 // Visitor that finds all references to a particular code object, | |
750 // including "CODE_TARGET" references in other code objects and replaces | |
751 // them on the fly. | |
752 class ReplacingVisitor : public ObjectVisitor { | |
753 public: | |
754 explicit ReplacingVisitor(Code* original, Code* substitution) | |
755 : original_(original), substitution_(substitution) { | |
756 } | |
757 | |
758 void VisitPointers(Object** start, Object** end) override { | |
759 for (Object** p = start; p < end; p++) { | |
760 if (*p == original_) { | |
761 *p = substitution_; | |
762 } | |
763 } | |
764 } | |
765 | |
766 void VisitCodeEntry(Address entry) override { | |
767 if (Code::GetObjectFromEntryAddress(entry) == original_) { | |
768 Address substitution_entry = substitution_->instruction_start(); | |
769 Memory::Address_at(entry) = substitution_entry; | |
770 } | |
771 } | |
772 | |
773 void VisitCodeTarget(RelocInfo* rinfo) override { | |
774 if (RelocInfo::IsCodeTarget(rinfo->rmode()) && | |
775 Code::GetCodeFromTargetAddress(rinfo->target_address()) == original_) { | |
776 Address substitution_entry = substitution_->instruction_start(); | |
777 rinfo->set_target_address(substitution_entry); | |
778 } | |
779 } | |
780 | |
781 void VisitDebugTarget(RelocInfo* rinfo) override { VisitCodeTarget(rinfo); } | |
782 | |
783 private: | |
784 Code* original_; | |
785 Code* substitution_; | |
786 }; | |
787 | |
788 | |
789 // Finds all references to original and replaces them with substitution. | 722 // Finds all references to original and replaces them with substitution. |
790 static void ReplaceCodeObject(Handle<Code> original, | 723 static void ReplaceCodeObject(Handle<Code> original, |
791 Handle<Code> substitution) { | 724 Handle<Code> substitution) { |
792 // Perform a full GC in order to ensure that we are not in the middle of an | 725 // Perform a full GC in order to ensure that we are not in the middle of an |
793 // incremental marking phase when we are replacing the code object. | 726 // incremental marking phase when we are replacing the code object. |
794 // Since we are not in an incremental marking phase we can write pointers | 727 // Since we are not in an incremental marking phase we can write pointers |
795 // to code objects (that are never in new space) without worrying about | 728 // to code objects (that are never in new space) without worrying about |
796 // write barriers. | 729 // write barriers. |
797 Heap* heap = original->GetHeap(); | 730 Heap* heap = original->GetHeap(); |
798 HeapIterator iterator(heap); | 731 HeapIterator iterator(heap); |
799 | |
800 DCHECK(!heap->InNewSpace(*substitution)); | |
801 | |
802 ReplacingVisitor visitor(*original, *substitution); | |
803 | |
804 // Iterate over all roots. Stack frames may have pointer into original code, | |
805 // so temporary replace the pointers with offset numbers | |
806 // in prologue/epilogue. | |
807 heap->IterateRoots(&visitor, VISIT_ALL); | |
808 | |
809 // Now iterate over all pointers of all objects, including code_target | 732 // Now iterate over all pointers of all objects, including code_target |
810 // implicit pointers. | 733 // implicit pointers. |
811 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { | 734 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { |
812 obj->Iterate(&visitor); | 735 if (obj->IsJSFunction()) { |
| 736 JSFunction* fun = JSFunction::cast(obj); |
| 737 if (fun->code() == *original) fun->ReplaceCode(*substitution); |
| 738 } else if (obj->IsSharedFunctionInfo()) { |
| 739 SharedFunctionInfo* info = SharedFunctionInfo::cast(obj); |
| 740 if (info->code() == *original) info->set_code(*substitution); |
| 741 } |
813 } | 742 } |
814 } | 743 } |
815 | 744 |
816 | 745 |
817 // Patch function literals. | 746 // Patch function literals. |
818 // Name 'literals' is a misnomer. Rather it's a cache for complex object | 747 // Name 'literals' is a misnomer. Rather it's a cache for complex object |
819 // boilerplates and for a native context. We must clean cached values. | 748 // boilerplates and for a native context. We must clean cached values. |
820 // Additionally we may need to allocate a new array if number of literals | 749 // Additionally we may need to allocate a new array if number of literals |
821 // changed. | 750 // changed. |
822 class LiteralFixer { | 751 class LiteralFixer { |
(...skipping 447 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1270 UnwrapSharedFunctionInfoFromJSValue(jsvalue); | 1199 UnwrapSharedFunctionInfoFromJSValue(jsvalue); |
1271 | 1200 |
1272 if (function->Inlines(*shared)) { | 1201 if (function->Inlines(*shared)) { |
1273 SetElementSloppy(result, i, Handle<Smi>(Smi::FromInt(status), isolate)); | 1202 SetElementSloppy(result, i, Handle<Smi>(Smi::FromInt(status), isolate)); |
1274 return true; | 1203 return true; |
1275 } | 1204 } |
1276 } | 1205 } |
1277 return false; | 1206 return false; |
1278 } | 1207 } |
1279 | 1208 |
1280 | |
1281 // Iterates over handler chain and removes all elements that are inside | |
1282 // frames being dropped. | |
1283 static bool FixTryCatchHandler(StackFrame* top_frame, | |
1284 StackFrame* bottom_frame) { | |
1285 Address* pointer_address = | |
1286 &Memory::Address_at(top_frame->isolate()->get_address_from_id( | |
1287 Isolate::kHandlerAddress)); | |
1288 | |
1289 while (*pointer_address < top_frame->sp()) { | |
1290 pointer_address = &Memory::Address_at(*pointer_address); | |
1291 } | |
1292 Address* above_frame_address = pointer_address; | |
1293 while (*pointer_address < bottom_frame->fp()) { | |
1294 pointer_address = &Memory::Address_at(*pointer_address); | |
1295 } | |
1296 bool change = *above_frame_address != *pointer_address; | |
1297 *above_frame_address = *pointer_address; | |
1298 return change; | |
1299 } | |
1300 | |
1301 | |
1302 // Initializes an artificial stack frame. The data it contains is used for: | |
1303 // a. successful work of frame dropper code which eventually gets control, | |
1304 // b. being compatible with a typed frame structure for various stack | |
1305 // iterators. | |
1306 // Frame structure (conforms to InternalFrame structure): | |
1307 // -- function | |
1308 // -- code | |
1309 // -- SMI marker | |
1310 // -- frame base | |
1311 static void SetUpFrameDropperFrame(StackFrame* bottom_js_frame, | |
1312 Handle<Code> code) { | |
1313 DCHECK(bottom_js_frame->is_java_script()); | |
1314 Address fp = bottom_js_frame->fp(); | |
1315 Memory::Object_at(fp + FrameDropperFrameConstants::kFunctionOffset) = | |
1316 Memory::Object_at(fp + StandardFrameConstants::kFunctionOffset); | |
1317 Memory::Object_at(fp + FrameDropperFrameConstants::kFrameTypeOffset) = | |
1318 Smi::FromInt(StackFrame::INTERNAL); | |
1319 Memory::Object_at(fp + FrameDropperFrameConstants::kCodeOffset) = *code; | |
1320 } | |
1321 | |
1322 | |
1323 // Removes specified range of frames from stack. There may be 1 or more | |
1324 // frames in range. Anyway the bottom frame is restarted rather than dropped, | |
1325 // and therefore has to be a JavaScript frame. | |
1326 // Returns error message or NULL. | |
1327 static const char* DropFrames(Vector<StackFrame*> frames, int top_frame_index, | |
1328 int bottom_js_frame_index, | |
1329 LiveEditFrameDropMode* mode) { | |
1330 if (!LiveEdit::kFrameDropperSupported) { | |
1331 return "Stack manipulations are not supported in this architecture."; | |
1332 } | |
1333 | |
1334 StackFrame* pre_top_frame = frames[top_frame_index - 1]; | |
1335 StackFrame* top_frame = frames[top_frame_index]; | |
1336 StackFrame* bottom_js_frame = frames[bottom_js_frame_index]; | |
1337 | |
1338 DCHECK(bottom_js_frame->is_java_script()); | |
1339 | |
1340 // Check the nature of the top frame. | |
1341 Isolate* isolate = bottom_js_frame->isolate(); | |
1342 Code* pre_top_frame_code = pre_top_frame->LookupCode(); | |
1343 bool frame_has_padding = true; | |
1344 if (pre_top_frame_code == | |
1345 isolate->builtins()->builtin(Builtins::kSlot_DebugBreak)) { | |
1346 // OK, we can drop debug break slot. | |
1347 *mode = LIVE_EDIT_FRAME_DROPPED_IN_DEBUG_SLOT_CALL; | |
1348 } else if (pre_top_frame_code == | |
1349 isolate->builtins()->builtin(Builtins::kFrameDropper_LiveEdit)) { | |
1350 // OK, we can drop our own code. | |
1351 pre_top_frame = frames[top_frame_index - 2]; | |
1352 top_frame = frames[top_frame_index - 1]; | |
1353 *mode = LIVE_EDIT_CURRENTLY_SET_MODE; | |
1354 frame_has_padding = false; | |
1355 } else if (pre_top_frame_code == | |
1356 isolate->builtins()->builtin(Builtins::kReturn_DebugBreak)) { | |
1357 *mode = LIVE_EDIT_FRAME_DROPPED_IN_RETURN_CALL; | |
1358 } else if (pre_top_frame_code->kind() == Code::STUB && | |
1359 CodeStub::GetMajorKey(pre_top_frame_code) == CodeStub::CEntry) { | |
1360 // Entry from our unit tests on 'debugger' statement. | |
1361 // It's fine, we support this case. | |
1362 *mode = LIVE_EDIT_FRAME_DROPPED_IN_DIRECT_CALL; | |
1363 // We don't have a padding from 'debugger' statement call. | |
1364 // Here the stub is CEntry, it's not debug-only and can't be padded. | |
1365 // If anyone would complain, a proxy padded stub could be added. | |
1366 frame_has_padding = false; | |
1367 } else if (pre_top_frame->type() == StackFrame::ARGUMENTS_ADAPTOR) { | |
1368 // This must be adaptor that remain from the frame dropping that | |
1369 // is still on stack. A frame dropper frame must be above it. | |
1370 DCHECK(frames[top_frame_index - 2]->LookupCode() == | |
1371 isolate->builtins()->builtin(Builtins::kFrameDropper_LiveEdit)); | |
1372 pre_top_frame = frames[top_frame_index - 3]; | |
1373 top_frame = frames[top_frame_index - 2]; | |
1374 *mode = LIVE_EDIT_CURRENTLY_SET_MODE; | |
1375 frame_has_padding = false; | |
1376 } else if (pre_top_frame_code->kind() == Code::BYTECODE_HANDLER) { | |
1377 // Interpreted bytecode takes up two stack frames, one for the bytecode | |
1378 // handler and one for the interpreter entry trampoline. Therefore we shift | |
1379 // up by one frame. | |
1380 *mode = LIVE_EDIT_FRAME_DROPPED_IN_DIRECT_CALL; | |
1381 pre_top_frame = frames[top_frame_index - 2]; | |
1382 top_frame = frames[top_frame_index - 1]; | |
1383 } else { | |
1384 return "Unknown structure of stack above changing function"; | |
1385 } | |
1386 | |
1387 Address unused_stack_top = top_frame->sp(); | |
1388 Address unused_stack_bottom = | |
1389 bottom_js_frame->fp() - FrameDropperFrameConstants::kFixedFrameSize + | |
1390 2 * kPointerSize; // Bigger address end is exclusive. | |
1391 | |
1392 Address* top_frame_pc_address = top_frame->pc_address(); | |
1393 | |
1394 // top_frame may be damaged below this point. Do not used it. | |
1395 DCHECK(!(top_frame = NULL)); | |
1396 | |
1397 if (unused_stack_top > unused_stack_bottom) { | |
1398 if (frame_has_padding) { | |
1399 int shortage_bytes = | |
1400 static_cast<int>(unused_stack_top - unused_stack_bottom); | |
1401 | |
1402 Address padding_start = | |
1403 pre_top_frame->fp() - | |
1404 (FrameDropperFrameConstants::kFixedFrameSize - kPointerSize); | |
1405 | |
1406 Address padding_pointer = padding_start; | |
1407 Smi* padding_object = Smi::FromInt(LiveEdit::kFramePaddingValue); | |
1408 while (Memory::Object_at(padding_pointer) == padding_object) { | |
1409 padding_pointer -= kPointerSize; | |
1410 } | |
1411 int padding_counter = | |
1412 Smi::cast(Memory::Object_at(padding_pointer))->value(); | |
1413 if (padding_counter * kPointerSize < shortage_bytes) { | |
1414 return "Not enough space for frame dropper frame " | |
1415 "(even with padding frame)"; | |
1416 } | |
1417 Memory::Object_at(padding_pointer) = | |
1418 Smi::FromInt(padding_counter - shortage_bytes / kPointerSize); | |
1419 | |
1420 StackFrame* pre_pre_frame = frames[top_frame_index - 2]; | |
1421 | |
1422 MemMove(padding_start + kPointerSize - shortage_bytes, | |
1423 padding_start + kPointerSize, | |
1424 FrameDropperFrameConstants::kFixedFrameSize - kPointerSize); | |
1425 | |
1426 pre_top_frame->UpdateFp(pre_top_frame->fp() - shortage_bytes); | |
1427 pre_pre_frame->SetCallerFp(pre_top_frame->fp()); | |
1428 unused_stack_top -= shortage_bytes; | |
1429 | |
1430 STATIC_ASSERT(sizeof(Address) == kPointerSize); | |
1431 top_frame_pc_address -= shortage_bytes / kPointerSize; | |
1432 } else { | |
1433 return "Not enough space for frame dropper frame"; | |
1434 } | |
1435 } | |
1436 | |
1437 // Committing now. After this point we should return only NULL value. | |
1438 | |
1439 FixTryCatchHandler(pre_top_frame, bottom_js_frame); | |
1440 // Make sure FixTryCatchHandler is idempotent. | |
1441 DCHECK(!FixTryCatchHandler(pre_top_frame, bottom_js_frame)); | |
1442 | |
1443 Handle<Code> code = isolate->builtins()->FrameDropper_LiveEdit(); | |
1444 *top_frame_pc_address = code->entry(); | |
1445 pre_top_frame->SetCallerFp(bottom_js_frame->fp()); | |
1446 | |
1447 SetUpFrameDropperFrame(bottom_js_frame, code); | |
1448 | |
1449 for (Address a = unused_stack_top; | |
1450 a < unused_stack_bottom; | |
1451 a += kPointerSize) { | |
1452 Memory::Object_at(a) = Smi::kZero; | |
1453 } | |
1454 | |
1455 return NULL; | |
1456 } | |
1457 | |
1458 | |
1459 // Describes a set of call frames that execute any of listed functions. | 1209 // Describes a set of call frames that execute any of listed functions. |
1460 // Finding no such frames does not mean error. | 1210 // Finding no such frames does not mean error. |
1461 class MultipleFunctionTarget { | 1211 class MultipleFunctionTarget { |
1462 public: | 1212 public: |
1463 MultipleFunctionTarget(Handle<JSArray> old_shared_array, | 1213 MultipleFunctionTarget(Handle<JSArray> old_shared_array, |
1464 Handle<JSArray> new_shared_array, | 1214 Handle<JSArray> new_shared_array, |
1465 Handle<JSArray> result) | 1215 Handle<JSArray> result) |
1466 : old_shared_array_(old_shared_array), | 1216 : old_shared_array_(old_shared_array), |
1467 new_shared_array_(new_shared_array), | 1217 new_shared_array_(new_shared_array), |
1468 result_(result) {} | 1218 result_(result) {} |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1536 | 1286 |
1537 // Drops all call frame matched by target and all frames above them. | 1287 // Drops all call frame matched by target and all frames above them. |
1538 template <typename TARGET> | 1288 template <typename TARGET> |
1539 static const char* DropActivationsInActiveThreadImpl(Isolate* isolate, | 1289 static const char* DropActivationsInActiveThreadImpl(Isolate* isolate, |
1540 TARGET& target, // NOLINT | 1290 TARGET& target, // NOLINT |
1541 bool do_drop) { | 1291 bool do_drop) { |
1542 Debug* debug = isolate->debug(); | 1292 Debug* debug = isolate->debug(); |
1543 Zone zone(isolate->allocator(), ZONE_NAME); | 1293 Zone zone(isolate->allocator(), ZONE_NAME); |
1544 Vector<StackFrame*> frames = CreateStackMap(isolate, &zone); | 1294 Vector<StackFrame*> frames = CreateStackMap(isolate, &zone); |
1545 | 1295 |
1546 | |
1547 int top_frame_index = -1; | 1296 int top_frame_index = -1; |
1548 int frame_index = 0; | 1297 int frame_index = 0; |
1549 for (; frame_index < frames.length(); frame_index++) { | 1298 for (; frame_index < frames.length(); frame_index++) { |
1550 StackFrame* frame = frames[frame_index]; | 1299 StackFrame* frame = frames[frame_index]; |
1551 if (frame->id() == debug->break_frame_id()) { | 1300 if (frame->id() == debug->break_frame_id()) { |
1552 top_frame_index = frame_index; | 1301 top_frame_index = frame_index; |
1553 break; | 1302 break; |
1554 } | 1303 } |
1555 if (target.MatchActivation( | 1304 if (target.MatchActivation( |
1556 frame, LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE)) { | 1305 frame, LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE)) { |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1621 if (!do_drop) { | 1370 if (!do_drop) { |
1622 // We are in check-only mode. | 1371 // We are in check-only mode. |
1623 return NULL; | 1372 return NULL; |
1624 } | 1373 } |
1625 | 1374 |
1626 if (!target_frame_found) { | 1375 if (!target_frame_found) { |
1627 // Nothing to drop. | 1376 // Nothing to drop. |
1628 return target.GetNotFoundMessage(); | 1377 return target.GetNotFoundMessage(); |
1629 } | 1378 } |
1630 | 1379 |
1631 LiveEditFrameDropMode drop_mode = LIVE_EDIT_FRAMES_UNTOUCHED; | 1380 if (!LiveEdit::kFrameDropperSupported) { |
1632 const char* error_message = | 1381 return "Stack manipulations are not supported in this architecture."; |
1633 DropFrames(frames, top_frame_index, bottom_js_frame_index, &drop_mode); | |
1634 | |
1635 if (error_message != NULL) { | |
1636 return error_message; | |
1637 } | 1382 } |
1638 | 1383 |
1639 // Adjust break_frame after some frames has been dropped. | 1384 debug->ScheduleFrameRestart(frames[bottom_js_frame_index]); |
1640 StackFrame::Id new_id = StackFrame::NO_ID; | |
1641 for (int i = bottom_js_frame_index + 1; i < frames.length(); i++) { | |
1642 if (frames[i]->type() == StackFrame::JAVA_SCRIPT || | |
1643 frames[i]->type() == StackFrame::INTERPRETED) { | |
1644 new_id = frames[i]->id(); | |
1645 break; | |
1646 } | |
1647 } | |
1648 debug->FramesHaveBeenDropped(new_id, drop_mode); | |
1649 return NULL; | 1385 return NULL; |
1650 } | 1386 } |
1651 | 1387 |
1652 | 1388 |
1653 // Fills result array with statuses of functions. Modifies the stack | 1389 // Fills result array with statuses of functions. Modifies the stack |
1654 // removing all listed function if possible and if do_drop is true. | 1390 // removing all listed function if possible and if do_drop is true. |
1655 static const char* DropActivationsInActiveThread( | 1391 static const char* DropActivationsInActiveThread( |
1656 Handle<JSArray> old_shared_array, Handle<JSArray> new_shared_array, | 1392 Handle<JSArray> old_shared_array, Handle<JSArray> new_shared_array, |
1657 Handle<JSArray> result, bool do_drop) { | 1393 Handle<JSArray> result, bool do_drop) { |
1658 MultipleFunctionTarget target(old_shared_array, new_shared_array, result); | 1394 MultipleFunctionTarget target(old_shared_array, new_shared_array, result); |
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1935 scope_info_length++; | 1671 scope_info_length++; |
1936 | 1672 |
1937 current_scope = current_scope->outer_scope(); | 1673 current_scope = current_scope->outer_scope(); |
1938 } | 1674 } |
1939 | 1675 |
1940 return scope_info_list; | 1676 return scope_info_list; |
1941 } | 1677 } |
1942 | 1678 |
1943 } // namespace internal | 1679 } // namespace internal |
1944 } // namespace v8 | 1680 } // namespace v8 |
OLD | NEW |