| OLD | NEW |
| 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| 11 // with the distribution. | 11 // with the distribution. |
| (...skipping 14 matching lines...) Expand all Loading... |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 #include <stdlib.h> | 28 #include <stdlib.h> |
| 29 | 29 |
| 30 #include "v8.h" | 30 #include "v8.h" |
| 31 | 31 |
| 32 #include "accessors.h" | 32 #include "accessors.h" |
| 33 #include "api.h" | 33 #include "api.h" |
| 34 #include "arguments.h" | 34 #include "arguments.h" |
| 35 #include "codegen.h" | 35 #include "codegen.h" |
| 36 #include "compilation-cache.h" |
| 36 #include "compiler.h" | 37 #include "compiler.h" |
| 37 #include "cpu.h" | 38 #include "cpu.h" |
| 38 #include "dateparser-inl.h" | 39 #include "dateparser-inl.h" |
| 39 #include "debug.h" | 40 #include "debug.h" |
| 41 #include "deoptimizer.h" |
| 40 #include "execution.h" | 42 #include "execution.h" |
| 41 #include "jsregexp.h" | 43 #include "jsregexp.h" |
| 42 #include "liveedit.h" | 44 #include "liveedit.h" |
| 43 #include "parser.h" | 45 #include "parser.h" |
| 44 #include "platform.h" | 46 #include "platform.h" |
| 45 #include "runtime.h" | 47 #include "runtime.h" |
| 48 #include "runtime-profiler.h" |
| 46 #include "scopeinfo.h" | 49 #include "scopeinfo.h" |
| 47 #include "smart-pointer.h" | 50 #include "smart-pointer.h" |
| 48 #include "stub-cache.h" | 51 #include "stub-cache.h" |
| 49 #include "v8threads.h" | 52 #include "v8threads.h" |
| 50 #include "string-search.h" | 53 #include "string-search.h" |
| 51 | 54 |
| 52 namespace v8 { | 55 namespace v8 { |
| 53 namespace internal { | 56 namespace internal { |
| 54 | 57 |
| 55 | 58 |
| (...skipping 578 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 634 new_proto_map->set_is_hidden_prototype(); | 637 new_proto_map->set_is_hidden_prototype(); |
| 635 | 638 |
| 636 // Set the object's prototype to proto. | 639 // Set the object's prototype to proto. |
| 637 new_map->set_prototype(proto); | 640 new_map->set_prototype(proto); |
| 638 jsobject->set_map(new_map); | 641 jsobject->set_map(new_map); |
| 639 | 642 |
| 640 return isolate->heap()->undefined_value(); | 643 return isolate->heap()->undefined_value(); |
| 641 } | 644 } |
| 642 | 645 |
| 643 | 646 |
| 647 // Sets the magic number that identifies a function as one of the special |
| 648 // math functions that can be inlined. |
| 649 static MaybeObject* Runtime_SetMathFunctionId(RUNTIME_CALLING_CONVENTION) { |
| 650 RUNTIME_GET_ISOLATE; |
| 651 NoHandleAllocation ha; |
| 652 ASSERT(args.length() == 2); |
| 653 CONVERT_CHECKED(JSFunction, function, args[0]); |
| 654 CONVERT_CHECKED(Smi, id, args[1]); |
| 655 RUNTIME_ASSERT(id->value() >= 0); |
| 656 RUNTIME_ASSERT(id->value() < SharedFunctionInfo::max_math_id_number()); |
| 657 |
| 658 function->shared()->set_math_function_id(id->value()); |
| 659 |
| 660 return isolate->heap()->undefined_value(); |
| 661 } |
| 662 |
| 663 |
| 644 static MaybeObject* Runtime_IsConstructCall(RUNTIME_CALLING_CONVENTION) { | 664 static MaybeObject* Runtime_IsConstructCall(RUNTIME_CALLING_CONVENTION) { |
| 645 RUNTIME_GET_ISOLATE; | 665 RUNTIME_GET_ISOLATE; |
| 646 NoHandleAllocation ha; | 666 NoHandleAllocation ha; |
| 647 ASSERT(args.length() == 0); | 667 ASSERT(args.length() == 0); |
| 648 JavaScriptFrameIterator it; | 668 JavaScriptFrameIterator it; |
| 649 return isolate->heap()->ToBoolean(it.frame()->IsConstructor()); | 669 return isolate->heap()->ToBoolean(it.frame()->IsConstructor()); |
| 650 } | 670 } |
| 651 | 671 |
| 652 | 672 |
| 653 // Recursively traverses hidden prototypes if property is not found | 673 // Recursively traverses hidden prototypes if property is not found |
| (...skipping 1054 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1708 int pos = fun->shared()->start_position(); | 1728 int pos = fun->shared()->start_position(); |
| 1709 return Smi::FromInt(pos); | 1729 return Smi::FromInt(pos); |
| 1710 } | 1730 } |
| 1711 | 1731 |
| 1712 | 1732 |
| 1713 static MaybeObject* Runtime_FunctionGetPositionForOffset( | 1733 static MaybeObject* Runtime_FunctionGetPositionForOffset( |
| 1714 RUNTIME_CALLING_CONVENTION) { | 1734 RUNTIME_CALLING_CONVENTION) { |
| 1715 RUNTIME_GET_ISOLATE; | 1735 RUNTIME_GET_ISOLATE; |
| 1716 ASSERT(args.length() == 2); | 1736 ASSERT(args.length() == 2); |
| 1717 | 1737 |
| 1718 CONVERT_CHECKED(JSFunction, fun, args[0]); | 1738 CONVERT_CHECKED(Code, code, args[0]); |
| 1719 CONVERT_NUMBER_CHECKED(int, offset, Int32, args[1]); | 1739 CONVERT_NUMBER_CHECKED(int, offset, Int32, args[1]); |
| 1720 | 1740 |
| 1721 Code* code = fun->code(); | |
| 1722 RUNTIME_ASSERT(0 <= offset && offset < code->Size()); | 1741 RUNTIME_ASSERT(0 <= offset && offset < code->Size()); |
| 1723 | 1742 |
| 1724 Address pc = code->address() + offset; | 1743 Address pc = code->address() + offset; |
| 1725 return Smi::FromInt(fun->code()->SourcePosition(pc)); | 1744 return Smi::FromInt(code->SourcePosition(pc)); |
| 1726 } | 1745 } |
| 1727 | 1746 |
| 1728 | 1747 |
| 1729 static MaybeObject* Runtime_FunctionSetInstanceClassName( | 1748 static MaybeObject* Runtime_FunctionSetInstanceClassName( |
| 1730 RUNTIME_CALLING_CONVENTION) { | 1749 RUNTIME_CALLING_CONVENTION) { |
| 1731 RUNTIME_GET_ISOLATE; | 1750 RUNTIME_GET_ISOLATE; |
| 1732 NoHandleAllocation ha; | 1751 NoHandleAllocation ha; |
| 1733 ASSERT(args.length() == 2); | 1752 ASSERT(args.length() == 2); |
| 1734 | 1753 |
| 1735 CONVERT_CHECKED(JSFunction, fun, args[0]); | 1754 CONVERT_CHECKED(JSFunction, fun, args[0]); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1800 Handle<Context> context(target->context()); | 1819 Handle<Context> context(target->context()); |
| 1801 | 1820 |
| 1802 if (!code->IsNull()) { | 1821 if (!code->IsNull()) { |
| 1803 RUNTIME_ASSERT(code->IsJSFunction()); | 1822 RUNTIME_ASSERT(code->IsJSFunction()); |
| 1804 Handle<JSFunction> fun = Handle<JSFunction>::cast(code); | 1823 Handle<JSFunction> fun = Handle<JSFunction>::cast(code); |
| 1805 Handle<SharedFunctionInfo> shared(fun->shared()); | 1824 Handle<SharedFunctionInfo> shared(fun->shared()); |
| 1806 | 1825 |
| 1807 if (!EnsureCompiled(shared, KEEP_EXCEPTION)) { | 1826 if (!EnsureCompiled(shared, KEEP_EXCEPTION)) { |
| 1808 return Failure::Exception(); | 1827 return Failure::Exception(); |
| 1809 } | 1828 } |
| 1829 // Since we don't store the source for this we should never |
| 1830 // optimize this. |
| 1831 shared->code()->set_optimizable(false); |
| 1832 |
| 1810 // Set the code, scope info, formal parameter count, | 1833 // Set the code, scope info, formal parameter count, |
| 1811 // and the length of the target function. | 1834 // and the length of the target function. |
| 1812 target->shared()->set_code(shared->code()); | 1835 target->shared()->set_code(shared->code()); |
| 1813 target->set_code(shared->code()); | 1836 target->ReplaceCode(shared->code()); |
| 1814 target->shared()->set_scope_info(shared->scope_info()); | 1837 target->shared()->set_scope_info(shared->scope_info()); |
| 1815 target->shared()->set_length(shared->length()); | 1838 target->shared()->set_length(shared->length()); |
| 1816 target->shared()->set_formal_parameter_count( | 1839 target->shared()->set_formal_parameter_count( |
| 1817 shared->formal_parameter_count()); | 1840 shared->formal_parameter_count()); |
| 1818 // Set the source code of the target function to undefined. | 1841 // Set the source code of the target function to undefined. |
| 1819 // SetCode is only used for built-in constructors like String, | 1842 // SetCode is only used for built-in constructors like String, |
| 1820 // Array, and Object, and some web code | 1843 // Array, and Object, and some web code |
| 1821 // doesn't like seeing source code for constructors. | 1844 // doesn't like seeing source code for constructors. |
| 1822 target->shared()->set_script(isolate->heap()->undefined_value()); | 1845 target->shared()->set_script(isolate->heap()->undefined_value()); |
| 1823 // Clear the optimization hints related to the compiled code as these are no | 1846 // Clear the optimization hints related to the compiled code as these are no |
| 1824 // longer valid when the code is overwritten. | 1847 // longer valid when the code is overwritten. |
| 1825 target->shared()->ClearThisPropertyAssignmentsInfo(); | 1848 target->shared()->ClearThisPropertyAssignmentsInfo(); |
| 1826 context = Handle<Context>(fun->context()); | 1849 context = Handle<Context>(fun->context()); |
| 1827 | 1850 |
| 1828 // Make sure we get a fresh copy of the literal vector to avoid | 1851 // Make sure we get a fresh copy of the literal vector to avoid |
| 1829 // cross context contamination. | 1852 // cross context contamination. |
| 1830 int number_of_literals = fun->NumberOfLiterals(); | 1853 int number_of_literals = fun->NumberOfLiterals(); |
| 1831 Handle<FixedArray> literals = | 1854 Handle<FixedArray> literals = |
| 1832 isolate->factory()->NewFixedArray(number_of_literals, TENURED); | 1855 isolate->factory()->NewFixedArray(number_of_literals, TENURED); |
| 1833 if (number_of_literals > 0) { | 1856 if (number_of_literals > 0) { |
| 1834 // Insert the object, regexp and array functions in the literals | 1857 // Insert the object, regexp and array functions in the literals |
| 1835 // array prefix. These are the functions that will be used when | 1858 // array prefix. These are the functions that will be used when |
| 1836 // creating object, regexp and array literals. | 1859 // creating object, regexp and array literals. |
| 1837 literals->set(JSFunction::kLiteralGlobalContextIndex, | 1860 literals->set(JSFunction::kLiteralGlobalContextIndex, |
| 1838 context->global_context()); | 1861 context->global_context()); |
| 1839 } | 1862 } |
| 1840 // It's okay to skip the write barrier here because the literals | 1863 // It's okay to skip the write barrier here because the literals |
| 1841 // are guaranteed to be in old space. | 1864 // are guaranteed to be in old space. |
| 1842 target->set_literals(*literals, SKIP_WRITE_BARRIER); | 1865 target->set_literals(*literals, SKIP_WRITE_BARRIER); |
| 1866 target->set_next_function_link(isolate->heap()->undefined_value()); |
| 1843 } | 1867 } |
| 1844 | 1868 |
| 1845 target->set_context(*context); | 1869 target->set_context(*context); |
| 1846 return *target; | 1870 return *target; |
| 1847 } | 1871 } |
| 1848 | 1872 |
| 1849 | 1873 |
| 1850 static MaybeObject* Runtime_SetExpectedNumberOfProperties( | 1874 static MaybeObject* Runtime_SetExpectedNumberOfProperties( |
| 1851 RUNTIME_CALLING_CONVENTION) { | 1875 RUNTIME_CALLING_CONVENTION) { |
| 1852 RUNTIME_GET_ISOLATE; | 1876 RUNTIME_GET_ISOLATE; |
| (...skipping 3716 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5569 double value = HeapNumber::cast(obj)->value(); | 5593 double value = HeapNumber::cast(obj)->value(); |
| 5570 int int_value = FastD2I(value); | 5594 int int_value = FastD2I(value); |
| 5571 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) { | 5595 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) { |
| 5572 return Smi::FromInt(int_value); | 5596 return Smi::FromInt(int_value); |
| 5573 } | 5597 } |
| 5574 } | 5598 } |
| 5575 return isolate->heap()->nan_value(); | 5599 return isolate->heap()->nan_value(); |
| 5576 } | 5600 } |
| 5577 | 5601 |
| 5578 | 5602 |
| 5603 static MaybeObject* Runtime_AllocateHeapNumber(RUNTIME_CALLING_CONVENTION) { |
| 5604 RUNTIME_GET_ISOLATE; |
| 5605 NoHandleAllocation ha; |
| 5606 ASSERT(args.length() == 0); |
| 5607 return isolate->heap()->AllocateHeapNumber(0); |
| 5608 } |
| 5609 |
| 5610 |
| 5579 static MaybeObject* Runtime_NumberAdd(RUNTIME_CALLING_CONVENTION) { | 5611 static MaybeObject* Runtime_NumberAdd(RUNTIME_CALLING_CONVENTION) { |
| 5580 RUNTIME_GET_ISOLATE; | 5612 RUNTIME_GET_ISOLATE; |
| 5581 NoHandleAllocation ha; | 5613 NoHandleAllocation ha; |
| 5582 ASSERT(args.length() == 2); | 5614 ASSERT(args.length() == 2); |
| 5583 | 5615 |
| 5584 CONVERT_DOUBLE_CHECKED(x, args[0]); | 5616 CONVERT_DOUBLE_CHECKED(x, args[0]); |
| 5585 CONVERT_DOUBLE_CHECKED(y, args[1]); | 5617 CONVERT_DOUBLE_CHECKED(y, args[1]); |
| 5586 return isolate->heap()->NumberFromDouble(x + y); | 5618 return isolate->heap()->NumberFromDouble(x + y); |
| 5587 } | 5619 } |
| 5588 | 5620 |
| (...skipping 1308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6897 // allocate JSFunctions since it does not properly initialize | 6929 // allocate JSFunctions since it does not properly initialize |
| 6898 // the shared part of the function. Since the receiver is | 6930 // the shared part of the function. Since the receiver is |
| 6899 // ignored anyway, we use the global object as the receiver | 6931 // ignored anyway, we use the global object as the receiver |
| 6900 // instead of a new JSFunction object. This way, errors are | 6932 // instead of a new JSFunction object. This way, errors are |
| 6901 // reported the same way whether or not 'Function' is called | 6933 // reported the same way whether or not 'Function' is called |
| 6902 // using 'new'. | 6934 // using 'new'. |
| 6903 return isolate->context()->global(); | 6935 return isolate->context()->global(); |
| 6904 } | 6936 } |
| 6905 } | 6937 } |
| 6906 | 6938 |
| 6907 // The function should be compiled for the optimization hints to be available. | 6939 // The function should be compiled for the optimization hints to be |
| 6908 Handle<SharedFunctionInfo> shared(function->shared()); | 6940 // available. We cannot use EnsureCompiled because that forces a |
| 6909 EnsureCompiled(shared, CLEAR_EXCEPTION); | 6941 // compilation through the shared function info which makes it |
| 6942 // impossible for us to optimize. |
| 6943 Handle<SharedFunctionInfo> shared(function->shared(), isolate); |
| 6944 if (!function->is_compiled()) CompileLazy(function, CLEAR_EXCEPTION); |
| 6910 | 6945 |
| 6911 if (!function->has_initial_map() && | 6946 if (!function->has_initial_map() && |
| 6912 shared->IsInobjectSlackTrackingInProgress()) { | 6947 shared->IsInobjectSlackTrackingInProgress()) { |
| 6913 // The tracking is already in progress for another function. We can only | 6948 // The tracking is already in progress for another function. We can only |
| 6914 // track one initial_map at a time, so we force the completion before the | 6949 // track one initial_map at a time, so we force the completion before the |
| 6915 // function is called as a constructor for the first time. | 6950 // function is called as a constructor for the first time. |
| 6916 shared->CompleteInobjectSlackTracking(); | 6951 shared->CompleteInobjectSlackTracking(); |
| 6917 } | 6952 } |
| 6918 | 6953 |
| 6919 bool first_allocation = !shared->live_objects_may_exist(); | 6954 bool first_allocation = !shared->live_objects_may_exist(); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 6945 | 6980 |
| 6946 static MaybeObject* Runtime_LazyCompile(RUNTIME_CALLING_CONVENTION) { | 6981 static MaybeObject* Runtime_LazyCompile(RUNTIME_CALLING_CONVENTION) { |
| 6947 RUNTIME_GET_ISOLATE; | 6982 RUNTIME_GET_ISOLATE; |
| 6948 HandleScope scope(isolate); | 6983 HandleScope scope(isolate); |
| 6949 ASSERT(args.length() == 1); | 6984 ASSERT(args.length() == 1); |
| 6950 | 6985 |
| 6951 Handle<JSFunction> function = args.at<JSFunction>(0); | 6986 Handle<JSFunction> function = args.at<JSFunction>(0); |
| 6952 #ifdef DEBUG | 6987 #ifdef DEBUG |
| 6953 if (FLAG_trace_lazy && !function->shared()->is_compiled()) { | 6988 if (FLAG_trace_lazy && !function->shared()->is_compiled()) { |
| 6954 PrintF("[lazy: "); | 6989 PrintF("[lazy: "); |
| 6955 function->shared()->name()->Print(); | 6990 function->PrintName(); |
| 6956 PrintF("]\n"); | 6991 PrintF("]\n"); |
| 6957 } | 6992 } |
| 6958 #endif | 6993 #endif |
| 6959 | 6994 |
| 6960 // Compile the target function. Here we compile using CompileLazyInLoop in | 6995 // Compile the target function. Here we compile using CompileLazyInLoop in |
| 6961 // order to get the optimized version. This helps code like delta-blue | 6996 // order to get the optimized version. This helps code like delta-blue |
| 6962 // that calls performance-critical routines through constructors. A | 6997 // that calls performance-critical routines through constructors. A |
| 6963 // constructor call doesn't use a CallIC, it uses a LoadIC followed by a | 6998 // constructor call doesn't use a CallIC, it uses a LoadIC followed by a |
| 6964 // direct call. Since the in-loop tracking takes place through CallICs | 6999 // direct call. Since the in-loop tracking takes place through CallICs |
| 6965 // this means that things called through constructors are never known to | 7000 // this means that things called through constructors are never known to |
| 6966 // be in loops. We compile them as if they are in loops here just in case. | 7001 // be in loops. We compile them as if they are in loops here just in case. |
| 6967 ASSERT(!function->is_compiled()); | 7002 ASSERT(!function->is_compiled()); |
| 6968 if (!CompileLazyInLoop(function, KEEP_EXCEPTION)) { | 7003 if (!CompileLazyInLoop(function, KEEP_EXCEPTION)) { |
| 6969 return Failure::Exception(); | 7004 return Failure::Exception(); |
| 6970 } | 7005 } |
| 6971 | 7006 |
| 7007 // All done. Return the compiled code. |
| 7008 ASSERT(function->is_compiled()); |
| 6972 return function->code(); | 7009 return function->code(); |
| 6973 } | 7010 } |
| 6974 | 7011 |
| 6975 | 7012 |
| 7013 static MaybeObject* Runtime_LazyRecompile(RUNTIME_CALLING_CONVENTION) { |
| 7014 RUNTIME_GET_ISOLATE; |
| 7015 HandleScope scope(isolate); |
| 7016 ASSERT(args.length() == 1); |
| 7017 Handle<JSFunction> function = args.at<JSFunction>(0); |
| 7018 // If the function is not optimizable or debugger is active continue using the |
| 7019 // code from the full compiler. |
| 7020 if (!function->shared()->code()->optimizable() || |
| 7021 isolate->debug()->has_break_points()) { |
| 7022 function->ReplaceCode(function->shared()->code()); |
| 7023 return function->code(); |
| 7024 } |
| 7025 if (CompileOptimized(function, AstNode::kNoNumber)) { |
| 7026 return function->code(); |
| 7027 } |
| 7028 function->ReplaceCode(function->shared()->code()); |
| 7029 return Failure::Exception(); |
| 7030 } |
| 7031 |
| 7032 |
| 7033 static MaybeObject* Runtime_NotifyDeoptimized(RUNTIME_CALLING_CONVENTION) { |
| 7034 RUNTIME_GET_ISOLATE; |
| 7035 HandleScope scope(isolate); |
| 7036 ASSERT(args.length() == 1); |
| 7037 RUNTIME_ASSERT(args[0]->IsSmi()); |
| 7038 Deoptimizer::BailoutType type = |
| 7039 static_cast<Deoptimizer::BailoutType>(Smi::cast(args[0])->value()); |
| 7040 Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate); |
| 7041 ASSERT(isolate->heap()->IsAllocationAllowed()); |
| 7042 int frames = deoptimizer->output_count(); |
| 7043 |
| 7044 JavaScriptFrameIterator it; |
| 7045 JavaScriptFrame* frame = NULL; |
| 7046 for (int i = 0; i < frames; i++) { |
| 7047 if (i != 0) it.Advance(); |
| 7048 frame = it.frame(); |
| 7049 deoptimizer->InsertHeapNumberValues(frames - i - 1, frame); |
| 7050 } |
| 7051 delete deoptimizer; |
| 7052 |
| 7053 RUNTIME_ASSERT(frame->function()->IsJSFunction()); |
| 7054 Handle<JSFunction> function(JSFunction::cast(frame->function()), isolate); |
| 7055 Handle<Object> arguments; |
| 7056 for (int i = frame->ComputeExpressionsCount() - 1; i >= 0; --i) { |
| 7057 if (frame->GetExpression(i) == isolate->heap()->the_hole_value()) { |
| 7058 if (arguments.is_null()) { |
| 7059 // FunctionGetArguments can't throw an exception, so cast away the |
| 7060 // doubt with an assert. |
| 7061 arguments = Handle<Object>( |
| 7062 Accessors::FunctionGetArguments(*function, |
| 7063 NULL)->ToObjectUnchecked()); |
| 7064 ASSERT(*arguments != isolate->heap()->null_value()); |
| 7065 ASSERT(*arguments != isolate->heap()->undefined_value()); |
| 7066 } |
| 7067 frame->SetExpression(i, *arguments); |
| 7068 } |
| 7069 } |
| 7070 |
| 7071 isolate->compilation_cache()->MarkForLazyOptimizing(function); |
| 7072 if (type == Deoptimizer::EAGER) { |
| 7073 RUNTIME_ASSERT(function->IsOptimized()); |
| 7074 } else { |
| 7075 RUNTIME_ASSERT(!function->IsOptimized()); |
| 7076 } |
| 7077 |
| 7078 // Avoid doing too much work when running with --always-opt and keep |
| 7079 // the optimized code around. |
| 7080 if (FLAG_always_opt || type == Deoptimizer::LAZY) { |
| 7081 return isolate->heap()->undefined_value(); |
| 7082 } |
| 7083 |
| 7084 // Count the number of optimized activations of the function. |
| 7085 int activations = 0; |
| 7086 while (!it.done()) { |
| 7087 JavaScriptFrame* frame = it.frame(); |
| 7088 if (frame->is_optimized() && frame->function() == *function) { |
| 7089 activations++; |
| 7090 } |
| 7091 it.Advance(); |
| 7092 } |
| 7093 |
| 7094 // TODO(kasperl): For now, we cannot support removing the optimized |
| 7095 // code when we have recursive invocations of the same function. |
| 7096 if (activations == 0) { |
| 7097 if (FLAG_trace_deopt) { |
| 7098 PrintF("[removing optimized code for: "); |
| 7099 function->PrintName(); |
| 7100 PrintF("]\n"); |
| 7101 } |
| 7102 function->ReplaceCode(function->shared()->code()); |
| 7103 } |
| 7104 return isolate->heap()->undefined_value(); |
| 7105 } |
| 7106 |
| 7107 |
| 7108 static MaybeObject* Runtime_NotifyOSR(RUNTIME_CALLING_CONVENTION) { |
| 7109 RUNTIME_GET_ISOLATE; |
| 7110 Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate); |
| 7111 delete deoptimizer; |
| 7112 return isolate->heap()->undefined_value(); |
| 7113 } |
| 7114 |
| 7115 |
| 7116 static MaybeObject* Runtime_DeoptimizeFunction(RUNTIME_CALLING_CONVENTION) { |
| 7117 RUNTIME_GET_ISOLATE; |
| 7118 HandleScope scope(isolate); |
| 7119 ASSERT(args.length() == 1); |
| 7120 CONVERT_ARG_CHECKED(JSFunction, function, 0); |
| 7121 if (!function->IsOptimized()) return isolate->heap()->undefined_value(); |
| 7122 |
| 7123 Deoptimizer::DeoptimizeFunction(*function); |
| 7124 |
| 7125 return isolate->heap()->undefined_value(); |
| 7126 } |
| 7127 |
| 7128 |
| 7129 static MaybeObject* Runtime_CompileForOnStackReplacement( |
| 7130 RUNTIME_CALLING_CONVENTION) { |
| 7131 RUNTIME_GET_ISOLATE; |
| 7132 HandleScope scope(isolate); |
| 7133 ASSERT(args.length() == 1); |
| 7134 CONVERT_ARG_CHECKED(JSFunction, function, 0); |
| 7135 |
| 7136 // We're not prepared to handle a function with arguments object. |
| 7137 ASSERT(!function->shared()->scope_info()->HasArgumentsShadow()); |
| 7138 |
| 7139 // We have hit a back edge in an unoptimized frame for a function that was |
| 7140 // selected for on-stack replacement. Find the unoptimized code object. |
| 7141 Handle<Code> unoptimized(function->shared()->code(), isolate); |
| 7142 // Keep track of whether we've succeeded in optimizing. |
| 7143 bool succeeded = unoptimized->optimizable(); |
| 7144 if (succeeded) { |
| 7145 // If we are trying to do OSR when there are already optimized |
| 7146 // activations of the function, it means (a) the function is directly or |
| 7147 // indirectly recursive and (b) an optimized invocation has been |
| 7148 // deoptimized so that we are currently in an unoptimized activation. |
| 7149 // Check for optimized activations of this function. |
| 7150 JavaScriptFrameIterator it; |
| 7151 while (succeeded && !it.done()) { |
| 7152 JavaScriptFrame* frame = it.frame(); |
| 7153 succeeded = !frame->is_optimized() || frame->function() != *function; |
| 7154 it.Advance(); |
| 7155 } |
| 7156 } |
| 7157 |
| 7158 int ast_id = AstNode::kNoNumber; |
| 7159 if (succeeded) { |
| 7160 // The top JS function is this one, the PC is somewhere in the |
| 7161 // unoptimized code. |
| 7162 JavaScriptFrameIterator it; |
| 7163 JavaScriptFrame* frame = it.frame(); |
| 7164 ASSERT(frame->function() == *function); |
| 7165 ASSERT(frame->LookupCode(isolate) == *unoptimized); |
| 7166 ASSERT(unoptimized->contains(frame->pc())); |
| 7167 |
| 7168 // Use linear search of the unoptimized code's stack check table to find |
| 7169 // the AST id matching the PC. |
| 7170 Address start = unoptimized->instruction_start(); |
| 7171 unsigned target_pc_offset = frame->pc() - start; |
| 7172 Address table_cursor = start + unoptimized->stack_check_table_start(); |
| 7173 uint32_t table_length = Memory::uint32_at(table_cursor); |
| 7174 table_cursor += kIntSize; |
| 7175 for (unsigned i = 0; i < table_length; ++i) { |
| 7176 // Table entries are (AST id, pc offset) pairs. |
| 7177 uint32_t pc_offset = Memory::uint32_at(table_cursor + kIntSize); |
| 7178 if (pc_offset == target_pc_offset) { |
| 7179 ast_id = static_cast<int>(Memory::uint32_at(table_cursor)); |
| 7180 break; |
| 7181 } |
| 7182 table_cursor += 2 * kIntSize; |
| 7183 } |
| 7184 ASSERT(ast_id != AstNode::kNoNumber); |
| 7185 if (FLAG_trace_osr) { |
| 7186 PrintF("[replacing on-stack at AST id %d in ", ast_id); |
| 7187 function->PrintName(); |
| 7188 PrintF("]\n"); |
| 7189 } |
| 7190 |
| 7191 // Try to compile the optimized code. A true return value from |
| 7192 // CompileOptimized means that compilation succeeded, not necessarily |
| 7193 // that optimization succeeded. |
| 7194 if (CompileOptimized(function, ast_id) && function->IsOptimized()) { |
| 7195 DeoptimizationInputData* data = DeoptimizationInputData::cast( |
| 7196 function->code()->deoptimization_data()); |
| 7197 if (FLAG_trace_osr) { |
| 7198 PrintF("[on-stack replacement offset %d in optimized code]\n", |
| 7199 data->OsrPcOffset()->value()); |
| 7200 } |
| 7201 ASSERT(data->OsrAstId()->value() == ast_id); |
| 7202 ASSERT(data->OsrPcOffset()->value() >= 0); |
| 7203 } else { |
| 7204 succeeded = false; |
| 7205 } |
| 7206 } |
| 7207 |
| 7208 // Revert to the original stack checks in the original unoptimized code. |
| 7209 if (FLAG_trace_osr) { |
| 7210 PrintF("[restoring original stack checks in "); |
| 7211 function->PrintName(); |
| 7212 PrintF("]\n"); |
| 7213 } |
| 7214 StackCheckStub check_stub; |
| 7215 Handle<Code> check_code = check_stub.GetCode(); |
| 7216 Handle<Code> replacement_code( |
| 7217 isolate->builtins()->builtin(Builtins::OnStackReplacement)); |
| 7218 // Iterate the unoptimized code and revert all the patched stack checks. |
| 7219 for (RelocIterator it(*unoptimized, RelocInfo::kCodeTargetMask); |
| 7220 !it.done(); |
| 7221 it.next()) { |
| 7222 RelocInfo* rinfo = it.rinfo(); |
| 7223 if (rinfo->target_address() == replacement_code->entry()) { |
| 7224 Deoptimizer::RevertStackCheckCode(rinfo, *check_code); |
| 7225 } |
| 7226 } |
| 7227 |
| 7228 // Allow OSR only at nesting level zero again. |
| 7229 unoptimized->set_allow_osr_at_loop_nesting_level(0); |
| 7230 |
| 7231 // If the optimization attempt succeeded, return the AST id tagged as a |
| 7232 // smi. This tells the builtin that we need to translate the unoptimized |
| 7233 // frame to an optimized one. |
| 7234 if (succeeded) { |
| 7235 ASSERT(function->code()->kind() == Code::OPTIMIZED_FUNCTION); |
| 7236 return Smi::FromInt(ast_id); |
| 7237 } else { |
| 7238 return Smi::FromInt(-1); |
| 7239 } |
| 7240 } |
| 7241 |
| 7242 |
| 6976 static MaybeObject* Runtime_GetFunctionDelegate(RUNTIME_CALLING_CONVENTION) { | 7243 static MaybeObject* Runtime_GetFunctionDelegate(RUNTIME_CALLING_CONVENTION) { |
| 6977 RUNTIME_GET_ISOLATE; | 7244 RUNTIME_GET_ISOLATE; |
| 6978 HandleScope scope(isolate); | 7245 HandleScope scope(isolate); |
| 6979 ASSERT(args.length() == 1); | 7246 ASSERT(args.length() == 1); |
| 6980 RUNTIME_ASSERT(!args[0]->IsJSFunction()); | 7247 RUNTIME_ASSERT(!args[0]->IsJSFunction()); |
| 6981 return *Execution::GetFunctionDelegate(args.at<Object>(0)); | 7248 return *Execution::GetFunctionDelegate(args.at<Object>(0)); |
| 6982 } | 7249 } |
| 6983 | 7250 |
| 6984 | 7251 |
| 6985 static MaybeObject* Runtime_GetConstructorDelegate(RUNTIME_CALLING_CONVENTION) { | 7252 static MaybeObject* Runtime_GetConstructorDelegate(RUNTIME_CALLING_CONVENTION) { |
| (...skipping 1319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8305 HandleScope scope(isolate); | 8572 HandleScope scope(isolate); |
| 8306 CONVERT_ARG_CHECKED(JSObject, array, 0); | 8573 CONVERT_ARG_CHECKED(JSObject, array, 0); |
| 8307 CONVERT_NUMBER_CHECKED(uint32_t, length, Uint32, args[1]); | 8574 CONVERT_NUMBER_CHECKED(uint32_t, length, Uint32, args[1]); |
| 8308 if (array->elements()->IsDictionary()) { | 8575 if (array->elements()->IsDictionary()) { |
| 8309 // Create an array and get all the keys into it, then remove all the | 8576 // Create an array and get all the keys into it, then remove all the |
| 8310 // keys that are not integers in the range 0 to length-1. | 8577 // keys that are not integers in the range 0 to length-1. |
| 8311 Handle<FixedArray> keys = GetKeysInFixedArrayFor(array, INCLUDE_PROTOS); | 8578 Handle<FixedArray> keys = GetKeysInFixedArrayFor(array, INCLUDE_PROTOS); |
| 8312 int keys_length = keys->length(); | 8579 int keys_length = keys->length(); |
| 8313 for (int i = 0; i < keys_length; i++) { | 8580 for (int i = 0; i < keys_length; i++) { |
| 8314 Object* key = keys->get(i); | 8581 Object* key = keys->get(i); |
| 8315 uint32_t index; | 8582 uint32_t index = 0; |
| 8316 if (!key->ToArrayIndex(&index) || index >= length) { | 8583 if (!key->ToArrayIndex(&index) || index >= length) { |
| 8317 // Zap invalid keys. | 8584 // Zap invalid keys. |
| 8318 keys->set_undefined(i); | 8585 keys->set_undefined(i); |
| 8319 } | 8586 } |
| 8320 } | 8587 } |
| 8321 return *isolate->factory()->NewJSArrayWithElements(keys); | 8588 return *isolate->factory()->NewJSArrayWithElements(keys); |
| 8322 } else { | 8589 } else { |
| 8323 ASSERT(array->HasFastElements()); | 8590 ASSERT(array->HasFastElements()); |
| 8324 Handle<FixedArray> single_interval = isolate->factory()->NewFixedArray(2); | 8591 Handle<FixedArray> single_interval = isolate->factory()->NewFixedArray(2); |
| 8325 // -1 means start of array. | 8592 // -1 means start of array. |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8439 } | 8706 } |
| 8440 return value; | 8707 return value; |
| 8441 case CONSTANT_FUNCTION: | 8708 case CONSTANT_FUNCTION: |
| 8442 return result->GetConstantFunction(); | 8709 return result->GetConstantFunction(); |
| 8443 case CALLBACKS: { | 8710 case CALLBACKS: { |
| 8444 Object* structure = result->GetCallbackObject(); | 8711 Object* structure = result->GetCallbackObject(); |
| 8445 if (structure->IsProxy() || structure->IsAccessorInfo()) { | 8712 if (structure->IsProxy() || structure->IsAccessorInfo()) { |
| 8446 MaybeObject* maybe_value = receiver->GetPropertyWithCallback( | 8713 MaybeObject* maybe_value = receiver->GetPropertyWithCallback( |
| 8447 receiver, structure, name, result->holder()); | 8714 receiver, structure, name, result->holder()); |
| 8448 if (!maybe_value->ToObject(&value)) { | 8715 if (!maybe_value->ToObject(&value)) { |
| 8716 if (maybe_value->IsRetryAfterGC()) return maybe_value; |
| 8449 ASSERT(maybe_value->IsException()); | 8717 ASSERT(maybe_value->IsException()); |
| 8450 maybe_value = heap->isolate()->pending_exception(); | 8718 maybe_value = heap->isolate()->pending_exception(); |
| 8451 heap->isolate()->clear_pending_exception(); | 8719 heap->isolate()->clear_pending_exception(); |
| 8452 if (caught_exception != NULL) { | 8720 if (caught_exception != NULL) { |
| 8453 *caught_exception = true; | 8721 *caught_exception = true; |
| 8454 } | 8722 } |
| 8455 return maybe_value; | 8723 return maybe_value; |
| 8456 } | 8724 } |
| 8457 return value; | 8725 return value; |
| 8458 } else { | 8726 } else { |
| (...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8759 return heap->undefined_value(); | 9027 return heap->undefined_value(); |
| 8760 } | 9028 } |
| 8761 int count = 0; | 9029 int count = 0; |
| 8762 JavaScriptFrameIterator it(id); | 9030 JavaScriptFrameIterator it(id); |
| 8763 for (; !it.done(); it.Advance()) { | 9031 for (; !it.done(); it.Advance()) { |
| 8764 if (count == index) break; | 9032 if (count == index) break; |
| 8765 count++; | 9033 count++; |
| 8766 } | 9034 } |
| 8767 if (it.done()) return heap->undefined_value(); | 9035 if (it.done()) return heap->undefined_value(); |
| 8768 | 9036 |
| 9037 bool is_optimized_frame = |
| 9038 it.frame()->LookupCode(isolate)->kind() == Code::OPTIMIZED_FUNCTION; |
| 9039 |
| 8769 // Traverse the saved contexts chain to find the active context for the | 9040 // Traverse the saved contexts chain to find the active context for the |
| 8770 // selected frame. | 9041 // selected frame. |
| 8771 SaveContext* save = isolate->save_context(); | 9042 SaveContext* save = isolate->save_context(); |
| 8772 while (save != NULL && !save->below(it.frame())) { | 9043 while (save != NULL && !save->below(it.frame())) { |
| 8773 save = save->prev(); | 9044 save = save->prev(); |
| 8774 } | 9045 } |
| 8775 ASSERT(save != NULL); | 9046 ASSERT(save != NULL); |
| 8776 | 9047 |
| 8777 // Get the frame id. | 9048 // Get the frame id. |
| 8778 Handle<Object> frame_id(WrapFrameId(it.frame()->id()), isolate); | 9049 Handle<Object> frame_id(WrapFrameId(it.frame()->id()), isolate); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 8792 // Get the context. | 9063 // Get the context. |
| 8793 Handle<Context> context(Context::cast(it.frame()->context())); | 9064 Handle<Context> context(Context::cast(it.frame()->context())); |
| 8794 | 9065 |
| 8795 // Get the locals names and values into a temporary array. | 9066 // Get the locals names and values into a temporary array. |
| 8796 // | 9067 // |
| 8797 // TODO(1240907): Hide compiler-introduced stack variables | 9068 // TODO(1240907): Hide compiler-introduced stack variables |
| 8798 // (e.g. .result)? For users of the debugger, they will probably be | 9069 // (e.g. .result)? For users of the debugger, they will probably be |
| 8799 // confusing. | 9070 // confusing. |
| 8800 Handle<FixedArray> locals = | 9071 Handle<FixedArray> locals = |
| 8801 isolate->factory()->NewFixedArray(info.NumberOfLocals() * 2); | 9072 isolate->factory()->NewFixedArray(info.NumberOfLocals() * 2); |
| 9073 |
| 9074 // Fill in the names of the locals. |
| 8802 for (int i = 0; i < info.NumberOfLocals(); i++) { | 9075 for (int i = 0; i < info.NumberOfLocals(); i++) { |
| 8803 // Name of the local. | |
| 8804 locals->set(i * 2, *info.LocalName(i)); | 9076 locals->set(i * 2, *info.LocalName(i)); |
| 9077 } |
| 8805 | 9078 |
| 8806 // Fetch the value of the local - either from the stack or from a | 9079 // Fill in the values of the locals. |
| 8807 // heap-allocated context. | 9080 for (int i = 0; i < info.NumberOfLocals(); i++) { |
| 8808 if (i < info.number_of_stack_slots()) { | 9081 if (is_optimized_frame) { |
| 9082 // If we are inspecting an optimized frame use undefined as the |
| 9083 // value for all locals. |
| 9084 // |
| 9085 // TODO(3141533): We should be able to get the correct values |
| 9086 // for locals in optimized frames. |
| 9087 locals->set(i * 2 + 1, isolate->heap()->undefined_value()); |
| 9088 } else if (i < info.number_of_stack_slots()) { |
| 9089 // Get the value from the stack. |
| 8809 locals->set(i * 2 + 1, it.frame()->GetExpression(i)); | 9090 locals->set(i * 2 + 1, it.frame()->GetExpression(i)); |
| 8810 } else { | 9091 } else { |
| 8811 Handle<String> name = info.LocalName(i); | |
| 8812 // Traverse the context chain to the function context as all local | 9092 // Traverse the context chain to the function context as all local |
| 8813 // variables stored in the context will be on the function context. | 9093 // variables stored in the context will be on the function context. |
| 9094 Handle<String> name = info.LocalName(i); |
| 8814 while (!context->is_function_context()) { | 9095 while (!context->is_function_context()) { |
| 8815 context = Handle<Context>(context->previous()); | 9096 context = Handle<Context>(context->previous()); |
| 8816 } | 9097 } |
| 8817 ASSERT(context->is_function_context()); | 9098 ASSERT(context->is_function_context()); |
| 8818 locals->set(i * 2 + 1, | 9099 locals->set(i * 2 + 1, |
| 8819 context->get(scope_info->ContextSlotIndex(*name, NULL))); | 9100 context->get(scope_info->ContextSlotIndex(*name, NULL))); |
| 8820 } | 9101 } |
| 8821 } | 9102 } |
| 8822 | 9103 |
| 8823 // Check whether this frame is positioned at return. | 9104 // Check whether this frame is positioned at return. If not top |
| 8824 int at_return = (index == 0) ? | 9105 // frame or if the frame is optimized it cannot be at a return. |
| 8825 isolate->debug()->IsBreakAtReturn(it.frame()) : false; | 9106 bool at_return = false; |
| 9107 if (!is_optimized_frame && index == 0) { |
| 9108 at_return = isolate->debug()->IsBreakAtReturn(it.frame()); |
| 9109 } |
| 8826 | 9110 |
| 8827 // If positioned just before return find the value to be returned and add it | 9111 // If positioned just before return find the value to be returned and add it |
| 8828 // to the frame information. | 9112 // to the frame information. |
| 8829 Handle<Object> return_value = isolate->factory()->undefined_value(); | 9113 Handle<Object> return_value = isolate->factory()->undefined_value(); |
| 8830 if (at_return) { | 9114 if (at_return) { |
| 8831 StackFrameIterator it2; | 9115 StackFrameIterator it2; |
| 8832 Address internal_frame_sp = NULL; | 9116 Address internal_frame_sp = NULL; |
| 8833 while (!it2.done()) { | 9117 while (!it2.done()) { |
| 8834 if (it2.frame()->is_internal()) { | 9118 if (it2.frame()->is_internal()) { |
| 8835 internal_frame_sp = it2.frame()->sp(); | 9119 internal_frame_sp = it2.frame()->sp(); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8911 | 9195 |
| 8912 // Add arguments name and value. | 9196 // Add arguments name and value. |
| 8913 for (int i = 0; i < argument_count; i++) { | 9197 for (int i = 0; i < argument_count; i++) { |
| 8914 // Name of the argument. | 9198 // Name of the argument. |
| 8915 if (i < info.number_of_parameters()) { | 9199 if (i < info.number_of_parameters()) { |
| 8916 details->set(details_index++, *info.parameter_name(i)); | 9200 details->set(details_index++, *info.parameter_name(i)); |
| 8917 } else { | 9201 } else { |
| 8918 details->set(details_index++, heap->undefined_value()); | 9202 details->set(details_index++, heap->undefined_value()); |
| 8919 } | 9203 } |
| 8920 | 9204 |
| 8921 // Parameter value. | 9205 // Parameter value. If we are inspecting an optimized frame, use |
| 8922 if (i < it.frame()->GetProvidedParametersCount()) { | 9206 // undefined as the value. |
| 9207 // |
| 9208 // TODO(3141533): We should be able to get the actual parameter |
| 9209 // value for optimized frames. |
| 9210 if (!is_optimized_frame && |
| 9211 (i < it.frame()->GetProvidedParametersCount())) { |
| 8923 details->set(details_index++, it.frame()->GetParameter(i)); | 9212 details->set(details_index++, it.frame()->GetParameter(i)); |
| 8924 } else { | 9213 } else { |
| 8925 details->set(details_index++, heap->undefined_value()); | 9214 details->set(details_index++, heap->undefined_value()); |
| 8926 } | 9215 } |
| 8927 } | 9216 } |
| 8928 | 9217 |
| 8929 // Add locals name and value from the temporary copy from the function frame. | 9218 // Add locals name and value from the temporary copy from the function frame. |
| 8930 for (int i = 0; i < info.NumberOfLocals() * 2; i++) { | 9219 for (int i = 0; i < info.NumberOfLocals() * 2; i++) { |
| 8931 details->set(details_index++, locals->get(i)); | 9220 details->set(details_index++, locals->get(i)); |
| 8932 } | 9221 } |
| (...skipping 598 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9531 return Smi::FromInt(source_position); | 9820 return Smi::FromInt(source_position); |
| 9532 } | 9821 } |
| 9533 | 9822 |
| 9534 | 9823 |
| 9535 Object* Runtime::FindSharedFunctionInfoInScript(Isolate* isolate, | 9824 Object* Runtime::FindSharedFunctionInfoInScript(Isolate* isolate, |
| 9536 Handle<Script> script, | 9825 Handle<Script> script, |
| 9537 int position) { | 9826 int position) { |
| 9538 // Iterate the heap looking for SharedFunctionInfo generated from the | 9827 // Iterate the heap looking for SharedFunctionInfo generated from the |
| 9539 // script. The inner most SharedFunctionInfo containing the source position | 9828 // script. The inner most SharedFunctionInfo containing the source position |
| 9540 // for the requested break point is found. | 9829 // for the requested break point is found. |
| 9541 // NOTE: This might reqire several heap iterations. If the SharedFunctionInfo | 9830 // NOTE: This might require several heap iterations. If the SharedFunctionInfo |
| 9542 // which is found is not compiled it is compiled and the heap is iterated | 9831 // which is found is not compiled it is compiled and the heap is iterated |
| 9543 // again as the compilation might create inner functions from the newly | 9832 // again as the compilation might create inner functions from the newly |
| 9544 // compiled function and the actual requested break point might be in one of | 9833 // compiled function and the actual requested break point might be in one of |
| 9545 // these functions. | 9834 // these functions. |
| 9546 bool done = false; | 9835 bool done = false; |
| 9547 // The current candidate for the source position: | 9836 // The current candidate for the source position: |
| 9548 int target_start_position = RelocInfo::kNoPosition; | 9837 int target_start_position = RelocInfo::kNoPosition; |
| 9549 Handle<SharedFunctionInfo> target; | 9838 Handle<SharedFunctionInfo> target; |
| 9550 while (!done) { | 9839 while (!done) { |
| 9551 HeapIterator iterator; | 9840 HeapIterator iterator; |
| (...skipping 836 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10388 old_script_name); | 10677 old_script_name); |
| 10389 | 10678 |
| 10390 if (old_script->IsScript()) { | 10679 if (old_script->IsScript()) { |
| 10391 Handle<Script> script_handle(Script::cast(old_script)); | 10680 Handle<Script> script_handle(Script::cast(old_script)); |
| 10392 return *(GetScriptWrapper(script_handle)); | 10681 return *(GetScriptWrapper(script_handle)); |
| 10393 } else { | 10682 } else { |
| 10394 return isolate->heap()->null_value(); | 10683 return isolate->heap()->null_value(); |
| 10395 } | 10684 } |
| 10396 } | 10685 } |
| 10397 | 10686 |
| 10687 |
| 10688 static MaybeObject* Runtime_LiveEditFunctionSourceUpdated( |
| 10689 RUNTIME_CALLING_CONVENTION) { |
| 10690 RUNTIME_GET_ISOLATE; |
| 10691 ASSERT(args.length() == 1); |
| 10692 HandleScope scope(isolate); |
| 10693 CONVERT_ARG_CHECKED(JSArray, shared_info, 0); |
| 10694 return LiveEdit::FunctionSourceUpdated(shared_info); |
| 10695 } |
| 10696 |
| 10697 |
| 10398 // Replaces code of SharedFunctionInfo with a new one. | 10698 // Replaces code of SharedFunctionInfo with a new one. |
| 10399 static MaybeObject* Runtime_LiveEditReplaceFunctionCode( | 10699 static MaybeObject* Runtime_LiveEditReplaceFunctionCode( |
| 10400 RUNTIME_CALLING_CONVENTION) { | 10700 RUNTIME_CALLING_CONVENTION) { |
| 10401 RUNTIME_GET_ISOLATE; | 10701 RUNTIME_GET_ISOLATE; |
| 10402 ASSERT(args.length() == 2); | 10702 ASSERT(args.length() == 2); |
| 10403 HandleScope scope(isolate); | 10703 HandleScope scope(isolate); |
| 10404 CONVERT_ARG_CHECKED(JSArray, new_compile_info, 0); | 10704 CONVERT_ARG_CHECKED(JSArray, new_compile_info, 0); |
| 10405 CONVERT_ARG_CHECKED(JSArray, shared_info, 1); | 10705 CONVERT_ARG_CHECKED(JSArray, shared_info, 1); |
| 10406 | 10706 |
| 10407 return LiveEdit::ReplaceFunctionCode(new_compile_info, shared_info); | 10707 return LiveEdit::ReplaceFunctionCode(new_compile_info, shared_info); |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10501 // A testing entry. Returns statement position which is the closest to | 10801 // A testing entry. Returns statement position which is the closest to |
| 10502 // source_position. | 10802 // source_position. |
| 10503 static MaybeObject* Runtime_GetFunctionCodePositionFromSource( | 10803 static MaybeObject* Runtime_GetFunctionCodePositionFromSource( |
| 10504 RUNTIME_CALLING_CONVENTION) { | 10804 RUNTIME_CALLING_CONVENTION) { |
| 10505 RUNTIME_GET_ISOLATE; | 10805 RUNTIME_GET_ISOLATE; |
| 10506 ASSERT(args.length() == 2); | 10806 ASSERT(args.length() == 2); |
| 10507 HandleScope scope(isolate); | 10807 HandleScope scope(isolate); |
| 10508 CONVERT_ARG_CHECKED(JSFunction, function, 0); | 10808 CONVERT_ARG_CHECKED(JSFunction, function, 0); |
| 10509 CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]); | 10809 CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]); |
| 10510 | 10810 |
| 10511 Handle<Code> code(function->code()); | 10811 Handle<Code> code(function->code(), isolate); |
| 10812 |
| 10813 if (code->kind() != Code::FUNCTION && |
| 10814 code->kind() != Code::OPTIMIZED_FUNCTION) { |
| 10815 return isolate->heap()->undefined_value(); |
| 10816 } |
| 10512 | 10817 |
| 10513 RelocIterator it(*code, RelocInfo::ModeMask(RelocInfo::STATEMENT_POSITION)); | 10818 RelocIterator it(*code, RelocInfo::ModeMask(RelocInfo::STATEMENT_POSITION)); |
| 10514 int closest_pc = 0; | 10819 int closest_pc = 0; |
| 10515 int distance = kMaxInt; | 10820 int distance = kMaxInt; |
| 10516 while (!it.done()) { | 10821 while (!it.done()) { |
| 10517 int statement_position = static_cast<int>(it.rinfo()->data()); | 10822 int statement_position = static_cast<int>(it.rinfo()->data()); |
| 10518 // Check if this break point is closer that what was previously found. | 10823 // Check if this break point is closer that what was previously found. |
| 10519 if (source_position <= statement_position && | 10824 if (source_position <= statement_position && |
| 10520 statement_position - source_position < distance) { | 10825 statement_position - source_position < distance) { |
| 10521 closest_pc = | 10826 closest_pc = |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10661 return false; | 10966 return false; |
| 10662 } | 10967 } |
| 10663 // Skip all frames until we've seen the caller. Also, skip the most | 10968 // Skip all frames until we've seen the caller. Also, skip the most |
| 10664 // obvious builtin calls. Some builtin calls (such as Number.ADD | 10969 // obvious builtin calls. Some builtin calls (such as Number.ADD |
| 10665 // which is invoked using 'call') are very difficult to recognize | 10970 // which is invoked using 'call') are very difficult to recognize |
| 10666 // so we're leaving them in for now. | 10971 // so we're leaving them in for now. |
| 10667 return *seen_caller && !frame->receiver()->IsJSBuiltinsObject(); | 10972 return *seen_caller && !frame->receiver()->IsJSBuiltinsObject(); |
| 10668 } | 10973 } |
| 10669 | 10974 |
| 10670 | 10975 |
| 10671 // Collect the raw data for a stack trace. Returns an array of three | 10976 // Collect the raw data for a stack trace. Returns an array of 4 |
| 10672 // element segments each containing a receiver, function and native | 10977 // element segments each containing a receiver, function, code and |
| 10673 // code offset. | 10978 // native code offset. |
| 10674 static MaybeObject* Runtime_CollectStackTrace(RUNTIME_CALLING_CONVENTION) { | 10979 static MaybeObject* Runtime_CollectStackTrace(RUNTIME_CALLING_CONVENTION) { |
| 10675 RUNTIME_GET_ISOLATE; | 10980 RUNTIME_GET_ISOLATE; |
| 10676 ASSERT_EQ(args.length(), 2); | 10981 ASSERT_EQ(args.length(), 2); |
| 10677 Handle<Object> caller = args.at<Object>(0); | 10982 Handle<Object> caller = args.at<Object>(0); |
| 10678 CONVERT_NUMBER_CHECKED(int32_t, limit, Int32, args[1]); | 10983 CONVERT_NUMBER_CHECKED(int32_t, limit, Int32, args[1]); |
| 10679 | 10984 |
| 10680 HandleScope scope(isolate); | 10985 HandleScope scope(isolate); |
| 10681 | 10986 |
| 10682 limit = Max(limit, 0); // Ensure that limit is not negative. | 10987 limit = Max(limit, 0); // Ensure that limit is not negative. |
| 10683 int initial_size = Min(limit, 10); | 10988 int initial_size = Min(limit, 10); |
| 10684 Handle<JSArray> result = isolate->factory()->NewJSArray(initial_size * 3); | 10989 Handle<JSArray> result = isolate->factory()->NewJSArray(initial_size * 4); |
| 10685 | 10990 |
| 10686 StackFrameIterator iter; | 10991 StackFrameIterator iter; |
| 10687 // If the caller parameter is a function we skip frames until we're | 10992 // If the caller parameter is a function we skip frames until we're |
| 10688 // under it before starting to collect. | 10993 // under it before starting to collect. |
| 10689 bool seen_caller = !caller->IsJSFunction(); | 10994 bool seen_caller = !caller->IsJSFunction(); |
| 10690 int cursor = 0; | 10995 int cursor = 0; |
| 10691 int frames_seen = 0; | 10996 int frames_seen = 0; |
| 10692 while (!iter.done() && frames_seen < limit) { | 10997 while (!iter.done() && frames_seen < limit) { |
| 10693 StackFrame* raw_frame = iter.frame(); | 10998 StackFrame* raw_frame = iter.frame(); |
| 10694 if (ShowFrameInStackTrace(raw_frame, *caller, &seen_caller)) { | 10999 if (ShowFrameInStackTrace(raw_frame, *caller, &seen_caller)) { |
| 10695 frames_seen++; | 11000 frames_seen++; |
| 10696 JavaScriptFrame* frame = JavaScriptFrame::cast(raw_frame); | 11001 JavaScriptFrame* frame = JavaScriptFrame::cast(raw_frame); |
| 10697 Object* recv = frame->receiver(); | 11002 List<FrameSummary> frames(3); // Max 2 levels of inlining. |
| 10698 Object* fun = frame->function(); | 11003 frame->Summarize(&frames); |
| 10699 Address pc = frame->pc(); | 11004 for (int i = frames.length() - 1; i >= 0; i--) { |
| 10700 Address start = frame->LookupCode(isolate)->address(); | 11005 Handle<Object> recv = frames[i].receiver(); |
| 10701 Smi* offset = Smi::FromInt(static_cast<int>(pc - start)); | 11006 Handle<JSFunction> fun = frames[i].function(); |
| 10702 FixedArray* elements = FixedArray::cast(result->elements()); | 11007 Handle<Code> code = frames[i].code(); |
| 10703 if (cursor + 2 < elements->length()) { | 11008 Handle<Smi> offset(Smi::FromInt(frames[i].offset())); |
| 10704 elements->set(cursor++, recv); | 11009 FixedArray* elements = FixedArray::cast(result->elements()); |
| 10705 elements->set(cursor++, fun); | 11010 if (cursor + 3 < elements->length()) { |
| 10706 elements->set(cursor++, offset); | 11011 elements->set(cursor++, *recv); |
| 10707 } else { | 11012 elements->set(cursor++, *fun); |
| 10708 HandleScope scope(isolate); | 11013 elements->set(cursor++, *code); |
| 10709 Handle<Object> recv_handle(recv, isolate); | 11014 elements->set(cursor++, *offset); |
| 10710 Handle<Object> fun_handle(fun, isolate); | 11015 } else { |
| 10711 SetElement(result, cursor++, recv_handle); | 11016 SetElement(result, cursor++, recv); |
| 10712 SetElement(result, cursor++, fun_handle); | 11017 SetElement(result, cursor++, fun); |
| 10713 SetElement(result, cursor++, Handle<Smi>(offset)); | 11018 SetElement(result, cursor++, code); |
| 11019 SetElement(result, cursor++, offset); |
| 11020 } |
| 10714 } | 11021 } |
| 10715 } | 11022 } |
| 10716 iter.Advance(); | 11023 iter.Advance(); |
| 10717 } | 11024 } |
| 10718 | 11025 |
| 10719 result->set_length(Smi::FromInt(cursor)); | 11026 result->set_length(Smi::FromInt(cursor)); |
| 10720 return *result; | 11027 return *result; |
| 10721 } | 11028 } |
| 10722 | 11029 |
| 10723 | 11030 |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10963 } else { | 11270 } else { |
| 10964 // Handle last resort GC and make sure to allow future allocations | 11271 // Handle last resort GC and make sure to allow future allocations |
| 10965 // to grow the heap without causing GCs (if possible). | 11272 // to grow the heap without causing GCs (if possible). |
| 10966 COUNTERS->gc_last_resort_from_js()->Increment(); | 11273 COUNTERS->gc_last_resort_from_js()->Increment(); |
| 10967 HEAP->CollectAllGarbage(false); | 11274 HEAP->CollectAllGarbage(false); |
| 10968 } | 11275 } |
| 10969 } | 11276 } |
| 10970 | 11277 |
| 10971 | 11278 |
| 10972 } } // namespace v8::internal | 11279 } } // namespace v8::internal |
| OLD | NEW |