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 <stdlib.h> | 5 #include <stdlib.h> |
6 #include <limits> | 6 #include <limits> |
7 | 7 |
8 #include "src/v8.h" | 8 #include "src/v8.h" |
9 | 9 |
10 #include "src/accessors.h" | 10 #include "src/accessors.h" |
11 #include "src/allocation-site-scopes.h" | 11 #include "src/allocation-site-scopes.h" |
12 #include "src/api.h" | 12 #include "src/api.h" |
13 #include "src/arguments.h" | 13 #include "src/arguments.h" |
14 #include "src/bailout-reason.h" | 14 #include "src/bailout-reason.h" |
15 #include "src/base/cpu.h" | 15 #include "src/base/cpu.h" |
16 #include "src/base/platform/platform.h" | 16 #include "src/base/platform/platform.h" |
17 #include "src/bootstrapper.h" | 17 #include "src/bootstrapper.h" |
18 #include "src/codegen.h" | 18 #include "src/codegen.h" |
19 #include "src/compilation-cache.h" | 19 #include "src/compilation-cache.h" |
20 #include "src/compiler.h" | 20 #include "src/compiler.h" |
21 #include "src/conversions.h" | 21 #include "src/conversions.h" |
22 #include "src/cpu-profiler.h" | |
23 #include "src/date.h" | |
24 #include "src/dateparser-inl.h" | |
25 #include "src/debug.h" | |
26 #include "src/deoptimizer.h" | 22 #include "src/deoptimizer.h" |
27 #include "src/execution.h" | 23 #include "src/execution.h" |
28 #include "src/full-codegen.h" | 24 #include "src/full-codegen.h" |
29 #include "src/global-handles.h" | 25 #include "src/global-handles.h" |
30 #include "src/isolate-inl.h" | 26 #include "src/isolate-inl.h" |
31 #include "src/liveedit.h" | |
32 #include "src/misc-intrinsics.h" | |
33 #include "src/parser.h" | 27 #include "src/parser.h" |
34 #include "src/prototype.h" | 28 #include "src/prototype.h" |
35 #include "src/runtime/runtime.h" | 29 #include "src/runtime/runtime.h" |
36 #include "src/runtime/runtime-utils.h" | 30 #include "src/runtime/runtime-utils.h" |
37 #include "src/runtime-profiler.h" | |
38 #include "src/scopeinfo.h" | 31 #include "src/scopeinfo.h" |
39 #include "src/smart-pointers.h" | 32 #include "src/smart-pointers.h" |
40 #include "src/utils.h" | 33 #include "src/utils.h" |
41 #include "src/v8threads.h" | 34 #include "src/v8threads.h" |
42 #include "src/vm-state-inl.h" | |
43 | 35 |
44 | 36 |
45 namespace v8 { | 37 namespace v8 { |
46 namespace internal { | 38 namespace internal { |
47 | 39 |
48 // Header of runtime functions. | 40 // Header of runtime functions. |
49 #define F(name, number_of_args, result_size) \ | 41 #define F(name, number_of_args, result_size) \ |
50 Object* Runtime_##name(int args_length, Object** args_object, \ | 42 Object* Runtime_##name(int args_length, Object** args_object, \ |
51 Isolate* isolate); | 43 Isolate* isolate); |
52 | 44 |
(...skipping 607 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
660 } | 652 } |
661 iter.AdvanceIgnoringProxies(); | 653 iter.AdvanceIgnoringProxies(); |
662 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { | 654 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { |
663 return *PrototypeIterator::GetCurrent(iter); | 655 return *PrototypeIterator::GetCurrent(iter); |
664 } | 656 } |
665 } while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)); | 657 } while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)); |
666 return *PrototypeIterator::GetCurrent(iter); | 658 return *PrototypeIterator::GetCurrent(iter); |
667 } | 659 } |
668 | 660 |
669 | 661 |
670 static inline Handle<Object> GetPrototypeSkipHiddenPrototypes( | |
671 Isolate* isolate, Handle<Object> receiver) { | |
672 PrototypeIterator iter(isolate, receiver); | |
673 while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) { | |
674 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { | |
675 return PrototypeIterator::GetCurrent(iter); | |
676 } | |
677 iter.Advance(); | |
678 } | |
679 return PrototypeIterator::GetCurrent(iter); | |
680 } | |
681 | |
682 | |
683 RUNTIME_FUNCTION(Runtime_InternalSetPrototype) { | 662 RUNTIME_FUNCTION(Runtime_InternalSetPrototype) { |
684 HandleScope scope(isolate); | 663 HandleScope scope(isolate); |
685 DCHECK(args.length() == 2); | 664 DCHECK(args.length() == 2); |
686 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0); | 665 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0); |
687 CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1); | 666 CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1); |
688 DCHECK(!obj->IsAccessCheckNeeded()); | 667 DCHECK(!obj->IsAccessCheckNeeded()); |
689 DCHECK(!obj->map()->is_observed()); | 668 DCHECK(!obj->map()->is_observed()); |
690 Handle<Object> result; | 669 Handle<Object> result; |
691 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 670 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
692 isolate, result, JSObject::SetPrototype(obj, prototype, false)); | 671 isolate, result, JSObject::SetPrototype(obj, prototype, false)); |
693 return *result; | 672 return *result; |
694 } | 673 } |
695 | 674 |
696 | 675 |
697 RUNTIME_FUNCTION(Runtime_SetPrototype) { | 676 RUNTIME_FUNCTION(Runtime_SetPrototype) { |
698 HandleScope scope(isolate); | 677 HandleScope scope(isolate); |
699 DCHECK(args.length() == 2); | 678 DCHECK(args.length() == 2); |
700 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0); | 679 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0); |
701 CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1); | 680 CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1); |
702 if (obj->IsAccessCheckNeeded() && | 681 if (obj->IsAccessCheckNeeded() && |
703 !isolate->MayNamedAccess(obj, isolate->factory()->proto_string(), | 682 !isolate->MayNamedAccess(obj, isolate->factory()->proto_string(), |
704 v8::ACCESS_SET)) { | 683 v8::ACCESS_SET)) { |
705 isolate->ReportFailedAccessCheck(obj, v8::ACCESS_SET); | 684 isolate->ReportFailedAccessCheck(obj, v8::ACCESS_SET); |
706 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); | 685 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); |
707 return isolate->heap()->undefined_value(); | 686 return isolate->heap()->undefined_value(); |
708 } | 687 } |
709 if (obj->map()->is_observed()) { | 688 if (obj->map()->is_observed()) { |
710 Handle<Object> old_value = GetPrototypeSkipHiddenPrototypes(isolate, obj); | 689 Handle<Object> old_value = |
| 690 Object::GetPrototypeSkipHiddenPrototypes(isolate, obj); |
711 Handle<Object> result; | 691 Handle<Object> result; |
712 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 692 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
713 isolate, result, JSObject::SetPrototype(obj, prototype, true)); | 693 isolate, result, JSObject::SetPrototype(obj, prototype, true)); |
714 | 694 |
715 Handle<Object> new_value = GetPrototypeSkipHiddenPrototypes(isolate, obj); | 695 Handle<Object> new_value = |
| 696 Object::GetPrototypeSkipHiddenPrototypes(isolate, obj); |
716 if (!new_value->SameValue(*old_value)) { | 697 if (!new_value->SameValue(*old_value)) { |
717 JSObject::EnqueueChangeRecord( | 698 JSObject::EnqueueChangeRecord( |
718 obj, "setPrototype", isolate->factory()->proto_string(), old_value); | 699 obj, "setPrototype", isolate->factory()->proto_string(), old_value); |
719 } | 700 } |
720 return *result; | 701 return *result; |
721 } | 702 } |
722 Handle<Object> result; | 703 Handle<Object> result; |
723 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 704 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
724 isolate, result, JSObject::SetPrototype(obj, prototype, true)); | 705 isolate, result, JSObject::SetPrototype(obj, prototype, true)); |
725 return *result; | 706 return *result; |
(...skipping 749 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1475 | 1456 |
1476 RUNTIME_FUNCTION(Runtime_FunctionMarkNameShouldPrintAsAnonymous) { | 1457 RUNTIME_FUNCTION(Runtime_FunctionMarkNameShouldPrintAsAnonymous) { |
1477 SealHandleScope shs(isolate); | 1458 SealHandleScope shs(isolate); |
1478 DCHECK(args.length() == 1); | 1459 DCHECK(args.length() == 1); |
1479 CONVERT_ARG_CHECKED(JSFunction, f, 0); | 1460 CONVERT_ARG_CHECKED(JSFunction, f, 0); |
1480 f->shared()->set_name_should_print_as_anonymous(true); | 1461 f->shared()->set_name_should_print_as_anonymous(true); |
1481 return isolate->heap()->undefined_value(); | 1462 return isolate->heap()->undefined_value(); |
1482 } | 1463 } |
1483 | 1464 |
1484 | 1465 |
1485 RUNTIME_FUNCTION(Runtime_FunctionIsGenerator) { | |
1486 SealHandleScope shs(isolate); | |
1487 DCHECK(args.length() == 1); | |
1488 CONVERT_ARG_CHECKED(JSFunction, f, 0); | |
1489 return isolate->heap()->ToBoolean(f->shared()->is_generator()); | |
1490 } | |
1491 | |
1492 | |
1493 RUNTIME_FUNCTION(Runtime_FunctionIsArrow) { | 1466 RUNTIME_FUNCTION(Runtime_FunctionIsArrow) { |
1494 SealHandleScope shs(isolate); | 1467 SealHandleScope shs(isolate); |
1495 DCHECK(args.length() == 1); | 1468 DCHECK(args.length() == 1); |
1496 CONVERT_ARG_CHECKED(JSFunction, f, 0); | 1469 CONVERT_ARG_CHECKED(JSFunction, f, 0); |
1497 return isolate->heap()->ToBoolean(f->shared()->is_arrow()); | 1470 return isolate->heap()->ToBoolean(f->shared()->is_arrow()); |
1498 } | 1471 } |
1499 | 1472 |
1500 | 1473 |
1501 RUNTIME_FUNCTION(Runtime_FunctionIsConciseMethod) { | 1474 RUNTIME_FUNCTION(Runtime_FunctionIsConciseMethod) { |
1502 SealHandleScope shs(isolate); | 1475 SealHandleScope shs(isolate); |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1676 if (isolate->logger()->is_logging_code_events() || | 1649 if (isolate->logger()->is_logging_code_events() || |
1677 isolate->cpu_profiler()->is_profiling()) { | 1650 isolate->cpu_profiler()->is_profiling()) { |
1678 isolate->logger()->LogExistingFunction(source_shared, | 1651 isolate->logger()->LogExistingFunction(source_shared, |
1679 Handle<Code>(source_shared->code())); | 1652 Handle<Code>(source_shared->code())); |
1680 } | 1653 } |
1681 | 1654 |
1682 return *target; | 1655 return *target; |
1683 } | 1656 } |
1684 | 1657 |
1685 | 1658 |
1686 RUNTIME_FUNCTION(Runtime_CreateJSGeneratorObject) { | |
1687 HandleScope scope(isolate); | |
1688 DCHECK(args.length() == 0); | |
1689 | |
1690 JavaScriptFrameIterator it(isolate); | |
1691 JavaScriptFrame* frame = it.frame(); | |
1692 Handle<JSFunction> function(frame->function()); | |
1693 RUNTIME_ASSERT(function->shared()->is_generator()); | |
1694 | |
1695 Handle<JSGeneratorObject> generator; | |
1696 if (frame->IsConstructor()) { | |
1697 generator = handle(JSGeneratorObject::cast(frame->receiver())); | |
1698 } else { | |
1699 generator = isolate->factory()->NewJSGeneratorObject(function); | |
1700 } | |
1701 generator->set_function(*function); | |
1702 generator->set_context(Context::cast(frame->context())); | |
1703 generator->set_receiver(frame->receiver()); | |
1704 generator->set_continuation(0); | |
1705 generator->set_operand_stack(isolate->heap()->empty_fixed_array()); | |
1706 generator->set_stack_handler_index(-1); | |
1707 | |
1708 return *generator; | |
1709 } | |
1710 | |
1711 | |
1712 RUNTIME_FUNCTION(Runtime_SuspendJSGeneratorObject) { | |
1713 HandleScope handle_scope(isolate); | |
1714 DCHECK(args.length() == 1); | |
1715 CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator_object, 0); | |
1716 | |
1717 JavaScriptFrameIterator stack_iterator(isolate); | |
1718 JavaScriptFrame* frame = stack_iterator.frame(); | |
1719 RUNTIME_ASSERT(frame->function()->shared()->is_generator()); | |
1720 DCHECK_EQ(frame->function(), generator_object->function()); | |
1721 | |
1722 // The caller should have saved the context and continuation already. | |
1723 DCHECK_EQ(generator_object->context(), Context::cast(frame->context())); | |
1724 DCHECK_LT(0, generator_object->continuation()); | |
1725 | |
1726 // We expect there to be at least two values on the operand stack: the return | |
1727 // value of the yield expression, and the argument to this runtime call. | |
1728 // Neither of those should be saved. | |
1729 int operands_count = frame->ComputeOperandsCount(); | |
1730 DCHECK_GE(operands_count, 2); | |
1731 operands_count -= 2; | |
1732 | |
1733 if (operands_count == 0) { | |
1734 // Although it's semantically harmless to call this function with an | |
1735 // operands_count of zero, it is also unnecessary. | |
1736 DCHECK_EQ(generator_object->operand_stack(), | |
1737 isolate->heap()->empty_fixed_array()); | |
1738 DCHECK_EQ(generator_object->stack_handler_index(), -1); | |
1739 // If there are no operands on the stack, there shouldn't be a handler | |
1740 // active either. | |
1741 DCHECK(!frame->HasHandler()); | |
1742 } else { | |
1743 int stack_handler_index = -1; | |
1744 Handle<FixedArray> operand_stack = | |
1745 isolate->factory()->NewFixedArray(operands_count); | |
1746 frame->SaveOperandStack(*operand_stack, &stack_handler_index); | |
1747 generator_object->set_operand_stack(*operand_stack); | |
1748 generator_object->set_stack_handler_index(stack_handler_index); | |
1749 } | |
1750 | |
1751 return isolate->heap()->undefined_value(); | |
1752 } | |
1753 | |
1754 | |
1755 // Note that this function is the slow path for resuming generators. It is only | |
1756 // called if the suspended activation had operands on the stack, stack handlers | |
1757 // needing rewinding, or if the resume should throw an exception. The fast path | |
1758 // is handled directly in FullCodeGenerator::EmitGeneratorResume(), which is | |
1759 // inlined into GeneratorNext and GeneratorThrow. EmitGeneratorResumeResume is | |
1760 // called in any case, as it needs to reconstruct the stack frame and make space | |
1761 // for arguments and operands. | |
1762 RUNTIME_FUNCTION(Runtime_ResumeJSGeneratorObject) { | |
1763 SealHandleScope shs(isolate); | |
1764 DCHECK(args.length() == 3); | |
1765 CONVERT_ARG_CHECKED(JSGeneratorObject, generator_object, 0); | |
1766 CONVERT_ARG_CHECKED(Object, value, 1); | |
1767 CONVERT_SMI_ARG_CHECKED(resume_mode_int, 2); | |
1768 JavaScriptFrameIterator stack_iterator(isolate); | |
1769 JavaScriptFrame* frame = stack_iterator.frame(); | |
1770 | |
1771 DCHECK_EQ(frame->function(), generator_object->function()); | |
1772 DCHECK(frame->function()->is_compiled()); | |
1773 | |
1774 STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting < 0); | |
1775 STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed == 0); | |
1776 | |
1777 Address pc = generator_object->function()->code()->instruction_start(); | |
1778 int offset = generator_object->continuation(); | |
1779 DCHECK(offset > 0); | |
1780 frame->set_pc(pc + offset); | |
1781 if (FLAG_enable_ool_constant_pool) { | |
1782 frame->set_constant_pool( | |
1783 generator_object->function()->code()->constant_pool()); | |
1784 } | |
1785 generator_object->set_continuation(JSGeneratorObject::kGeneratorExecuting); | |
1786 | |
1787 FixedArray* operand_stack = generator_object->operand_stack(); | |
1788 int operands_count = operand_stack->length(); | |
1789 if (operands_count != 0) { | |
1790 frame->RestoreOperandStack(operand_stack, | |
1791 generator_object->stack_handler_index()); | |
1792 generator_object->set_operand_stack(isolate->heap()->empty_fixed_array()); | |
1793 generator_object->set_stack_handler_index(-1); | |
1794 } | |
1795 | |
1796 JSGeneratorObject::ResumeMode resume_mode = | |
1797 static_cast<JSGeneratorObject::ResumeMode>(resume_mode_int); | |
1798 switch (resume_mode) { | |
1799 case JSGeneratorObject::NEXT: | |
1800 return value; | |
1801 case JSGeneratorObject::THROW: | |
1802 return isolate->Throw(value); | |
1803 } | |
1804 | |
1805 UNREACHABLE(); | |
1806 return isolate->ThrowIllegalOperation(); | |
1807 } | |
1808 | |
1809 | |
1810 RUNTIME_FUNCTION(Runtime_ThrowGeneratorStateError) { | |
1811 HandleScope scope(isolate); | |
1812 DCHECK(args.length() == 1); | |
1813 CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0); | |
1814 int continuation = generator->continuation(); | |
1815 const char* message = continuation == JSGeneratorObject::kGeneratorClosed | |
1816 ? "generator_finished" | |
1817 : "generator_running"; | |
1818 Vector<Handle<Object> > argv = HandleVector<Object>(NULL, 0); | |
1819 THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewError(message, argv)); | |
1820 } | |
1821 | |
1822 | |
1823 RUNTIME_FUNCTION(Runtime_ObjectFreeze) { | 1659 RUNTIME_FUNCTION(Runtime_ObjectFreeze) { |
1824 HandleScope scope(isolate); | 1660 HandleScope scope(isolate); |
1825 DCHECK(args.length() == 1); | 1661 DCHECK(args.length() == 1); |
1826 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); | 1662 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); |
1827 | 1663 |
1828 // %ObjectFreeze is a fast path and these cases are handled elsewhere. | 1664 // %ObjectFreeze is a fast path and these cases are handled elsewhere. |
1829 RUNTIME_ASSERT(!object->HasSloppyArgumentsElements() && | 1665 RUNTIME_ASSERT(!object->HasSloppyArgumentsElements() && |
1830 !object->map()->is_observed() && !object->IsJSProxy()); | 1666 !object->map()->is_observed() && !object->IsJSProxy()); |
1831 | 1667 |
1832 Handle<Object> result; | 1668 Handle<Object> result; |
(...skipping 751 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2584 JSObject::TransitionElementsKind(boilerplate_object, transitioned_kind); | 2420 JSObject::TransitionElementsKind(boilerplate_object, transitioned_kind); |
2585 } | 2421 } |
2586 } | 2422 } |
2587 FixedArray* object_array = FixedArray::cast(object->elements()); | 2423 FixedArray* object_array = FixedArray::cast(object->elements()); |
2588 object_array->set(store_index, *value); | 2424 object_array->set(store_index, *value); |
2589 } | 2425 } |
2590 return *object; | 2426 return *object; |
2591 } | 2427 } |
2592 | 2428 |
2593 | 2429 |
2594 // Check whether debugger and is about to step into the callback that is passed | |
2595 // to a built-in function such as Array.forEach. | |
2596 RUNTIME_FUNCTION(Runtime_DebugCallbackSupportsStepping) { | |
2597 DCHECK(args.length() == 1); | |
2598 if (!isolate->debug()->is_active() || !isolate->debug()->StepInActive()) { | |
2599 return isolate->heap()->false_value(); | |
2600 } | |
2601 CONVERT_ARG_CHECKED(Object, callback, 0); | |
2602 // We do not step into the callback if it's a builtin or not even a function. | |
2603 return isolate->heap()->ToBoolean(callback->IsJSFunction() && | |
2604 !JSFunction::cast(callback)->IsBuiltin()); | |
2605 } | |
2606 | |
2607 | |
2608 // Set one shot breakpoints for the callback function that is passed to a | |
2609 // built-in function such as Array.forEach to enable stepping into the callback. | |
2610 RUNTIME_FUNCTION(Runtime_DebugPrepareStepInIfStepping) { | |
2611 DCHECK(args.length() == 1); | |
2612 Debug* debug = isolate->debug(); | |
2613 if (!debug->IsStepping()) return isolate->heap()->undefined_value(); | |
2614 | |
2615 HandleScope scope(isolate); | |
2616 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0); | |
2617 RUNTIME_ASSERT(object->IsJSFunction() || object->IsJSGeneratorObject()); | |
2618 Handle<JSFunction> fun; | |
2619 if (object->IsJSFunction()) { | |
2620 fun = Handle<JSFunction>::cast(object); | |
2621 } else { | |
2622 fun = Handle<JSFunction>( | |
2623 Handle<JSGeneratorObject>::cast(object)->function(), isolate); | |
2624 } | |
2625 // When leaving the function, step out has been activated, but not performed | |
2626 // if we do not leave the builtin. To be able to step into the function | |
2627 // again, we need to clear the step out at this point. | |
2628 debug->ClearStepOut(); | |
2629 debug->FloodWithOneShot(fun); | |
2630 return isolate->heap()->undefined_value(); | |
2631 } | |
2632 | |
2633 | |
2634 RUNTIME_FUNCTION(Runtime_DebugPushPromise) { | |
2635 DCHECK(args.length() == 1); | |
2636 HandleScope scope(isolate); | |
2637 CONVERT_ARG_HANDLE_CHECKED(JSObject, promise, 0); | |
2638 isolate->PushPromise(promise); | |
2639 return isolate->heap()->undefined_value(); | |
2640 } | |
2641 | |
2642 | |
2643 RUNTIME_FUNCTION(Runtime_DebugPopPromise) { | |
2644 DCHECK(args.length() == 0); | |
2645 SealHandleScope shs(isolate); | |
2646 isolate->PopPromise(); | |
2647 return isolate->heap()->undefined_value(); | |
2648 } | |
2649 | |
2650 | |
2651 RUNTIME_FUNCTION(Runtime_DebugPromiseEvent) { | |
2652 DCHECK(args.length() == 1); | |
2653 HandleScope scope(isolate); | |
2654 CONVERT_ARG_HANDLE_CHECKED(JSObject, data, 0); | |
2655 isolate->debug()->OnPromiseEvent(data); | |
2656 return isolate->heap()->undefined_value(); | |
2657 } | |
2658 | |
2659 | |
2660 RUNTIME_FUNCTION(Runtime_DebugPromiseRejectEvent) { | 2430 RUNTIME_FUNCTION(Runtime_DebugPromiseRejectEvent) { |
2661 DCHECK(args.length() == 2); | 2431 DCHECK(args.length() == 2); |
2662 HandleScope scope(isolate); | 2432 HandleScope scope(isolate); |
2663 CONVERT_ARG_HANDLE_CHECKED(JSObject, promise, 0); | 2433 CONVERT_ARG_HANDLE_CHECKED(JSObject, promise, 0); |
2664 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); | 2434 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); |
2665 isolate->debug()->OnPromiseReject(promise, value); | 2435 isolate->debug()->OnPromiseReject(promise, value); |
2666 return isolate->heap()->undefined_value(); | 2436 return isolate->heap()->undefined_value(); |
2667 } | 2437 } |
2668 | 2438 |
2669 | 2439 |
2670 RUNTIME_FUNCTION(Runtime_DebugAsyncTaskEvent) { | |
2671 DCHECK(args.length() == 1); | |
2672 HandleScope scope(isolate); | |
2673 CONVERT_ARG_HANDLE_CHECKED(JSObject, data, 0); | |
2674 isolate->debug()->OnAsyncTaskEvent(data); | |
2675 return isolate->heap()->undefined_value(); | |
2676 } | |
2677 | |
2678 | |
2679 RUNTIME_FUNCTION(Runtime_DeleteProperty) { | 2440 RUNTIME_FUNCTION(Runtime_DeleteProperty) { |
2680 HandleScope scope(isolate); | 2441 HandleScope scope(isolate); |
2681 DCHECK(args.length() == 3); | 2442 DCHECK(args.length() == 3); |
2682 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0); | 2443 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0); |
2683 CONVERT_ARG_HANDLE_CHECKED(Name, key, 1); | 2444 CONVERT_ARG_HANDLE_CHECKED(Name, key, 1); |
2684 CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode, 2); | 2445 CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode, 2); |
2685 JSReceiver::DeleteMode delete_mode = strict_mode == STRICT | 2446 JSReceiver::DeleteMode delete_mode = strict_mode == STRICT |
2686 ? JSReceiver::STRICT_DELETION | 2447 ? JSReceiver::STRICT_DELETION |
2687 : JSReceiver::NORMAL_DELETION; | 2448 : JSReceiver::NORMAL_DELETION; |
2688 Handle<Object> result; | 2449 Handle<Object> result; |
(...skipping 577 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3266 } | 3027 } |
3267 | 3028 |
3268 | 3029 |
3269 RUNTIME_FUNCTION(Runtime_AllocateHeapNumber) { | 3030 RUNTIME_FUNCTION(Runtime_AllocateHeapNumber) { |
3270 HandleScope scope(isolate); | 3031 HandleScope scope(isolate); |
3271 DCHECK(args.length() == 0); | 3032 DCHECK(args.length() == 0); |
3272 return *isolate->factory()->NewHeapNumber(0); | 3033 return *isolate->factory()->NewHeapNumber(0); |
3273 } | 3034 } |
3274 | 3035 |
3275 | 3036 |
3276 | |
3277 | |
3278 | |
3279 RUNTIME_FUNCTION(Runtime_DateMakeDay) { | |
3280 SealHandleScope shs(isolate); | |
3281 DCHECK(args.length() == 2); | |
3282 | |
3283 CONVERT_SMI_ARG_CHECKED(year, 0); | |
3284 CONVERT_SMI_ARG_CHECKED(month, 1); | |
3285 | |
3286 int days = isolate->date_cache()->DaysFromYearMonth(year, month); | |
3287 RUNTIME_ASSERT(Smi::IsValid(days)); | |
3288 return Smi::FromInt(days); | |
3289 } | |
3290 | |
3291 | |
3292 RUNTIME_FUNCTION(Runtime_DateSetValue) { | |
3293 HandleScope scope(isolate); | |
3294 DCHECK(args.length() == 3); | |
3295 | |
3296 CONVERT_ARG_HANDLE_CHECKED(JSDate, date, 0); | |
3297 CONVERT_DOUBLE_ARG_CHECKED(time, 1); | |
3298 CONVERT_SMI_ARG_CHECKED(is_utc, 2); | |
3299 | |
3300 DateCache* date_cache = isolate->date_cache(); | |
3301 | |
3302 Handle<Object> value; | |
3303 ; | |
3304 bool is_value_nan = false; | |
3305 if (std::isnan(time)) { | |
3306 value = isolate->factory()->nan_value(); | |
3307 is_value_nan = true; | |
3308 } else if (!is_utc && (time < -DateCache::kMaxTimeBeforeUTCInMs || | |
3309 time > DateCache::kMaxTimeBeforeUTCInMs)) { | |
3310 value = isolate->factory()->nan_value(); | |
3311 is_value_nan = true; | |
3312 } else { | |
3313 time = is_utc ? time : date_cache->ToUTC(static_cast<int64_t>(time)); | |
3314 if (time < -DateCache::kMaxTimeInMs || time > DateCache::kMaxTimeInMs) { | |
3315 value = isolate->factory()->nan_value(); | |
3316 is_value_nan = true; | |
3317 } else { | |
3318 value = isolate->factory()->NewNumber(DoubleToInteger(time)); | |
3319 } | |
3320 } | |
3321 date->SetValue(*value, is_value_nan); | |
3322 return *value; | |
3323 } | |
3324 | |
3325 | |
3326 static Handle<JSObject> NewSloppyArguments(Isolate* isolate, | 3037 static Handle<JSObject> NewSloppyArguments(Isolate* isolate, |
3327 Handle<JSFunction> callee, | 3038 Handle<JSFunction> callee, |
3328 Object** parameters, | 3039 Object** parameters, |
3329 int argument_count) { | 3040 int argument_count) { |
3330 Handle<JSObject> result = | 3041 Handle<JSObject> result = |
3331 isolate->factory()->NewArgumentsObject(callee, argument_count); | 3042 isolate->factory()->NewArgumentsObject(callee, argument_count); |
3332 | 3043 |
3333 // Allocate the elements if needed. | 3044 // Allocate the elements if needed. |
3334 int parameter_count = callee->shared()->formal_parameter_count(); | 3045 int parameter_count = callee->shared()->formal_parameter_count(); |
3335 if (argument_count > 0) { | 3046 if (argument_count > 0) { |
(...skipping 1003 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4339 | 4050 |
4340 RUNTIME_FUNCTION(Runtime_ThrowUnsupportedSuperError) { | 4051 RUNTIME_FUNCTION(Runtime_ThrowUnsupportedSuperError) { |
4341 HandleScope scope(isolate); | 4052 HandleScope scope(isolate); |
4342 DCHECK(args.length() == 0); | 4053 DCHECK(args.length() == 0); |
4343 THROW_NEW_ERROR_RETURN_FAILURE( | 4054 THROW_NEW_ERROR_RETURN_FAILURE( |
4344 isolate, | 4055 isolate, |
4345 NewReferenceError("unsupported_super", HandleVector<Object>(NULL, 0))); | 4056 NewReferenceError("unsupported_super", HandleVector<Object>(NULL, 0))); |
4346 } | 4057 } |
4347 | 4058 |
4348 | 4059 |
4349 RUNTIME_FUNCTION(Runtime_ThrowNotDateError) { | |
4350 HandleScope scope(isolate); | |
4351 DCHECK(args.length() == 0); | |
4352 THROW_NEW_ERROR_RETURN_FAILURE( | |
4353 isolate, NewTypeError("not_date_object", HandleVector<Object>(NULL, 0))); | |
4354 } | |
4355 | |
4356 | |
4357 RUNTIME_FUNCTION(Runtime_StackGuard) { | 4060 RUNTIME_FUNCTION(Runtime_StackGuard) { |
4358 SealHandleScope shs(isolate); | 4061 SealHandleScope shs(isolate); |
4359 DCHECK(args.length() == 0); | 4062 DCHECK(args.length() == 0); |
4360 | 4063 |
4361 // First check if this is a real stack overflow. | 4064 // First check if this is a real stack overflow. |
4362 StackLimitCheck check(isolate); | 4065 StackLimitCheck check(isolate); |
4363 if (check.JsHasOverflowed()) { | 4066 if (check.JsHasOverflowed()) { |
4364 return isolate->StackOverflow(); | 4067 return isolate->StackOverflow(); |
4365 } | 4068 } |
4366 | 4069 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4415 | 4118 |
4416 RUNTIME_FUNCTION(Runtime_TraceExit) { | 4119 RUNTIME_FUNCTION(Runtime_TraceExit) { |
4417 SealHandleScope shs(isolate); | 4120 SealHandleScope shs(isolate); |
4418 DCHECK(args.length() == 1); | 4121 DCHECK(args.length() == 1); |
4419 CONVERT_ARG_CHECKED(Object, obj, 0); | 4122 CONVERT_ARG_CHECKED(Object, obj, 0); |
4420 PrintTransition(isolate, obj); | 4123 PrintTransition(isolate, obj); |
4421 return obj; // return TOS | 4124 return obj; // return TOS |
4422 } | 4125 } |
4423 | 4126 |
4424 | 4127 |
4425 RUNTIME_FUNCTION(Runtime_DateCurrentTime) { | |
4426 HandleScope scope(isolate); | |
4427 DCHECK(args.length() == 0); | |
4428 if (FLAG_log_timer_events) LOG(isolate, CurrentTimeEvent()); | |
4429 | |
4430 // According to ECMA-262, section 15.9.1, page 117, the precision of | |
4431 // the number in a Date object representing a particular instant in | |
4432 // time is milliseconds. Therefore, we floor the result of getting | |
4433 // the OS time. | |
4434 double millis; | |
4435 if (FLAG_verify_predictable) { | |
4436 millis = 1388534400000.0; // Jan 1 2014 00:00:00 GMT+0000 | |
4437 millis += Floor(isolate->heap()->synthetic_time()); | |
4438 } else { | |
4439 millis = Floor(base::OS::TimeCurrentMillis()); | |
4440 } | |
4441 return *isolate->factory()->NewNumber(millis); | |
4442 } | |
4443 | |
4444 | |
4445 RUNTIME_FUNCTION(Runtime_DateParseString) { | |
4446 HandleScope scope(isolate); | |
4447 DCHECK(args.length() == 2); | |
4448 CONVERT_ARG_HANDLE_CHECKED(String, str, 0); | |
4449 CONVERT_ARG_HANDLE_CHECKED(JSArray, output, 1); | |
4450 | |
4451 RUNTIME_ASSERT(output->HasFastElements()); | |
4452 JSObject::EnsureCanContainHeapObjectElements(output); | |
4453 RUNTIME_ASSERT(output->HasFastObjectElements()); | |
4454 Handle<FixedArray> output_array(FixedArray::cast(output->elements())); | |
4455 RUNTIME_ASSERT(output_array->length() >= DateParser::OUTPUT_SIZE); | |
4456 | |
4457 str = String::Flatten(str); | |
4458 DisallowHeapAllocation no_gc; | |
4459 | |
4460 bool result; | |
4461 String::FlatContent str_content = str->GetFlatContent(); | |
4462 if (str_content.IsOneByte()) { | |
4463 result = DateParser::Parse(str_content.ToOneByteVector(), *output_array, | |
4464 isolate->unicode_cache()); | |
4465 } else { | |
4466 DCHECK(str_content.IsTwoByte()); | |
4467 result = DateParser::Parse(str_content.ToUC16Vector(), *output_array, | |
4468 isolate->unicode_cache()); | |
4469 } | |
4470 | |
4471 if (result) { | |
4472 return *output; | |
4473 } else { | |
4474 return isolate->heap()->null_value(); | |
4475 } | |
4476 } | |
4477 | |
4478 | |
4479 RUNTIME_FUNCTION(Runtime_DateLocalTimezone) { | |
4480 HandleScope scope(isolate); | |
4481 DCHECK(args.length() == 1); | |
4482 | |
4483 CONVERT_DOUBLE_ARG_CHECKED(x, 0); | |
4484 RUNTIME_ASSERT(x >= -DateCache::kMaxTimeBeforeUTCInMs && | |
4485 x <= DateCache::kMaxTimeBeforeUTCInMs); | |
4486 const char* zone = | |
4487 isolate->date_cache()->LocalTimezone(static_cast<int64_t>(x)); | |
4488 Handle<String> result = | |
4489 isolate->factory()->NewStringFromUtf8(CStrVector(zone)).ToHandleChecked(); | |
4490 return *result; | |
4491 } | |
4492 | |
4493 | |
4494 RUNTIME_FUNCTION(Runtime_DateToUTC) { | |
4495 HandleScope scope(isolate); | |
4496 DCHECK(args.length() == 1); | |
4497 | |
4498 CONVERT_DOUBLE_ARG_CHECKED(x, 0); | |
4499 RUNTIME_ASSERT(x >= -DateCache::kMaxTimeBeforeUTCInMs && | |
4500 x <= DateCache::kMaxTimeBeforeUTCInMs); | |
4501 int64_t time = isolate->date_cache()->ToUTC(static_cast<int64_t>(x)); | |
4502 | |
4503 return *isolate->factory()->NewNumber(static_cast<double>(time)); | |
4504 } | |
4505 | |
4506 | |
4507 RUNTIME_FUNCTION(Runtime_DateCacheVersion) { | |
4508 HandleScope hs(isolate); | |
4509 DCHECK(args.length() == 0); | |
4510 if (!isolate->eternal_handles()->Exists(EternalHandles::DATE_CACHE_VERSION)) { | |
4511 Handle<FixedArray> date_cache_version = | |
4512 isolate->factory()->NewFixedArray(1, TENURED); | |
4513 date_cache_version->set(0, Smi::FromInt(0)); | |
4514 isolate->eternal_handles()->CreateSingleton( | |
4515 isolate, *date_cache_version, EternalHandles::DATE_CACHE_VERSION); | |
4516 } | |
4517 Handle<FixedArray> date_cache_version = | |
4518 Handle<FixedArray>::cast(isolate->eternal_handles()->GetSingleton( | |
4519 EternalHandles::DATE_CACHE_VERSION)); | |
4520 // Return result as a JS array. | |
4521 Handle<JSObject> result = | |
4522 isolate->factory()->NewJSObject(isolate->array_function()); | |
4523 JSArray::SetContent(Handle<JSArray>::cast(result), date_cache_version); | |
4524 return *result; | |
4525 } | |
4526 | |
4527 | |
4528 RUNTIME_FUNCTION(Runtime_GlobalProxy) { | 4128 RUNTIME_FUNCTION(Runtime_GlobalProxy) { |
4529 SealHandleScope shs(isolate); | 4129 SealHandleScope shs(isolate); |
4530 DCHECK(args.length() == 1); | 4130 DCHECK(args.length() == 1); |
4531 CONVERT_ARG_CHECKED(Object, global, 0); | 4131 CONVERT_ARG_CHECKED(Object, global, 0); |
4532 if (!global->IsJSGlobalObject()) return isolate->heap()->null_value(); | 4132 if (!global->IsJSGlobalObject()) return isolate->heap()->null_value(); |
4533 return JSGlobalObject::cast(global)->global_proxy(); | 4133 return JSGlobalObject::cast(global)->global_proxy(); |
4534 } | 4134 } |
4535 | 4135 |
4536 | 4136 |
4537 RUNTIME_FUNCTION(Runtime_IsAttachedGlobal) { | 4137 RUNTIME_FUNCTION(Runtime_IsAttachedGlobal) { |
(...skipping 879 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5417 AccessorComponent component = flag == 0 ? ACCESSOR_GETTER : ACCESSOR_SETTER; | 5017 AccessorComponent component = flag == 0 ? ACCESSOR_GETTER : ACCESSOR_SETTER; |
5418 if (!receiver->IsJSObject()) return isolate->heap()->undefined_value(); | 5018 if (!receiver->IsJSObject()) return isolate->heap()->undefined_value(); |
5419 Handle<Object> result; | 5019 Handle<Object> result; |
5420 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 5020 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
5421 isolate, result, | 5021 isolate, result, |
5422 JSObject::GetAccessor(Handle<JSObject>::cast(receiver), name, component)); | 5022 JSObject::GetAccessor(Handle<JSObject>::cast(receiver), name, component)); |
5423 return *result; | 5023 return *result; |
5424 } | 5024 } |
5425 | 5025 |
5426 | 5026 |
5427 RUNTIME_FUNCTION(Runtime_DebugBreak) { | |
5428 SealHandleScope shs(isolate); | |
5429 DCHECK(args.length() == 0); | |
5430 isolate->debug()->HandleDebugBreak(); | |
5431 return isolate->heap()->undefined_value(); | |
5432 } | |
5433 | |
5434 | |
5435 // Helper functions for wrapping and unwrapping stack frame ids. | |
5436 static Smi* WrapFrameId(StackFrame::Id id) { | |
5437 DCHECK(IsAligned(OffsetFrom(id), static_cast<intptr_t>(4))); | |
5438 return Smi::FromInt(id >> 2); | |
5439 } | |
5440 | |
5441 | |
5442 static StackFrame::Id UnwrapFrameId(int wrapped) { | |
5443 return static_cast<StackFrame::Id>(wrapped << 2); | |
5444 } | |
5445 | |
5446 | |
5447 // Adds a JavaScript function as a debug event listener. | |
5448 // args[0]: debug event listener function to set or null or undefined for | |
5449 // clearing the event listener function | |
5450 // args[1]: object supplied during callback | |
5451 RUNTIME_FUNCTION(Runtime_SetDebugEventListener) { | |
5452 SealHandleScope shs(isolate); | |
5453 DCHECK(args.length() == 2); | |
5454 RUNTIME_ASSERT(args[0]->IsJSFunction() || args[0]->IsUndefined() || | |
5455 args[0]->IsNull()); | |
5456 CONVERT_ARG_HANDLE_CHECKED(Object, callback, 0); | |
5457 CONVERT_ARG_HANDLE_CHECKED(Object, data, 1); | |
5458 isolate->debug()->SetEventListener(callback, data); | |
5459 | |
5460 return isolate->heap()->undefined_value(); | |
5461 } | |
5462 | |
5463 | |
5464 RUNTIME_FUNCTION(Runtime_Break) { | |
5465 SealHandleScope shs(isolate); | |
5466 DCHECK(args.length() == 0); | |
5467 isolate->stack_guard()->RequestDebugBreak(); | |
5468 return isolate->heap()->undefined_value(); | |
5469 } | |
5470 | |
5471 | |
5472 static Handle<Object> DebugGetProperty(LookupIterator* it, | |
5473 bool* has_caught = NULL) { | |
5474 for (; it->IsFound(); it->Next()) { | |
5475 switch (it->state()) { | |
5476 case LookupIterator::NOT_FOUND: | |
5477 case LookupIterator::TRANSITION: | |
5478 UNREACHABLE(); | |
5479 case LookupIterator::ACCESS_CHECK: | |
5480 // Ignore access checks. | |
5481 break; | |
5482 case LookupIterator::INTERCEPTOR: | |
5483 case LookupIterator::JSPROXY: | |
5484 return it->isolate()->factory()->undefined_value(); | |
5485 case LookupIterator::ACCESSOR: { | |
5486 Handle<Object> accessors = it->GetAccessors(); | |
5487 if (!accessors->IsAccessorInfo()) { | |
5488 return it->isolate()->factory()->undefined_value(); | |
5489 } | |
5490 MaybeHandle<Object> maybe_result = JSObject::GetPropertyWithAccessor( | |
5491 it->GetReceiver(), it->name(), it->GetHolder<JSObject>(), | |
5492 accessors); | |
5493 Handle<Object> result; | |
5494 if (!maybe_result.ToHandle(&result)) { | |
5495 result = handle(it->isolate()->pending_exception(), it->isolate()); | |
5496 it->isolate()->clear_pending_exception(); | |
5497 if (has_caught != NULL) *has_caught = true; | |
5498 } | |
5499 return result; | |
5500 } | |
5501 | |
5502 case LookupIterator::DATA: | |
5503 return it->GetDataValue(); | |
5504 } | |
5505 } | |
5506 | |
5507 return it->isolate()->factory()->undefined_value(); | |
5508 } | |
5509 | |
5510 | |
5511 // Get debugger related details for an object property, in the following format: | |
5512 // 0: Property value | |
5513 // 1: Property details | |
5514 // 2: Property value is exception | |
5515 // 3: Getter function if defined | |
5516 // 4: Setter function if defined | |
5517 // Items 2-4 are only filled if the property has either a getter or a setter. | |
5518 RUNTIME_FUNCTION(Runtime_DebugGetPropertyDetails) { | |
5519 HandleScope scope(isolate); | |
5520 | |
5521 DCHECK(args.length() == 2); | |
5522 | |
5523 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0); | |
5524 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1); | |
5525 | |
5526 // Make sure to set the current context to the context before the debugger was | |
5527 // entered (if the debugger is entered). The reason for switching context here | |
5528 // is that for some property lookups (accessors and interceptors) callbacks | |
5529 // into the embedding application can occour, and the embedding application | |
5530 // could have the assumption that its own native context is the current | |
5531 // context and not some internal debugger context. | |
5532 SaveContext save(isolate); | |
5533 if (isolate->debug()->in_debug_scope()) { | |
5534 isolate->set_context(*isolate->debug()->debugger_entry()->GetContext()); | |
5535 } | |
5536 | |
5537 // Check if the name is trivially convertible to an index and get the element | |
5538 // if so. | |
5539 uint32_t index; | |
5540 if (name->AsArrayIndex(&index)) { | |
5541 Handle<FixedArray> details = isolate->factory()->NewFixedArray(2); | |
5542 Handle<Object> element_or_char; | |
5543 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | |
5544 isolate, element_or_char, | |
5545 Runtime::GetElementOrCharAt(isolate, obj, index)); | |
5546 details->set(0, *element_or_char); | |
5547 details->set(1, | |
5548 PropertyDetails(NONE, NORMAL, Representation::None()).AsSmi()); | |
5549 return *isolate->factory()->NewJSArrayWithElements(details); | |
5550 } | |
5551 | |
5552 LookupIterator it(obj, name, LookupIterator::HIDDEN); | |
5553 bool has_caught = false; | |
5554 Handle<Object> value = DebugGetProperty(&it, &has_caught); | |
5555 if (!it.IsFound()) return isolate->heap()->undefined_value(); | |
5556 | |
5557 Handle<Object> maybe_pair; | |
5558 if (it.state() == LookupIterator::ACCESSOR) { | |
5559 maybe_pair = it.GetAccessors(); | |
5560 } | |
5561 | |
5562 // If the callback object is a fixed array then it contains JavaScript | |
5563 // getter and/or setter. | |
5564 bool has_js_accessors = !maybe_pair.is_null() && maybe_pair->IsAccessorPair(); | |
5565 Handle<FixedArray> details = | |
5566 isolate->factory()->NewFixedArray(has_js_accessors ? 6 : 3); | |
5567 details->set(0, *value); | |
5568 // TODO(verwaest): Get rid of this random way of handling interceptors. | |
5569 PropertyDetails d = it.state() == LookupIterator::INTERCEPTOR | |
5570 ? PropertyDetails(NONE, NORMAL, 0) | |
5571 : it.property_details(); | |
5572 details->set(1, d.AsSmi()); | |
5573 details->set( | |
5574 2, isolate->heap()->ToBoolean(it.state() == LookupIterator::INTERCEPTOR)); | |
5575 if (has_js_accessors) { | |
5576 AccessorPair* accessors = AccessorPair::cast(*maybe_pair); | |
5577 details->set(3, isolate->heap()->ToBoolean(has_caught)); | |
5578 details->set(4, accessors->GetComponent(ACCESSOR_GETTER)); | |
5579 details->set(5, accessors->GetComponent(ACCESSOR_SETTER)); | |
5580 } | |
5581 | |
5582 return *isolate->factory()->NewJSArrayWithElements(details); | |
5583 } | |
5584 | |
5585 | |
5586 RUNTIME_FUNCTION(Runtime_DebugGetProperty) { | |
5587 HandleScope scope(isolate); | |
5588 | |
5589 DCHECK(args.length() == 2); | |
5590 | |
5591 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0); | |
5592 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1); | |
5593 | |
5594 LookupIterator it(obj, name); | |
5595 return *DebugGetProperty(&it); | |
5596 } | |
5597 | |
5598 | |
5599 // Return the property type calculated from the property details. | |
5600 // args[0]: smi with property details. | |
5601 RUNTIME_FUNCTION(Runtime_DebugPropertyTypeFromDetails) { | |
5602 SealHandleScope shs(isolate); | |
5603 DCHECK(args.length() == 1); | |
5604 CONVERT_PROPERTY_DETAILS_CHECKED(details, 0); | |
5605 return Smi::FromInt(static_cast<int>(details.type())); | |
5606 } | |
5607 | |
5608 | |
5609 // Return the property attribute calculated from the property details. | |
5610 // args[0]: smi with property details. | |
5611 RUNTIME_FUNCTION(Runtime_DebugPropertyAttributesFromDetails) { | |
5612 SealHandleScope shs(isolate); | |
5613 DCHECK(args.length() == 1); | |
5614 CONVERT_PROPERTY_DETAILS_CHECKED(details, 0); | |
5615 return Smi::FromInt(static_cast<int>(details.attributes())); | |
5616 } | |
5617 | |
5618 | |
5619 // Return the property insertion index calculated from the property details. | |
5620 // args[0]: smi with property details. | |
5621 RUNTIME_FUNCTION(Runtime_DebugPropertyIndexFromDetails) { | |
5622 SealHandleScope shs(isolate); | |
5623 DCHECK(args.length() == 1); | |
5624 CONVERT_PROPERTY_DETAILS_CHECKED(details, 0); | |
5625 // TODO(verwaest): Depends on the type of details. | |
5626 return Smi::FromInt(details.dictionary_index()); | |
5627 } | |
5628 | |
5629 | |
5630 // Return property value from named interceptor. | |
5631 // args[0]: object | |
5632 // args[1]: property name | |
5633 RUNTIME_FUNCTION(Runtime_DebugNamedInterceptorPropertyValue) { | |
5634 HandleScope scope(isolate); | |
5635 DCHECK(args.length() == 2); | |
5636 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0); | |
5637 RUNTIME_ASSERT(obj->HasNamedInterceptor()); | |
5638 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1); | |
5639 | |
5640 Handle<Object> result; | |
5641 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, | |
5642 JSObject::GetProperty(obj, name)); | |
5643 return *result; | |
5644 } | |
5645 | |
5646 | |
5647 // Return element value from indexed interceptor. | |
5648 // args[0]: object | |
5649 // args[1]: index | |
5650 RUNTIME_FUNCTION(Runtime_DebugIndexedInterceptorElementValue) { | |
5651 HandleScope scope(isolate); | |
5652 DCHECK(args.length() == 2); | |
5653 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0); | |
5654 RUNTIME_ASSERT(obj->HasIndexedInterceptor()); | |
5655 CONVERT_NUMBER_CHECKED(uint32_t, index, Uint32, args[1]); | |
5656 Handle<Object> result; | |
5657 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | |
5658 isolate, result, JSObject::GetElementWithInterceptor(obj, obj, index)); | |
5659 return *result; | |
5660 } | |
5661 | |
5662 | |
5663 static bool CheckExecutionState(Isolate* isolate, int break_id) { | |
5664 return !isolate->debug()->debug_context().is_null() && | |
5665 isolate->debug()->break_id() != 0 && | |
5666 isolate->debug()->break_id() == break_id; | |
5667 } | |
5668 | |
5669 | |
5670 RUNTIME_FUNCTION(Runtime_CheckExecutionState) { | |
5671 SealHandleScope shs(isolate); | |
5672 DCHECK(args.length() == 1); | |
5673 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]); | |
5674 RUNTIME_ASSERT(CheckExecutionState(isolate, break_id)); | |
5675 return isolate->heap()->true_value(); | |
5676 } | |
5677 | |
5678 | |
5679 RUNTIME_FUNCTION(Runtime_GetFrameCount) { | |
5680 HandleScope scope(isolate); | |
5681 DCHECK(args.length() == 1); | |
5682 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]); | |
5683 RUNTIME_ASSERT(CheckExecutionState(isolate, break_id)); | |
5684 | |
5685 // Count all frames which are relevant to debugging stack trace. | |
5686 int n = 0; | |
5687 StackFrame::Id id = isolate->debug()->break_frame_id(); | |
5688 if (id == StackFrame::NO_ID) { | |
5689 // If there is no JavaScript stack frame count is 0. | |
5690 return Smi::FromInt(0); | |
5691 } | |
5692 | |
5693 for (JavaScriptFrameIterator it(isolate, id); !it.done(); it.Advance()) { | |
5694 List<FrameSummary> frames(FLAG_max_inlining_levels + 1); | |
5695 it.frame()->Summarize(&frames); | |
5696 for (int i = frames.length() - 1; i >= 0; i--) { | |
5697 // Omit functions from native scripts. | |
5698 if (!frames[i].function()->IsFromNativeScript()) n++; | |
5699 } | |
5700 } | |
5701 return Smi::FromInt(n); | |
5702 } | |
5703 | |
5704 | |
5705 class FrameInspector { | |
5706 public: | |
5707 FrameInspector(JavaScriptFrame* frame, int inlined_jsframe_index, | |
5708 Isolate* isolate) | |
5709 : frame_(frame), deoptimized_frame_(NULL), isolate_(isolate) { | |
5710 // Calculate the deoptimized frame. | |
5711 if (frame->is_optimized()) { | |
5712 deoptimized_frame_ = Deoptimizer::DebuggerInspectableFrame( | |
5713 frame, inlined_jsframe_index, isolate); | |
5714 } | |
5715 has_adapted_arguments_ = frame_->has_adapted_arguments(); | |
5716 is_bottommost_ = inlined_jsframe_index == 0; | |
5717 is_optimized_ = frame_->is_optimized(); | |
5718 } | |
5719 | |
5720 ~FrameInspector() { | |
5721 // Get rid of the calculated deoptimized frame if any. | |
5722 if (deoptimized_frame_ != NULL) { | |
5723 Deoptimizer::DeleteDebuggerInspectableFrame(deoptimized_frame_, isolate_); | |
5724 } | |
5725 } | |
5726 | |
5727 int GetParametersCount() { | |
5728 return is_optimized_ ? deoptimized_frame_->parameters_count() | |
5729 : frame_->ComputeParametersCount(); | |
5730 } | |
5731 int expression_count() { return deoptimized_frame_->expression_count(); } | |
5732 Object* GetFunction() { | |
5733 return is_optimized_ ? deoptimized_frame_->GetFunction() | |
5734 : frame_->function(); | |
5735 } | |
5736 Object* GetParameter(int index) { | |
5737 return is_optimized_ ? deoptimized_frame_->GetParameter(index) | |
5738 : frame_->GetParameter(index); | |
5739 } | |
5740 Object* GetExpression(int index) { | |
5741 return is_optimized_ ? deoptimized_frame_->GetExpression(index) | |
5742 : frame_->GetExpression(index); | |
5743 } | |
5744 int GetSourcePosition() { | |
5745 return is_optimized_ ? deoptimized_frame_->GetSourcePosition() | |
5746 : frame_->LookupCode()->SourcePosition(frame_->pc()); | |
5747 } | |
5748 bool IsConstructor() { | |
5749 return is_optimized_ && !is_bottommost_ | |
5750 ? deoptimized_frame_->HasConstructStub() | |
5751 : frame_->IsConstructor(); | |
5752 } | |
5753 Object* GetContext() { | |
5754 return is_optimized_ ? deoptimized_frame_->GetContext() : frame_->context(); | |
5755 } | |
5756 | |
5757 // To inspect all the provided arguments the frame might need to be | |
5758 // replaced with the arguments frame. | |
5759 void SetArgumentsFrame(JavaScriptFrame* frame) { | |
5760 DCHECK(has_adapted_arguments_); | |
5761 frame_ = frame; | |
5762 is_optimized_ = frame_->is_optimized(); | |
5763 DCHECK(!is_optimized_); | |
5764 } | |
5765 | |
5766 private: | |
5767 JavaScriptFrame* frame_; | |
5768 DeoptimizedFrameInfo* deoptimized_frame_; | |
5769 Isolate* isolate_; | |
5770 bool is_optimized_; | |
5771 bool is_bottommost_; | |
5772 bool has_adapted_arguments_; | |
5773 | |
5774 DISALLOW_COPY_AND_ASSIGN(FrameInspector); | |
5775 }; | |
5776 | |
5777 | |
5778 static const int kFrameDetailsFrameIdIndex = 0; | |
5779 static const int kFrameDetailsReceiverIndex = 1; | |
5780 static const int kFrameDetailsFunctionIndex = 2; | |
5781 static const int kFrameDetailsArgumentCountIndex = 3; | |
5782 static const int kFrameDetailsLocalCountIndex = 4; | |
5783 static const int kFrameDetailsSourcePositionIndex = 5; | |
5784 static const int kFrameDetailsConstructCallIndex = 6; | |
5785 static const int kFrameDetailsAtReturnIndex = 7; | |
5786 static const int kFrameDetailsFlagsIndex = 8; | |
5787 static const int kFrameDetailsFirstDynamicIndex = 9; | |
5788 | |
5789 | |
5790 static SaveContext* FindSavedContextForFrame(Isolate* isolate, | |
5791 JavaScriptFrame* frame) { | |
5792 SaveContext* save = isolate->save_context(); | |
5793 while (save != NULL && !save->IsBelowFrame(frame)) { | |
5794 save = save->prev(); | |
5795 } | |
5796 DCHECK(save != NULL); | |
5797 return save; | |
5798 } | |
5799 | |
5800 | |
5801 // Advances the iterator to the frame that matches the index and returns the | |
5802 // inlined frame index, or -1 if not found. Skips native JS functions. | |
5803 static int FindIndexedNonNativeFrame(JavaScriptFrameIterator* it, int index) { | |
5804 int count = -1; | |
5805 for (; !it->done(); it->Advance()) { | |
5806 List<FrameSummary> frames(FLAG_max_inlining_levels + 1); | |
5807 it->frame()->Summarize(&frames); | |
5808 for (int i = frames.length() - 1; i >= 0; i--) { | |
5809 // Omit functions from native scripts. | |
5810 if (frames[i].function()->IsFromNativeScript()) continue; | |
5811 if (++count == index) return i; | |
5812 } | |
5813 } | |
5814 return -1; | |
5815 } | |
5816 | |
5817 | |
5818 // Return an array with frame details | |
5819 // args[0]: number: break id | |
5820 // args[1]: number: frame index | |
5821 // | |
5822 // The array returned contains the following information: | |
5823 // 0: Frame id | |
5824 // 1: Receiver | |
5825 // 2: Function | |
5826 // 3: Argument count | |
5827 // 4: Local count | |
5828 // 5: Source position | |
5829 // 6: Constructor call | |
5830 // 7: Is at return | |
5831 // 8: Flags | |
5832 // Arguments name, value | |
5833 // Locals name, value | |
5834 // Return value if any | |
5835 RUNTIME_FUNCTION(Runtime_GetFrameDetails) { | |
5836 HandleScope scope(isolate); | |
5837 DCHECK(args.length() == 2); | |
5838 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]); | |
5839 RUNTIME_ASSERT(CheckExecutionState(isolate, break_id)); | |
5840 | |
5841 CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]); | |
5842 Heap* heap = isolate->heap(); | |
5843 | |
5844 // Find the relevant frame with the requested index. | |
5845 StackFrame::Id id = isolate->debug()->break_frame_id(); | |
5846 if (id == StackFrame::NO_ID) { | |
5847 // If there are no JavaScript stack frames return undefined. | |
5848 return heap->undefined_value(); | |
5849 } | |
5850 | |
5851 JavaScriptFrameIterator it(isolate, id); | |
5852 // Inlined frame index in optimized frame, starting from outer function. | |
5853 int inlined_jsframe_index = FindIndexedNonNativeFrame(&it, index); | |
5854 if (inlined_jsframe_index == -1) return heap->undefined_value(); | |
5855 | |
5856 FrameInspector frame_inspector(it.frame(), inlined_jsframe_index, isolate); | |
5857 bool is_optimized = it.frame()->is_optimized(); | |
5858 | |
5859 // Traverse the saved contexts chain to find the active context for the | |
5860 // selected frame. | |
5861 SaveContext* save = FindSavedContextForFrame(isolate, it.frame()); | |
5862 | |
5863 // Get the frame id. | |
5864 Handle<Object> frame_id(WrapFrameId(it.frame()->id()), isolate); | |
5865 | |
5866 // Find source position in unoptimized code. | |
5867 int position = frame_inspector.GetSourcePosition(); | |
5868 | |
5869 // Check for constructor frame. | |
5870 bool constructor = frame_inspector.IsConstructor(); | |
5871 | |
5872 // Get scope info and read from it for local variable information. | |
5873 Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction())); | |
5874 Handle<SharedFunctionInfo> shared(function->shared()); | |
5875 Handle<ScopeInfo> scope_info(shared->scope_info()); | |
5876 DCHECK(*scope_info != ScopeInfo::Empty(isolate)); | |
5877 | |
5878 // Get the locals names and values into a temporary array. | |
5879 int local_count = scope_info->LocalCount(); | |
5880 for (int slot = 0; slot < scope_info->LocalCount(); ++slot) { | |
5881 // Hide compiler-introduced temporary variables, whether on the stack or on | |
5882 // the context. | |
5883 if (scope_info->LocalIsSynthetic(slot)) local_count--; | |
5884 } | |
5885 | |
5886 Handle<FixedArray> locals = | |
5887 isolate->factory()->NewFixedArray(local_count * 2); | |
5888 | |
5889 // Fill in the values of the locals. | |
5890 int local = 0; | |
5891 int i = 0; | |
5892 for (; i < scope_info->StackLocalCount(); ++i) { | |
5893 // Use the value from the stack. | |
5894 if (scope_info->LocalIsSynthetic(i)) continue; | |
5895 locals->set(local * 2, scope_info->LocalName(i)); | |
5896 locals->set(local * 2 + 1, frame_inspector.GetExpression(i)); | |
5897 local++; | |
5898 } | |
5899 if (local < local_count) { | |
5900 // Get the context containing declarations. | |
5901 Handle<Context> context( | |
5902 Context::cast(frame_inspector.GetContext())->declaration_context()); | |
5903 for (; i < scope_info->LocalCount(); ++i) { | |
5904 if (scope_info->LocalIsSynthetic(i)) continue; | |
5905 Handle<String> name(scope_info->LocalName(i)); | |
5906 VariableMode mode; | |
5907 InitializationFlag init_flag; | |
5908 MaybeAssignedFlag maybe_assigned_flag; | |
5909 locals->set(local * 2, *name); | |
5910 int context_slot_index = ScopeInfo::ContextSlotIndex( | |
5911 scope_info, name, &mode, &init_flag, &maybe_assigned_flag); | |
5912 Object* value = context->get(context_slot_index); | |
5913 locals->set(local * 2 + 1, value); | |
5914 local++; | |
5915 } | |
5916 } | |
5917 | |
5918 // Check whether this frame is positioned at return. If not top | |
5919 // frame or if the frame is optimized it cannot be at a return. | |
5920 bool at_return = false; | |
5921 if (!is_optimized && index == 0) { | |
5922 at_return = isolate->debug()->IsBreakAtReturn(it.frame()); | |
5923 } | |
5924 | |
5925 // If positioned just before return find the value to be returned and add it | |
5926 // to the frame information. | |
5927 Handle<Object> return_value = isolate->factory()->undefined_value(); | |
5928 if (at_return) { | |
5929 StackFrameIterator it2(isolate); | |
5930 Address internal_frame_sp = NULL; | |
5931 while (!it2.done()) { | |
5932 if (it2.frame()->is_internal()) { | |
5933 internal_frame_sp = it2.frame()->sp(); | |
5934 } else { | |
5935 if (it2.frame()->is_java_script()) { | |
5936 if (it2.frame()->id() == it.frame()->id()) { | |
5937 // The internal frame just before the JavaScript frame contains the | |
5938 // value to return on top. A debug break at return will create an | |
5939 // internal frame to store the return value (eax/rax/r0) before | |
5940 // entering the debug break exit frame. | |
5941 if (internal_frame_sp != NULL) { | |
5942 return_value = | |
5943 Handle<Object>(Memory::Object_at(internal_frame_sp), isolate); | |
5944 break; | |
5945 } | |
5946 } | |
5947 } | |
5948 | |
5949 // Indicate that the previous frame was not an internal frame. | |
5950 internal_frame_sp = NULL; | |
5951 } | |
5952 it2.Advance(); | |
5953 } | |
5954 } | |
5955 | |
5956 // Now advance to the arguments adapter frame (if any). It contains all | |
5957 // the provided parameters whereas the function frame always have the number | |
5958 // of arguments matching the functions parameters. The rest of the | |
5959 // information (except for what is collected above) is the same. | |
5960 if ((inlined_jsframe_index == 0) && it.frame()->has_adapted_arguments()) { | |
5961 it.AdvanceToArgumentsFrame(); | |
5962 frame_inspector.SetArgumentsFrame(it.frame()); | |
5963 } | |
5964 | |
5965 // Find the number of arguments to fill. At least fill the number of | |
5966 // parameters for the function and fill more if more parameters are provided. | |
5967 int argument_count = scope_info->ParameterCount(); | |
5968 if (argument_count < frame_inspector.GetParametersCount()) { | |
5969 argument_count = frame_inspector.GetParametersCount(); | |
5970 } | |
5971 | |
5972 // Calculate the size of the result. | |
5973 int details_size = kFrameDetailsFirstDynamicIndex + | |
5974 2 * (argument_count + local_count) + (at_return ? 1 : 0); | |
5975 Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size); | |
5976 | |
5977 // Add the frame id. | |
5978 details->set(kFrameDetailsFrameIdIndex, *frame_id); | |
5979 | |
5980 // Add the function (same as in function frame). | |
5981 details->set(kFrameDetailsFunctionIndex, frame_inspector.GetFunction()); | |
5982 | |
5983 // Add the arguments count. | |
5984 details->set(kFrameDetailsArgumentCountIndex, Smi::FromInt(argument_count)); | |
5985 | |
5986 // Add the locals count | |
5987 details->set(kFrameDetailsLocalCountIndex, Smi::FromInt(local_count)); | |
5988 | |
5989 // Add the source position. | |
5990 if (position != RelocInfo::kNoPosition) { | |
5991 details->set(kFrameDetailsSourcePositionIndex, Smi::FromInt(position)); | |
5992 } else { | |
5993 details->set(kFrameDetailsSourcePositionIndex, heap->undefined_value()); | |
5994 } | |
5995 | |
5996 // Add the constructor information. | |
5997 details->set(kFrameDetailsConstructCallIndex, heap->ToBoolean(constructor)); | |
5998 | |
5999 // Add the at return information. | |
6000 details->set(kFrameDetailsAtReturnIndex, heap->ToBoolean(at_return)); | |
6001 | |
6002 // Add flags to indicate information on whether this frame is | |
6003 // bit 0: invoked in the debugger context. | |
6004 // bit 1: optimized frame. | |
6005 // bit 2: inlined in optimized frame | |
6006 int flags = 0; | |
6007 if (*save->context() == *isolate->debug()->debug_context()) { | |
6008 flags |= 1 << 0; | |
6009 } | |
6010 if (is_optimized) { | |
6011 flags |= 1 << 1; | |
6012 flags |= inlined_jsframe_index << 2; | |
6013 } | |
6014 details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags)); | |
6015 | |
6016 // Fill the dynamic part. | |
6017 int details_index = kFrameDetailsFirstDynamicIndex; | |
6018 | |
6019 // Add arguments name and value. | |
6020 for (int i = 0; i < argument_count; i++) { | |
6021 // Name of the argument. | |
6022 if (i < scope_info->ParameterCount()) { | |
6023 details->set(details_index++, scope_info->ParameterName(i)); | |
6024 } else { | |
6025 details->set(details_index++, heap->undefined_value()); | |
6026 } | |
6027 | |
6028 // Parameter value. | |
6029 if (i < frame_inspector.GetParametersCount()) { | |
6030 // Get the value from the stack. | |
6031 details->set(details_index++, frame_inspector.GetParameter(i)); | |
6032 } else { | |
6033 details->set(details_index++, heap->undefined_value()); | |
6034 } | |
6035 } | |
6036 | |
6037 // Add locals name and value from the temporary copy from the function frame. | |
6038 for (int i = 0; i < local_count * 2; i++) { | |
6039 details->set(details_index++, locals->get(i)); | |
6040 } | |
6041 | |
6042 // Add the value being returned. | |
6043 if (at_return) { | |
6044 details->set(details_index++, *return_value); | |
6045 } | |
6046 | |
6047 // Add the receiver (same as in function frame). | |
6048 // THIS MUST BE DONE LAST SINCE WE MIGHT ADVANCE | |
6049 // THE FRAME ITERATOR TO WRAP THE RECEIVER. | |
6050 Handle<Object> receiver(it.frame()->receiver(), isolate); | |
6051 if (!receiver->IsJSObject() && shared->strict_mode() == SLOPPY && | |
6052 !function->IsBuiltin()) { | |
6053 // If the receiver is not a JSObject and the function is not a | |
6054 // builtin or strict-mode we have hit an optimization where a | |
6055 // value object is not converted into a wrapped JS objects. To | |
6056 // hide this optimization from the debugger, we wrap the receiver | |
6057 // by creating correct wrapper object based on the calling frame's | |
6058 // native context. | |
6059 it.Advance(); | |
6060 if (receiver->IsUndefined()) { | |
6061 receiver = handle(function->global_proxy()); | |
6062 } else { | |
6063 Context* context = Context::cast(it.frame()->context()); | |
6064 Handle<Context> native_context(Context::cast(context->native_context())); | |
6065 if (!Object::ToObject(isolate, receiver, native_context) | |
6066 .ToHandle(&receiver)) { | |
6067 // This only happens if the receiver is forcibly set in %_CallFunction. | |
6068 return heap->undefined_value(); | |
6069 } | |
6070 } | |
6071 } | |
6072 details->set(kFrameDetailsReceiverIndex, *receiver); | |
6073 | |
6074 DCHECK_EQ(details_size, details_index); | |
6075 return *isolate->factory()->NewJSArrayWithElements(details); | |
6076 } | |
6077 | |
6078 | |
6079 static bool ParameterIsShadowedByContextLocal(Handle<ScopeInfo> info, | |
6080 Handle<String> parameter_name) { | |
6081 VariableMode mode; | |
6082 InitializationFlag init_flag; | |
6083 MaybeAssignedFlag maybe_assigned_flag; | |
6084 return ScopeInfo::ContextSlotIndex(info, parameter_name, &mode, &init_flag, | |
6085 &maybe_assigned_flag) != -1; | |
6086 } | |
6087 | |
6088 | |
6089 // Create a plain JSObject which materializes the local scope for the specified | |
6090 // frame. | |
6091 MUST_USE_RESULT | |
6092 static MaybeHandle<JSObject> MaterializeStackLocalsWithFrameInspector( | |
6093 Isolate* isolate, Handle<JSObject> target, Handle<JSFunction> function, | |
6094 FrameInspector* frame_inspector) { | |
6095 Handle<SharedFunctionInfo> shared(function->shared()); | |
6096 Handle<ScopeInfo> scope_info(shared->scope_info()); | |
6097 | |
6098 // First fill all parameters. | |
6099 for (int i = 0; i < scope_info->ParameterCount(); ++i) { | |
6100 // Do not materialize the parameter if it is shadowed by a context local. | |
6101 Handle<String> name(scope_info->ParameterName(i)); | |
6102 if (ParameterIsShadowedByContextLocal(scope_info, name)) continue; | |
6103 | |
6104 HandleScope scope(isolate); | |
6105 Handle<Object> value(i < frame_inspector->GetParametersCount() | |
6106 ? frame_inspector->GetParameter(i) | |
6107 : isolate->heap()->undefined_value(), | |
6108 isolate); | |
6109 DCHECK(!value->IsTheHole()); | |
6110 | |
6111 RETURN_ON_EXCEPTION(isolate, Runtime::SetObjectProperty( | |
6112 isolate, target, name, value, SLOPPY), | |
6113 JSObject); | |
6114 } | |
6115 | |
6116 // Second fill all stack locals. | |
6117 for (int i = 0; i < scope_info->StackLocalCount(); ++i) { | |
6118 if (scope_info->LocalIsSynthetic(i)) continue; | |
6119 Handle<String> name(scope_info->StackLocalName(i)); | |
6120 Handle<Object> value(frame_inspector->GetExpression(i), isolate); | |
6121 if (value->IsTheHole()) continue; | |
6122 | |
6123 RETURN_ON_EXCEPTION(isolate, Runtime::SetObjectProperty( | |
6124 isolate, target, name, value, SLOPPY), | |
6125 JSObject); | |
6126 } | |
6127 | |
6128 return target; | |
6129 } | |
6130 | |
6131 | |
6132 static void UpdateStackLocalsFromMaterializedObject(Isolate* isolate, | |
6133 Handle<JSObject> target, | |
6134 Handle<JSFunction> function, | |
6135 JavaScriptFrame* frame, | |
6136 int inlined_jsframe_index) { | |
6137 if (inlined_jsframe_index != 0 || frame->is_optimized()) { | |
6138 // Optimized frames are not supported. | |
6139 // TODO(yangguo): make sure all code deoptimized when debugger is active | |
6140 // and assert that this cannot happen. | |
6141 return; | |
6142 } | |
6143 | |
6144 Handle<SharedFunctionInfo> shared(function->shared()); | |
6145 Handle<ScopeInfo> scope_info(shared->scope_info()); | |
6146 | |
6147 // Parameters. | |
6148 for (int i = 0; i < scope_info->ParameterCount(); ++i) { | |
6149 // Shadowed parameters were not materialized. | |
6150 Handle<String> name(scope_info->ParameterName(i)); | |
6151 if (ParameterIsShadowedByContextLocal(scope_info, name)) continue; | |
6152 | |
6153 DCHECK(!frame->GetParameter(i)->IsTheHole()); | |
6154 HandleScope scope(isolate); | |
6155 Handle<Object> value = | |
6156 Object::GetPropertyOrElement(target, name).ToHandleChecked(); | |
6157 frame->SetParameterValue(i, *value); | |
6158 } | |
6159 | |
6160 // Stack locals. | |
6161 for (int i = 0; i < scope_info->StackLocalCount(); ++i) { | |
6162 if (scope_info->LocalIsSynthetic(i)) continue; | |
6163 if (frame->GetExpression(i)->IsTheHole()) continue; | |
6164 HandleScope scope(isolate); | |
6165 Handle<Object> value = Object::GetPropertyOrElement( | |
6166 target, handle(scope_info->StackLocalName(i), | |
6167 isolate)).ToHandleChecked(); | |
6168 frame->SetExpression(i, *value); | |
6169 } | |
6170 } | |
6171 | |
6172 | |
6173 MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeLocalContext( | |
6174 Isolate* isolate, Handle<JSObject> target, Handle<JSFunction> function, | |
6175 JavaScriptFrame* frame) { | |
6176 HandleScope scope(isolate); | |
6177 Handle<SharedFunctionInfo> shared(function->shared()); | |
6178 Handle<ScopeInfo> scope_info(shared->scope_info()); | |
6179 | |
6180 if (!scope_info->HasContext()) return target; | |
6181 | |
6182 // Third fill all context locals. | |
6183 Handle<Context> frame_context(Context::cast(frame->context())); | |
6184 Handle<Context> function_context(frame_context->declaration_context()); | |
6185 if (!ScopeInfo::CopyContextLocalsToScopeObject(scope_info, function_context, | |
6186 target)) { | |
6187 return MaybeHandle<JSObject>(); | |
6188 } | |
6189 | |
6190 // Finally copy any properties from the function context extension. | |
6191 // These will be variables introduced by eval. | |
6192 if (function_context->closure() == *function) { | |
6193 if (function_context->has_extension() && | |
6194 !function_context->IsNativeContext()) { | |
6195 Handle<JSObject> ext(JSObject::cast(function_context->extension())); | |
6196 Handle<FixedArray> keys; | |
6197 ASSIGN_RETURN_ON_EXCEPTION( | |
6198 isolate, keys, JSReceiver::GetKeys(ext, JSReceiver::INCLUDE_PROTOS), | |
6199 JSObject); | |
6200 | |
6201 for (int i = 0; i < keys->length(); i++) { | |
6202 // Names of variables introduced by eval are strings. | |
6203 DCHECK(keys->get(i)->IsString()); | |
6204 Handle<String> key(String::cast(keys->get(i))); | |
6205 Handle<Object> value; | |
6206 ASSIGN_RETURN_ON_EXCEPTION( | |
6207 isolate, value, Object::GetPropertyOrElement(ext, key), JSObject); | |
6208 RETURN_ON_EXCEPTION(isolate, Runtime::SetObjectProperty( | |
6209 isolate, target, key, value, SLOPPY), | |
6210 JSObject); | |
6211 } | |
6212 } | |
6213 } | |
6214 | |
6215 return target; | |
6216 } | |
6217 | |
6218 | |
6219 MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeLocalScope( | |
6220 Isolate* isolate, JavaScriptFrame* frame, int inlined_jsframe_index) { | |
6221 FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate); | |
6222 Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction())); | |
6223 | |
6224 Handle<JSObject> local_scope = | |
6225 isolate->factory()->NewJSObject(isolate->object_function()); | |
6226 ASSIGN_RETURN_ON_EXCEPTION( | |
6227 isolate, local_scope, | |
6228 MaterializeStackLocalsWithFrameInspector(isolate, local_scope, function, | |
6229 &frame_inspector), | |
6230 JSObject); | |
6231 | |
6232 return MaterializeLocalContext(isolate, local_scope, function, frame); | |
6233 } | |
6234 | |
6235 | |
6236 // Set the context local variable value. | |
6237 static bool SetContextLocalValue(Isolate* isolate, Handle<ScopeInfo> scope_info, | |
6238 Handle<Context> context, | |
6239 Handle<String> variable_name, | |
6240 Handle<Object> new_value) { | |
6241 for (int i = 0; i < scope_info->ContextLocalCount(); i++) { | |
6242 Handle<String> next_name(scope_info->ContextLocalName(i)); | |
6243 if (String::Equals(variable_name, next_name)) { | |
6244 VariableMode mode; | |
6245 InitializationFlag init_flag; | |
6246 MaybeAssignedFlag maybe_assigned_flag; | |
6247 int context_index = ScopeInfo::ContextSlotIndex( | |
6248 scope_info, next_name, &mode, &init_flag, &maybe_assigned_flag); | |
6249 context->set(context_index, *new_value); | |
6250 return true; | |
6251 } | |
6252 } | |
6253 | |
6254 return false; | |
6255 } | |
6256 | |
6257 | |
6258 static bool SetLocalVariableValue(Isolate* isolate, JavaScriptFrame* frame, | |
6259 int inlined_jsframe_index, | |
6260 Handle<String> variable_name, | |
6261 Handle<Object> new_value) { | |
6262 if (inlined_jsframe_index != 0 || frame->is_optimized()) { | |
6263 // Optimized frames are not supported. | |
6264 return false; | |
6265 } | |
6266 | |
6267 Handle<JSFunction> function(frame->function()); | |
6268 Handle<SharedFunctionInfo> shared(function->shared()); | |
6269 Handle<ScopeInfo> scope_info(shared->scope_info()); | |
6270 | |
6271 bool default_result = false; | |
6272 | |
6273 // Parameters. | |
6274 for (int i = 0; i < scope_info->ParameterCount(); ++i) { | |
6275 HandleScope scope(isolate); | |
6276 if (String::Equals(handle(scope_info->ParameterName(i)), variable_name)) { | |
6277 frame->SetParameterValue(i, *new_value); | |
6278 // Argument might be shadowed in heap context, don't stop here. | |
6279 default_result = true; | |
6280 } | |
6281 } | |
6282 | |
6283 // Stack locals. | |
6284 for (int i = 0; i < scope_info->StackLocalCount(); ++i) { | |
6285 HandleScope scope(isolate); | |
6286 if (String::Equals(handle(scope_info->StackLocalName(i)), variable_name)) { | |
6287 frame->SetExpression(i, *new_value); | |
6288 return true; | |
6289 } | |
6290 } | |
6291 | |
6292 if (scope_info->HasContext()) { | |
6293 // Context locals. | |
6294 Handle<Context> frame_context(Context::cast(frame->context())); | |
6295 Handle<Context> function_context(frame_context->declaration_context()); | |
6296 if (SetContextLocalValue(isolate, scope_info, function_context, | |
6297 variable_name, new_value)) { | |
6298 return true; | |
6299 } | |
6300 | |
6301 // Function context extension. These are variables introduced by eval. | |
6302 if (function_context->closure() == *function) { | |
6303 if (function_context->has_extension() && | |
6304 !function_context->IsNativeContext()) { | |
6305 Handle<JSObject> ext(JSObject::cast(function_context->extension())); | |
6306 | |
6307 Maybe<bool> maybe = JSReceiver::HasProperty(ext, variable_name); | |
6308 DCHECK(maybe.has_value); | |
6309 if (maybe.value) { | |
6310 // We don't expect this to do anything except replacing | |
6311 // property value. | |
6312 Runtime::SetObjectProperty(isolate, ext, variable_name, new_value, | |
6313 SLOPPY).Assert(); | |
6314 return true; | |
6315 } | |
6316 } | |
6317 } | |
6318 } | |
6319 | |
6320 return default_result; | |
6321 } | |
6322 | |
6323 | |
6324 // Create a plain JSObject which materializes the closure content for the | |
6325 // context. | |
6326 MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeClosure( | |
6327 Isolate* isolate, Handle<Context> context) { | |
6328 DCHECK(context->IsFunctionContext()); | |
6329 | |
6330 Handle<SharedFunctionInfo> shared(context->closure()->shared()); | |
6331 Handle<ScopeInfo> scope_info(shared->scope_info()); | |
6332 | |
6333 // Allocate and initialize a JSObject with all the content of this function | |
6334 // closure. | |
6335 Handle<JSObject> closure_scope = | |
6336 isolate->factory()->NewJSObject(isolate->object_function()); | |
6337 | |
6338 // Fill all context locals to the context extension. | |
6339 if (!ScopeInfo::CopyContextLocalsToScopeObject(scope_info, context, | |
6340 closure_scope)) { | |
6341 return MaybeHandle<JSObject>(); | |
6342 } | |
6343 | |
6344 // Finally copy any properties from the function context extension. This will | |
6345 // be variables introduced by eval. | |
6346 if (context->has_extension()) { | |
6347 Handle<JSObject> ext(JSObject::cast(context->extension())); | |
6348 Handle<FixedArray> keys; | |
6349 ASSIGN_RETURN_ON_EXCEPTION( | |
6350 isolate, keys, JSReceiver::GetKeys(ext, JSReceiver::INCLUDE_PROTOS), | |
6351 JSObject); | |
6352 | |
6353 for (int i = 0; i < keys->length(); i++) { | |
6354 HandleScope scope(isolate); | |
6355 // Names of variables introduced by eval are strings. | |
6356 DCHECK(keys->get(i)->IsString()); | |
6357 Handle<String> key(String::cast(keys->get(i))); | |
6358 Handle<Object> value; | |
6359 ASSIGN_RETURN_ON_EXCEPTION( | |
6360 isolate, value, Object::GetPropertyOrElement(ext, key), JSObject); | |
6361 RETURN_ON_EXCEPTION(isolate, Runtime::DefineObjectProperty( | |
6362 closure_scope, key, value, NONE), | |
6363 JSObject); | |
6364 } | |
6365 } | |
6366 | |
6367 return closure_scope; | |
6368 } | |
6369 | |
6370 | |
6371 // This method copies structure of MaterializeClosure method above. | |
6372 static bool SetClosureVariableValue(Isolate* isolate, Handle<Context> context, | |
6373 Handle<String> variable_name, | |
6374 Handle<Object> new_value) { | |
6375 DCHECK(context->IsFunctionContext()); | |
6376 | |
6377 Handle<SharedFunctionInfo> shared(context->closure()->shared()); | |
6378 Handle<ScopeInfo> scope_info(shared->scope_info()); | |
6379 | |
6380 // Context locals to the context extension. | |
6381 if (SetContextLocalValue(isolate, scope_info, context, variable_name, | |
6382 new_value)) { | |
6383 return true; | |
6384 } | |
6385 | |
6386 // Properties from the function context extension. This will | |
6387 // be variables introduced by eval. | |
6388 if (context->has_extension()) { | |
6389 Handle<JSObject> ext(JSObject::cast(context->extension())); | |
6390 Maybe<bool> maybe = JSReceiver::HasProperty(ext, variable_name); | |
6391 DCHECK(maybe.has_value); | |
6392 if (maybe.value) { | |
6393 // We don't expect this to do anything except replacing property value. | |
6394 Runtime::DefineObjectProperty(ext, variable_name, new_value, NONE) | |
6395 .Assert(); | |
6396 return true; | |
6397 } | |
6398 } | |
6399 | |
6400 return false; | |
6401 } | |
6402 | |
6403 | |
6404 // Create a plain JSObject which materializes the scope for the specified | |
6405 // catch context. | |
6406 MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeCatchScope( | |
6407 Isolate* isolate, Handle<Context> context) { | |
6408 DCHECK(context->IsCatchContext()); | |
6409 Handle<String> name(String::cast(context->extension())); | |
6410 Handle<Object> thrown_object(context->get(Context::THROWN_OBJECT_INDEX), | |
6411 isolate); | |
6412 Handle<JSObject> catch_scope = | |
6413 isolate->factory()->NewJSObject(isolate->object_function()); | |
6414 RETURN_ON_EXCEPTION(isolate, Runtime::DefineObjectProperty( | |
6415 catch_scope, name, thrown_object, NONE), | |
6416 JSObject); | |
6417 return catch_scope; | |
6418 } | |
6419 | |
6420 | |
6421 static bool SetCatchVariableValue(Isolate* isolate, Handle<Context> context, | |
6422 Handle<String> variable_name, | |
6423 Handle<Object> new_value) { | |
6424 DCHECK(context->IsCatchContext()); | |
6425 Handle<String> name(String::cast(context->extension())); | |
6426 if (!String::Equals(name, variable_name)) { | |
6427 return false; | |
6428 } | |
6429 context->set(Context::THROWN_OBJECT_INDEX, *new_value); | |
6430 return true; | |
6431 } | |
6432 | |
6433 | |
6434 // Create a plain JSObject which materializes the block scope for the specified | |
6435 // block context. | |
6436 MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeBlockScope( | |
6437 Isolate* isolate, Handle<Context> context) { | |
6438 DCHECK(context->IsBlockContext()); | |
6439 Handle<ScopeInfo> scope_info(ScopeInfo::cast(context->extension())); | |
6440 | |
6441 // Allocate and initialize a JSObject with all the arguments, stack locals | |
6442 // heap locals and extension properties of the debugged function. | |
6443 Handle<JSObject> block_scope = | |
6444 isolate->factory()->NewJSObject(isolate->object_function()); | |
6445 | |
6446 // Fill all context locals. | |
6447 if (!ScopeInfo::CopyContextLocalsToScopeObject(scope_info, context, | |
6448 block_scope)) { | |
6449 return MaybeHandle<JSObject>(); | |
6450 } | |
6451 | |
6452 return block_scope; | |
6453 } | |
6454 | |
6455 | |
6456 // Create a plain JSObject which materializes the module scope for the specified | |
6457 // module context. | |
6458 MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeModuleScope( | |
6459 Isolate* isolate, Handle<Context> context) { | |
6460 DCHECK(context->IsModuleContext()); | |
6461 Handle<ScopeInfo> scope_info(ScopeInfo::cast(context->extension())); | |
6462 | |
6463 // Allocate and initialize a JSObject with all the members of the debugged | |
6464 // module. | |
6465 Handle<JSObject> module_scope = | |
6466 isolate->factory()->NewJSObject(isolate->object_function()); | |
6467 | |
6468 // Fill all context locals. | |
6469 if (!ScopeInfo::CopyContextLocalsToScopeObject(scope_info, context, | |
6470 module_scope)) { | |
6471 return MaybeHandle<JSObject>(); | |
6472 } | |
6473 | |
6474 return module_scope; | |
6475 } | |
6476 | |
6477 | |
6478 // Iterate over the actual scopes visible from a stack frame or from a closure. | |
6479 // The iteration proceeds from the innermost visible nested scope outwards. | |
6480 // All scopes are backed by an actual context except the local scope, | |
6481 // which is inserted "artificially" in the context chain. | |
6482 class ScopeIterator { | |
6483 public: | |
6484 enum ScopeType { | |
6485 ScopeTypeGlobal = 0, | |
6486 ScopeTypeLocal, | |
6487 ScopeTypeWith, | |
6488 ScopeTypeClosure, | |
6489 ScopeTypeCatch, | |
6490 ScopeTypeBlock, | |
6491 ScopeTypeModule | |
6492 }; | |
6493 | |
6494 ScopeIterator(Isolate* isolate, JavaScriptFrame* frame, | |
6495 int inlined_jsframe_index, bool ignore_nested_scopes = false) | |
6496 : isolate_(isolate), | |
6497 frame_(frame), | |
6498 inlined_jsframe_index_(inlined_jsframe_index), | |
6499 function_(frame->function()), | |
6500 context_(Context::cast(frame->context())), | |
6501 nested_scope_chain_(4), | |
6502 failed_(false) { | |
6503 // Catch the case when the debugger stops in an internal function. | |
6504 Handle<SharedFunctionInfo> shared_info(function_->shared()); | |
6505 Handle<ScopeInfo> scope_info(shared_info->scope_info()); | |
6506 if (shared_info->script() == isolate->heap()->undefined_value()) { | |
6507 while (context_->closure() == *function_) { | |
6508 context_ = Handle<Context>(context_->previous(), isolate_); | |
6509 } | |
6510 return; | |
6511 } | |
6512 | |
6513 // Get the debug info (create it if it does not exist). | |
6514 if (!isolate->debug()->EnsureDebugInfo(shared_info, function_)) { | |
6515 // Return if ensuring debug info failed. | |
6516 return; | |
6517 } | |
6518 | |
6519 // Currently it takes too much time to find nested scopes due to script | |
6520 // parsing. Sometimes we want to run the ScopeIterator as fast as possible | |
6521 // (for example, while collecting async call stacks on every | |
6522 // addEventListener call), even if we drop some nested scopes. | |
6523 // Later we may optimize getting the nested scopes (cache the result?) | |
6524 // and include nested scopes into the "fast" iteration case as well. | |
6525 if (!ignore_nested_scopes) { | |
6526 Handle<DebugInfo> debug_info = Debug::GetDebugInfo(shared_info); | |
6527 | |
6528 // Find the break point where execution has stopped. | |
6529 BreakLocationIterator break_location_iterator(debug_info, | |
6530 ALL_BREAK_LOCATIONS); | |
6531 // pc points to the instruction after the current one, possibly a break | |
6532 // location as well. So the "- 1" to exclude it from the search. | |
6533 break_location_iterator.FindBreakLocationFromAddress(frame->pc() - 1); | |
6534 | |
6535 // Within the return sequence at the moment it is not possible to | |
6536 // get a source position which is consistent with the current scope chain. | |
6537 // Thus all nested with, catch and block contexts are skipped and we only | |
6538 // provide the function scope. | |
6539 ignore_nested_scopes = break_location_iterator.IsExit(); | |
6540 } | |
6541 | |
6542 if (ignore_nested_scopes) { | |
6543 if (scope_info->HasContext()) { | |
6544 context_ = Handle<Context>(context_->declaration_context(), isolate_); | |
6545 } else { | |
6546 while (context_->closure() == *function_) { | |
6547 context_ = Handle<Context>(context_->previous(), isolate_); | |
6548 } | |
6549 } | |
6550 if (scope_info->scope_type() == FUNCTION_SCOPE) { | |
6551 nested_scope_chain_.Add(scope_info); | |
6552 } | |
6553 } else { | |
6554 // Reparse the code and analyze the scopes. | |
6555 Handle<Script> script(Script::cast(shared_info->script())); | |
6556 Scope* scope = NULL; | |
6557 | |
6558 // Check whether we are in global, eval or function code. | |
6559 Handle<ScopeInfo> scope_info(shared_info->scope_info()); | |
6560 if (scope_info->scope_type() != FUNCTION_SCOPE) { | |
6561 // Global or eval code. | |
6562 CompilationInfoWithZone info(script); | |
6563 if (scope_info->scope_type() == GLOBAL_SCOPE) { | |
6564 info.MarkAsGlobal(); | |
6565 } else { | |
6566 DCHECK(scope_info->scope_type() == EVAL_SCOPE); | |
6567 info.MarkAsEval(); | |
6568 info.SetContext(Handle<Context>(function_->context())); | |
6569 } | |
6570 if (Parser::Parse(&info) && Scope::Analyze(&info)) { | |
6571 scope = info.function()->scope(); | |
6572 } | |
6573 RetrieveScopeChain(scope, shared_info); | |
6574 } else { | |
6575 // Function code | |
6576 CompilationInfoWithZone info(shared_info); | |
6577 if (Parser::Parse(&info) && Scope::Analyze(&info)) { | |
6578 scope = info.function()->scope(); | |
6579 } | |
6580 RetrieveScopeChain(scope, shared_info); | |
6581 } | |
6582 } | |
6583 } | |
6584 | |
6585 ScopeIterator(Isolate* isolate, Handle<JSFunction> function) | |
6586 : isolate_(isolate), | |
6587 frame_(NULL), | |
6588 inlined_jsframe_index_(0), | |
6589 function_(function), | |
6590 context_(function->context()), | |
6591 failed_(false) { | |
6592 if (function->IsBuiltin()) { | |
6593 context_ = Handle<Context>(); | |
6594 } | |
6595 } | |
6596 | |
6597 // More scopes? | |
6598 bool Done() { | |
6599 DCHECK(!failed_); | |
6600 return context_.is_null(); | |
6601 } | |
6602 | |
6603 bool Failed() { return failed_; } | |
6604 | |
6605 // Move to the next scope. | |
6606 void Next() { | |
6607 DCHECK(!failed_); | |
6608 ScopeType scope_type = Type(); | |
6609 if (scope_type == ScopeTypeGlobal) { | |
6610 // The global scope is always the last in the chain. | |
6611 DCHECK(context_->IsNativeContext()); | |
6612 context_ = Handle<Context>(); | |
6613 return; | |
6614 } | |
6615 if (nested_scope_chain_.is_empty()) { | |
6616 context_ = Handle<Context>(context_->previous(), isolate_); | |
6617 } else { | |
6618 if (nested_scope_chain_.last()->HasContext()) { | |
6619 DCHECK(context_->previous() != NULL); | |
6620 context_ = Handle<Context>(context_->previous(), isolate_); | |
6621 } | |
6622 nested_scope_chain_.RemoveLast(); | |
6623 } | |
6624 } | |
6625 | |
6626 // Return the type of the current scope. | |
6627 ScopeType Type() { | |
6628 DCHECK(!failed_); | |
6629 if (!nested_scope_chain_.is_empty()) { | |
6630 Handle<ScopeInfo> scope_info = nested_scope_chain_.last(); | |
6631 switch (scope_info->scope_type()) { | |
6632 case FUNCTION_SCOPE: | |
6633 DCHECK(context_->IsFunctionContext() || !scope_info->HasContext()); | |
6634 return ScopeTypeLocal; | |
6635 case MODULE_SCOPE: | |
6636 DCHECK(context_->IsModuleContext()); | |
6637 return ScopeTypeModule; | |
6638 case GLOBAL_SCOPE: | |
6639 DCHECK(context_->IsNativeContext()); | |
6640 return ScopeTypeGlobal; | |
6641 case WITH_SCOPE: | |
6642 DCHECK(context_->IsWithContext()); | |
6643 return ScopeTypeWith; | |
6644 case CATCH_SCOPE: | |
6645 DCHECK(context_->IsCatchContext()); | |
6646 return ScopeTypeCatch; | |
6647 case BLOCK_SCOPE: | |
6648 DCHECK(!scope_info->HasContext() || context_->IsBlockContext()); | |
6649 return ScopeTypeBlock; | |
6650 case EVAL_SCOPE: | |
6651 UNREACHABLE(); | |
6652 } | |
6653 } | |
6654 if (context_->IsNativeContext()) { | |
6655 DCHECK(context_->global_object()->IsGlobalObject()); | |
6656 return ScopeTypeGlobal; | |
6657 } | |
6658 if (context_->IsFunctionContext()) { | |
6659 return ScopeTypeClosure; | |
6660 } | |
6661 if (context_->IsCatchContext()) { | |
6662 return ScopeTypeCatch; | |
6663 } | |
6664 if (context_->IsBlockContext()) { | |
6665 return ScopeTypeBlock; | |
6666 } | |
6667 if (context_->IsModuleContext()) { | |
6668 return ScopeTypeModule; | |
6669 } | |
6670 DCHECK(context_->IsWithContext()); | |
6671 return ScopeTypeWith; | |
6672 } | |
6673 | |
6674 // Return the JavaScript object with the content of the current scope. | |
6675 MaybeHandle<JSObject> ScopeObject() { | |
6676 DCHECK(!failed_); | |
6677 switch (Type()) { | |
6678 case ScopeIterator::ScopeTypeGlobal: | |
6679 return Handle<JSObject>(CurrentContext()->global_object()); | |
6680 case ScopeIterator::ScopeTypeLocal: | |
6681 // Materialize the content of the local scope into a JSObject. | |
6682 DCHECK(nested_scope_chain_.length() == 1); | |
6683 return MaterializeLocalScope(isolate_, frame_, inlined_jsframe_index_); | |
6684 case ScopeIterator::ScopeTypeWith: | |
6685 // Return the with object. | |
6686 return Handle<JSObject>(JSObject::cast(CurrentContext()->extension())); | |
6687 case ScopeIterator::ScopeTypeCatch: | |
6688 return MaterializeCatchScope(isolate_, CurrentContext()); | |
6689 case ScopeIterator::ScopeTypeClosure: | |
6690 // Materialize the content of the closure scope into a JSObject. | |
6691 return MaterializeClosure(isolate_, CurrentContext()); | |
6692 case ScopeIterator::ScopeTypeBlock: | |
6693 return MaterializeBlockScope(isolate_, CurrentContext()); | |
6694 case ScopeIterator::ScopeTypeModule: | |
6695 return MaterializeModuleScope(isolate_, CurrentContext()); | |
6696 } | |
6697 UNREACHABLE(); | |
6698 return Handle<JSObject>(); | |
6699 } | |
6700 | |
6701 bool SetVariableValue(Handle<String> variable_name, | |
6702 Handle<Object> new_value) { | |
6703 DCHECK(!failed_); | |
6704 switch (Type()) { | |
6705 case ScopeIterator::ScopeTypeGlobal: | |
6706 break; | |
6707 case ScopeIterator::ScopeTypeLocal: | |
6708 return SetLocalVariableValue(isolate_, frame_, inlined_jsframe_index_, | |
6709 variable_name, new_value); | |
6710 case ScopeIterator::ScopeTypeWith: | |
6711 break; | |
6712 case ScopeIterator::ScopeTypeCatch: | |
6713 return SetCatchVariableValue(isolate_, CurrentContext(), variable_name, | |
6714 new_value); | |
6715 case ScopeIterator::ScopeTypeClosure: | |
6716 return SetClosureVariableValue(isolate_, CurrentContext(), | |
6717 variable_name, new_value); | |
6718 case ScopeIterator::ScopeTypeBlock: | |
6719 // TODO(2399): should we implement it? | |
6720 break; | |
6721 case ScopeIterator::ScopeTypeModule: | |
6722 // TODO(2399): should we implement it? | |
6723 break; | |
6724 } | |
6725 return false; | |
6726 } | |
6727 | |
6728 Handle<ScopeInfo> CurrentScopeInfo() { | |
6729 DCHECK(!failed_); | |
6730 if (!nested_scope_chain_.is_empty()) { | |
6731 return nested_scope_chain_.last(); | |
6732 } else if (context_->IsBlockContext()) { | |
6733 return Handle<ScopeInfo>(ScopeInfo::cast(context_->extension())); | |
6734 } else if (context_->IsFunctionContext()) { | |
6735 return Handle<ScopeInfo>(context_->closure()->shared()->scope_info()); | |
6736 } | |
6737 return Handle<ScopeInfo>::null(); | |
6738 } | |
6739 | |
6740 // Return the context for this scope. For the local context there might not | |
6741 // be an actual context. | |
6742 Handle<Context> CurrentContext() { | |
6743 DCHECK(!failed_); | |
6744 if (Type() == ScopeTypeGlobal || nested_scope_chain_.is_empty()) { | |
6745 return context_; | |
6746 } else if (nested_scope_chain_.last()->HasContext()) { | |
6747 return context_; | |
6748 } else { | |
6749 return Handle<Context>(); | |
6750 } | |
6751 } | |
6752 | |
6753 #ifdef DEBUG | |
6754 // Debug print of the content of the current scope. | |
6755 void DebugPrint() { | |
6756 OFStream os(stdout); | |
6757 DCHECK(!failed_); | |
6758 switch (Type()) { | |
6759 case ScopeIterator::ScopeTypeGlobal: | |
6760 os << "Global:\n"; | |
6761 CurrentContext()->Print(os); | |
6762 break; | |
6763 | |
6764 case ScopeIterator::ScopeTypeLocal: { | |
6765 os << "Local:\n"; | |
6766 function_->shared()->scope_info()->Print(); | |
6767 if (!CurrentContext().is_null()) { | |
6768 CurrentContext()->Print(os); | |
6769 if (CurrentContext()->has_extension()) { | |
6770 Handle<Object> extension(CurrentContext()->extension(), isolate_); | |
6771 if (extension->IsJSContextExtensionObject()) { | |
6772 extension->Print(os); | |
6773 } | |
6774 } | |
6775 } | |
6776 break; | |
6777 } | |
6778 | |
6779 case ScopeIterator::ScopeTypeWith: | |
6780 os << "With:\n"; | |
6781 CurrentContext()->extension()->Print(os); | |
6782 break; | |
6783 | |
6784 case ScopeIterator::ScopeTypeCatch: | |
6785 os << "Catch:\n"; | |
6786 CurrentContext()->extension()->Print(os); | |
6787 CurrentContext()->get(Context::THROWN_OBJECT_INDEX)->Print(os); | |
6788 break; | |
6789 | |
6790 case ScopeIterator::ScopeTypeClosure: | |
6791 os << "Closure:\n"; | |
6792 CurrentContext()->Print(os); | |
6793 if (CurrentContext()->has_extension()) { | |
6794 Handle<Object> extension(CurrentContext()->extension(), isolate_); | |
6795 if (extension->IsJSContextExtensionObject()) { | |
6796 extension->Print(os); | |
6797 } | |
6798 } | |
6799 break; | |
6800 | |
6801 default: | |
6802 UNREACHABLE(); | |
6803 } | |
6804 PrintF("\n"); | |
6805 } | |
6806 #endif | |
6807 | |
6808 private: | |
6809 Isolate* isolate_; | |
6810 JavaScriptFrame* frame_; | |
6811 int inlined_jsframe_index_; | |
6812 Handle<JSFunction> function_; | |
6813 Handle<Context> context_; | |
6814 List<Handle<ScopeInfo> > nested_scope_chain_; | |
6815 bool failed_; | |
6816 | |
6817 void RetrieveScopeChain(Scope* scope, | |
6818 Handle<SharedFunctionInfo> shared_info) { | |
6819 if (scope != NULL) { | |
6820 int source_position = shared_info->code()->SourcePosition(frame_->pc()); | |
6821 scope->GetNestedScopeChain(&nested_scope_chain_, source_position); | |
6822 } else { | |
6823 // A failed reparse indicates that the preparser has diverged from the | |
6824 // parser or that the preparse data given to the initial parse has been | |
6825 // faulty. We fail in debug mode but in release mode we only provide the | |
6826 // information we get from the context chain but nothing about | |
6827 // completely stack allocated scopes or stack allocated locals. | |
6828 // Or it could be due to stack overflow. | |
6829 DCHECK(isolate_->has_pending_exception()); | |
6830 failed_ = true; | |
6831 } | |
6832 } | |
6833 | |
6834 DISALLOW_IMPLICIT_CONSTRUCTORS(ScopeIterator); | |
6835 }; | |
6836 | |
6837 | |
6838 RUNTIME_FUNCTION(Runtime_GetScopeCount) { | |
6839 HandleScope scope(isolate); | |
6840 DCHECK(args.length() == 2); | |
6841 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]); | |
6842 RUNTIME_ASSERT(CheckExecutionState(isolate, break_id)); | |
6843 | |
6844 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1); | |
6845 | |
6846 // Get the frame where the debugging is performed. | |
6847 StackFrame::Id id = UnwrapFrameId(wrapped_id); | |
6848 JavaScriptFrameIterator it(isolate, id); | |
6849 JavaScriptFrame* frame = it.frame(); | |
6850 | |
6851 // Count the visible scopes. | |
6852 int n = 0; | |
6853 for (ScopeIterator it(isolate, frame, 0); !it.Done(); it.Next()) { | |
6854 n++; | |
6855 } | |
6856 | |
6857 return Smi::FromInt(n); | |
6858 } | |
6859 | |
6860 | |
6861 // Returns the list of step-in positions (text offset) in a function of the | |
6862 // stack frame in a range from the current debug break position to the end | |
6863 // of the corresponding statement. | |
6864 RUNTIME_FUNCTION(Runtime_GetStepInPositions) { | |
6865 HandleScope scope(isolate); | |
6866 DCHECK(args.length() == 2); | |
6867 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]); | |
6868 RUNTIME_ASSERT(CheckExecutionState(isolate, break_id)); | |
6869 | |
6870 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1); | |
6871 | |
6872 // Get the frame where the debugging is performed. | |
6873 StackFrame::Id id = UnwrapFrameId(wrapped_id); | |
6874 JavaScriptFrameIterator frame_it(isolate, id); | |
6875 RUNTIME_ASSERT(!frame_it.done()); | |
6876 | |
6877 JavaScriptFrame* frame = frame_it.frame(); | |
6878 | |
6879 Handle<JSFunction> fun = Handle<JSFunction>(frame->function()); | |
6880 Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>(fun->shared()); | |
6881 | |
6882 if (!isolate->debug()->EnsureDebugInfo(shared, fun)) { | |
6883 return isolate->heap()->undefined_value(); | |
6884 } | |
6885 | |
6886 Handle<DebugInfo> debug_info = Debug::GetDebugInfo(shared); | |
6887 | |
6888 int len = 0; | |
6889 Handle<JSArray> array(isolate->factory()->NewJSArray(10)); | |
6890 // Find the break point where execution has stopped. | |
6891 BreakLocationIterator break_location_iterator(debug_info, | |
6892 ALL_BREAK_LOCATIONS); | |
6893 | |
6894 break_location_iterator.FindBreakLocationFromAddress(frame->pc() - 1); | |
6895 int current_statement_pos = break_location_iterator.statement_position(); | |
6896 | |
6897 while (!break_location_iterator.Done()) { | |
6898 bool accept; | |
6899 if (break_location_iterator.pc() > frame->pc()) { | |
6900 accept = true; | |
6901 } else { | |
6902 StackFrame::Id break_frame_id = isolate->debug()->break_frame_id(); | |
6903 // The break point is near our pc. Could be a step-in possibility, | |
6904 // that is currently taken by active debugger call. | |
6905 if (break_frame_id == StackFrame::NO_ID) { | |
6906 // We are not stepping. | |
6907 accept = false; | |
6908 } else { | |
6909 JavaScriptFrameIterator additional_frame_it(isolate, break_frame_id); | |
6910 // If our frame is a top frame and we are stepping, we can do step-in | |
6911 // at this place. | |
6912 accept = additional_frame_it.frame()->id() == id; | |
6913 } | |
6914 } | |
6915 if (accept) { | |
6916 if (break_location_iterator.IsStepInLocation(isolate)) { | |
6917 Smi* position_value = Smi::FromInt(break_location_iterator.position()); | |
6918 RETURN_FAILURE_ON_EXCEPTION( | |
6919 isolate, JSObject::SetElement( | |
6920 array, len, Handle<Object>(position_value, isolate), | |
6921 NONE, SLOPPY)); | |
6922 len++; | |
6923 } | |
6924 } | |
6925 // Advance iterator. | |
6926 break_location_iterator.Next(); | |
6927 if (current_statement_pos != break_location_iterator.statement_position()) { | |
6928 break; | |
6929 } | |
6930 } | |
6931 return *array; | |
6932 } | |
6933 | |
6934 | |
6935 static const int kScopeDetailsTypeIndex = 0; | |
6936 static const int kScopeDetailsObjectIndex = 1; | |
6937 static const int kScopeDetailsSize = 2; | |
6938 | |
6939 | |
6940 MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeScopeDetails( | |
6941 Isolate* isolate, ScopeIterator* it) { | |
6942 // Calculate the size of the result. | |
6943 int details_size = kScopeDetailsSize; | |
6944 Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size); | |
6945 | |
6946 // Fill in scope details. | |
6947 details->set(kScopeDetailsTypeIndex, Smi::FromInt(it->Type())); | |
6948 Handle<JSObject> scope_object; | |
6949 ASSIGN_RETURN_ON_EXCEPTION(isolate, scope_object, it->ScopeObject(), | |
6950 JSObject); | |
6951 details->set(kScopeDetailsObjectIndex, *scope_object); | |
6952 | |
6953 return isolate->factory()->NewJSArrayWithElements(details); | |
6954 } | |
6955 | |
6956 | |
6957 // Return an array with scope details | |
6958 // args[0]: number: break id | |
6959 // args[1]: number: frame index | |
6960 // args[2]: number: inlined frame index | |
6961 // args[3]: number: scope index | |
6962 // | |
6963 // The array returned contains the following information: | |
6964 // 0: Scope type | |
6965 // 1: Scope object | |
6966 RUNTIME_FUNCTION(Runtime_GetScopeDetails) { | |
6967 HandleScope scope(isolate); | |
6968 DCHECK(args.length() == 4); | |
6969 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]); | |
6970 RUNTIME_ASSERT(CheckExecutionState(isolate, break_id)); | |
6971 | |
6972 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1); | |
6973 CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]); | |
6974 CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]); | |
6975 | |
6976 // Get the frame where the debugging is performed. | |
6977 StackFrame::Id id = UnwrapFrameId(wrapped_id); | |
6978 JavaScriptFrameIterator frame_it(isolate, id); | |
6979 JavaScriptFrame* frame = frame_it.frame(); | |
6980 | |
6981 // Find the requested scope. | |
6982 int n = 0; | |
6983 ScopeIterator it(isolate, frame, inlined_jsframe_index); | |
6984 for (; !it.Done() && n < index; it.Next()) { | |
6985 n++; | |
6986 } | |
6987 if (it.Done()) { | |
6988 return isolate->heap()->undefined_value(); | |
6989 } | |
6990 Handle<JSObject> details; | |
6991 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, details, | |
6992 MaterializeScopeDetails(isolate, &it)); | |
6993 return *details; | |
6994 } | |
6995 | |
6996 | |
6997 // Return an array of scope details | |
6998 // args[0]: number: break id | |
6999 // args[1]: number: frame index | |
7000 // args[2]: number: inlined frame index | |
7001 // args[3]: boolean: ignore nested scopes | |
7002 // | |
7003 // The array returned contains arrays with the following information: | |
7004 // 0: Scope type | |
7005 // 1: Scope object | |
7006 RUNTIME_FUNCTION(Runtime_GetAllScopesDetails) { | |
7007 HandleScope scope(isolate); | |
7008 DCHECK(args.length() == 3 || args.length() == 4); | |
7009 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]); | |
7010 RUNTIME_ASSERT(CheckExecutionState(isolate, break_id)); | |
7011 | |
7012 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1); | |
7013 CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]); | |
7014 | |
7015 bool ignore_nested_scopes = false; | |
7016 if (args.length() == 4) { | |
7017 CONVERT_BOOLEAN_ARG_CHECKED(flag, 3); | |
7018 ignore_nested_scopes = flag; | |
7019 } | |
7020 | |
7021 // Get the frame where the debugging is performed. | |
7022 StackFrame::Id id = UnwrapFrameId(wrapped_id); | |
7023 JavaScriptFrameIterator frame_it(isolate, id); | |
7024 JavaScriptFrame* frame = frame_it.frame(); | |
7025 | |
7026 List<Handle<JSObject> > result(4); | |
7027 ScopeIterator it(isolate, frame, inlined_jsframe_index, ignore_nested_scopes); | |
7028 for (; !it.Done(); it.Next()) { | |
7029 Handle<JSObject> details; | |
7030 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, details, | |
7031 MaterializeScopeDetails(isolate, &it)); | |
7032 result.Add(details); | |
7033 } | |
7034 | |
7035 Handle<FixedArray> array = isolate->factory()->NewFixedArray(result.length()); | |
7036 for (int i = 0; i < result.length(); ++i) { | |
7037 array->set(i, *result[i]); | |
7038 } | |
7039 return *isolate->factory()->NewJSArrayWithElements(array); | |
7040 } | |
7041 | |
7042 | |
7043 RUNTIME_FUNCTION(Runtime_GetFunctionScopeCount) { | |
7044 HandleScope scope(isolate); | |
7045 DCHECK(args.length() == 1); | |
7046 | |
7047 // Check arguments. | |
7048 CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0); | |
7049 | |
7050 // Count the visible scopes. | |
7051 int n = 0; | |
7052 for (ScopeIterator it(isolate, fun); !it.Done(); it.Next()) { | |
7053 n++; | |
7054 } | |
7055 | |
7056 return Smi::FromInt(n); | |
7057 } | |
7058 | |
7059 | |
7060 RUNTIME_FUNCTION(Runtime_GetFunctionScopeDetails) { | |
7061 HandleScope scope(isolate); | |
7062 DCHECK(args.length() == 2); | |
7063 | |
7064 // Check arguments. | |
7065 CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0); | |
7066 CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]); | |
7067 | |
7068 // Find the requested scope. | |
7069 int n = 0; | |
7070 ScopeIterator it(isolate, fun); | |
7071 for (; !it.Done() && n < index; it.Next()) { | |
7072 n++; | |
7073 } | |
7074 if (it.Done()) { | |
7075 return isolate->heap()->undefined_value(); | |
7076 } | |
7077 | |
7078 Handle<JSObject> details; | |
7079 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, details, | |
7080 MaterializeScopeDetails(isolate, &it)); | |
7081 return *details; | |
7082 } | |
7083 | |
7084 | |
7085 static bool SetScopeVariableValue(ScopeIterator* it, int index, | |
7086 Handle<String> variable_name, | |
7087 Handle<Object> new_value) { | |
7088 for (int n = 0; !it->Done() && n < index; it->Next()) { | |
7089 n++; | |
7090 } | |
7091 if (it->Done()) { | |
7092 return false; | |
7093 } | |
7094 return it->SetVariableValue(variable_name, new_value); | |
7095 } | |
7096 | |
7097 | |
7098 // Change variable value in closure or local scope | |
7099 // args[0]: number or JsFunction: break id or function | |
7100 // args[1]: number: frame index (when arg[0] is break id) | |
7101 // args[2]: number: inlined frame index (when arg[0] is break id) | |
7102 // args[3]: number: scope index | |
7103 // args[4]: string: variable name | |
7104 // args[5]: object: new value | |
7105 // | |
7106 // Return true if success and false otherwise | |
7107 RUNTIME_FUNCTION(Runtime_SetScopeVariableValue) { | |
7108 HandleScope scope(isolate); | |
7109 DCHECK(args.length() == 6); | |
7110 | |
7111 // Check arguments. | |
7112 CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]); | |
7113 CONVERT_ARG_HANDLE_CHECKED(String, variable_name, 4); | |
7114 CONVERT_ARG_HANDLE_CHECKED(Object, new_value, 5); | |
7115 | |
7116 bool res; | |
7117 if (args[0]->IsNumber()) { | |
7118 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]); | |
7119 RUNTIME_ASSERT(CheckExecutionState(isolate, break_id)); | |
7120 | |
7121 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1); | |
7122 CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]); | |
7123 | |
7124 // Get the frame where the debugging is performed. | |
7125 StackFrame::Id id = UnwrapFrameId(wrapped_id); | |
7126 JavaScriptFrameIterator frame_it(isolate, id); | |
7127 JavaScriptFrame* frame = frame_it.frame(); | |
7128 | |
7129 ScopeIterator it(isolate, frame, inlined_jsframe_index); | |
7130 res = SetScopeVariableValue(&it, index, variable_name, new_value); | |
7131 } else { | |
7132 CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0); | |
7133 ScopeIterator it(isolate, fun); | |
7134 res = SetScopeVariableValue(&it, index, variable_name, new_value); | |
7135 } | |
7136 | |
7137 return isolate->heap()->ToBoolean(res); | |
7138 } | |
7139 | |
7140 | |
7141 RUNTIME_FUNCTION(Runtime_DebugPrintScopes) { | |
7142 HandleScope scope(isolate); | |
7143 DCHECK(args.length() == 0); | |
7144 | |
7145 #ifdef DEBUG | |
7146 // Print the scopes for the top frame. | |
7147 StackFrameLocator locator(isolate); | |
7148 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); | |
7149 for (ScopeIterator it(isolate, frame, 0); !it.Done(); it.Next()) { | |
7150 it.DebugPrint(); | |
7151 } | |
7152 #endif | |
7153 return isolate->heap()->undefined_value(); | |
7154 } | |
7155 | |
7156 | |
7157 RUNTIME_FUNCTION(Runtime_GetThreadCount) { | |
7158 HandleScope scope(isolate); | |
7159 DCHECK(args.length() == 1); | |
7160 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]); | |
7161 RUNTIME_ASSERT(CheckExecutionState(isolate, break_id)); | |
7162 | |
7163 // Count all archived V8 threads. | |
7164 int n = 0; | |
7165 for (ThreadState* thread = isolate->thread_manager()->FirstThreadStateInUse(); | |
7166 thread != NULL; thread = thread->Next()) { | |
7167 n++; | |
7168 } | |
7169 | |
7170 // Total number of threads is current thread and archived threads. | |
7171 return Smi::FromInt(n + 1); | |
7172 } | |
7173 | |
7174 | |
7175 static const int kThreadDetailsCurrentThreadIndex = 0; | |
7176 static const int kThreadDetailsThreadIdIndex = 1; | |
7177 static const int kThreadDetailsSize = 2; | |
7178 | |
7179 // Return an array with thread details | |
7180 // args[0]: number: break id | |
7181 // args[1]: number: thread index | |
7182 // | |
7183 // The array returned contains the following information: | |
7184 // 0: Is current thread? | |
7185 // 1: Thread id | |
7186 RUNTIME_FUNCTION(Runtime_GetThreadDetails) { | |
7187 HandleScope scope(isolate); | |
7188 DCHECK(args.length() == 2); | |
7189 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]); | |
7190 RUNTIME_ASSERT(CheckExecutionState(isolate, break_id)); | |
7191 | |
7192 CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]); | |
7193 | |
7194 // Allocate array for result. | |
7195 Handle<FixedArray> details = | |
7196 isolate->factory()->NewFixedArray(kThreadDetailsSize); | |
7197 | |
7198 // Thread index 0 is current thread. | |
7199 if (index == 0) { | |
7200 // Fill the details. | |
7201 details->set(kThreadDetailsCurrentThreadIndex, | |
7202 isolate->heap()->true_value()); | |
7203 details->set(kThreadDetailsThreadIdIndex, | |
7204 Smi::FromInt(ThreadId::Current().ToInteger())); | |
7205 } else { | |
7206 // Find the thread with the requested index. | |
7207 int n = 1; | |
7208 ThreadState* thread = isolate->thread_manager()->FirstThreadStateInUse(); | |
7209 while (index != n && thread != NULL) { | |
7210 thread = thread->Next(); | |
7211 n++; | |
7212 } | |
7213 if (thread == NULL) { | |
7214 return isolate->heap()->undefined_value(); | |
7215 } | |
7216 | |
7217 // Fill the details. | |
7218 details->set(kThreadDetailsCurrentThreadIndex, | |
7219 isolate->heap()->false_value()); | |
7220 details->set(kThreadDetailsThreadIdIndex, | |
7221 Smi::FromInt(thread->id().ToInteger())); | |
7222 } | |
7223 | |
7224 // Convert to JS array and return. | |
7225 return *isolate->factory()->NewJSArrayWithElements(details); | |
7226 } | |
7227 | |
7228 | |
7229 // Sets the disable break state | |
7230 // args[0]: disable break state | |
7231 RUNTIME_FUNCTION(Runtime_SetDisableBreak) { | |
7232 HandleScope scope(isolate); | |
7233 DCHECK(args.length() == 1); | |
7234 CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 0); | |
7235 isolate->debug()->set_disable_break(disable_break); | |
7236 return isolate->heap()->undefined_value(); | |
7237 } | |
7238 | |
7239 | |
7240 static bool IsPositionAlignmentCodeCorrect(int alignment) { | |
7241 return alignment == STATEMENT_ALIGNED || alignment == BREAK_POSITION_ALIGNED; | |
7242 } | |
7243 | |
7244 | |
7245 RUNTIME_FUNCTION(Runtime_GetBreakLocations) { | |
7246 HandleScope scope(isolate); | |
7247 DCHECK(args.length() == 2); | |
7248 | |
7249 CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0); | |
7250 CONVERT_NUMBER_CHECKED(int32_t, statement_aligned_code, Int32, args[1]); | |
7251 | |
7252 if (!IsPositionAlignmentCodeCorrect(statement_aligned_code)) { | |
7253 return isolate->ThrowIllegalOperation(); | |
7254 } | |
7255 BreakPositionAlignment alignment = | |
7256 static_cast<BreakPositionAlignment>(statement_aligned_code); | |
7257 | |
7258 Handle<SharedFunctionInfo> shared(fun->shared()); | |
7259 // Find the number of break points | |
7260 Handle<Object> break_locations = | |
7261 Debug::GetSourceBreakLocations(shared, alignment); | |
7262 if (break_locations->IsUndefined()) return isolate->heap()->undefined_value(); | |
7263 // Return array as JS array | |
7264 return *isolate->factory()->NewJSArrayWithElements( | |
7265 Handle<FixedArray>::cast(break_locations)); | |
7266 } | |
7267 | |
7268 | |
7269 // Set a break point in a function. | |
7270 // args[0]: function | |
7271 // args[1]: number: break source position (within the function source) | |
7272 // args[2]: number: break point object | |
7273 RUNTIME_FUNCTION(Runtime_SetFunctionBreakPoint) { | |
7274 HandleScope scope(isolate); | |
7275 DCHECK(args.length() == 3); | |
7276 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); | |
7277 CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]); | |
7278 RUNTIME_ASSERT(source_position >= function->shared()->start_position() && | |
7279 source_position <= function->shared()->end_position()); | |
7280 CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 2); | |
7281 | |
7282 // Set break point. | |
7283 RUNTIME_ASSERT(isolate->debug()->SetBreakPoint( | |
7284 function, break_point_object_arg, &source_position)); | |
7285 | |
7286 return Smi::FromInt(source_position); | |
7287 } | |
7288 | |
7289 | |
7290 // Changes the state of a break point in a script and returns source position | |
7291 // where break point was set. NOTE: Regarding performance see the NOTE for | |
7292 // GetScriptFromScriptData. | |
7293 // args[0]: script to set break point in | |
7294 // args[1]: number: break source position (within the script source) | |
7295 // args[2]: number, breakpoint position alignment | |
7296 // args[3]: number: break point object | |
7297 RUNTIME_FUNCTION(Runtime_SetScriptBreakPoint) { | |
7298 HandleScope scope(isolate); | |
7299 DCHECK(args.length() == 4); | |
7300 CONVERT_ARG_HANDLE_CHECKED(JSValue, wrapper, 0); | |
7301 CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]); | |
7302 RUNTIME_ASSERT(source_position >= 0); | |
7303 CONVERT_NUMBER_CHECKED(int32_t, statement_aligned_code, Int32, args[2]); | |
7304 CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 3); | |
7305 | |
7306 if (!IsPositionAlignmentCodeCorrect(statement_aligned_code)) { | |
7307 return isolate->ThrowIllegalOperation(); | |
7308 } | |
7309 BreakPositionAlignment alignment = | |
7310 static_cast<BreakPositionAlignment>(statement_aligned_code); | |
7311 | |
7312 // Get the script from the script wrapper. | |
7313 RUNTIME_ASSERT(wrapper->value()->IsScript()); | |
7314 Handle<Script> script(Script::cast(wrapper->value())); | |
7315 | |
7316 // Set break point. | |
7317 if (!isolate->debug()->SetBreakPointForScript(script, break_point_object_arg, | |
7318 &source_position, alignment)) { | |
7319 return isolate->heap()->undefined_value(); | |
7320 } | |
7321 | |
7322 return Smi::FromInt(source_position); | |
7323 } | |
7324 | |
7325 | |
7326 // Clear a break point | |
7327 // args[0]: number: break point object | |
7328 RUNTIME_FUNCTION(Runtime_ClearBreakPoint) { | |
7329 HandleScope scope(isolate); | |
7330 DCHECK(args.length() == 1); | |
7331 CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 0); | |
7332 | |
7333 // Clear break point. | |
7334 isolate->debug()->ClearBreakPoint(break_point_object_arg); | |
7335 | |
7336 return isolate->heap()->undefined_value(); | |
7337 } | |
7338 | |
7339 | |
7340 // Change the state of break on exceptions. | |
7341 // args[0]: Enum value indicating whether to affect caught/uncaught exceptions. | |
7342 // args[1]: Boolean indicating on/off. | |
7343 RUNTIME_FUNCTION(Runtime_ChangeBreakOnException) { | |
7344 HandleScope scope(isolate); | |
7345 DCHECK(args.length() == 2); | |
7346 CONVERT_NUMBER_CHECKED(uint32_t, type_arg, Uint32, args[0]); | |
7347 CONVERT_BOOLEAN_ARG_CHECKED(enable, 1); | |
7348 | |
7349 // If the number doesn't match an enum value, the ChangeBreakOnException | |
7350 // function will default to affecting caught exceptions. | |
7351 ExceptionBreakType type = static_cast<ExceptionBreakType>(type_arg); | |
7352 // Update break point state. | |
7353 isolate->debug()->ChangeBreakOnException(type, enable); | |
7354 return isolate->heap()->undefined_value(); | |
7355 } | |
7356 | |
7357 | |
7358 // Returns the state of break on exceptions | |
7359 // args[0]: boolean indicating uncaught exceptions | |
7360 RUNTIME_FUNCTION(Runtime_IsBreakOnException) { | |
7361 HandleScope scope(isolate); | |
7362 DCHECK(args.length() == 1); | |
7363 CONVERT_NUMBER_CHECKED(uint32_t, type_arg, Uint32, args[0]); | |
7364 | |
7365 ExceptionBreakType type = static_cast<ExceptionBreakType>(type_arg); | |
7366 bool result = isolate->debug()->IsBreakOnException(type); | |
7367 return Smi::FromInt(result); | |
7368 } | |
7369 | |
7370 | |
7371 // Prepare for stepping | |
7372 // args[0]: break id for checking execution state | |
7373 // args[1]: step action from the enumeration StepAction | |
7374 // args[2]: number of times to perform the step, for step out it is the number | |
7375 // of frames to step down. | |
7376 RUNTIME_FUNCTION(Runtime_PrepareStep) { | |
7377 HandleScope scope(isolate); | |
7378 DCHECK(args.length() == 4); | |
7379 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]); | |
7380 RUNTIME_ASSERT(CheckExecutionState(isolate, break_id)); | |
7381 | |
7382 if (!args[1]->IsNumber() || !args[2]->IsNumber()) { | |
7383 return isolate->Throw(isolate->heap()->illegal_argument_string()); | |
7384 } | |
7385 | |
7386 CONVERT_NUMBER_CHECKED(int, wrapped_frame_id, Int32, args[3]); | |
7387 | |
7388 StackFrame::Id frame_id; | |
7389 if (wrapped_frame_id == 0) { | |
7390 frame_id = StackFrame::NO_ID; | |
7391 } else { | |
7392 frame_id = UnwrapFrameId(wrapped_frame_id); | |
7393 } | |
7394 | |
7395 // Get the step action and check validity. | |
7396 StepAction step_action = static_cast<StepAction>(NumberToInt32(args[1])); | |
7397 if (step_action != StepIn && step_action != StepNext && | |
7398 step_action != StepOut && step_action != StepInMin && | |
7399 step_action != StepMin) { | |
7400 return isolate->Throw(isolate->heap()->illegal_argument_string()); | |
7401 } | |
7402 | |
7403 if (frame_id != StackFrame::NO_ID && step_action != StepNext && | |
7404 step_action != StepMin && step_action != StepOut) { | |
7405 return isolate->ThrowIllegalOperation(); | |
7406 } | |
7407 | |
7408 // Get the number of steps. | |
7409 int step_count = NumberToInt32(args[2]); | |
7410 if (step_count < 1) { | |
7411 return isolate->Throw(isolate->heap()->illegal_argument_string()); | |
7412 } | |
7413 | |
7414 // Clear all current stepping setup. | |
7415 isolate->debug()->ClearStepping(); | |
7416 | |
7417 // Prepare step. | |
7418 isolate->debug()->PrepareStep(static_cast<StepAction>(step_action), | |
7419 step_count, frame_id); | |
7420 return isolate->heap()->undefined_value(); | |
7421 } | |
7422 | |
7423 | |
7424 // Clear all stepping set by PrepareStep. | |
7425 RUNTIME_FUNCTION(Runtime_ClearStepping) { | |
7426 HandleScope scope(isolate); | |
7427 DCHECK(args.length() == 0); | |
7428 isolate->debug()->ClearStepping(); | |
7429 return isolate->heap()->undefined_value(); | |
7430 } | |
7431 | |
7432 | |
7433 // Helper function to find or create the arguments object for | |
7434 // Runtime_DebugEvaluate. | |
7435 MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeArgumentsObject( | |
7436 Isolate* isolate, Handle<JSObject> target, Handle<JSFunction> function) { | |
7437 // Do not materialize the arguments object for eval or top-level code. | |
7438 // Skip if "arguments" is already taken. | |
7439 if (!function->shared()->is_function()) return target; | |
7440 Maybe<bool> maybe = JSReceiver::HasOwnProperty( | |
7441 target, isolate->factory()->arguments_string()); | |
7442 if (!maybe.has_value) return MaybeHandle<JSObject>(); | |
7443 if (maybe.value) return target; | |
7444 | |
7445 // FunctionGetArguments can't throw an exception. | |
7446 Handle<JSObject> arguments = | |
7447 Handle<JSObject>::cast(Accessors::FunctionGetArguments(function)); | |
7448 Handle<String> arguments_str = isolate->factory()->arguments_string(); | |
7449 RETURN_ON_EXCEPTION(isolate, Runtime::DefineObjectProperty( | |
7450 target, arguments_str, arguments, NONE), | |
7451 JSObject); | |
7452 return target; | |
7453 } | |
7454 | |
7455 | |
7456 // Compile and evaluate source for the given context. | |
7457 static MaybeHandle<Object> DebugEvaluate(Isolate* isolate, | |
7458 Handle<Context> context, | |
7459 Handle<Object> context_extension, | |
7460 Handle<Object> receiver, | |
7461 Handle<String> source) { | |
7462 if (context_extension->IsJSObject()) { | |
7463 Handle<JSObject> extension = Handle<JSObject>::cast(context_extension); | |
7464 Handle<JSFunction> closure(context->closure(), isolate); | |
7465 context = isolate->factory()->NewWithContext(closure, context, extension); | |
7466 } | |
7467 | |
7468 Handle<JSFunction> eval_fun; | |
7469 ASSIGN_RETURN_ON_EXCEPTION( | |
7470 isolate, eval_fun, Compiler::GetFunctionFromEval(source, context, SLOPPY, | |
7471 NO_PARSE_RESTRICTION, | |
7472 RelocInfo::kNoPosition), | |
7473 Object); | |
7474 | |
7475 Handle<Object> result; | |
7476 ASSIGN_RETURN_ON_EXCEPTION( | |
7477 isolate, result, Execution::Call(isolate, eval_fun, receiver, 0, NULL), | |
7478 Object); | |
7479 | |
7480 // Skip the global proxy as it has no properties and always delegates to the | |
7481 // real global object. | |
7482 if (result->IsJSGlobalProxy()) { | |
7483 PrototypeIterator iter(isolate, result); | |
7484 // TODO(verwaest): This will crash when the global proxy is detached. | |
7485 result = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); | |
7486 } | |
7487 | |
7488 // Clear the oneshot breakpoints so that the debugger does not step further. | |
7489 isolate->debug()->ClearStepping(); | |
7490 return result; | |
7491 } | |
7492 | |
7493 | |
7494 static Handle<JSObject> NewJSObjectWithNullProto(Isolate* isolate) { | |
7495 Handle<JSObject> result = | |
7496 isolate->factory()->NewJSObject(isolate->object_function()); | |
7497 Handle<Map> new_map = Map::Copy(Handle<Map>(result->map())); | |
7498 new_map->set_prototype(*isolate->factory()->null_value()); | |
7499 JSObject::MigrateToMap(result, new_map); | |
7500 return result; | |
7501 } | |
7502 | |
7503 | |
7504 // Evaluate a piece of JavaScript in the context of a stack frame for | |
7505 // debugging. Things that need special attention are: | |
7506 // - Parameters and stack-allocated locals need to be materialized. Altered | |
7507 // values need to be written back to the stack afterwards. | |
7508 // - The arguments object needs to materialized. | |
7509 RUNTIME_FUNCTION(Runtime_DebugEvaluate) { | |
7510 HandleScope scope(isolate); | |
7511 | |
7512 // Check the execution state and decode arguments frame and source to be | |
7513 // evaluated. | |
7514 DCHECK(args.length() == 6); | |
7515 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]); | |
7516 RUNTIME_ASSERT(CheckExecutionState(isolate, break_id)); | |
7517 | |
7518 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1); | |
7519 CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]); | |
7520 CONVERT_ARG_HANDLE_CHECKED(String, source, 3); | |
7521 CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 4); | |
7522 CONVERT_ARG_HANDLE_CHECKED(Object, context_extension, 5); | |
7523 | |
7524 // Handle the processing of break. | |
7525 DisableBreak disable_break_scope(isolate->debug(), disable_break); | |
7526 | |
7527 // Get the frame where the debugging is performed. | |
7528 StackFrame::Id id = UnwrapFrameId(wrapped_id); | |
7529 JavaScriptFrameIterator it(isolate, id); | |
7530 JavaScriptFrame* frame = it.frame(); | |
7531 FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate); | |
7532 Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction())); | |
7533 | |
7534 // Traverse the saved contexts chain to find the active context for the | |
7535 // selected frame. | |
7536 SaveContext* save = FindSavedContextForFrame(isolate, frame); | |
7537 | |
7538 SaveContext savex(isolate); | |
7539 isolate->set_context(*(save->context())); | |
7540 | |
7541 // Materialize stack locals and the arguments object. | |
7542 Handle<JSObject> materialized = NewJSObjectWithNullProto(isolate); | |
7543 | |
7544 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | |
7545 isolate, materialized, | |
7546 MaterializeStackLocalsWithFrameInspector(isolate, materialized, function, | |
7547 &frame_inspector)); | |
7548 | |
7549 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | |
7550 isolate, materialized, | |
7551 MaterializeArgumentsObject(isolate, materialized, function)); | |
7552 | |
7553 // At this point, the lookup chain may look like this: | |
7554 // [inner context] -> [function stack]+[function context] -> [outer context] | |
7555 // The function stack is not an actual context, it complements the function | |
7556 // context. In order to have the same lookup chain when debug-evaluating, | |
7557 // we materialize the stack and insert it into the context chain as a | |
7558 // with-context before the function context. | |
7559 // [inner context] -> [with context] -> [function context] -> [outer context] | |
7560 // Ordering the with-context before the function context forces a dynamic | |
7561 // lookup instead of a static lookup that could fail as the scope info is | |
7562 // outdated and may expect variables to still be stack-allocated. | |
7563 // Afterwards, we write changes to the with-context back to the stack | |
7564 // and remove it from the context chain. | |
7565 // This could cause lookup failures if debug-evaluate creates a closure that | |
7566 // uses this temporary context chain. | |
7567 | |
7568 Handle<Context> eval_context(Context::cast(frame_inspector.GetContext())); | |
7569 DCHECK(!eval_context.is_null()); | |
7570 Handle<Context> function_context = eval_context; | |
7571 Handle<Context> outer_context(function->context(), isolate); | |
7572 Handle<Context> inner_context; | |
7573 // We iterate to find the function's context. If the function has no | |
7574 // context-allocated variables, we iterate until we hit the outer context. | |
7575 while (!function_context->IsFunctionContext() && | |
7576 !function_context.is_identical_to(outer_context)) { | |
7577 inner_context = function_context; | |
7578 function_context = Handle<Context>(function_context->previous(), isolate); | |
7579 } | |
7580 | |
7581 Handle<Context> materialized_context = isolate->factory()->NewWithContext( | |
7582 function, function_context, materialized); | |
7583 | |
7584 if (inner_context.is_null()) { | |
7585 // No inner context. The with-context is now inner-most. | |
7586 eval_context = materialized_context; | |
7587 } else { | |
7588 inner_context->set_previous(*materialized_context); | |
7589 } | |
7590 | |
7591 Handle<Object> receiver(frame->receiver(), isolate); | |
7592 MaybeHandle<Object> maybe_result = | |
7593 DebugEvaluate(isolate, eval_context, context_extension, receiver, source); | |
7594 | |
7595 // Remove with-context if it was inserted in between. | |
7596 if (!inner_context.is_null()) inner_context->set_previous(*function_context); | |
7597 | |
7598 Handle<Object> result; | |
7599 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, maybe_result); | |
7600 | |
7601 // Write back potential changes to materialized stack locals to the stack. | |
7602 UpdateStackLocalsFromMaterializedObject(isolate, materialized, function, | |
7603 frame, inlined_jsframe_index); | |
7604 | |
7605 return *result; | |
7606 } | |
7607 | |
7608 | |
7609 RUNTIME_FUNCTION(Runtime_DebugEvaluateGlobal) { | |
7610 HandleScope scope(isolate); | |
7611 | |
7612 // Check the execution state and decode arguments frame and source to be | |
7613 // evaluated. | |
7614 DCHECK(args.length() == 4); | |
7615 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]); | |
7616 RUNTIME_ASSERT(CheckExecutionState(isolate, break_id)); | |
7617 | |
7618 CONVERT_ARG_HANDLE_CHECKED(String, source, 1); | |
7619 CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 2); | |
7620 CONVERT_ARG_HANDLE_CHECKED(Object, context_extension, 3); | |
7621 | |
7622 // Handle the processing of break. | |
7623 DisableBreak disable_break_scope(isolate->debug(), disable_break); | |
7624 | |
7625 // Enter the top context from before the debugger was invoked. | |
7626 SaveContext save(isolate); | |
7627 SaveContext* top = &save; | |
7628 while (top != NULL && *top->context() == *isolate->debug()->debug_context()) { | |
7629 top = top->prev(); | |
7630 } | |
7631 if (top != NULL) { | |
7632 isolate->set_context(*top->context()); | |
7633 } | |
7634 | |
7635 // Get the native context now set to the top context from before the | |
7636 // debugger was invoked. | |
7637 Handle<Context> context = isolate->native_context(); | |
7638 Handle<JSObject> receiver(context->global_proxy()); | |
7639 Handle<Object> result; | |
7640 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | |
7641 isolate, result, | |
7642 DebugEvaluate(isolate, context, context_extension, receiver, source)); | |
7643 return *result; | |
7644 } | |
7645 | |
7646 | |
7647 RUNTIME_FUNCTION(Runtime_DebugGetLoadedScripts) { | |
7648 HandleScope scope(isolate); | |
7649 DCHECK(args.length() == 0); | |
7650 | |
7651 // Fill the script objects. | |
7652 Handle<FixedArray> instances = isolate->debug()->GetLoadedScripts(); | |
7653 | |
7654 // Convert the script objects to proper JS objects. | |
7655 for (int i = 0; i < instances->length(); i++) { | |
7656 Handle<Script> script = Handle<Script>(Script::cast(instances->get(i))); | |
7657 // Get the script wrapper in a local handle before calling GetScriptWrapper, | |
7658 // because using | |
7659 // instances->set(i, *GetScriptWrapper(script)) | |
7660 // is unsafe as GetScriptWrapper might call GC and the C++ compiler might | |
7661 // already have dereferenced the instances handle. | |
7662 Handle<JSObject> wrapper = Script::GetWrapper(script); | |
7663 instances->set(i, *wrapper); | |
7664 } | |
7665 | |
7666 // Return result as a JS array. | |
7667 Handle<JSObject> result = | |
7668 isolate->factory()->NewJSObject(isolate->array_function()); | |
7669 JSArray::SetContent(Handle<JSArray>::cast(result), instances); | |
7670 return *result; | |
7671 } | |
7672 | |
7673 | |
7674 // Helper function used by Runtime_DebugReferencedBy below. | |
7675 static int DebugReferencedBy(HeapIterator* iterator, JSObject* target, | |
7676 Object* instance_filter, int max_references, | |
7677 FixedArray* instances, int instances_size, | |
7678 JSFunction* arguments_function) { | |
7679 Isolate* isolate = target->GetIsolate(); | |
7680 SealHandleScope shs(isolate); | |
7681 DisallowHeapAllocation no_allocation; | |
7682 | |
7683 // Iterate the heap. | |
7684 int count = 0; | |
7685 JSObject* last = NULL; | |
7686 HeapObject* heap_obj = NULL; | |
7687 while (((heap_obj = iterator->next()) != NULL) && | |
7688 (max_references == 0 || count < max_references)) { | |
7689 // Only look at all JSObjects. | |
7690 if (heap_obj->IsJSObject()) { | |
7691 // Skip context extension objects and argument arrays as these are | |
7692 // checked in the context of functions using them. | |
7693 JSObject* obj = JSObject::cast(heap_obj); | |
7694 if (obj->IsJSContextExtensionObject() || | |
7695 obj->map()->constructor() == arguments_function) { | |
7696 continue; | |
7697 } | |
7698 | |
7699 // Check if the JS object has a reference to the object looked for. | |
7700 if (obj->ReferencesObject(target)) { | |
7701 // Check instance filter if supplied. This is normally used to avoid | |
7702 // references from mirror objects (see Runtime_IsInPrototypeChain). | |
7703 if (!instance_filter->IsUndefined()) { | |
7704 for (PrototypeIterator iter(isolate, obj); !iter.IsAtEnd(); | |
7705 iter.Advance()) { | |
7706 if (iter.GetCurrent() == instance_filter) { | |
7707 obj = NULL; // Don't add this object. | |
7708 break; | |
7709 } | |
7710 } | |
7711 } | |
7712 | |
7713 if (obj != NULL) { | |
7714 // Valid reference found add to instance array if supplied an update | |
7715 // count. | |
7716 if (instances != NULL && count < instances_size) { | |
7717 instances->set(count, obj); | |
7718 } | |
7719 last = obj; | |
7720 count++; | |
7721 } | |
7722 } | |
7723 } | |
7724 } | |
7725 | |
7726 // Check for circular reference only. This can happen when the object is only | |
7727 // referenced from mirrors and has a circular reference in which case the | |
7728 // object is not really alive and would have been garbage collected if not | |
7729 // referenced from the mirror. | |
7730 if (count == 1 && last == target) { | |
7731 count = 0; | |
7732 } | |
7733 | |
7734 // Return the number of referencing objects found. | |
7735 return count; | |
7736 } | |
7737 | |
7738 | |
7739 // Scan the heap for objects with direct references to an object | |
7740 // args[0]: the object to find references to | |
7741 // args[1]: constructor function for instances to exclude (Mirror) | |
7742 // args[2]: the the maximum number of objects to return | |
7743 RUNTIME_FUNCTION(Runtime_DebugReferencedBy) { | |
7744 HandleScope scope(isolate); | |
7745 DCHECK(args.length() == 3); | |
7746 | |
7747 // Check parameters. | |
7748 CONVERT_ARG_HANDLE_CHECKED(JSObject, target, 0); | |
7749 CONVERT_ARG_HANDLE_CHECKED(Object, instance_filter, 1); | |
7750 RUNTIME_ASSERT(instance_filter->IsUndefined() || | |
7751 instance_filter->IsJSObject()); | |
7752 CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[2]); | |
7753 RUNTIME_ASSERT(max_references >= 0); | |
7754 | |
7755 | |
7756 // Get the constructor function for context extension and arguments array. | |
7757 Handle<JSFunction> arguments_function( | |
7758 JSFunction::cast(isolate->sloppy_arguments_map()->constructor())); | |
7759 | |
7760 // Get the number of referencing objects. | |
7761 int count; | |
7762 // First perform a full GC in order to avoid dead objects and to make the heap | |
7763 // iterable. | |
7764 Heap* heap = isolate->heap(); | |
7765 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "%DebugConstructedBy"); | |
7766 { | |
7767 HeapIterator heap_iterator(heap); | |
7768 count = DebugReferencedBy(&heap_iterator, *target, *instance_filter, | |
7769 max_references, NULL, 0, *arguments_function); | |
7770 } | |
7771 | |
7772 // Allocate an array to hold the result. | |
7773 Handle<FixedArray> instances = isolate->factory()->NewFixedArray(count); | |
7774 | |
7775 // Fill the referencing objects. | |
7776 { | |
7777 HeapIterator heap_iterator(heap); | |
7778 count = DebugReferencedBy(&heap_iterator, *target, *instance_filter, | |
7779 max_references, *instances, count, | |
7780 *arguments_function); | |
7781 } | |
7782 | |
7783 // Return result as JS array. | |
7784 Handle<JSFunction> constructor = isolate->array_function(); | |
7785 | |
7786 Handle<JSObject> result = isolate->factory()->NewJSObject(constructor); | |
7787 JSArray::SetContent(Handle<JSArray>::cast(result), instances); | |
7788 return *result; | |
7789 } | |
7790 | |
7791 | |
7792 // Helper function used by Runtime_DebugConstructedBy below. | |
7793 static int DebugConstructedBy(HeapIterator* iterator, JSFunction* constructor, | |
7794 int max_references, FixedArray* instances, | |
7795 int instances_size) { | |
7796 DisallowHeapAllocation no_allocation; | |
7797 | |
7798 // Iterate the heap. | |
7799 int count = 0; | |
7800 HeapObject* heap_obj = NULL; | |
7801 while (((heap_obj = iterator->next()) != NULL) && | |
7802 (max_references == 0 || count < max_references)) { | |
7803 // Only look at all JSObjects. | |
7804 if (heap_obj->IsJSObject()) { | |
7805 JSObject* obj = JSObject::cast(heap_obj); | |
7806 if (obj->map()->constructor() == constructor) { | |
7807 // Valid reference found add to instance array if supplied an update | |
7808 // count. | |
7809 if (instances != NULL && count < instances_size) { | |
7810 instances->set(count, obj); | |
7811 } | |
7812 count++; | |
7813 } | |
7814 } | |
7815 } | |
7816 | |
7817 // Return the number of referencing objects found. | |
7818 return count; | |
7819 } | |
7820 | |
7821 | |
7822 // Scan the heap for objects constructed by a specific function. | |
7823 // args[0]: the constructor to find instances of | |
7824 // args[1]: the the maximum number of objects to return | |
7825 RUNTIME_FUNCTION(Runtime_DebugConstructedBy) { | |
7826 HandleScope scope(isolate); | |
7827 DCHECK(args.length() == 2); | |
7828 | |
7829 | |
7830 // Check parameters. | |
7831 CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 0); | |
7832 CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[1]); | |
7833 RUNTIME_ASSERT(max_references >= 0); | |
7834 | |
7835 // Get the number of referencing objects. | |
7836 int count; | |
7837 // First perform a full GC in order to avoid dead objects and to make the heap | |
7838 // iterable. | |
7839 Heap* heap = isolate->heap(); | |
7840 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "%DebugConstructedBy"); | |
7841 { | |
7842 HeapIterator heap_iterator(heap); | |
7843 count = DebugConstructedBy(&heap_iterator, *constructor, max_references, | |
7844 NULL, 0); | |
7845 } | |
7846 | |
7847 // Allocate an array to hold the result. | |
7848 Handle<FixedArray> instances = isolate->factory()->NewFixedArray(count); | |
7849 | |
7850 // Fill the referencing objects. | |
7851 { | |
7852 HeapIterator heap_iterator2(heap); | |
7853 count = DebugConstructedBy(&heap_iterator2, *constructor, max_references, | |
7854 *instances, count); | |
7855 } | |
7856 | |
7857 // Return result as JS array. | |
7858 Handle<JSFunction> array_function = isolate->array_function(); | |
7859 Handle<JSObject> result = isolate->factory()->NewJSObject(array_function); | |
7860 JSArray::SetContent(Handle<JSArray>::cast(result), instances); | |
7861 return *result; | |
7862 } | |
7863 | |
7864 | |
7865 // Find the effective prototype object as returned by __proto__. | |
7866 // args[0]: the object to find the prototype for. | |
7867 RUNTIME_FUNCTION(Runtime_DebugGetPrototype) { | |
7868 HandleScope shs(isolate); | |
7869 DCHECK(args.length() == 1); | |
7870 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0); | |
7871 return *GetPrototypeSkipHiddenPrototypes(isolate, obj); | |
7872 } | |
7873 | |
7874 | |
7875 // Patches script source (should be called upon BeforeCompile event). | |
7876 RUNTIME_FUNCTION(Runtime_DebugSetScriptSource) { | |
7877 HandleScope scope(isolate); | |
7878 DCHECK(args.length() == 2); | |
7879 | |
7880 CONVERT_ARG_HANDLE_CHECKED(JSValue, script_wrapper, 0); | |
7881 CONVERT_ARG_HANDLE_CHECKED(String, source, 1); | |
7882 | |
7883 RUNTIME_ASSERT(script_wrapper->value()->IsScript()); | |
7884 Handle<Script> script(Script::cast(script_wrapper->value())); | |
7885 | |
7886 int compilation_state = script->compilation_state(); | |
7887 RUNTIME_ASSERT(compilation_state == Script::COMPILATION_STATE_INITIAL); | |
7888 script->set_source(*source); | |
7889 | |
7890 return isolate->heap()->undefined_value(); | |
7891 } | |
7892 | |
7893 | |
7894 RUNTIME_FUNCTION(Runtime_DebugDisassembleFunction) { | |
7895 HandleScope scope(isolate); | |
7896 #ifdef DEBUG | |
7897 DCHECK(args.length() == 1); | |
7898 // Get the function and make sure it is compiled. | |
7899 CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0); | |
7900 if (!Compiler::EnsureCompiled(func, KEEP_EXCEPTION)) { | |
7901 return isolate->heap()->exception(); | |
7902 } | |
7903 OFStream os(stdout); | |
7904 func->code()->Print(os); | |
7905 os << endl; | |
7906 #endif // DEBUG | |
7907 return isolate->heap()->undefined_value(); | |
7908 } | |
7909 | |
7910 | |
7911 RUNTIME_FUNCTION(Runtime_DebugDisassembleConstructor) { | |
7912 HandleScope scope(isolate); | |
7913 #ifdef DEBUG | |
7914 DCHECK(args.length() == 1); | |
7915 // Get the function and make sure it is compiled. | |
7916 CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0); | |
7917 if (!Compiler::EnsureCompiled(func, KEEP_EXCEPTION)) { | |
7918 return isolate->heap()->exception(); | |
7919 } | |
7920 OFStream os(stdout); | |
7921 func->shared()->construct_stub()->Print(os); | |
7922 os << endl; | |
7923 #endif // DEBUG | |
7924 return isolate->heap()->undefined_value(); | |
7925 } | |
7926 | |
7927 | |
7928 RUNTIME_FUNCTION(Runtime_FunctionGetInferredName) { | |
7929 SealHandleScope shs(isolate); | |
7930 DCHECK(args.length() == 1); | |
7931 | |
7932 CONVERT_ARG_CHECKED(JSFunction, f, 0); | |
7933 return f->shared()->inferred_name(); | |
7934 } | |
7935 | |
7936 | |
7937 static int FindSharedFunctionInfosForScript(HeapIterator* iterator, | |
7938 Script* script, | |
7939 FixedArray* buffer) { | |
7940 DisallowHeapAllocation no_allocation; | |
7941 int counter = 0; | |
7942 int buffer_size = buffer->length(); | |
7943 for (HeapObject* obj = iterator->next(); obj != NULL; | |
7944 obj = iterator->next()) { | |
7945 DCHECK(obj != NULL); | |
7946 if (!obj->IsSharedFunctionInfo()) { | |
7947 continue; | |
7948 } | |
7949 SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj); | |
7950 if (shared->script() != script) { | |
7951 continue; | |
7952 } | |
7953 if (counter < buffer_size) { | |
7954 buffer->set(counter, shared); | |
7955 } | |
7956 counter++; | |
7957 } | |
7958 return counter; | |
7959 } | |
7960 | |
7961 | |
7962 // For a script finds all SharedFunctionInfo's in the heap that points | |
7963 // to this script. Returns JSArray of SharedFunctionInfo wrapped | |
7964 // in OpaqueReferences. | |
7965 RUNTIME_FUNCTION(Runtime_LiveEditFindSharedFunctionInfosForScript) { | |
7966 HandleScope scope(isolate); | |
7967 CHECK(isolate->debug()->live_edit_enabled()); | |
7968 DCHECK(args.length() == 1); | |
7969 CONVERT_ARG_CHECKED(JSValue, script_value, 0); | |
7970 | |
7971 RUNTIME_ASSERT(script_value->value()->IsScript()); | |
7972 Handle<Script> script = Handle<Script>(Script::cast(script_value->value())); | |
7973 | |
7974 const int kBufferSize = 32; | |
7975 | |
7976 Handle<FixedArray> array; | |
7977 array = isolate->factory()->NewFixedArray(kBufferSize); | |
7978 int number; | |
7979 Heap* heap = isolate->heap(); | |
7980 { | |
7981 HeapIterator heap_iterator(heap); | |
7982 Script* scr = *script; | |
7983 FixedArray* arr = *array; | |
7984 number = FindSharedFunctionInfosForScript(&heap_iterator, scr, arr); | |
7985 } | |
7986 if (number > kBufferSize) { | |
7987 array = isolate->factory()->NewFixedArray(number); | |
7988 HeapIterator heap_iterator(heap); | |
7989 Script* scr = *script; | |
7990 FixedArray* arr = *array; | |
7991 FindSharedFunctionInfosForScript(&heap_iterator, scr, arr); | |
7992 } | |
7993 | |
7994 Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(array); | |
7995 result->set_length(Smi::FromInt(number)); | |
7996 | |
7997 LiveEdit::WrapSharedFunctionInfos(result); | |
7998 | |
7999 return *result; | |
8000 } | |
8001 | |
8002 | |
8003 // For a script calculates compilation information about all its functions. | |
8004 // The script source is explicitly specified by the second argument. | |
8005 // The source of the actual script is not used, however it is important that | |
8006 // all generated code keeps references to this particular instance of script. | |
8007 // Returns a JSArray of compilation infos. The array is ordered so that | |
8008 // each function with all its descendant is always stored in a continues range | |
8009 // with the function itself going first. The root function is a script function. | |
8010 RUNTIME_FUNCTION(Runtime_LiveEditGatherCompileInfo) { | |
8011 HandleScope scope(isolate); | |
8012 CHECK(isolate->debug()->live_edit_enabled()); | |
8013 DCHECK(args.length() == 2); | |
8014 CONVERT_ARG_CHECKED(JSValue, script, 0); | |
8015 CONVERT_ARG_HANDLE_CHECKED(String, source, 1); | |
8016 | |
8017 RUNTIME_ASSERT(script->value()->IsScript()); | |
8018 Handle<Script> script_handle = Handle<Script>(Script::cast(script->value())); | |
8019 | |
8020 Handle<JSArray> result; | |
8021 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | |
8022 isolate, result, LiveEdit::GatherCompileInfo(script_handle, source)); | |
8023 return *result; | |
8024 } | |
8025 | |
8026 | |
8027 // Changes the source of the script to a new_source. | |
8028 // If old_script_name is provided (i.e. is a String), also creates a copy of | |
8029 // the script with its original source and sends notification to debugger. | |
8030 RUNTIME_FUNCTION(Runtime_LiveEditReplaceScript) { | |
8031 HandleScope scope(isolate); | |
8032 CHECK(isolate->debug()->live_edit_enabled()); | |
8033 DCHECK(args.length() == 3); | |
8034 CONVERT_ARG_CHECKED(JSValue, original_script_value, 0); | |
8035 CONVERT_ARG_HANDLE_CHECKED(String, new_source, 1); | |
8036 CONVERT_ARG_HANDLE_CHECKED(Object, old_script_name, 2); | |
8037 | |
8038 RUNTIME_ASSERT(original_script_value->value()->IsScript()); | |
8039 Handle<Script> original_script(Script::cast(original_script_value->value())); | |
8040 | |
8041 Handle<Object> old_script = LiveEdit::ChangeScriptSource( | |
8042 original_script, new_source, old_script_name); | |
8043 | |
8044 if (old_script->IsScript()) { | |
8045 Handle<Script> script_handle = Handle<Script>::cast(old_script); | |
8046 return *Script::GetWrapper(script_handle); | |
8047 } else { | |
8048 return isolate->heap()->null_value(); | |
8049 } | |
8050 } | |
8051 | |
8052 | |
8053 RUNTIME_FUNCTION(Runtime_LiveEditFunctionSourceUpdated) { | |
8054 HandleScope scope(isolate); | |
8055 CHECK(isolate->debug()->live_edit_enabled()); | |
8056 DCHECK(args.length() == 1); | |
8057 CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_info, 0); | |
8058 RUNTIME_ASSERT(SharedInfoWrapper::IsInstance(shared_info)); | |
8059 | |
8060 LiveEdit::FunctionSourceUpdated(shared_info); | |
8061 return isolate->heap()->undefined_value(); | |
8062 } | |
8063 | |
8064 | |
8065 // Replaces code of SharedFunctionInfo with a new one. | |
8066 RUNTIME_FUNCTION(Runtime_LiveEditReplaceFunctionCode) { | |
8067 HandleScope scope(isolate); | |
8068 CHECK(isolate->debug()->live_edit_enabled()); | |
8069 DCHECK(args.length() == 2); | |
8070 CONVERT_ARG_HANDLE_CHECKED(JSArray, new_compile_info, 0); | |
8071 CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_info, 1); | |
8072 RUNTIME_ASSERT(SharedInfoWrapper::IsInstance(shared_info)); | |
8073 | |
8074 LiveEdit::ReplaceFunctionCode(new_compile_info, shared_info); | |
8075 return isolate->heap()->undefined_value(); | |
8076 } | |
8077 | |
8078 | |
8079 // Connects SharedFunctionInfo to another script. | |
8080 RUNTIME_FUNCTION(Runtime_LiveEditFunctionSetScript) { | |
8081 HandleScope scope(isolate); | |
8082 CHECK(isolate->debug()->live_edit_enabled()); | |
8083 DCHECK(args.length() == 2); | |
8084 CONVERT_ARG_HANDLE_CHECKED(Object, function_object, 0); | |
8085 CONVERT_ARG_HANDLE_CHECKED(Object, script_object, 1); | |
8086 | |
8087 if (function_object->IsJSValue()) { | |
8088 Handle<JSValue> function_wrapper = Handle<JSValue>::cast(function_object); | |
8089 if (script_object->IsJSValue()) { | |
8090 RUNTIME_ASSERT(JSValue::cast(*script_object)->value()->IsScript()); | |
8091 Script* script = Script::cast(JSValue::cast(*script_object)->value()); | |
8092 script_object = Handle<Object>(script, isolate); | |
8093 } | |
8094 RUNTIME_ASSERT(function_wrapper->value()->IsSharedFunctionInfo()); | |
8095 LiveEdit::SetFunctionScript(function_wrapper, script_object); | |
8096 } else { | |
8097 // Just ignore this. We may not have a SharedFunctionInfo for some functions | |
8098 // and we check it in this function. | |
8099 } | |
8100 | |
8101 return isolate->heap()->undefined_value(); | |
8102 } | |
8103 | |
8104 | |
8105 // In a code of a parent function replaces original function as embedded object | |
8106 // with a substitution one. | |
8107 RUNTIME_FUNCTION(Runtime_LiveEditReplaceRefToNestedFunction) { | |
8108 HandleScope scope(isolate); | |
8109 CHECK(isolate->debug()->live_edit_enabled()); | |
8110 DCHECK(args.length() == 3); | |
8111 | |
8112 CONVERT_ARG_HANDLE_CHECKED(JSValue, parent_wrapper, 0); | |
8113 CONVERT_ARG_HANDLE_CHECKED(JSValue, orig_wrapper, 1); | |
8114 CONVERT_ARG_HANDLE_CHECKED(JSValue, subst_wrapper, 2); | |
8115 RUNTIME_ASSERT(parent_wrapper->value()->IsSharedFunctionInfo()); | |
8116 RUNTIME_ASSERT(orig_wrapper->value()->IsSharedFunctionInfo()); | |
8117 RUNTIME_ASSERT(subst_wrapper->value()->IsSharedFunctionInfo()); | |
8118 | |
8119 LiveEdit::ReplaceRefToNestedFunction(parent_wrapper, orig_wrapper, | |
8120 subst_wrapper); | |
8121 return isolate->heap()->undefined_value(); | |
8122 } | |
8123 | |
8124 | |
8125 // Updates positions of a shared function info (first parameter) according | |
8126 // to script source change. Text change is described in second parameter as | |
8127 // array of groups of 3 numbers: | |
8128 // (change_begin, change_end, change_end_new_position). | |
8129 // Each group describes a change in text; groups are sorted by change_begin. | |
8130 RUNTIME_FUNCTION(Runtime_LiveEditPatchFunctionPositions) { | |
8131 HandleScope scope(isolate); | |
8132 CHECK(isolate->debug()->live_edit_enabled()); | |
8133 DCHECK(args.length() == 2); | |
8134 CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_array, 0); | |
8135 CONVERT_ARG_HANDLE_CHECKED(JSArray, position_change_array, 1); | |
8136 RUNTIME_ASSERT(SharedInfoWrapper::IsInstance(shared_array)) | |
8137 | |
8138 LiveEdit::PatchFunctionPositions(shared_array, position_change_array); | |
8139 return isolate->heap()->undefined_value(); | |
8140 } | |
8141 | |
8142 | |
8143 // For array of SharedFunctionInfo's (each wrapped in JSValue) | |
8144 // checks that none of them have activations on stacks (of any thread). | |
8145 // Returns array of the same length with corresponding results of | |
8146 // LiveEdit::FunctionPatchabilityStatus type. | |
8147 RUNTIME_FUNCTION(Runtime_LiveEditCheckAndDropActivations) { | |
8148 HandleScope scope(isolate); | |
8149 CHECK(isolate->debug()->live_edit_enabled()); | |
8150 DCHECK(args.length() == 2); | |
8151 CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_array, 0); | |
8152 CONVERT_BOOLEAN_ARG_CHECKED(do_drop, 1); | |
8153 RUNTIME_ASSERT(shared_array->length()->IsSmi()); | |
8154 RUNTIME_ASSERT(shared_array->HasFastElements()) | |
8155 int array_length = Smi::cast(shared_array->length())->value(); | |
8156 for (int i = 0; i < array_length; i++) { | |
8157 Handle<Object> element = | |
8158 Object::GetElement(isolate, shared_array, i).ToHandleChecked(); | |
8159 RUNTIME_ASSERT( | |
8160 element->IsJSValue() && | |
8161 Handle<JSValue>::cast(element)->value()->IsSharedFunctionInfo()); | |
8162 } | |
8163 | |
8164 return *LiveEdit::CheckAndDropActivations(shared_array, do_drop); | |
8165 } | |
8166 | |
8167 | |
8168 // Compares 2 strings line-by-line, then token-wise and returns diff in form | |
8169 // of JSArray of triplets (pos1, pos1_end, pos2_end) describing list | |
8170 // of diff chunks. | |
8171 RUNTIME_FUNCTION(Runtime_LiveEditCompareStrings) { | |
8172 HandleScope scope(isolate); | |
8173 CHECK(isolate->debug()->live_edit_enabled()); | |
8174 DCHECK(args.length() == 2); | |
8175 CONVERT_ARG_HANDLE_CHECKED(String, s1, 0); | |
8176 CONVERT_ARG_HANDLE_CHECKED(String, s2, 1); | |
8177 | |
8178 return *LiveEdit::CompareStrings(s1, s2); | |
8179 } | |
8180 | |
8181 | |
8182 // Restarts a call frame and completely drops all frames above. | |
8183 // Returns true if successful. Otherwise returns undefined or an error message. | |
8184 RUNTIME_FUNCTION(Runtime_LiveEditRestartFrame) { | |
8185 HandleScope scope(isolate); | |
8186 CHECK(isolate->debug()->live_edit_enabled()); | |
8187 DCHECK(args.length() == 2); | |
8188 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]); | |
8189 RUNTIME_ASSERT(CheckExecutionState(isolate, break_id)); | |
8190 | |
8191 CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]); | |
8192 Heap* heap = isolate->heap(); | |
8193 | |
8194 // Find the relevant frame with the requested index. | |
8195 StackFrame::Id id = isolate->debug()->break_frame_id(); | |
8196 if (id == StackFrame::NO_ID) { | |
8197 // If there are no JavaScript stack frames return undefined. | |
8198 return heap->undefined_value(); | |
8199 } | |
8200 | |
8201 JavaScriptFrameIterator it(isolate, id); | |
8202 int inlined_jsframe_index = FindIndexedNonNativeFrame(&it, index); | |
8203 if (inlined_jsframe_index == -1) return heap->undefined_value(); | |
8204 // We don't really care what the inlined frame index is, since we are | |
8205 // throwing away the entire frame anyways. | |
8206 const char* error_message = LiveEdit::RestartFrame(it.frame()); | |
8207 if (error_message) { | |
8208 return *(isolate->factory()->InternalizeUtf8String(error_message)); | |
8209 } | |
8210 return heap->true_value(); | |
8211 } | |
8212 | |
8213 | |
8214 // A testing entry. Returns statement position which is the closest to | |
8215 // source_position. | |
8216 RUNTIME_FUNCTION(Runtime_GetFunctionCodePositionFromSource) { | |
8217 HandleScope scope(isolate); | |
8218 CHECK(isolate->debug()->live_edit_enabled()); | |
8219 DCHECK(args.length() == 2); | |
8220 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); | |
8221 CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]); | |
8222 | |
8223 Handle<Code> code(function->code(), isolate); | |
8224 | |
8225 if (code->kind() != Code::FUNCTION && | |
8226 code->kind() != Code::OPTIMIZED_FUNCTION) { | |
8227 return isolate->heap()->undefined_value(); | |
8228 } | |
8229 | |
8230 RelocIterator it(*code, RelocInfo::ModeMask(RelocInfo::STATEMENT_POSITION)); | |
8231 int closest_pc = 0; | |
8232 int distance = kMaxInt; | |
8233 while (!it.done()) { | |
8234 int statement_position = static_cast<int>(it.rinfo()->data()); | |
8235 // Check if this break point is closer that what was previously found. | |
8236 if (source_position <= statement_position && | |
8237 statement_position - source_position < distance) { | |
8238 closest_pc = | |
8239 static_cast<int>(it.rinfo()->pc() - code->instruction_start()); | |
8240 distance = statement_position - source_position; | |
8241 // Check whether we can't get any closer. | |
8242 if (distance == 0) break; | |
8243 } | |
8244 it.next(); | |
8245 } | |
8246 | |
8247 return Smi::FromInt(closest_pc); | |
8248 } | |
8249 | |
8250 | |
8251 // Calls specified function with or without entering the debugger. | |
8252 // This is used in unit tests to run code as if debugger is entered or simply | |
8253 // to have a stack with C++ frame in the middle. | |
8254 RUNTIME_FUNCTION(Runtime_ExecuteInDebugContext) { | |
8255 HandleScope scope(isolate); | |
8256 DCHECK(args.length() == 2); | |
8257 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); | |
8258 CONVERT_BOOLEAN_ARG_CHECKED(without_debugger, 1); | |
8259 | |
8260 MaybeHandle<Object> maybe_result; | |
8261 if (without_debugger) { | |
8262 maybe_result = Execution::Call(isolate, function, | |
8263 handle(function->global_proxy()), 0, NULL); | |
8264 } else { | |
8265 DebugScope debug_scope(isolate->debug()); | |
8266 maybe_result = Execution::Call(isolate, function, | |
8267 handle(function->global_proxy()), 0, NULL); | |
8268 } | |
8269 Handle<Object> result; | |
8270 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, maybe_result); | |
8271 return *result; | |
8272 } | |
8273 | |
8274 | |
8275 // Performs a GC. | |
8276 // Presently, it only does a full GC. | |
8277 RUNTIME_FUNCTION(Runtime_CollectGarbage) { | |
8278 SealHandleScope shs(isolate); | |
8279 DCHECK(args.length() == 1); | |
8280 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, "%CollectGarbage"); | |
8281 return isolate->heap()->undefined_value(); | |
8282 } | |
8283 | |
8284 | |
8285 // Gets the current heap usage. | |
8286 RUNTIME_FUNCTION(Runtime_GetHeapUsage) { | |
8287 SealHandleScope shs(isolate); | |
8288 DCHECK(args.length() == 0); | |
8289 int usage = static_cast<int>(isolate->heap()->SizeOfObjects()); | |
8290 if (!Smi::IsValid(usage)) { | |
8291 return *isolate->factory()->NewNumberFromInt(usage); | |
8292 } | |
8293 return Smi::FromInt(usage); | |
8294 } | |
8295 | |
8296 | |
8297 // Finds the script object from the script data. NOTE: This operation uses | |
8298 // heap traversal to find the function generated for the source position | |
8299 // for the requested break point. For lazily compiled functions several heap | |
8300 // traversals might be required rendering this operation as a rather slow | |
8301 // operation. However for setting break points which is normally done through | |
8302 // some kind of user interaction the performance is not crucial. | |
8303 static Handle<Object> Runtime_GetScriptFromScriptName( | |
8304 Handle<String> script_name) { | |
8305 // Scan the heap for Script objects to find the script with the requested | |
8306 // script data. | |
8307 Handle<Script> script; | |
8308 Factory* factory = script_name->GetIsolate()->factory(); | |
8309 Heap* heap = script_name->GetHeap(); | |
8310 HeapIterator iterator(heap); | |
8311 HeapObject* obj = NULL; | |
8312 while (script.is_null() && ((obj = iterator.next()) != NULL)) { | |
8313 // If a script is found check if it has the script data requested. | |
8314 if (obj->IsScript()) { | |
8315 if (Script::cast(obj)->name()->IsString()) { | |
8316 if (String::cast(Script::cast(obj)->name())->Equals(*script_name)) { | |
8317 script = Handle<Script>(Script::cast(obj)); | |
8318 } | |
8319 } | |
8320 } | |
8321 } | |
8322 | |
8323 // If no script with the requested script data is found return undefined. | |
8324 if (script.is_null()) return factory->undefined_value(); | |
8325 | |
8326 // Return the script found. | |
8327 return Script::GetWrapper(script); | |
8328 } | |
8329 | |
8330 | |
8331 // Get the script object from script data. NOTE: Regarding performance | |
8332 // see the NOTE for GetScriptFromScriptData. | |
8333 // args[0]: script data for the script to find the source for | |
8334 RUNTIME_FUNCTION(Runtime_GetScript) { | |
8335 HandleScope scope(isolate); | |
8336 | |
8337 DCHECK(args.length() == 1); | |
8338 | |
8339 CONVERT_ARG_CHECKED(String, script_name, 0); | |
8340 | |
8341 // Find the requested script. | |
8342 Handle<Object> result = | |
8343 Runtime_GetScriptFromScriptName(Handle<String>(script_name)); | |
8344 return *result; | |
8345 } | |
8346 | |
8347 | |
8348 // Collect the raw data for a stack trace. Returns an array of 4 | 5027 // Collect the raw data for a stack trace. Returns an array of 4 |
8349 // element segments each containing a receiver, function, code and | 5028 // element segments each containing a receiver, function, code and |
8350 // native code offset. | 5029 // native code offset. |
8351 RUNTIME_FUNCTION(Runtime_CollectStackTrace) { | 5030 RUNTIME_FUNCTION(Runtime_CollectStackTrace) { |
8352 HandleScope scope(isolate); | 5031 HandleScope scope(isolate); |
8353 DCHECK(args.length() == 2); | 5032 DCHECK(args.length() == 2); |
8354 CONVERT_ARG_HANDLE_CHECKED(JSObject, error_object, 0); | 5033 CONVERT_ARG_HANDLE_CHECKED(JSObject, error_object, 0); |
8355 CONVERT_ARG_HANDLE_CHECKED(Object, caller, 1); | 5034 CONVERT_ARG_HANDLE_CHECKED(Object, caller, 1); |
8356 | 5035 |
8357 if (!isolate->bootstrapper()->IsActive()) { | 5036 if (!isolate->bootstrapper()->IsActive()) { |
8358 // Optionally capture a more detailed stack trace for the message. | 5037 // Optionally capture a more detailed stack trace for the message. |
8359 isolate->CaptureAndSetDetailedStackTrace(error_object); | 5038 isolate->CaptureAndSetDetailedStackTrace(error_object); |
8360 // Capture a simple stack trace for the stack property. | 5039 // Capture a simple stack trace for the stack property. |
8361 isolate->CaptureAndSetSimpleStackTrace(error_object, caller); | 5040 isolate->CaptureAndSetSimpleStackTrace(error_object, caller); |
8362 } | 5041 } |
8363 return isolate->heap()->undefined_value(); | 5042 return isolate->heap()->undefined_value(); |
8364 } | 5043 } |
8365 | 5044 |
8366 | 5045 |
8367 // Returns V8 version as a string. | |
8368 RUNTIME_FUNCTION(Runtime_GetV8Version) { | |
8369 HandleScope scope(isolate); | |
8370 DCHECK(args.length() == 0); | |
8371 | |
8372 const char* version_string = v8::V8::GetVersion(); | |
8373 | |
8374 return *isolate->factory()->NewStringFromAsciiChecked(version_string); | |
8375 } | |
8376 | |
8377 | |
8378 // Returns function of generator activation. | |
8379 RUNTIME_FUNCTION(Runtime_GeneratorGetFunction) { | |
8380 HandleScope scope(isolate); | |
8381 DCHECK(args.length() == 1); | |
8382 CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0); | |
8383 | |
8384 return generator->function(); | |
8385 } | |
8386 | |
8387 | |
8388 // Returns context of generator activation. | |
8389 RUNTIME_FUNCTION(Runtime_GeneratorGetContext) { | |
8390 HandleScope scope(isolate); | |
8391 DCHECK(args.length() == 1); | |
8392 CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0); | |
8393 | |
8394 return generator->context(); | |
8395 } | |
8396 | |
8397 | |
8398 // Returns receiver of generator activation. | |
8399 RUNTIME_FUNCTION(Runtime_GeneratorGetReceiver) { | |
8400 HandleScope scope(isolate); | |
8401 DCHECK(args.length() == 1); | |
8402 CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0); | |
8403 | |
8404 return generator->receiver(); | |
8405 } | |
8406 | |
8407 | |
8408 // Returns generator continuation as a PC offset, or the magic -1 or 0 values. | |
8409 RUNTIME_FUNCTION(Runtime_GeneratorGetContinuation) { | |
8410 HandleScope scope(isolate); | |
8411 DCHECK(args.length() == 1); | |
8412 CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0); | |
8413 | |
8414 return Smi::FromInt(generator->continuation()); | |
8415 } | |
8416 | |
8417 | |
8418 RUNTIME_FUNCTION(Runtime_GeneratorGetSourcePosition) { | |
8419 HandleScope scope(isolate); | |
8420 DCHECK(args.length() == 1); | |
8421 CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0); | |
8422 | |
8423 if (generator->is_suspended()) { | |
8424 Handle<Code> code(generator->function()->code(), isolate); | |
8425 int offset = generator->continuation(); | |
8426 | |
8427 RUNTIME_ASSERT(0 <= offset && offset < code->Size()); | |
8428 Address pc = code->address() + offset; | |
8429 | |
8430 return Smi::FromInt(code->SourcePosition(pc)); | |
8431 } | |
8432 | |
8433 return isolate->heap()->undefined_value(); | |
8434 } | |
8435 | |
8436 | |
8437 RUNTIME_FUNCTION(Runtime_LoadMutableDouble) { | 5046 RUNTIME_FUNCTION(Runtime_LoadMutableDouble) { |
8438 HandleScope scope(isolate); | 5047 HandleScope scope(isolate); |
8439 DCHECK(args.length() == 2); | 5048 DCHECK(args.length() == 2); |
8440 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); | 5049 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); |
8441 CONVERT_ARG_HANDLE_CHECKED(Smi, index, 1); | 5050 CONVERT_ARG_HANDLE_CHECKED(Smi, index, 1); |
8442 RUNTIME_ASSERT((index->value() & 1) == 1); | 5051 RUNTIME_ASSERT((index->value() & 1) == 1); |
8443 FieldIndex field_index = | 5052 FieldIndex field_index = |
8444 FieldIndex::ForLoadByFieldIndex(object->map(), index->value()); | 5053 FieldIndex::ForLoadByFieldIndex(object->map(), index->value()); |
8445 if (field_index.is_inobject()) { | 5054 if (field_index.is_inobject()) { |
8446 RUNTIME_ASSERT(field_index.property_index() < | 5055 RUNTIME_ASSERT(field_index.property_index() < |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8576 | 5185 |
8577 | 5186 |
8578 RUNTIME_FUNCTION(Runtime_MessageGetScript) { | 5187 RUNTIME_FUNCTION(Runtime_MessageGetScript) { |
8579 SealHandleScope shs(isolate); | 5188 SealHandleScope shs(isolate); |
8580 DCHECK(args.length() == 1); | 5189 DCHECK(args.length() == 1); |
8581 CONVERT_ARG_CHECKED(JSMessageObject, message, 0); | 5190 CONVERT_ARG_CHECKED(JSMessageObject, message, 0); |
8582 return message->script(); | 5191 return message->script(); |
8583 } | 5192 } |
8584 | 5193 |
8585 | 5194 |
8586 #ifdef DEBUG | |
8587 // ListNatives is ONLY used by the fuzz-natives.js in debug mode | |
8588 // Exclude the code in release mode. | |
8589 RUNTIME_FUNCTION(Runtime_ListNatives) { | |
8590 HandleScope scope(isolate); | |
8591 DCHECK(args.length() == 0); | |
8592 #define COUNT_ENTRY(Name, argc, ressize) +1 | |
8593 int entry_count = | |
8594 0 RUNTIME_FUNCTION_LIST(COUNT_ENTRY) INLINE_FUNCTION_LIST(COUNT_ENTRY) | |
8595 INLINE_OPTIMIZED_FUNCTION_LIST(COUNT_ENTRY); | |
8596 #undef COUNT_ENTRY | |
8597 Factory* factory = isolate->factory(); | |
8598 Handle<FixedArray> elements = factory->NewFixedArray(entry_count); | |
8599 int index = 0; | |
8600 bool inline_runtime_functions = false; | |
8601 #define ADD_ENTRY(Name, argc, ressize) \ | |
8602 { \ | |
8603 HandleScope inner(isolate); \ | |
8604 Handle<String> name; \ | |
8605 /* Inline runtime functions have an underscore in front of the name. */ \ | |
8606 if (inline_runtime_functions) { \ | |
8607 name = factory->NewStringFromStaticChars("_" #Name); \ | |
8608 } else { \ | |
8609 name = factory->NewStringFromStaticChars(#Name); \ | |
8610 } \ | |
8611 Handle<FixedArray> pair_elements = factory->NewFixedArray(2); \ | |
8612 pair_elements->set(0, *name); \ | |
8613 pair_elements->set(1, Smi::FromInt(argc)); \ | |
8614 Handle<JSArray> pair = factory->NewJSArrayWithElements(pair_elements); \ | |
8615 elements->set(index++, *pair); \ | |
8616 } | |
8617 inline_runtime_functions = false; | |
8618 RUNTIME_FUNCTION_LIST(ADD_ENTRY) | |
8619 INLINE_OPTIMIZED_FUNCTION_LIST(ADD_ENTRY) | |
8620 inline_runtime_functions = true; | |
8621 INLINE_FUNCTION_LIST(ADD_ENTRY) | |
8622 #undef ADD_ENTRY | |
8623 DCHECK_EQ(index, entry_count); | |
8624 Handle<JSArray> result = factory->NewJSArrayWithElements(elements); | |
8625 return *result; | |
8626 } | |
8627 #endif | |
8628 | |
8629 | |
8630 RUNTIME_FUNCTION(Runtime_IS_VAR) { | 5195 RUNTIME_FUNCTION(Runtime_IS_VAR) { |
8631 UNREACHABLE(); // implemented as macro in the parser | 5196 UNREACHABLE(); // implemented as macro in the parser |
8632 return NULL; | 5197 return NULL; |
8633 } | 5198 } |
8634 | 5199 |
8635 | 5200 |
8636 #define TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION(Type, type, TYPE, ctype, size) \ | |
8637 RUNTIME_FUNCTION(Runtime_HasExternal##Type##Elements) { \ | |
8638 CONVERT_ARG_CHECKED(JSObject, obj, 0); \ | |
8639 return isolate->heap()->ToBoolean(obj->HasExternal##Type##Elements()); \ | |
8640 } | |
8641 | |
8642 TYPED_ARRAYS(TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION) | |
8643 | |
8644 #undef TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION | |
8645 | |
8646 | |
8647 #define FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION(Type, type, TYPE, ctype, s) \ | |
8648 RUNTIME_FUNCTION(Runtime_HasFixed##Type##Elements) { \ | |
8649 CONVERT_ARG_CHECKED(JSObject, obj, 0); \ | |
8650 return isolate->heap()->ToBoolean(obj->HasFixed##Type##Elements()); \ | |
8651 } | |
8652 | |
8653 TYPED_ARRAYS(FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION) | |
8654 | |
8655 #undef FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION | |
8656 | |
8657 | |
8658 RUNTIME_FUNCTION(Runtime_IsJSGlobalProxy) { | 5201 RUNTIME_FUNCTION(Runtime_IsJSGlobalProxy) { |
8659 SealHandleScope shs(isolate); | 5202 SealHandleScope shs(isolate); |
8660 DCHECK(args.length() == 1); | 5203 DCHECK(args.length() == 1); |
8661 CONVERT_ARG_CHECKED(Object, obj, 0); | 5204 CONVERT_ARG_CHECKED(Object, obj, 0); |
8662 return isolate->heap()->ToBoolean(obj->IsJSGlobalProxy()); | 5205 return isolate->heap()->ToBoolean(obj->IsJSGlobalProxy()); |
8663 } | 5206 } |
8664 | 5207 |
8665 | 5208 |
8666 RUNTIME_FUNCTION(Runtime_IsObserved) { | 5209 RUNTIME_FUNCTION(Runtime_IsObserved) { |
8667 SealHandleScope shs(isolate); | 5210 SealHandleScope shs(isolate); |
(...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9105 SealHandleScope shs(isolate); | 5648 SealHandleScope shs(isolate); |
9106 DCHECK(args.length() == 2); | 5649 DCHECK(args.length() == 2); |
9107 CONVERT_ARG_CHECKED(Object, obj, 0); | 5650 CONVERT_ARG_CHECKED(Object, obj, 0); |
9108 CONVERT_ARG_CHECKED(Object, value, 1); | 5651 CONVERT_ARG_CHECKED(Object, value, 1); |
9109 if (!obj->IsJSValue()) return value; | 5652 if (!obj->IsJSValue()) return value; |
9110 JSValue::cast(obj)->set_value(value); | 5653 JSValue::cast(obj)->set_value(value); |
9111 return value; | 5654 return value; |
9112 } | 5655 } |
9113 | 5656 |
9114 | 5657 |
9115 RUNTIME_FUNCTION(RuntimeReference_DateField) { | |
9116 SealHandleScope shs(isolate); | |
9117 DCHECK(args.length() == 2); | |
9118 CONVERT_ARG_CHECKED(Object, obj, 0); | |
9119 CONVERT_SMI_ARG_CHECKED(index, 1); | |
9120 if (!obj->IsJSDate()) { | |
9121 HandleScope scope(isolate); | |
9122 THROW_NEW_ERROR_RETURN_FAILURE( | |
9123 isolate, | |
9124 NewTypeError("not_date_object", HandleVector<Object>(NULL, 0))); | |
9125 } | |
9126 JSDate* date = JSDate::cast(obj); | |
9127 if (index == 0) return date->value(); | |
9128 return JSDate::GetField(date, Smi::FromInt(index)); | |
9129 } | |
9130 | |
9131 | |
9132 RUNTIME_FUNCTION(RuntimeReference_ObjectEquals) { | 5658 RUNTIME_FUNCTION(RuntimeReference_ObjectEquals) { |
9133 SealHandleScope shs(isolate); | 5659 SealHandleScope shs(isolate); |
9134 DCHECK(args.length() == 2); | 5660 DCHECK(args.length() == 2); |
9135 CONVERT_ARG_CHECKED(Object, obj1, 0); | 5661 CONVERT_ARG_CHECKED(Object, obj1, 0); |
9136 CONVERT_ARG_CHECKED(Object, obj2, 1); | 5662 CONVERT_ARG_CHECKED(Object, obj2, 1); |
9137 return isolate->heap()->ToBoolean(obj1 == obj2); | 5663 return isolate->heap()->ToBoolean(obj1 == obj2); |
9138 } | 5664 } |
9139 | 5665 |
9140 | 5666 |
9141 RUNTIME_FUNCTION(RuntimeReference_IsObject) { | 5667 RUNTIME_FUNCTION(RuntimeReference_IsObject) { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9191 } | 5717 } |
9192 | 5718 |
9193 | 5719 |
9194 RUNTIME_FUNCTION(RuntimeReference_FastOneByteArrayJoin) { | 5720 RUNTIME_FUNCTION(RuntimeReference_FastOneByteArrayJoin) { |
9195 SealHandleScope shs(isolate); | 5721 SealHandleScope shs(isolate); |
9196 DCHECK(args.length() == 2); | 5722 DCHECK(args.length() == 2); |
9197 return isolate->heap()->undefined_value(); | 5723 return isolate->heap()->undefined_value(); |
9198 } | 5724 } |
9199 | 5725 |
9200 | 5726 |
9201 RUNTIME_FUNCTION(RuntimeReference_GeneratorNext) { | |
9202 UNREACHABLE(); // Optimization disabled in SetUpGenerators(). | |
9203 return NULL; | |
9204 } | |
9205 | |
9206 | |
9207 RUNTIME_FUNCTION(RuntimeReference_GeneratorThrow) { | |
9208 UNREACHABLE(); // Optimization disabled in SetUpGenerators(). | |
9209 return NULL; | |
9210 } | |
9211 | |
9212 | |
9213 RUNTIME_FUNCTION(RuntimeReference_ClassOf) { | 5727 RUNTIME_FUNCTION(RuntimeReference_ClassOf) { |
9214 SealHandleScope shs(isolate); | 5728 SealHandleScope shs(isolate); |
9215 DCHECK(args.length() == 1); | 5729 DCHECK(args.length() == 1); |
9216 CONVERT_ARG_CHECKED(Object, obj, 0); | 5730 CONVERT_ARG_CHECKED(Object, obj, 0); |
9217 if (!obj->IsJSReceiver()) return isolate->heap()->null_value(); | 5731 if (!obj->IsJSReceiver()) return isolate->heap()->null_value(); |
9218 return JSReceiver::cast(obj)->class_name(); | 5732 return JSReceiver::cast(obj)->class_name(); |
9219 } | 5733 } |
9220 | 5734 |
9221 | 5735 |
9222 RUNTIME_FUNCTION(RuntimeReference_GetFromCache) { | 5736 RUNTIME_FUNCTION(RuntimeReference_GetFromCache) { |
9223 HandleScope scope(isolate); | 5737 HandleScope scope(isolate); |
9224 DCHECK(args.length() == 2); | 5738 DCHECK(args.length() == 2); |
9225 CONVERT_SMI_ARG_CHECKED(id, 0); | 5739 CONVERT_SMI_ARG_CHECKED(id, 0); |
9226 args[0] = isolate->native_context()->jsfunction_result_caches()->get(id); | 5740 args[0] = isolate->native_context()->jsfunction_result_caches()->get(id); |
9227 return __RT_impl_Runtime_GetFromCache(args, isolate); | 5741 return __RT_impl_Runtime_GetFromCache(args, isolate); |
9228 } | 5742 } |
9229 | 5743 |
9230 | 5744 |
9231 RUNTIME_FUNCTION(RuntimeReference_DebugIsActive) { | |
9232 SealHandleScope shs(isolate); | |
9233 return Smi::FromInt(isolate->debug()->is_active()); | |
9234 } | |
9235 | |
9236 | |
9237 // ---------------------------------------------------------------------------- | 5745 // ---------------------------------------------------------------------------- |
9238 // Implementation of Runtime | 5746 // Implementation of Runtime |
9239 | 5747 |
9240 #define F(name, number_of_args, result_size) \ | 5748 #define F(name, number_of_args, result_size) \ |
9241 { \ | 5749 { \ |
9242 Runtime::k##name, Runtime::RUNTIME, #name, FUNCTION_ADDR(Runtime_##name), \ | 5750 Runtime::k##name, Runtime::RUNTIME, #name, FUNCTION_ADDR(Runtime_##name), \ |
9243 number_of_args, result_size \ | 5751 number_of_args, result_size \ |
9244 } \ | 5752 } \ |
9245 , | 5753 , |
9246 | 5754 |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9307 } | 5815 } |
9308 return NULL; | 5816 return NULL; |
9309 } | 5817 } |
9310 | 5818 |
9311 | 5819 |
9312 const Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) { | 5820 const Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) { |
9313 return &(kIntrinsicFunctions[static_cast<int>(id)]); | 5821 return &(kIntrinsicFunctions[static_cast<int>(id)]); |
9314 } | 5822 } |
9315 } | 5823 } |
9316 } // namespace v8::internal | 5824 } // namespace v8::internal |
OLD | NEW |