| 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" |
| (...skipping 22 matching lines...) Expand all Loading... |
| 33 #include "src/parser.h" | 33 #include "src/parser.h" |
| 34 #include "src/prototype.h" | 34 #include "src/prototype.h" |
| 35 #include "src/runtime/runtime.h" | 35 #include "src/runtime/runtime.h" |
| 36 #include "src/runtime/runtime-utils.h" | 36 #include "src/runtime/runtime-utils.h" |
| 37 #include "src/runtime-profiler.h" | 37 #include "src/runtime-profiler.h" |
| 38 #include "src/scopeinfo.h" | 38 #include "src/scopeinfo.h" |
| 39 #include "src/smart-pointers.h" | 39 #include "src/smart-pointers.h" |
| 40 #include "src/utils.h" | 40 #include "src/utils.h" |
| 41 #include "src/v8threads.h" | 41 #include "src/v8threads.h" |
| 42 #include "src/vm-state-inl.h" | 42 #include "src/vm-state-inl.h" |
| 43 #include "third_party/fdlibm/fdlibm.h" | |
| 44 | 43 |
| 45 | 44 |
| 46 #ifndef _STLP_VENDOR_CSTD | |
| 47 // STLPort doesn't import fpclassify and isless into the std namespace. | |
| 48 using std::fpclassify; | |
| 49 using std::isless; | |
| 50 #endif | |
| 51 | |
| 52 namespace v8 { | 45 namespace v8 { |
| 53 namespace internal { | 46 namespace internal { |
| 54 | 47 |
| 55 // Header of runtime functions. | 48 // Header of runtime functions. |
| 56 #define F(name, number_of_args, result_size) \ | 49 #define F(name, number_of_args, result_size) \ |
| 57 Object* Runtime_##name(int args_length, Object** args_object, \ | 50 Object* Runtime_##name(int args_length, Object** args_object, \ |
| 58 Isolate* isolate); | 51 Isolate* isolate); |
| 59 | 52 |
| 60 #define P(name, number_of_args, result_size) \ | 53 #define P(name, number_of_args, result_size) \ |
| 61 ObjectPair Runtime_##name(int args_length, Object** args_object, \ | 54 ObjectPair Runtime_##name(int args_length, Object** args_object, \ |
| (...skipping 578 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 640 | 633 |
| 641 RUNTIME_FUNCTION(Runtime_Fix) { | 634 RUNTIME_FUNCTION(Runtime_Fix) { |
| 642 HandleScope scope(isolate); | 635 HandleScope scope(isolate); |
| 643 DCHECK(args.length() == 1); | 636 DCHECK(args.length() == 1); |
| 644 CONVERT_ARG_HANDLE_CHECKED(JSProxy, proxy, 0); | 637 CONVERT_ARG_HANDLE_CHECKED(JSProxy, proxy, 0); |
| 645 JSProxy::Fix(proxy); | 638 JSProxy::Fix(proxy); |
| 646 return isolate->heap()->undefined_value(); | 639 return isolate->heap()->undefined_value(); |
| 647 } | 640 } |
| 648 | 641 |
| 649 | 642 |
| 650 void Runtime::FreeArrayBuffer(Isolate* isolate, | |
| 651 JSArrayBuffer* phantom_array_buffer) { | |
| 652 if (phantom_array_buffer->should_be_freed()) { | |
| 653 DCHECK(phantom_array_buffer->is_external()); | |
| 654 free(phantom_array_buffer->backing_store()); | |
| 655 } | |
| 656 if (phantom_array_buffer->is_external()) return; | |
| 657 | |
| 658 size_t allocated_length = | |
| 659 NumberToSize(isolate, phantom_array_buffer->byte_length()); | |
| 660 | |
| 661 reinterpret_cast<v8::Isolate*>(isolate) | |
| 662 ->AdjustAmountOfExternalAllocatedMemory( | |
| 663 -static_cast<int64_t>(allocated_length)); | |
| 664 CHECK(V8::ArrayBufferAllocator() != NULL); | |
| 665 V8::ArrayBufferAllocator()->Free(phantom_array_buffer->backing_store(), | |
| 666 allocated_length); | |
| 667 } | |
| 668 | |
| 669 | |
| 670 void Runtime::SetupArrayBuffer(Isolate* isolate, | |
| 671 Handle<JSArrayBuffer> array_buffer, | |
| 672 bool is_external, void* data, | |
| 673 size_t allocated_length) { | |
| 674 DCHECK(array_buffer->GetInternalFieldCount() == | |
| 675 v8::ArrayBuffer::kInternalFieldCount); | |
| 676 for (int i = 0; i < v8::ArrayBuffer::kInternalFieldCount; i++) { | |
| 677 array_buffer->SetInternalField(i, Smi::FromInt(0)); | |
| 678 } | |
| 679 array_buffer->set_backing_store(data); | |
| 680 array_buffer->set_flag(Smi::FromInt(0)); | |
| 681 array_buffer->set_is_external(is_external); | |
| 682 | |
| 683 Handle<Object> byte_length = | |
| 684 isolate->factory()->NewNumberFromSize(allocated_length); | |
| 685 CHECK(byte_length->IsSmi() || byte_length->IsHeapNumber()); | |
| 686 array_buffer->set_byte_length(*byte_length); | |
| 687 | |
| 688 array_buffer->set_weak_next(isolate->heap()->array_buffers_list()); | |
| 689 isolate->heap()->set_array_buffers_list(*array_buffer); | |
| 690 array_buffer->set_weak_first_view(isolate->heap()->undefined_value()); | |
| 691 } | |
| 692 | |
| 693 | |
| 694 bool Runtime::SetupArrayBufferAllocatingData(Isolate* isolate, | |
| 695 Handle<JSArrayBuffer> array_buffer, | |
| 696 size_t allocated_length, | |
| 697 bool initialize) { | |
| 698 void* data; | |
| 699 CHECK(V8::ArrayBufferAllocator() != NULL); | |
| 700 if (allocated_length != 0) { | |
| 701 if (initialize) { | |
| 702 data = V8::ArrayBufferAllocator()->Allocate(allocated_length); | |
| 703 } else { | |
| 704 data = | |
| 705 V8::ArrayBufferAllocator()->AllocateUninitialized(allocated_length); | |
| 706 } | |
| 707 if (data == NULL) return false; | |
| 708 } else { | |
| 709 data = NULL; | |
| 710 } | |
| 711 | |
| 712 SetupArrayBuffer(isolate, array_buffer, false, data, allocated_length); | |
| 713 | |
| 714 reinterpret_cast<v8::Isolate*>(isolate) | |
| 715 ->AdjustAmountOfExternalAllocatedMemory(allocated_length); | |
| 716 | |
| 717 return true; | |
| 718 } | |
| 719 | |
| 720 | |
| 721 void Runtime::NeuterArrayBuffer(Handle<JSArrayBuffer> array_buffer) { | |
| 722 Isolate* isolate = array_buffer->GetIsolate(); | |
| 723 for (Handle<Object> view_obj(array_buffer->weak_first_view(), isolate); | |
| 724 !view_obj->IsUndefined();) { | |
| 725 Handle<JSArrayBufferView> view(JSArrayBufferView::cast(*view_obj)); | |
| 726 if (view->IsJSTypedArray()) { | |
| 727 JSTypedArray::cast(*view)->Neuter(); | |
| 728 } else if (view->IsJSDataView()) { | |
| 729 JSDataView::cast(*view)->Neuter(); | |
| 730 } else { | |
| 731 UNREACHABLE(); | |
| 732 } | |
| 733 view_obj = handle(view->weak_next(), isolate); | |
| 734 } | |
| 735 array_buffer->Neuter(); | |
| 736 } | |
| 737 | |
| 738 | |
| 739 RUNTIME_FUNCTION(Runtime_ArrayBufferInitialize) { | |
| 740 HandleScope scope(isolate); | |
| 741 DCHECK(args.length() == 2); | |
| 742 CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, holder, 0); | |
| 743 CONVERT_NUMBER_ARG_HANDLE_CHECKED(byteLength, 1); | |
| 744 if (!holder->byte_length()->IsUndefined()) { | |
| 745 // ArrayBuffer is already initialized; probably a fuzz test. | |
| 746 return *holder; | |
| 747 } | |
| 748 size_t allocated_length = 0; | |
| 749 if (!TryNumberToSize(isolate, *byteLength, &allocated_length)) { | |
| 750 THROW_NEW_ERROR_RETURN_FAILURE( | |
| 751 isolate, NewRangeError("invalid_array_buffer_length", | |
| 752 HandleVector<Object>(NULL, 0))); | |
| 753 } | |
| 754 if (!Runtime::SetupArrayBufferAllocatingData(isolate, holder, | |
| 755 allocated_length)) { | |
| 756 THROW_NEW_ERROR_RETURN_FAILURE( | |
| 757 isolate, NewRangeError("invalid_array_buffer_length", | |
| 758 HandleVector<Object>(NULL, 0))); | |
| 759 } | |
| 760 return *holder; | |
| 761 } | |
| 762 | |
| 763 | |
| 764 RUNTIME_FUNCTION(Runtime_ArrayBufferGetByteLength) { | |
| 765 SealHandleScope shs(isolate); | |
| 766 DCHECK(args.length() == 1); | |
| 767 CONVERT_ARG_CHECKED(JSArrayBuffer, holder, 0); | |
| 768 return holder->byte_length(); | |
| 769 } | |
| 770 | |
| 771 | |
| 772 RUNTIME_FUNCTION(Runtime_ArrayBufferSliceImpl) { | |
| 773 HandleScope scope(isolate); | |
| 774 DCHECK(args.length() == 3); | |
| 775 CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, source, 0); | |
| 776 CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, target, 1); | |
| 777 CONVERT_NUMBER_ARG_HANDLE_CHECKED(first, 2); | |
| 778 RUNTIME_ASSERT(!source.is_identical_to(target)); | |
| 779 size_t start = 0; | |
| 780 RUNTIME_ASSERT(TryNumberToSize(isolate, *first, &start)); | |
| 781 size_t target_length = NumberToSize(isolate, target->byte_length()); | |
| 782 | |
| 783 if (target_length == 0) return isolate->heap()->undefined_value(); | |
| 784 | |
| 785 size_t source_byte_length = NumberToSize(isolate, source->byte_length()); | |
| 786 RUNTIME_ASSERT(start <= source_byte_length); | |
| 787 RUNTIME_ASSERT(source_byte_length - start >= target_length); | |
| 788 uint8_t* source_data = reinterpret_cast<uint8_t*>(source->backing_store()); | |
| 789 uint8_t* target_data = reinterpret_cast<uint8_t*>(target->backing_store()); | |
| 790 CopyBytes(target_data, source_data + start, target_length); | |
| 791 return isolate->heap()->undefined_value(); | |
| 792 } | |
| 793 | |
| 794 | |
| 795 RUNTIME_FUNCTION(Runtime_ArrayBufferIsView) { | |
| 796 HandleScope scope(isolate); | |
| 797 DCHECK(args.length() == 1); | |
| 798 CONVERT_ARG_CHECKED(Object, object, 0); | |
| 799 return isolate->heap()->ToBoolean(object->IsJSArrayBufferView()); | |
| 800 } | |
| 801 | |
| 802 | |
| 803 RUNTIME_FUNCTION(Runtime_ArrayBufferNeuter) { | |
| 804 HandleScope scope(isolate); | |
| 805 DCHECK(args.length() == 1); | |
| 806 CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, array_buffer, 0); | |
| 807 if (array_buffer->backing_store() == NULL) { | |
| 808 CHECK(Smi::FromInt(0) == array_buffer->byte_length()); | |
| 809 return isolate->heap()->undefined_value(); | |
| 810 } | |
| 811 DCHECK(!array_buffer->is_external()); | |
| 812 void* backing_store = array_buffer->backing_store(); | |
| 813 size_t byte_length = NumberToSize(isolate, array_buffer->byte_length()); | |
| 814 array_buffer->set_is_external(true); | |
| 815 Runtime::NeuterArrayBuffer(array_buffer); | |
| 816 V8::ArrayBufferAllocator()->Free(backing_store, byte_length); | |
| 817 return isolate->heap()->undefined_value(); | |
| 818 } | |
| 819 | |
| 820 | |
| 821 void Runtime::ArrayIdToTypeAndSize(int arrayId, ExternalArrayType* array_type, | |
| 822 ElementsKind* external_elements_kind, | |
| 823 ElementsKind* fixed_elements_kind, | |
| 824 size_t* element_size) { | |
| 825 switch (arrayId) { | |
| 826 #define ARRAY_ID_CASE(Type, type, TYPE, ctype, size) \ | |
| 827 case ARRAY_ID_##TYPE: \ | |
| 828 *array_type = kExternal##Type##Array; \ | |
| 829 *external_elements_kind = EXTERNAL_##TYPE##_ELEMENTS; \ | |
| 830 *fixed_elements_kind = TYPE##_ELEMENTS; \ | |
| 831 *element_size = size; \ | |
| 832 break; | |
| 833 | |
| 834 TYPED_ARRAYS(ARRAY_ID_CASE) | |
| 835 #undef ARRAY_ID_CASE | |
| 836 | |
| 837 default: | |
| 838 UNREACHABLE(); | |
| 839 } | |
| 840 } | |
| 841 | |
| 842 | |
| 843 RUNTIME_FUNCTION(Runtime_TypedArrayInitialize) { | |
| 844 HandleScope scope(isolate); | |
| 845 DCHECK(args.length() == 5); | |
| 846 CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0); | |
| 847 CONVERT_SMI_ARG_CHECKED(arrayId, 1); | |
| 848 CONVERT_ARG_HANDLE_CHECKED(Object, maybe_buffer, 2); | |
| 849 CONVERT_NUMBER_ARG_HANDLE_CHECKED(byte_offset_object, 3); | |
| 850 CONVERT_NUMBER_ARG_HANDLE_CHECKED(byte_length_object, 4); | |
| 851 | |
| 852 RUNTIME_ASSERT(arrayId >= Runtime::ARRAY_ID_FIRST && | |
| 853 arrayId <= Runtime::ARRAY_ID_LAST); | |
| 854 | |
| 855 ExternalArrayType array_type = kExternalInt8Array; // Bogus initialization. | |
| 856 size_t element_size = 1; // Bogus initialization. | |
| 857 ElementsKind external_elements_kind = | |
| 858 EXTERNAL_INT8_ELEMENTS; // Bogus initialization. | |
| 859 ElementsKind fixed_elements_kind = INT8_ELEMENTS; // Bogus initialization. | |
| 860 Runtime::ArrayIdToTypeAndSize(arrayId, &array_type, &external_elements_kind, | |
| 861 &fixed_elements_kind, &element_size); | |
| 862 RUNTIME_ASSERT(holder->map()->elements_kind() == fixed_elements_kind); | |
| 863 | |
| 864 size_t byte_offset = 0; | |
| 865 size_t byte_length = 0; | |
| 866 RUNTIME_ASSERT(TryNumberToSize(isolate, *byte_offset_object, &byte_offset)); | |
| 867 RUNTIME_ASSERT(TryNumberToSize(isolate, *byte_length_object, &byte_length)); | |
| 868 | |
| 869 if (maybe_buffer->IsJSArrayBuffer()) { | |
| 870 Handle<JSArrayBuffer> buffer = Handle<JSArrayBuffer>::cast(maybe_buffer); | |
| 871 size_t array_buffer_byte_length = | |
| 872 NumberToSize(isolate, buffer->byte_length()); | |
| 873 RUNTIME_ASSERT(byte_offset <= array_buffer_byte_length); | |
| 874 RUNTIME_ASSERT(array_buffer_byte_length - byte_offset >= byte_length); | |
| 875 } else { | |
| 876 RUNTIME_ASSERT(maybe_buffer->IsNull()); | |
| 877 } | |
| 878 | |
| 879 RUNTIME_ASSERT(byte_length % element_size == 0); | |
| 880 size_t length = byte_length / element_size; | |
| 881 | |
| 882 if (length > static_cast<unsigned>(Smi::kMaxValue)) { | |
| 883 THROW_NEW_ERROR_RETURN_FAILURE( | |
| 884 isolate, NewRangeError("invalid_typed_array_length", | |
| 885 HandleVector<Object>(NULL, 0))); | |
| 886 } | |
| 887 | |
| 888 // All checks are done, now we can modify objects. | |
| 889 | |
| 890 DCHECK(holder->GetInternalFieldCount() == | |
| 891 v8::ArrayBufferView::kInternalFieldCount); | |
| 892 for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) { | |
| 893 holder->SetInternalField(i, Smi::FromInt(0)); | |
| 894 } | |
| 895 Handle<Object> length_obj = isolate->factory()->NewNumberFromSize(length); | |
| 896 holder->set_length(*length_obj); | |
| 897 holder->set_byte_offset(*byte_offset_object); | |
| 898 holder->set_byte_length(*byte_length_object); | |
| 899 | |
| 900 if (!maybe_buffer->IsNull()) { | |
| 901 Handle<JSArrayBuffer> buffer = Handle<JSArrayBuffer>::cast(maybe_buffer); | |
| 902 holder->set_buffer(*buffer); | |
| 903 holder->set_weak_next(buffer->weak_first_view()); | |
| 904 buffer->set_weak_first_view(*holder); | |
| 905 | |
| 906 Handle<ExternalArray> elements = isolate->factory()->NewExternalArray( | |
| 907 static_cast<int>(length), array_type, | |
| 908 static_cast<uint8_t*>(buffer->backing_store()) + byte_offset); | |
| 909 Handle<Map> map = | |
| 910 JSObject::GetElementsTransitionMap(holder, external_elements_kind); | |
| 911 JSObject::SetMapAndElements(holder, map, elements); | |
| 912 DCHECK(IsExternalArrayElementsKind(holder->map()->elements_kind())); | |
| 913 } else { | |
| 914 holder->set_buffer(Smi::FromInt(0)); | |
| 915 holder->set_weak_next(isolate->heap()->undefined_value()); | |
| 916 Handle<FixedTypedArrayBase> elements = | |
| 917 isolate->factory()->NewFixedTypedArray(static_cast<int>(length), | |
| 918 array_type); | |
| 919 holder->set_elements(*elements); | |
| 920 } | |
| 921 return isolate->heap()->undefined_value(); | |
| 922 } | |
| 923 | |
| 924 | |
| 925 // Initializes a typed array from an array-like object. | |
| 926 // If an array-like object happens to be a typed array of the same type, | |
| 927 // initializes backing store using memove. | |
| 928 // | |
| 929 // Returns true if backing store was initialized or false otherwise. | |
| 930 RUNTIME_FUNCTION(Runtime_TypedArrayInitializeFromArrayLike) { | |
| 931 HandleScope scope(isolate); | |
| 932 DCHECK(args.length() == 4); | |
| 933 CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0); | |
| 934 CONVERT_SMI_ARG_CHECKED(arrayId, 1); | |
| 935 CONVERT_ARG_HANDLE_CHECKED(Object, source, 2); | |
| 936 CONVERT_NUMBER_ARG_HANDLE_CHECKED(length_obj, 3); | |
| 937 | |
| 938 RUNTIME_ASSERT(arrayId >= Runtime::ARRAY_ID_FIRST && | |
| 939 arrayId <= Runtime::ARRAY_ID_LAST); | |
| 940 | |
| 941 ExternalArrayType array_type = kExternalInt8Array; // Bogus initialization. | |
| 942 size_t element_size = 1; // Bogus initialization. | |
| 943 ElementsKind external_elements_kind = | |
| 944 EXTERNAL_INT8_ELEMENTS; // Bogus intialization. | |
| 945 ElementsKind fixed_elements_kind = INT8_ELEMENTS; // Bogus initialization. | |
| 946 Runtime::ArrayIdToTypeAndSize(arrayId, &array_type, &external_elements_kind, | |
| 947 &fixed_elements_kind, &element_size); | |
| 948 | |
| 949 RUNTIME_ASSERT(holder->map()->elements_kind() == fixed_elements_kind); | |
| 950 | |
| 951 Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer(); | |
| 952 if (source->IsJSTypedArray() && | |
| 953 JSTypedArray::cast(*source)->type() == array_type) { | |
| 954 length_obj = Handle<Object>(JSTypedArray::cast(*source)->length(), isolate); | |
| 955 } | |
| 956 size_t length = 0; | |
| 957 RUNTIME_ASSERT(TryNumberToSize(isolate, *length_obj, &length)); | |
| 958 | |
| 959 if ((length > static_cast<unsigned>(Smi::kMaxValue)) || | |
| 960 (length > (kMaxInt / element_size))) { | |
| 961 THROW_NEW_ERROR_RETURN_FAILURE( | |
| 962 isolate, NewRangeError("invalid_typed_array_length", | |
| 963 HandleVector<Object>(NULL, 0))); | |
| 964 } | |
| 965 size_t byte_length = length * element_size; | |
| 966 | |
| 967 DCHECK(holder->GetInternalFieldCount() == | |
| 968 v8::ArrayBufferView::kInternalFieldCount); | |
| 969 for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) { | |
| 970 holder->SetInternalField(i, Smi::FromInt(0)); | |
| 971 } | |
| 972 | |
| 973 // NOTE: not initializing backing store. | |
| 974 // We assume that the caller of this function will initialize holder | |
| 975 // with the loop | |
| 976 // for(i = 0; i < length; i++) { holder[i] = source[i]; } | |
| 977 // We assume that the caller of this function is always a typed array | |
| 978 // constructor. | |
| 979 // If source is a typed array, this loop will always run to completion, | |
| 980 // so we are sure that the backing store will be initialized. | |
| 981 // Otherwise, the indexing operation might throw, so the loop will not | |
| 982 // run to completion and the typed array might remain partly initialized. | |
| 983 // However we further assume that the caller of this function is a typed array | |
| 984 // constructor, and the exception will propagate out of the constructor, | |
| 985 // therefore uninitialized memory will not be accessible by a user program. | |
| 986 // | |
| 987 // TODO(dslomov): revise this once we support subclassing. | |
| 988 | |
| 989 if (!Runtime::SetupArrayBufferAllocatingData(isolate, buffer, byte_length, | |
| 990 false)) { | |
| 991 THROW_NEW_ERROR_RETURN_FAILURE( | |
| 992 isolate, NewRangeError("invalid_array_buffer_length", | |
| 993 HandleVector<Object>(NULL, 0))); | |
| 994 } | |
| 995 | |
| 996 holder->set_buffer(*buffer); | |
| 997 holder->set_byte_offset(Smi::FromInt(0)); | |
| 998 Handle<Object> byte_length_obj( | |
| 999 isolate->factory()->NewNumberFromSize(byte_length)); | |
| 1000 holder->set_byte_length(*byte_length_obj); | |
| 1001 holder->set_length(*length_obj); | |
| 1002 holder->set_weak_next(buffer->weak_first_view()); | |
| 1003 buffer->set_weak_first_view(*holder); | |
| 1004 | |
| 1005 Handle<ExternalArray> elements = isolate->factory()->NewExternalArray( | |
| 1006 static_cast<int>(length), array_type, | |
| 1007 static_cast<uint8_t*>(buffer->backing_store())); | |
| 1008 Handle<Map> map = | |
| 1009 JSObject::GetElementsTransitionMap(holder, external_elements_kind); | |
| 1010 JSObject::SetMapAndElements(holder, map, elements); | |
| 1011 | |
| 1012 if (source->IsJSTypedArray()) { | |
| 1013 Handle<JSTypedArray> typed_array(JSTypedArray::cast(*source)); | |
| 1014 | |
| 1015 if (typed_array->type() == holder->type()) { | |
| 1016 uint8_t* backing_store = | |
| 1017 static_cast<uint8_t*>(typed_array->GetBuffer()->backing_store()); | |
| 1018 size_t source_byte_offset = | |
| 1019 NumberToSize(isolate, typed_array->byte_offset()); | |
| 1020 memcpy(buffer->backing_store(), backing_store + source_byte_offset, | |
| 1021 byte_length); | |
| 1022 return isolate->heap()->true_value(); | |
| 1023 } | |
| 1024 } | |
| 1025 | |
| 1026 return isolate->heap()->false_value(); | |
| 1027 } | |
| 1028 | |
| 1029 | |
| 1030 #define BUFFER_VIEW_GETTER(Type, getter, accessor) \ | |
| 1031 RUNTIME_FUNCTION(Runtime_##Type##Get##getter) { \ | |
| 1032 HandleScope scope(isolate); \ | |
| 1033 DCHECK(args.length() == 1); \ | |
| 1034 CONVERT_ARG_HANDLE_CHECKED(JS##Type, holder, 0); \ | |
| 1035 return holder->accessor(); \ | |
| 1036 } | |
| 1037 | |
| 1038 BUFFER_VIEW_GETTER(ArrayBufferView, ByteLength, byte_length) | |
| 1039 BUFFER_VIEW_GETTER(ArrayBufferView, ByteOffset, byte_offset) | |
| 1040 BUFFER_VIEW_GETTER(TypedArray, Length, length) | |
| 1041 BUFFER_VIEW_GETTER(DataView, Buffer, buffer) | |
| 1042 | |
| 1043 #undef BUFFER_VIEW_GETTER | |
| 1044 | |
| 1045 RUNTIME_FUNCTION(Runtime_TypedArrayGetBuffer) { | |
| 1046 HandleScope scope(isolate); | |
| 1047 DCHECK(args.length() == 1); | |
| 1048 CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0); | |
| 1049 return *holder->GetBuffer(); | |
| 1050 } | |
| 1051 | |
| 1052 | |
| 1053 // Return codes for Runtime_TypedArraySetFastCases. | |
| 1054 // Should be synchronized with typedarray.js natives. | |
| 1055 enum TypedArraySetResultCodes { | |
| 1056 // Set from typed array of the same type. | |
| 1057 // This is processed by TypedArraySetFastCases | |
| 1058 TYPED_ARRAY_SET_TYPED_ARRAY_SAME_TYPE = 0, | |
| 1059 // Set from typed array of the different type, overlapping in memory. | |
| 1060 TYPED_ARRAY_SET_TYPED_ARRAY_OVERLAPPING = 1, | |
| 1061 // Set from typed array of the different type, non-overlapping. | |
| 1062 TYPED_ARRAY_SET_TYPED_ARRAY_NONOVERLAPPING = 2, | |
| 1063 // Set from non-typed array. | |
| 1064 TYPED_ARRAY_SET_NON_TYPED_ARRAY = 3 | |
| 1065 }; | |
| 1066 | |
| 1067 | |
| 1068 RUNTIME_FUNCTION(Runtime_TypedArraySetFastCases) { | |
| 1069 HandleScope scope(isolate); | |
| 1070 DCHECK(args.length() == 3); | |
| 1071 if (!args[0]->IsJSTypedArray()) { | |
| 1072 THROW_NEW_ERROR_RETURN_FAILURE( | |
| 1073 isolate, | |
| 1074 NewTypeError("not_typed_array", HandleVector<Object>(NULL, 0))); | |
| 1075 } | |
| 1076 | |
| 1077 if (!args[1]->IsJSTypedArray()) | |
| 1078 return Smi::FromInt(TYPED_ARRAY_SET_NON_TYPED_ARRAY); | |
| 1079 | |
| 1080 CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, target_obj, 0); | |
| 1081 CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, source_obj, 1); | |
| 1082 CONVERT_NUMBER_ARG_HANDLE_CHECKED(offset_obj, 2); | |
| 1083 | |
| 1084 Handle<JSTypedArray> target(JSTypedArray::cast(*target_obj)); | |
| 1085 Handle<JSTypedArray> source(JSTypedArray::cast(*source_obj)); | |
| 1086 size_t offset = 0; | |
| 1087 RUNTIME_ASSERT(TryNumberToSize(isolate, *offset_obj, &offset)); | |
| 1088 size_t target_length = NumberToSize(isolate, target->length()); | |
| 1089 size_t source_length = NumberToSize(isolate, source->length()); | |
| 1090 size_t target_byte_length = NumberToSize(isolate, target->byte_length()); | |
| 1091 size_t source_byte_length = NumberToSize(isolate, source->byte_length()); | |
| 1092 if (offset > target_length || offset + source_length > target_length || | |
| 1093 offset + source_length < offset) { // overflow | |
| 1094 THROW_NEW_ERROR_RETURN_FAILURE( | |
| 1095 isolate, NewRangeError("typed_array_set_source_too_large", | |
| 1096 HandleVector<Object>(NULL, 0))); | |
| 1097 } | |
| 1098 | |
| 1099 size_t target_offset = NumberToSize(isolate, target->byte_offset()); | |
| 1100 size_t source_offset = NumberToSize(isolate, source->byte_offset()); | |
| 1101 uint8_t* target_base = | |
| 1102 static_cast<uint8_t*>(target->GetBuffer()->backing_store()) + | |
| 1103 target_offset; | |
| 1104 uint8_t* source_base = | |
| 1105 static_cast<uint8_t*>(source->GetBuffer()->backing_store()) + | |
| 1106 source_offset; | |
| 1107 | |
| 1108 // Typed arrays of the same type: use memmove. | |
| 1109 if (target->type() == source->type()) { | |
| 1110 memmove(target_base + offset * target->element_size(), source_base, | |
| 1111 source_byte_length); | |
| 1112 return Smi::FromInt(TYPED_ARRAY_SET_TYPED_ARRAY_SAME_TYPE); | |
| 1113 } | |
| 1114 | |
| 1115 // Typed arrays of different types over the same backing store | |
| 1116 if ((source_base <= target_base && | |
| 1117 source_base + source_byte_length > target_base) || | |
| 1118 (target_base <= source_base && | |
| 1119 target_base + target_byte_length > source_base)) { | |
| 1120 // We do not support overlapping ArrayBuffers | |
| 1121 DCHECK(target->GetBuffer()->backing_store() == | |
| 1122 source->GetBuffer()->backing_store()); | |
| 1123 return Smi::FromInt(TYPED_ARRAY_SET_TYPED_ARRAY_OVERLAPPING); | |
| 1124 } else { // Non-overlapping typed arrays | |
| 1125 return Smi::FromInt(TYPED_ARRAY_SET_TYPED_ARRAY_NONOVERLAPPING); | |
| 1126 } | |
| 1127 } | |
| 1128 | |
| 1129 | |
| 1130 RUNTIME_FUNCTION(Runtime_TypedArrayMaxSizeInHeap) { | |
| 1131 DCHECK(args.length() == 0); | |
| 1132 DCHECK_OBJECT_SIZE(FLAG_typed_array_max_size_in_heap + | |
| 1133 FixedTypedArrayBase::kDataOffset); | |
| 1134 return Smi::FromInt(FLAG_typed_array_max_size_in_heap); | |
| 1135 } | |
| 1136 | |
| 1137 | |
| 1138 RUNTIME_FUNCTION(Runtime_DataViewInitialize) { | |
| 1139 HandleScope scope(isolate); | |
| 1140 DCHECK(args.length() == 4); | |
| 1141 CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0); | |
| 1142 CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, buffer, 1); | |
| 1143 CONVERT_NUMBER_ARG_HANDLE_CHECKED(byte_offset, 2); | |
| 1144 CONVERT_NUMBER_ARG_HANDLE_CHECKED(byte_length, 3); | |
| 1145 | |
| 1146 DCHECK(holder->GetInternalFieldCount() == | |
| 1147 v8::ArrayBufferView::kInternalFieldCount); | |
| 1148 for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) { | |
| 1149 holder->SetInternalField(i, Smi::FromInt(0)); | |
| 1150 } | |
| 1151 size_t buffer_length = 0; | |
| 1152 size_t offset = 0; | |
| 1153 size_t length = 0; | |
| 1154 RUNTIME_ASSERT( | |
| 1155 TryNumberToSize(isolate, buffer->byte_length(), &buffer_length)); | |
| 1156 RUNTIME_ASSERT(TryNumberToSize(isolate, *byte_offset, &offset)); | |
| 1157 RUNTIME_ASSERT(TryNumberToSize(isolate, *byte_length, &length)); | |
| 1158 | |
| 1159 // TODO(jkummerow): When we have a "safe numerics" helper class, use it here. | |
| 1160 // Entire range [offset, offset + length] must be in bounds. | |
| 1161 RUNTIME_ASSERT(offset <= buffer_length); | |
| 1162 RUNTIME_ASSERT(offset + length <= buffer_length); | |
| 1163 // No overflow. | |
| 1164 RUNTIME_ASSERT(offset + length >= offset); | |
| 1165 | |
| 1166 holder->set_buffer(*buffer); | |
| 1167 holder->set_byte_offset(*byte_offset); | |
| 1168 holder->set_byte_length(*byte_length); | |
| 1169 | |
| 1170 holder->set_weak_next(buffer->weak_first_view()); | |
| 1171 buffer->set_weak_first_view(*holder); | |
| 1172 | |
| 1173 return isolate->heap()->undefined_value(); | |
| 1174 } | |
| 1175 | |
| 1176 | |
| 1177 inline static bool NeedToFlipBytes(bool is_little_endian) { | |
| 1178 #ifdef V8_TARGET_LITTLE_ENDIAN | |
| 1179 return !is_little_endian; | |
| 1180 #else | |
| 1181 return is_little_endian; | |
| 1182 #endif | |
| 1183 } | |
| 1184 | |
| 1185 | |
| 1186 template <int n> | |
| 1187 inline void CopyBytes(uint8_t* target, uint8_t* source) { | |
| 1188 for (int i = 0; i < n; i++) { | |
| 1189 *(target++) = *(source++); | |
| 1190 } | |
| 1191 } | |
| 1192 | |
| 1193 | |
| 1194 template <int n> | |
| 1195 inline void FlipBytes(uint8_t* target, uint8_t* source) { | |
| 1196 source = source + (n - 1); | |
| 1197 for (int i = 0; i < n; i++) { | |
| 1198 *(target++) = *(source--); | |
| 1199 } | |
| 1200 } | |
| 1201 | |
| 1202 | |
| 1203 template <typename T> | |
| 1204 inline static bool DataViewGetValue(Isolate* isolate, | |
| 1205 Handle<JSDataView> data_view, | |
| 1206 Handle<Object> byte_offset_obj, | |
| 1207 bool is_little_endian, T* result) { | |
| 1208 size_t byte_offset = 0; | |
| 1209 if (!TryNumberToSize(isolate, *byte_offset_obj, &byte_offset)) { | |
| 1210 return false; | |
| 1211 } | |
| 1212 Handle<JSArrayBuffer> buffer(JSArrayBuffer::cast(data_view->buffer())); | |
| 1213 | |
| 1214 size_t data_view_byte_offset = | |
| 1215 NumberToSize(isolate, data_view->byte_offset()); | |
| 1216 size_t data_view_byte_length = | |
| 1217 NumberToSize(isolate, data_view->byte_length()); | |
| 1218 if (byte_offset + sizeof(T) > data_view_byte_length || | |
| 1219 byte_offset + sizeof(T) < byte_offset) { // overflow | |
| 1220 return false; | |
| 1221 } | |
| 1222 | |
| 1223 union Value { | |
| 1224 T data; | |
| 1225 uint8_t bytes[sizeof(T)]; | |
| 1226 }; | |
| 1227 | |
| 1228 Value value; | |
| 1229 size_t buffer_offset = data_view_byte_offset + byte_offset; | |
| 1230 DCHECK(NumberToSize(isolate, buffer->byte_length()) >= | |
| 1231 buffer_offset + sizeof(T)); | |
| 1232 uint8_t* source = | |
| 1233 static_cast<uint8_t*>(buffer->backing_store()) + buffer_offset; | |
| 1234 if (NeedToFlipBytes(is_little_endian)) { | |
| 1235 FlipBytes<sizeof(T)>(value.bytes, source); | |
| 1236 } else { | |
| 1237 CopyBytes<sizeof(T)>(value.bytes, source); | |
| 1238 } | |
| 1239 *result = value.data; | |
| 1240 return true; | |
| 1241 } | |
| 1242 | |
| 1243 | |
| 1244 template <typename T> | |
| 1245 static bool DataViewSetValue(Isolate* isolate, Handle<JSDataView> data_view, | |
| 1246 Handle<Object> byte_offset_obj, | |
| 1247 bool is_little_endian, T data) { | |
| 1248 size_t byte_offset = 0; | |
| 1249 if (!TryNumberToSize(isolate, *byte_offset_obj, &byte_offset)) { | |
| 1250 return false; | |
| 1251 } | |
| 1252 Handle<JSArrayBuffer> buffer(JSArrayBuffer::cast(data_view->buffer())); | |
| 1253 | |
| 1254 size_t data_view_byte_offset = | |
| 1255 NumberToSize(isolate, data_view->byte_offset()); | |
| 1256 size_t data_view_byte_length = | |
| 1257 NumberToSize(isolate, data_view->byte_length()); | |
| 1258 if (byte_offset + sizeof(T) > data_view_byte_length || | |
| 1259 byte_offset + sizeof(T) < byte_offset) { // overflow | |
| 1260 return false; | |
| 1261 } | |
| 1262 | |
| 1263 union Value { | |
| 1264 T data; | |
| 1265 uint8_t bytes[sizeof(T)]; | |
| 1266 }; | |
| 1267 | |
| 1268 Value value; | |
| 1269 value.data = data; | |
| 1270 size_t buffer_offset = data_view_byte_offset + byte_offset; | |
| 1271 DCHECK(NumberToSize(isolate, buffer->byte_length()) >= | |
| 1272 buffer_offset + sizeof(T)); | |
| 1273 uint8_t* target = | |
| 1274 static_cast<uint8_t*>(buffer->backing_store()) + buffer_offset; | |
| 1275 if (NeedToFlipBytes(is_little_endian)) { | |
| 1276 FlipBytes<sizeof(T)>(target, value.bytes); | |
| 1277 } else { | |
| 1278 CopyBytes<sizeof(T)>(target, value.bytes); | |
| 1279 } | |
| 1280 return true; | |
| 1281 } | |
| 1282 | |
| 1283 | |
| 1284 #define DATA_VIEW_GETTER(TypeName, Type, Converter) \ | |
| 1285 RUNTIME_FUNCTION(Runtime_DataViewGet##TypeName) { \ | |
| 1286 HandleScope scope(isolate); \ | |
| 1287 DCHECK(args.length() == 3); \ | |
| 1288 CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0); \ | |
| 1289 CONVERT_NUMBER_ARG_HANDLE_CHECKED(offset, 1); \ | |
| 1290 CONVERT_BOOLEAN_ARG_CHECKED(is_little_endian, 2); \ | |
| 1291 Type result; \ | |
| 1292 if (DataViewGetValue(isolate, holder, offset, is_little_endian, \ | |
| 1293 &result)) { \ | |
| 1294 return *isolate->factory()->Converter(result); \ | |
| 1295 } else { \ | |
| 1296 THROW_NEW_ERROR_RETURN_FAILURE( \ | |
| 1297 isolate, NewRangeError("invalid_data_view_accessor_offset", \ | |
| 1298 HandleVector<Object>(NULL, 0))); \ | |
| 1299 } \ | |
| 1300 } | |
| 1301 | |
| 1302 DATA_VIEW_GETTER(Uint8, uint8_t, NewNumberFromUint) | |
| 1303 DATA_VIEW_GETTER(Int8, int8_t, NewNumberFromInt) | |
| 1304 DATA_VIEW_GETTER(Uint16, uint16_t, NewNumberFromUint) | |
| 1305 DATA_VIEW_GETTER(Int16, int16_t, NewNumberFromInt) | |
| 1306 DATA_VIEW_GETTER(Uint32, uint32_t, NewNumberFromUint) | |
| 1307 DATA_VIEW_GETTER(Int32, int32_t, NewNumberFromInt) | |
| 1308 DATA_VIEW_GETTER(Float32, float, NewNumber) | |
| 1309 DATA_VIEW_GETTER(Float64, double, NewNumber) | |
| 1310 | |
| 1311 #undef DATA_VIEW_GETTER | |
| 1312 | |
| 1313 | |
| 1314 template <typename T> | |
| 1315 static T DataViewConvertValue(double value); | |
| 1316 | |
| 1317 | |
| 1318 template <> | |
| 1319 int8_t DataViewConvertValue<int8_t>(double value) { | |
| 1320 return static_cast<int8_t>(DoubleToInt32(value)); | |
| 1321 } | |
| 1322 | |
| 1323 | |
| 1324 template <> | |
| 1325 int16_t DataViewConvertValue<int16_t>(double value) { | |
| 1326 return static_cast<int16_t>(DoubleToInt32(value)); | |
| 1327 } | |
| 1328 | |
| 1329 | |
| 1330 template <> | |
| 1331 int32_t DataViewConvertValue<int32_t>(double value) { | |
| 1332 return DoubleToInt32(value); | |
| 1333 } | |
| 1334 | |
| 1335 | |
| 1336 template <> | |
| 1337 uint8_t DataViewConvertValue<uint8_t>(double value) { | |
| 1338 return static_cast<uint8_t>(DoubleToUint32(value)); | |
| 1339 } | |
| 1340 | |
| 1341 | |
| 1342 template <> | |
| 1343 uint16_t DataViewConvertValue<uint16_t>(double value) { | |
| 1344 return static_cast<uint16_t>(DoubleToUint32(value)); | |
| 1345 } | |
| 1346 | |
| 1347 | |
| 1348 template <> | |
| 1349 uint32_t DataViewConvertValue<uint32_t>(double value) { | |
| 1350 return DoubleToUint32(value); | |
| 1351 } | |
| 1352 | |
| 1353 | |
| 1354 template <> | |
| 1355 float DataViewConvertValue<float>(double value) { | |
| 1356 return static_cast<float>(value); | |
| 1357 } | |
| 1358 | |
| 1359 | |
| 1360 template <> | |
| 1361 double DataViewConvertValue<double>(double value) { | |
| 1362 return value; | |
| 1363 } | |
| 1364 | |
| 1365 | |
| 1366 #define DATA_VIEW_SETTER(TypeName, Type) \ | |
| 1367 RUNTIME_FUNCTION(Runtime_DataViewSet##TypeName) { \ | |
| 1368 HandleScope scope(isolate); \ | |
| 1369 DCHECK(args.length() == 4); \ | |
| 1370 CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0); \ | |
| 1371 CONVERT_NUMBER_ARG_HANDLE_CHECKED(offset, 1); \ | |
| 1372 CONVERT_NUMBER_ARG_HANDLE_CHECKED(value, 2); \ | |
| 1373 CONVERT_BOOLEAN_ARG_CHECKED(is_little_endian, 3); \ | |
| 1374 Type v = DataViewConvertValue<Type>(value->Number()); \ | |
| 1375 if (DataViewSetValue(isolate, holder, offset, is_little_endian, v)) { \ | |
| 1376 return isolate->heap()->undefined_value(); \ | |
| 1377 } else { \ | |
| 1378 THROW_NEW_ERROR_RETURN_FAILURE( \ | |
| 1379 isolate, NewRangeError("invalid_data_view_accessor_offset", \ | |
| 1380 HandleVector<Object>(NULL, 0))); \ | |
| 1381 } \ | |
| 1382 } | |
| 1383 | |
| 1384 DATA_VIEW_SETTER(Uint8, uint8_t) | |
| 1385 DATA_VIEW_SETTER(Int8, int8_t) | |
| 1386 DATA_VIEW_SETTER(Uint16, uint16_t) | |
| 1387 DATA_VIEW_SETTER(Int16, int16_t) | |
| 1388 DATA_VIEW_SETTER(Uint32, uint32_t) | |
| 1389 DATA_VIEW_SETTER(Int32, int32_t) | |
| 1390 DATA_VIEW_SETTER(Float32, float) | |
| 1391 DATA_VIEW_SETTER(Float64, double) | |
| 1392 | |
| 1393 #undef DATA_VIEW_SETTER | |
| 1394 | |
| 1395 | |
| 1396 RUNTIME_FUNCTION(Runtime_SetInitialize) { | |
| 1397 HandleScope scope(isolate); | |
| 1398 DCHECK(args.length() == 1); | |
| 1399 CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0); | |
| 1400 Handle<OrderedHashSet> table = isolate->factory()->NewOrderedHashSet(); | |
| 1401 holder->set_table(*table); | |
| 1402 return *holder; | |
| 1403 } | |
| 1404 | |
| 1405 | |
| 1406 RUNTIME_FUNCTION(Runtime_SetAdd) { | |
| 1407 HandleScope scope(isolate); | |
| 1408 DCHECK(args.length() == 2); | |
| 1409 CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0); | |
| 1410 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1); | |
| 1411 Handle<OrderedHashSet> table(OrderedHashSet::cast(holder->table())); | |
| 1412 table = OrderedHashSet::Add(table, key); | |
| 1413 holder->set_table(*table); | |
| 1414 return *holder; | |
| 1415 } | |
| 1416 | |
| 1417 | |
| 1418 RUNTIME_FUNCTION(Runtime_SetHas) { | |
| 1419 HandleScope scope(isolate); | |
| 1420 DCHECK(args.length() == 2); | |
| 1421 CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0); | |
| 1422 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1); | |
| 1423 Handle<OrderedHashSet> table(OrderedHashSet::cast(holder->table())); | |
| 1424 return isolate->heap()->ToBoolean(table->Contains(key)); | |
| 1425 } | |
| 1426 | |
| 1427 | |
| 1428 RUNTIME_FUNCTION(Runtime_SetDelete) { | |
| 1429 HandleScope scope(isolate); | |
| 1430 DCHECK(args.length() == 2); | |
| 1431 CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0); | |
| 1432 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1); | |
| 1433 Handle<OrderedHashSet> table(OrderedHashSet::cast(holder->table())); | |
| 1434 bool was_present = false; | |
| 1435 table = OrderedHashSet::Remove(table, key, &was_present); | |
| 1436 holder->set_table(*table); | |
| 1437 return isolate->heap()->ToBoolean(was_present); | |
| 1438 } | |
| 1439 | |
| 1440 | |
| 1441 RUNTIME_FUNCTION(Runtime_SetClear) { | |
| 1442 HandleScope scope(isolate); | |
| 1443 DCHECK(args.length() == 1); | |
| 1444 CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0); | |
| 1445 Handle<OrderedHashSet> table(OrderedHashSet::cast(holder->table())); | |
| 1446 table = OrderedHashSet::Clear(table); | |
| 1447 holder->set_table(*table); | |
| 1448 return isolate->heap()->undefined_value(); | |
| 1449 } | |
| 1450 | |
| 1451 | |
| 1452 RUNTIME_FUNCTION(Runtime_SetGetSize) { | |
| 1453 HandleScope scope(isolate); | |
| 1454 DCHECK(args.length() == 1); | |
| 1455 CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0); | |
| 1456 Handle<OrderedHashSet> table(OrderedHashSet::cast(holder->table())); | |
| 1457 return Smi::FromInt(table->NumberOfElements()); | |
| 1458 } | |
| 1459 | |
| 1460 | |
| 1461 RUNTIME_FUNCTION(Runtime_SetIteratorInitialize) { | |
| 1462 HandleScope scope(isolate); | |
| 1463 DCHECK(args.length() == 3); | |
| 1464 CONVERT_ARG_HANDLE_CHECKED(JSSetIterator, holder, 0); | |
| 1465 CONVERT_ARG_HANDLE_CHECKED(JSSet, set, 1); | |
| 1466 CONVERT_SMI_ARG_CHECKED(kind, 2) | |
| 1467 RUNTIME_ASSERT(kind == JSSetIterator::kKindValues || | |
| 1468 kind == JSSetIterator::kKindEntries); | |
| 1469 Handle<OrderedHashSet> table(OrderedHashSet::cast(set->table())); | |
| 1470 holder->set_table(*table); | |
| 1471 holder->set_index(Smi::FromInt(0)); | |
| 1472 holder->set_kind(Smi::FromInt(kind)); | |
| 1473 return isolate->heap()->undefined_value(); | |
| 1474 } | |
| 1475 | |
| 1476 | |
| 1477 RUNTIME_FUNCTION(Runtime_SetIteratorNext) { | |
| 1478 SealHandleScope shs(isolate); | |
| 1479 DCHECK(args.length() == 2); | |
| 1480 CONVERT_ARG_CHECKED(JSSetIterator, holder, 0); | |
| 1481 CONVERT_ARG_CHECKED(JSArray, value_array, 1); | |
| 1482 return holder->Next(value_array); | |
| 1483 } | |
| 1484 | |
| 1485 | |
| 1486 RUNTIME_FUNCTION(Runtime_MapInitialize) { | |
| 1487 HandleScope scope(isolate); | |
| 1488 DCHECK(args.length() == 1); | |
| 1489 CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0); | |
| 1490 Handle<OrderedHashMap> table = isolate->factory()->NewOrderedHashMap(); | |
| 1491 holder->set_table(*table); | |
| 1492 return *holder; | |
| 1493 } | |
| 1494 | |
| 1495 | |
| 1496 RUNTIME_FUNCTION(Runtime_MapGet) { | |
| 1497 HandleScope scope(isolate); | |
| 1498 DCHECK(args.length() == 2); | |
| 1499 CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0); | |
| 1500 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1); | |
| 1501 Handle<OrderedHashMap> table(OrderedHashMap::cast(holder->table())); | |
| 1502 Handle<Object> lookup(table->Lookup(key), isolate); | |
| 1503 return lookup->IsTheHole() ? isolate->heap()->undefined_value() : *lookup; | |
| 1504 } | |
| 1505 | |
| 1506 | |
| 1507 RUNTIME_FUNCTION(Runtime_MapHas) { | |
| 1508 HandleScope scope(isolate); | |
| 1509 DCHECK(args.length() == 2); | |
| 1510 CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0); | |
| 1511 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1); | |
| 1512 Handle<OrderedHashMap> table(OrderedHashMap::cast(holder->table())); | |
| 1513 Handle<Object> lookup(table->Lookup(key), isolate); | |
| 1514 return isolate->heap()->ToBoolean(!lookup->IsTheHole()); | |
| 1515 } | |
| 1516 | |
| 1517 | |
| 1518 RUNTIME_FUNCTION(Runtime_MapDelete) { | |
| 1519 HandleScope scope(isolate); | |
| 1520 DCHECK(args.length() == 2); | |
| 1521 CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0); | |
| 1522 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1); | |
| 1523 Handle<OrderedHashMap> table(OrderedHashMap::cast(holder->table())); | |
| 1524 bool was_present = false; | |
| 1525 Handle<OrderedHashMap> new_table = | |
| 1526 OrderedHashMap::Remove(table, key, &was_present); | |
| 1527 holder->set_table(*new_table); | |
| 1528 return isolate->heap()->ToBoolean(was_present); | |
| 1529 } | |
| 1530 | |
| 1531 | |
| 1532 RUNTIME_FUNCTION(Runtime_MapClear) { | |
| 1533 HandleScope scope(isolate); | |
| 1534 DCHECK(args.length() == 1); | |
| 1535 CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0); | |
| 1536 Handle<OrderedHashMap> table(OrderedHashMap::cast(holder->table())); | |
| 1537 table = OrderedHashMap::Clear(table); | |
| 1538 holder->set_table(*table); | |
| 1539 return isolate->heap()->undefined_value(); | |
| 1540 } | |
| 1541 | |
| 1542 | |
| 1543 RUNTIME_FUNCTION(Runtime_MapSet) { | |
| 1544 HandleScope scope(isolate); | |
| 1545 DCHECK(args.length() == 3); | |
| 1546 CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0); | |
| 1547 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1); | |
| 1548 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2); | |
| 1549 Handle<OrderedHashMap> table(OrderedHashMap::cast(holder->table())); | |
| 1550 Handle<OrderedHashMap> new_table = OrderedHashMap::Put(table, key, value); | |
| 1551 holder->set_table(*new_table); | |
| 1552 return *holder; | |
| 1553 } | |
| 1554 | |
| 1555 | |
| 1556 RUNTIME_FUNCTION(Runtime_MapGetSize) { | |
| 1557 HandleScope scope(isolate); | |
| 1558 DCHECK(args.length() == 1); | |
| 1559 CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0); | |
| 1560 Handle<OrderedHashMap> table(OrderedHashMap::cast(holder->table())); | |
| 1561 return Smi::FromInt(table->NumberOfElements()); | |
| 1562 } | |
| 1563 | |
| 1564 | |
| 1565 RUNTIME_FUNCTION(Runtime_MapIteratorInitialize) { | |
| 1566 HandleScope scope(isolate); | |
| 1567 DCHECK(args.length() == 3); | |
| 1568 CONVERT_ARG_HANDLE_CHECKED(JSMapIterator, holder, 0); | |
| 1569 CONVERT_ARG_HANDLE_CHECKED(JSMap, map, 1); | |
| 1570 CONVERT_SMI_ARG_CHECKED(kind, 2) | |
| 1571 RUNTIME_ASSERT(kind == JSMapIterator::kKindKeys || | |
| 1572 kind == JSMapIterator::kKindValues || | |
| 1573 kind == JSMapIterator::kKindEntries); | |
| 1574 Handle<OrderedHashMap> table(OrderedHashMap::cast(map->table())); | |
| 1575 holder->set_table(*table); | |
| 1576 holder->set_index(Smi::FromInt(0)); | |
| 1577 holder->set_kind(Smi::FromInt(kind)); | |
| 1578 return isolate->heap()->undefined_value(); | |
| 1579 } | |
| 1580 | |
| 1581 | |
| 1582 RUNTIME_FUNCTION(Runtime_GetWeakMapEntries) { | |
| 1583 HandleScope scope(isolate); | |
| 1584 DCHECK(args.length() == 1); | |
| 1585 CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, holder, 0); | |
| 1586 Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table())); | |
| 1587 Handle<FixedArray> entries = | |
| 1588 isolate->factory()->NewFixedArray(table->NumberOfElements() * 2); | |
| 1589 { | |
| 1590 DisallowHeapAllocation no_gc; | |
| 1591 int number_of_non_hole_elements = 0; | |
| 1592 for (int i = 0; i < table->Capacity(); i++) { | |
| 1593 Handle<Object> key(table->KeyAt(i), isolate); | |
| 1594 if (table->IsKey(*key)) { | |
| 1595 entries->set(number_of_non_hole_elements++, *key); | |
| 1596 Object* value = table->Lookup(key); | |
| 1597 entries->set(number_of_non_hole_elements++, value); | |
| 1598 } | |
| 1599 } | |
| 1600 DCHECK_EQ(table->NumberOfElements() * 2, number_of_non_hole_elements); | |
| 1601 } | |
| 1602 return *isolate->factory()->NewJSArrayWithElements(entries); | |
| 1603 } | |
| 1604 | |
| 1605 | |
| 1606 RUNTIME_FUNCTION(Runtime_MapIteratorNext) { | |
| 1607 SealHandleScope shs(isolate); | |
| 1608 DCHECK(args.length() == 2); | |
| 1609 CONVERT_ARG_CHECKED(JSMapIterator, holder, 0); | |
| 1610 CONVERT_ARG_CHECKED(JSArray, value_array, 1); | |
| 1611 return holder->Next(value_array); | |
| 1612 } | |
| 1613 | |
| 1614 | |
| 1615 static Handle<JSWeakCollection> WeakCollectionInitialize( | |
| 1616 Isolate* isolate, Handle<JSWeakCollection> weak_collection) { | |
| 1617 DCHECK(weak_collection->map()->inobject_properties() == 0); | |
| 1618 Handle<ObjectHashTable> table = ObjectHashTable::New(isolate, 0); | |
| 1619 weak_collection->set_table(*table); | |
| 1620 return weak_collection; | |
| 1621 } | |
| 1622 | |
| 1623 | |
| 1624 RUNTIME_FUNCTION(Runtime_WeakCollectionInitialize) { | |
| 1625 HandleScope scope(isolate); | |
| 1626 DCHECK(args.length() == 1); | |
| 1627 CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0); | |
| 1628 return *WeakCollectionInitialize(isolate, weak_collection); | |
| 1629 } | |
| 1630 | |
| 1631 | |
| 1632 RUNTIME_FUNCTION(Runtime_WeakCollectionGet) { | |
| 1633 HandleScope scope(isolate); | |
| 1634 DCHECK(args.length() == 2); | |
| 1635 CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0); | |
| 1636 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1); | |
| 1637 RUNTIME_ASSERT(key->IsJSReceiver() || key->IsSymbol()); | |
| 1638 Handle<ObjectHashTable> table( | |
| 1639 ObjectHashTable::cast(weak_collection->table())); | |
| 1640 RUNTIME_ASSERT(table->IsKey(*key)); | |
| 1641 Handle<Object> lookup(table->Lookup(key), isolate); | |
| 1642 return lookup->IsTheHole() ? isolate->heap()->undefined_value() : *lookup; | |
| 1643 } | |
| 1644 | |
| 1645 | |
| 1646 RUNTIME_FUNCTION(Runtime_WeakCollectionHas) { | |
| 1647 HandleScope scope(isolate); | |
| 1648 DCHECK(args.length() == 2); | |
| 1649 CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0); | |
| 1650 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1); | |
| 1651 RUNTIME_ASSERT(key->IsJSReceiver() || key->IsSymbol()); | |
| 1652 Handle<ObjectHashTable> table( | |
| 1653 ObjectHashTable::cast(weak_collection->table())); | |
| 1654 RUNTIME_ASSERT(table->IsKey(*key)); | |
| 1655 Handle<Object> lookup(table->Lookup(key), isolate); | |
| 1656 return isolate->heap()->ToBoolean(!lookup->IsTheHole()); | |
| 1657 } | |
| 1658 | |
| 1659 | |
| 1660 RUNTIME_FUNCTION(Runtime_WeakCollectionDelete) { | |
| 1661 HandleScope scope(isolate); | |
| 1662 DCHECK(args.length() == 2); | |
| 1663 CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0); | |
| 1664 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1); | |
| 1665 RUNTIME_ASSERT(key->IsJSReceiver() || key->IsSymbol()); | |
| 1666 Handle<ObjectHashTable> table( | |
| 1667 ObjectHashTable::cast(weak_collection->table())); | |
| 1668 RUNTIME_ASSERT(table->IsKey(*key)); | |
| 1669 bool was_present = false; | |
| 1670 Handle<ObjectHashTable> new_table = | |
| 1671 ObjectHashTable::Remove(table, key, &was_present); | |
| 1672 weak_collection->set_table(*new_table); | |
| 1673 return isolate->heap()->ToBoolean(was_present); | |
| 1674 } | |
| 1675 | |
| 1676 | |
| 1677 RUNTIME_FUNCTION(Runtime_WeakCollectionSet) { | |
| 1678 HandleScope scope(isolate); | |
| 1679 DCHECK(args.length() == 3); | |
| 1680 CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0); | |
| 1681 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1); | |
| 1682 RUNTIME_ASSERT(key->IsJSReceiver() || key->IsSymbol()); | |
| 1683 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2); | |
| 1684 Handle<ObjectHashTable> table( | |
| 1685 ObjectHashTable::cast(weak_collection->table())); | |
| 1686 RUNTIME_ASSERT(table->IsKey(*key)); | |
| 1687 Handle<ObjectHashTable> new_table = ObjectHashTable::Put(table, key, value); | |
| 1688 weak_collection->set_table(*new_table); | |
| 1689 return *weak_collection; | |
| 1690 } | |
| 1691 | |
| 1692 | |
| 1693 RUNTIME_FUNCTION(Runtime_GetWeakSetValues) { | |
| 1694 HandleScope scope(isolate); | |
| 1695 DCHECK(args.length() == 1); | |
| 1696 CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, holder, 0); | |
| 1697 Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table())); | |
| 1698 Handle<FixedArray> values = | |
| 1699 isolate->factory()->NewFixedArray(table->NumberOfElements()); | |
| 1700 { | |
| 1701 DisallowHeapAllocation no_gc; | |
| 1702 int number_of_non_hole_elements = 0; | |
| 1703 for (int i = 0; i < table->Capacity(); i++) { | |
| 1704 Handle<Object> key(table->KeyAt(i), isolate); | |
| 1705 if (table->IsKey(*key)) { | |
| 1706 values->set(number_of_non_hole_elements++, *key); | |
| 1707 } | |
| 1708 } | |
| 1709 DCHECK_EQ(table->NumberOfElements(), number_of_non_hole_elements); | |
| 1710 } | |
| 1711 return *isolate->factory()->NewJSArrayWithElements(values); | |
| 1712 } | |
| 1713 | |
| 1714 | |
| 1715 RUNTIME_FUNCTION(Runtime_GetPrototype) { | 643 RUNTIME_FUNCTION(Runtime_GetPrototype) { |
| 1716 HandleScope scope(isolate); | 644 HandleScope scope(isolate); |
| 1717 DCHECK(args.length() == 1); | 645 DCHECK(args.length() == 1); |
| 1718 CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0); | 646 CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0); |
| 1719 // We don't expect access checks to be needed on JSProxy objects. | 647 // We don't expect access checks to be needed on JSProxy objects. |
| 1720 DCHECK(!obj->IsAccessCheckNeeded() || obj->IsJSObject()); | 648 DCHECK(!obj->IsAccessCheckNeeded() || obj->IsJSObject()); |
| 1721 PrototypeIterator iter(isolate, obj, PrototypeIterator::START_AT_RECEIVER); | 649 PrototypeIterator iter(isolate, obj, PrototypeIterator::START_AT_RECEIVER); |
| 1722 do { | 650 do { |
| 1723 if (PrototypeIterator::GetCurrent(iter)->IsAccessCheckNeeded() && | 651 if (PrototypeIterator::GetCurrent(iter)->IsAccessCheckNeeded() && |
| 1724 !isolate->MayNamedAccess( | 652 !isolate->MayNamedAccess( |
| (...skipping 1127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2852 // %ObjectFreeze is a fast path and these cases are handled elsewhere. | 1780 // %ObjectFreeze is a fast path and these cases are handled elsewhere. |
| 2853 RUNTIME_ASSERT(!object->HasSloppyArgumentsElements() && | 1781 RUNTIME_ASSERT(!object->HasSloppyArgumentsElements() && |
| 2854 !object->map()->is_observed() && !object->IsJSProxy()); | 1782 !object->map()->is_observed() && !object->IsJSProxy()); |
| 2855 | 1783 |
| 2856 Handle<Object> result; | 1784 Handle<Object> result; |
| 2857 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, JSObject::Freeze(object)); | 1785 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, JSObject::Freeze(object)); |
| 2858 return *result; | 1786 return *result; |
| 2859 } | 1787 } |
| 2860 | 1788 |
| 2861 | 1789 |
| 2862 RUNTIME_FUNCTION(Runtime_NumberToRadixString) { | |
| 2863 HandleScope scope(isolate); | |
| 2864 DCHECK(args.length() == 2); | |
| 2865 CONVERT_SMI_ARG_CHECKED(radix, 1); | |
| 2866 RUNTIME_ASSERT(2 <= radix && radix <= 36); | |
| 2867 | |
| 2868 // Fast case where the result is a one character string. | |
| 2869 if (args[0]->IsSmi()) { | |
| 2870 int value = args.smi_at(0); | |
| 2871 if (value >= 0 && value < radix) { | |
| 2872 // Character array used for conversion. | |
| 2873 static const char kCharTable[] = "0123456789abcdefghijklmnopqrstuvwxyz"; | |
| 2874 return *isolate->factory()->LookupSingleCharacterStringFromCode( | |
| 2875 kCharTable[value]); | |
| 2876 } | |
| 2877 } | |
| 2878 | |
| 2879 // Slow case. | |
| 2880 CONVERT_DOUBLE_ARG_CHECKED(value, 0); | |
| 2881 if (std::isnan(value)) { | |
| 2882 return isolate->heap()->nan_string(); | |
| 2883 } | |
| 2884 if (std::isinf(value)) { | |
| 2885 if (value < 0) { | |
| 2886 return isolate->heap()->minus_infinity_string(); | |
| 2887 } | |
| 2888 return isolate->heap()->infinity_string(); | |
| 2889 } | |
| 2890 char* str = DoubleToRadixCString(value, radix); | |
| 2891 Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str); | |
| 2892 DeleteArray(str); | |
| 2893 return *result; | |
| 2894 } | |
| 2895 | |
| 2896 | |
| 2897 RUNTIME_FUNCTION(Runtime_NumberToFixed) { | |
| 2898 HandleScope scope(isolate); | |
| 2899 DCHECK(args.length() == 2); | |
| 2900 | |
| 2901 CONVERT_DOUBLE_ARG_CHECKED(value, 0); | |
| 2902 CONVERT_DOUBLE_ARG_CHECKED(f_number, 1); | |
| 2903 int f = FastD2IChecked(f_number); | |
| 2904 // See DoubleToFixedCString for these constants: | |
| 2905 RUNTIME_ASSERT(f >= 0 && f <= 20); | |
| 2906 RUNTIME_ASSERT(!Double(value).IsSpecial()); | |
| 2907 char* str = DoubleToFixedCString(value, f); | |
| 2908 Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str); | |
| 2909 DeleteArray(str); | |
| 2910 return *result; | |
| 2911 } | |
| 2912 | |
| 2913 | |
| 2914 RUNTIME_FUNCTION(Runtime_NumberToExponential) { | |
| 2915 HandleScope scope(isolate); | |
| 2916 DCHECK(args.length() == 2); | |
| 2917 | |
| 2918 CONVERT_DOUBLE_ARG_CHECKED(value, 0); | |
| 2919 CONVERT_DOUBLE_ARG_CHECKED(f_number, 1); | |
| 2920 int f = FastD2IChecked(f_number); | |
| 2921 RUNTIME_ASSERT(f >= -1 && f <= 20); | |
| 2922 RUNTIME_ASSERT(!Double(value).IsSpecial()); | |
| 2923 char* str = DoubleToExponentialCString(value, f); | |
| 2924 Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str); | |
| 2925 DeleteArray(str); | |
| 2926 return *result; | |
| 2927 } | |
| 2928 | |
| 2929 | |
| 2930 RUNTIME_FUNCTION(Runtime_NumberToPrecision) { | |
| 2931 HandleScope scope(isolate); | |
| 2932 DCHECK(args.length() == 2); | |
| 2933 | |
| 2934 CONVERT_DOUBLE_ARG_CHECKED(value, 0); | |
| 2935 CONVERT_DOUBLE_ARG_CHECKED(f_number, 1); | |
| 2936 int f = FastD2IChecked(f_number); | |
| 2937 RUNTIME_ASSERT(f >= 1 && f <= 21); | |
| 2938 RUNTIME_ASSERT(!Double(value).IsSpecial()); | |
| 2939 char* str = DoubleToPrecisionCString(value, f); | |
| 2940 Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str); | |
| 2941 DeleteArray(str); | |
| 2942 return *result; | |
| 2943 } | |
| 2944 | |
| 2945 | |
| 2946 RUNTIME_FUNCTION(Runtime_IsValidSmi) { | |
| 2947 SealHandleScope shs(isolate); | |
| 2948 DCHECK(args.length() == 1); | |
| 2949 | |
| 2950 CONVERT_NUMBER_CHECKED(int32_t, number, Int32, args[0]); | |
| 2951 return isolate->heap()->ToBoolean(Smi::IsValid(number)); | |
| 2952 } | |
| 2953 | |
| 2954 | |
| 2955 // Returns a single character string where first character equals | 1790 // Returns a single character string where first character equals |
| 2956 // string->Get(index). | 1791 // string->Get(index). |
| 2957 static Handle<Object> GetCharAt(Handle<String> string, uint32_t index) { | 1792 static Handle<Object> GetCharAt(Handle<String> string, uint32_t index) { |
| 2958 if (index < static_cast<uint32_t>(string->length())) { | 1793 if (index < static_cast<uint32_t>(string->length())) { |
| 2959 Factory* factory = string->GetIsolate()->factory(); | 1794 Factory* factory = string->GetIsolate()->factory(); |
| 2960 return factory->LookupSingleCharacterStringFromCode( | 1795 return factory->LookupSingleCharacterStringFromCode( |
| 2961 String::Flatten(string)->Get(index)); | 1796 String::Flatten(string)->Get(index)); |
| 2962 } | 1797 } |
| 2963 return Execution::CharAt(string, index); | 1798 return Execution::CharAt(string, index); |
| 2964 } | 1799 } |
| (...skipping 1403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4368 return isolate->heap()->ToBoolean(value <= 0); | 3203 return isolate->heap()->ToBoolean(value <= 0); |
| 4369 case Token::GTE: | 3204 case Token::GTE: |
| 4370 return isolate->heap()->ToBoolean(value >= 0); | 3205 return isolate->heap()->ToBoolean(value >= 0); |
| 4371 default: | 3206 default: |
| 4372 // This should only happen during natives fuzzing. | 3207 // This should only happen during natives fuzzing. |
| 4373 return isolate->heap()->undefined_value(); | 3208 return isolate->heap()->undefined_value(); |
| 4374 } | 3209 } |
| 4375 } | 3210 } |
| 4376 | 3211 |
| 4377 | 3212 |
| 4378 static bool AreDigits(const uint8_t* s, int from, int to) { | |
| 4379 for (int i = from; i < to; i++) { | |
| 4380 if (s[i] < '0' || s[i] > '9') return false; | |
| 4381 } | |
| 4382 | |
| 4383 return true; | |
| 4384 } | |
| 4385 | |
| 4386 | |
| 4387 static int ParseDecimalInteger(const uint8_t* s, int from, int to) { | |
| 4388 DCHECK(to - from < 10); // Overflow is not possible. | |
| 4389 DCHECK(from < to); | |
| 4390 int d = s[from] - '0'; | |
| 4391 | |
| 4392 for (int i = from + 1; i < to; i++) { | |
| 4393 d = 10 * d + (s[i] - '0'); | |
| 4394 } | |
| 4395 | |
| 4396 return d; | |
| 4397 } | |
| 4398 | |
| 4399 | |
| 4400 RUNTIME_FUNCTION(Runtime_StringToNumber) { | |
| 4401 HandleScope handle_scope(isolate); | |
| 4402 DCHECK(args.length() == 1); | |
| 4403 CONVERT_ARG_HANDLE_CHECKED(String, subject, 0); | |
| 4404 subject = String::Flatten(subject); | |
| 4405 | |
| 4406 // Fast case: short integer or some sorts of junk values. | |
| 4407 if (subject->IsSeqOneByteString()) { | |
| 4408 int len = subject->length(); | |
| 4409 if (len == 0) return Smi::FromInt(0); | |
| 4410 | |
| 4411 DisallowHeapAllocation no_gc; | |
| 4412 uint8_t const* data = Handle<SeqOneByteString>::cast(subject)->GetChars(); | |
| 4413 bool minus = (data[0] == '-'); | |
| 4414 int start_pos = (minus ? 1 : 0); | |
| 4415 | |
| 4416 if (start_pos == len) { | |
| 4417 return isolate->heap()->nan_value(); | |
| 4418 } else if (data[start_pos] > '9') { | |
| 4419 // Fast check for a junk value. A valid string may start from a | |
| 4420 // whitespace, a sign ('+' or '-'), the decimal point, a decimal digit | |
| 4421 // or the 'I' character ('Infinity'). All of that have codes not greater | |
| 4422 // than '9' except 'I' and . | |
| 4423 if (data[start_pos] != 'I' && data[start_pos] != 0xa0) { | |
| 4424 return isolate->heap()->nan_value(); | |
| 4425 } | |
| 4426 } else if (len - start_pos < 10 && AreDigits(data, start_pos, len)) { | |
| 4427 // The maximal/minimal smi has 10 digits. If the string has less digits | |
| 4428 // we know it will fit into the smi-data type. | |
| 4429 int d = ParseDecimalInteger(data, start_pos, len); | |
| 4430 if (minus) { | |
| 4431 if (d == 0) return isolate->heap()->minus_zero_value(); | |
| 4432 d = -d; | |
| 4433 } else if (!subject->HasHashCode() && len <= String::kMaxArrayIndexSize && | |
| 4434 (len == 1 || data[0] != '0')) { | |
| 4435 // String hash is not calculated yet but all the data are present. | |
| 4436 // Update the hash field to speed up sequential convertions. | |
| 4437 uint32_t hash = StringHasher::MakeArrayIndexHash(d, len); | |
| 4438 #ifdef DEBUG | |
| 4439 subject->Hash(); // Force hash calculation. | |
| 4440 DCHECK_EQ(static_cast<int>(subject->hash_field()), | |
| 4441 static_cast<int>(hash)); | |
| 4442 #endif | |
| 4443 subject->set_hash_field(hash); | |
| 4444 } | |
| 4445 return Smi::FromInt(d); | |
| 4446 } | |
| 4447 } | |
| 4448 | |
| 4449 // Slower case. | |
| 4450 int flags = ALLOW_HEX; | |
| 4451 if (FLAG_harmony_numeric_literals) { | |
| 4452 // The current spec draft has not updated "ToNumber Applied to the String | |
| 4453 // Type", https://bugs.ecmascript.org/show_bug.cgi?id=1584 | |
| 4454 flags |= ALLOW_OCTAL | ALLOW_BINARY; | |
| 4455 } | |
| 4456 | |
| 4457 return *isolate->factory()->NewNumber( | |
| 4458 StringToDouble(isolate->unicode_cache(), *subject, flags)); | |
| 4459 } | |
| 4460 | |
| 4461 | |
| 4462 RUNTIME_FUNCTION(Runtime_StringParseInt) { | |
| 4463 HandleScope handle_scope(isolate); | |
| 4464 DCHECK(args.length() == 2); | |
| 4465 CONVERT_ARG_HANDLE_CHECKED(String, subject, 0); | |
| 4466 CONVERT_NUMBER_CHECKED(int, radix, Int32, args[1]); | |
| 4467 RUNTIME_ASSERT(radix == 0 || (2 <= radix && radix <= 36)); | |
| 4468 | |
| 4469 subject = String::Flatten(subject); | |
| 4470 double value; | |
| 4471 | |
| 4472 { | |
| 4473 DisallowHeapAllocation no_gc; | |
| 4474 String::FlatContent flat = subject->GetFlatContent(); | |
| 4475 | |
| 4476 // ECMA-262 section 15.1.2.3, empty string is NaN | |
| 4477 if (flat.IsOneByte()) { | |
| 4478 value = | |
| 4479 StringToInt(isolate->unicode_cache(), flat.ToOneByteVector(), radix); | |
| 4480 } else { | |
| 4481 value = StringToInt(isolate->unicode_cache(), flat.ToUC16Vector(), radix); | |
| 4482 } | |
| 4483 } | |
| 4484 | |
| 4485 return *isolate->factory()->NewNumber(value); | |
| 4486 } | |
| 4487 | |
| 4488 | |
| 4489 RUNTIME_FUNCTION(Runtime_StringParseFloat) { | |
| 4490 HandleScope shs(isolate); | |
| 4491 DCHECK(args.length() == 1); | |
| 4492 CONVERT_ARG_HANDLE_CHECKED(String, subject, 0); | |
| 4493 | |
| 4494 subject = String::Flatten(subject); | |
| 4495 double value = StringToDouble(isolate->unicode_cache(), *subject, | |
| 4496 ALLOW_TRAILING_JUNK, base::OS::nan_value()); | |
| 4497 | |
| 4498 return *isolate->factory()->NewNumber(value); | |
| 4499 } | |
| 4500 | |
| 4501 | |
| 4502 RUNTIME_FUNCTION(Runtime_NewStringWrapper) { | 3213 RUNTIME_FUNCTION(Runtime_NewStringWrapper) { |
| 4503 HandleScope scope(isolate); | 3214 HandleScope scope(isolate); |
| 4504 DCHECK(args.length() == 1); | 3215 DCHECK(args.length() == 1); |
| 4505 CONVERT_ARG_HANDLE_CHECKED(String, value, 0); | 3216 CONVERT_ARG_HANDLE_CHECKED(String, value, 0); |
| 4506 return *Object::ToObject(isolate, value).ToHandleChecked(); | 3217 return *Object::ToObject(isolate, value).ToHandleChecked(); |
| 4507 } | 3218 } |
| 4508 | 3219 |
| 4509 | 3220 |
| 4510 RUNTIME_FUNCTION(Runtime_NumberToStringRT) { | |
| 4511 HandleScope scope(isolate); | |
| 4512 DCHECK(args.length() == 1); | |
| 4513 CONVERT_NUMBER_ARG_HANDLE_CHECKED(number, 0); | |
| 4514 | |
| 4515 return *isolate->factory()->NumberToString(number); | |
| 4516 } | |
| 4517 | |
| 4518 | |
| 4519 RUNTIME_FUNCTION(Runtime_NumberToStringSkipCache) { | |
| 4520 HandleScope scope(isolate); | |
| 4521 DCHECK(args.length() == 1); | |
| 4522 CONVERT_NUMBER_ARG_HANDLE_CHECKED(number, 0); | |
| 4523 | |
| 4524 return *isolate->factory()->NumberToString(number, false); | |
| 4525 } | |
| 4526 | |
| 4527 | |
| 4528 RUNTIME_FUNCTION(Runtime_NumberToInteger) { | |
| 4529 HandleScope scope(isolate); | |
| 4530 DCHECK(args.length() == 1); | |
| 4531 | |
| 4532 CONVERT_DOUBLE_ARG_CHECKED(number, 0); | |
| 4533 return *isolate->factory()->NewNumber(DoubleToInteger(number)); | |
| 4534 } | |
| 4535 | |
| 4536 | |
| 4537 RUNTIME_FUNCTION(Runtime_NumberToIntegerMapMinusZero) { | |
| 4538 HandleScope scope(isolate); | |
| 4539 DCHECK(args.length() == 1); | |
| 4540 | |
| 4541 CONVERT_DOUBLE_ARG_CHECKED(number, 0); | |
| 4542 double double_value = DoubleToInteger(number); | |
| 4543 // Map both -0 and +0 to +0. | |
| 4544 if (double_value == 0) double_value = 0; | |
| 4545 | |
| 4546 return *isolate->factory()->NewNumber(double_value); | |
| 4547 } | |
| 4548 | |
| 4549 | |
| 4550 RUNTIME_FUNCTION(Runtime_NumberToJSUint32) { | |
| 4551 HandleScope scope(isolate); | |
| 4552 DCHECK(args.length() == 1); | |
| 4553 | |
| 4554 CONVERT_NUMBER_CHECKED(int32_t, number, Uint32, args[0]); | |
| 4555 return *isolate->factory()->NewNumberFromUint(number); | |
| 4556 } | |
| 4557 | |
| 4558 | |
| 4559 RUNTIME_FUNCTION(Runtime_NumberToJSInt32) { | |
| 4560 HandleScope scope(isolate); | |
| 4561 DCHECK(args.length() == 1); | |
| 4562 | |
| 4563 CONVERT_DOUBLE_ARG_CHECKED(number, 0); | |
| 4564 return *isolate->factory()->NewNumberFromInt(DoubleToInt32(number)); | |
| 4565 } | |
| 4566 | |
| 4567 | |
| 4568 // Converts a Number to a Smi, if possible. Returns NaN if the number is not | |
| 4569 // a small integer. | |
| 4570 RUNTIME_FUNCTION(Runtime_NumberToSmi) { | |
| 4571 SealHandleScope shs(isolate); | |
| 4572 DCHECK(args.length() == 1); | |
| 4573 CONVERT_ARG_CHECKED(Object, obj, 0); | |
| 4574 if (obj->IsSmi()) { | |
| 4575 return obj; | |
| 4576 } | |
| 4577 if (obj->IsHeapNumber()) { | |
| 4578 double value = HeapNumber::cast(obj)->value(); | |
| 4579 int int_value = FastD2I(value); | |
| 4580 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) { | |
| 4581 return Smi::FromInt(int_value); | |
| 4582 } | |
| 4583 } | |
| 4584 return isolate->heap()->nan_value(); | |
| 4585 } | |
| 4586 | |
| 4587 | |
| 4588 RUNTIME_FUNCTION(Runtime_AllocateHeapNumber) { | 3221 RUNTIME_FUNCTION(Runtime_AllocateHeapNumber) { |
| 4589 HandleScope scope(isolate); | 3222 HandleScope scope(isolate); |
| 4590 DCHECK(args.length() == 0); | 3223 DCHECK(args.length() == 0); |
| 4591 return *isolate->factory()->NewHeapNumber(0); | 3224 return *isolate->factory()->NewHeapNumber(0); |
| 4592 } | 3225 } |
| 4593 | 3226 |
| 4594 | 3227 |
| 4595 RUNTIME_FUNCTION(Runtime_NumberAdd) { | 3228 |
| 4596 HandleScope scope(isolate); | |
| 4597 DCHECK(args.length() == 2); | |
| 4598 | |
| 4599 CONVERT_DOUBLE_ARG_CHECKED(x, 0); | |
| 4600 CONVERT_DOUBLE_ARG_CHECKED(y, 1); | |
| 4601 return *isolate->factory()->NewNumber(x + y); | |
| 4602 } | |
| 4603 | |
| 4604 | |
| 4605 RUNTIME_FUNCTION(Runtime_NumberSub) { | |
| 4606 HandleScope scope(isolate); | |
| 4607 DCHECK(args.length() == 2); | |
| 4608 | |
| 4609 CONVERT_DOUBLE_ARG_CHECKED(x, 0); | |
| 4610 CONVERT_DOUBLE_ARG_CHECKED(y, 1); | |
| 4611 return *isolate->factory()->NewNumber(x - y); | |
| 4612 } | |
| 4613 | |
| 4614 | |
| 4615 RUNTIME_FUNCTION(Runtime_NumberMul) { | |
| 4616 HandleScope scope(isolate); | |
| 4617 DCHECK(args.length() == 2); | |
| 4618 | |
| 4619 CONVERT_DOUBLE_ARG_CHECKED(x, 0); | |
| 4620 CONVERT_DOUBLE_ARG_CHECKED(y, 1); | |
| 4621 return *isolate->factory()->NewNumber(x * y); | |
| 4622 } | |
| 4623 | |
| 4624 | |
| 4625 RUNTIME_FUNCTION(Runtime_NumberUnaryMinus) { | |
| 4626 HandleScope scope(isolate); | |
| 4627 DCHECK(args.length() == 1); | |
| 4628 | |
| 4629 CONVERT_DOUBLE_ARG_CHECKED(x, 0); | |
| 4630 return *isolate->factory()->NewNumber(-x); | |
| 4631 } | |
| 4632 | |
| 4633 | |
| 4634 RUNTIME_FUNCTION(Runtime_NumberDiv) { | |
| 4635 HandleScope scope(isolate); | |
| 4636 DCHECK(args.length() == 2); | |
| 4637 | |
| 4638 CONVERT_DOUBLE_ARG_CHECKED(x, 0); | |
| 4639 CONVERT_DOUBLE_ARG_CHECKED(y, 1); | |
| 4640 return *isolate->factory()->NewNumber(x / y); | |
| 4641 } | |
| 4642 | |
| 4643 | |
| 4644 RUNTIME_FUNCTION(Runtime_NumberMod) { | |
| 4645 HandleScope scope(isolate); | |
| 4646 DCHECK(args.length() == 2); | |
| 4647 | |
| 4648 CONVERT_DOUBLE_ARG_CHECKED(x, 0); | |
| 4649 CONVERT_DOUBLE_ARG_CHECKED(y, 1); | |
| 4650 return *isolate->factory()->NewNumber(modulo(x, y)); | |
| 4651 } | |
| 4652 | |
| 4653 | |
| 4654 RUNTIME_FUNCTION(Runtime_NumberImul) { | |
| 4655 HandleScope scope(isolate); | |
| 4656 DCHECK(args.length() == 2); | |
| 4657 | |
| 4658 // We rely on implementation-defined behavior below, but at least not on | |
| 4659 // undefined behavior. | |
| 4660 CONVERT_NUMBER_CHECKED(uint32_t, x, Int32, args[0]); | |
| 4661 CONVERT_NUMBER_CHECKED(uint32_t, y, Int32, args[1]); | |
| 4662 int32_t product = static_cast<int32_t>(x * y); | |
| 4663 return *isolate->factory()->NewNumberFromInt(product); | |
| 4664 } | |
| 4665 | |
| 4666 | |
| 4667 RUNTIME_FUNCTION(Runtime_NumberOr) { | |
| 4668 HandleScope scope(isolate); | |
| 4669 DCHECK(args.length() == 2); | |
| 4670 | |
| 4671 CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]); | |
| 4672 CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]); | |
| 4673 return *isolate->factory()->NewNumberFromInt(x | y); | |
| 4674 } | |
| 4675 | |
| 4676 | |
| 4677 RUNTIME_FUNCTION(Runtime_NumberAnd) { | |
| 4678 HandleScope scope(isolate); | |
| 4679 DCHECK(args.length() == 2); | |
| 4680 | |
| 4681 CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]); | |
| 4682 CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]); | |
| 4683 return *isolate->factory()->NewNumberFromInt(x & y); | |
| 4684 } | |
| 4685 | |
| 4686 | |
| 4687 RUNTIME_FUNCTION(Runtime_NumberXor) { | |
| 4688 HandleScope scope(isolate); | |
| 4689 DCHECK(args.length() == 2); | |
| 4690 | |
| 4691 CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]); | |
| 4692 CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]); | |
| 4693 return *isolate->factory()->NewNumberFromInt(x ^ y); | |
| 4694 } | |
| 4695 | |
| 4696 | |
| 4697 RUNTIME_FUNCTION(Runtime_NumberShl) { | |
| 4698 HandleScope scope(isolate); | |
| 4699 DCHECK(args.length() == 2); | |
| 4700 | |
| 4701 CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]); | |
| 4702 CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]); | |
| 4703 return *isolate->factory()->NewNumberFromInt(x << (y & 0x1f)); | |
| 4704 } | |
| 4705 | |
| 4706 | |
| 4707 RUNTIME_FUNCTION(Runtime_NumberShr) { | |
| 4708 HandleScope scope(isolate); | |
| 4709 DCHECK(args.length() == 2); | |
| 4710 | |
| 4711 CONVERT_NUMBER_CHECKED(uint32_t, x, Uint32, args[0]); | |
| 4712 CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]); | |
| 4713 return *isolate->factory()->NewNumberFromUint(x >> (y & 0x1f)); | |
| 4714 } | |
| 4715 | |
| 4716 | |
| 4717 RUNTIME_FUNCTION(Runtime_NumberSar) { | |
| 4718 HandleScope scope(isolate); | |
| 4719 DCHECK(args.length() == 2); | |
| 4720 | |
| 4721 CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]); | |
| 4722 CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]); | |
| 4723 return *isolate->factory()->NewNumberFromInt( | |
| 4724 ArithmeticShiftRight(x, y & 0x1f)); | |
| 4725 } | |
| 4726 | |
| 4727 | |
| 4728 RUNTIME_FUNCTION(Runtime_NumberEquals) { | |
| 4729 SealHandleScope shs(isolate); | |
| 4730 DCHECK(args.length() == 2); | |
| 4731 | |
| 4732 CONVERT_DOUBLE_ARG_CHECKED(x, 0); | |
| 4733 CONVERT_DOUBLE_ARG_CHECKED(y, 1); | |
| 4734 if (std::isnan(x)) return Smi::FromInt(NOT_EQUAL); | |
| 4735 if (std::isnan(y)) return Smi::FromInt(NOT_EQUAL); | |
| 4736 if (x == y) return Smi::FromInt(EQUAL); | |
| 4737 Object* result; | |
| 4738 if ((fpclassify(x) == FP_ZERO) && (fpclassify(y) == FP_ZERO)) { | |
| 4739 result = Smi::FromInt(EQUAL); | |
| 4740 } else { | |
| 4741 result = Smi::FromInt(NOT_EQUAL); | |
| 4742 } | |
| 4743 return result; | |
| 4744 } | |
| 4745 | |
| 4746 | |
| 4747 RUNTIME_FUNCTION(Runtime_NumberCompare) { | |
| 4748 SealHandleScope shs(isolate); | |
| 4749 DCHECK(args.length() == 3); | |
| 4750 | |
| 4751 CONVERT_DOUBLE_ARG_CHECKED(x, 0); | |
| 4752 CONVERT_DOUBLE_ARG_CHECKED(y, 1); | |
| 4753 CONVERT_ARG_HANDLE_CHECKED(Object, uncomparable_result, 2) | |
| 4754 if (std::isnan(x) || std::isnan(y)) return *uncomparable_result; | |
| 4755 if (x == y) return Smi::FromInt(EQUAL); | |
| 4756 if (isless(x, y)) return Smi::FromInt(LESS); | |
| 4757 return Smi::FromInt(GREATER); | |
| 4758 } | |
| 4759 | |
| 4760 | |
| 4761 // Compare two Smis as if they were converted to strings and then | |
| 4762 // compared lexicographically. | |
| 4763 RUNTIME_FUNCTION(Runtime_SmiLexicographicCompare) { | |
| 4764 SealHandleScope shs(isolate); | |
| 4765 DCHECK(args.length() == 2); | |
| 4766 CONVERT_SMI_ARG_CHECKED(x_value, 0); | |
| 4767 CONVERT_SMI_ARG_CHECKED(y_value, 1); | |
| 4768 | |
| 4769 // If the integers are equal so are the string representations. | |
| 4770 if (x_value == y_value) return Smi::FromInt(EQUAL); | |
| 4771 | |
| 4772 // If one of the integers is zero the normal integer order is the | |
| 4773 // same as the lexicographic order of the string representations. | |
| 4774 if (x_value == 0 || y_value == 0) | |
| 4775 return Smi::FromInt(x_value < y_value ? LESS : GREATER); | |
| 4776 | |
| 4777 // If only one of the integers is negative the negative number is | |
| 4778 // smallest because the char code of '-' is less than the char code | |
| 4779 // of any digit. Otherwise, we make both values positive. | |
| 4780 | |
| 4781 // Use unsigned values otherwise the logic is incorrect for -MIN_INT on | |
| 4782 // architectures using 32-bit Smis. | |
| 4783 uint32_t x_scaled = x_value; | |
| 4784 uint32_t y_scaled = y_value; | |
| 4785 if (x_value < 0 || y_value < 0) { | |
| 4786 if (y_value >= 0) return Smi::FromInt(LESS); | |
| 4787 if (x_value >= 0) return Smi::FromInt(GREATER); | |
| 4788 x_scaled = -x_value; | |
| 4789 y_scaled = -y_value; | |
| 4790 } | |
| 4791 | |
| 4792 static const uint32_t kPowersOf10[] = { | |
| 4793 1, 10, 100, 1000, | |
| 4794 10 * 1000, 100 * 1000, 1000 * 1000, 10 * 1000 * 1000, | |
| 4795 100 * 1000 * 1000, 1000 * 1000 * 1000}; | |
| 4796 | |
| 4797 // If the integers have the same number of decimal digits they can be | |
| 4798 // compared directly as the numeric order is the same as the | |
| 4799 // lexicographic order. If one integer has fewer digits, it is scaled | |
| 4800 // by some power of 10 to have the same number of digits as the longer | |
| 4801 // integer. If the scaled integers are equal it means the shorter | |
| 4802 // integer comes first in the lexicographic order. | |
| 4803 | |
| 4804 // From http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10 | |
| 4805 int x_log2 = IntegerLog2(x_scaled); | |
| 4806 int x_log10 = ((x_log2 + 1) * 1233) >> 12; | |
| 4807 x_log10 -= x_scaled < kPowersOf10[x_log10]; | |
| 4808 | |
| 4809 int y_log2 = IntegerLog2(y_scaled); | |
| 4810 int y_log10 = ((y_log2 + 1) * 1233) >> 12; | |
| 4811 y_log10 -= y_scaled < kPowersOf10[y_log10]; | |
| 4812 | |
| 4813 int tie = EQUAL; | |
| 4814 | |
| 4815 if (x_log10 < y_log10) { | |
| 4816 // X has fewer digits. We would like to simply scale up X but that | |
| 4817 // might overflow, e.g when comparing 9 with 1_000_000_000, 9 would | |
| 4818 // be scaled up to 9_000_000_000. So we scale up by the next | |
| 4819 // smallest power and scale down Y to drop one digit. It is OK to | |
| 4820 // drop one digit from the longer integer since the final digit is | |
| 4821 // past the length of the shorter integer. | |
| 4822 x_scaled *= kPowersOf10[y_log10 - x_log10 - 1]; | |
| 4823 y_scaled /= 10; | |
| 4824 tie = LESS; | |
| 4825 } else if (y_log10 < x_log10) { | |
| 4826 y_scaled *= kPowersOf10[x_log10 - y_log10 - 1]; | |
| 4827 x_scaled /= 10; | |
| 4828 tie = GREATER; | |
| 4829 } | |
| 4830 | |
| 4831 if (x_scaled < y_scaled) return Smi::FromInt(LESS); | |
| 4832 if (x_scaled > y_scaled) return Smi::FromInt(GREATER); | |
| 4833 return Smi::FromInt(tie); | |
| 4834 } | |
| 4835 | |
| 4836 | |
| 4837 | |
| 4838 | |
| 4839 | |
| 4840 #define RUNTIME_UNARY_MATH(Name, name) \ | |
| 4841 RUNTIME_FUNCTION(Runtime_Math##Name) { \ | |
| 4842 HandleScope scope(isolate); \ | |
| 4843 DCHECK(args.length() == 1); \ | |
| 4844 isolate->counters()->math_##name()->Increment(); \ | |
| 4845 CONVERT_DOUBLE_ARG_CHECKED(x, 0); \ | |
| 4846 return *isolate->factory()->NewHeapNumber(std::name(x)); \ | |
| 4847 } | |
| 4848 | |
| 4849 RUNTIME_UNARY_MATH(Acos, acos) | |
| 4850 RUNTIME_UNARY_MATH(Asin, asin) | |
| 4851 RUNTIME_UNARY_MATH(Atan, atan) | |
| 4852 RUNTIME_UNARY_MATH(LogRT, log) | |
| 4853 #undef RUNTIME_UNARY_MATH | |
| 4854 | |
| 4855 | |
| 4856 RUNTIME_FUNCTION(Runtime_DoubleHi) { | |
| 4857 HandleScope scope(isolate); | |
| 4858 DCHECK(args.length() == 1); | |
| 4859 CONVERT_DOUBLE_ARG_CHECKED(x, 0); | |
| 4860 uint64_t integer = double_to_uint64(x); | |
| 4861 integer = (integer >> 32) & 0xFFFFFFFFu; | |
| 4862 return *isolate->factory()->NewNumber(static_cast<int32_t>(integer)); | |
| 4863 } | |
| 4864 | |
| 4865 | |
| 4866 RUNTIME_FUNCTION(Runtime_DoubleLo) { | |
| 4867 HandleScope scope(isolate); | |
| 4868 DCHECK(args.length() == 1); | |
| 4869 CONVERT_DOUBLE_ARG_CHECKED(x, 0); | |
| 4870 return *isolate->factory()->NewNumber( | |
| 4871 static_cast<int32_t>(double_to_uint64(x) & 0xFFFFFFFFu)); | |
| 4872 } | |
| 4873 | |
| 4874 | |
| 4875 RUNTIME_FUNCTION(Runtime_ConstructDouble) { | |
| 4876 HandleScope scope(isolate); | |
| 4877 DCHECK(args.length() == 2); | |
| 4878 CONVERT_NUMBER_CHECKED(uint32_t, hi, Uint32, args[0]); | |
| 4879 CONVERT_NUMBER_CHECKED(uint32_t, lo, Uint32, args[1]); | |
| 4880 uint64_t result = (static_cast<uint64_t>(hi) << 32) | lo; | |
| 4881 return *isolate->factory()->NewNumber(uint64_to_double(result)); | |
| 4882 } | |
| 4883 | |
| 4884 | |
| 4885 RUNTIME_FUNCTION(Runtime_RemPiO2) { | |
| 4886 HandleScope handle_scope(isolate); | |
| 4887 DCHECK(args.length() == 1); | |
| 4888 CONVERT_DOUBLE_ARG_CHECKED(x, 0); | |
| 4889 Factory* factory = isolate->factory(); | |
| 4890 double y[2]; | |
| 4891 int n = fdlibm::rempio2(x, y); | |
| 4892 Handle<FixedArray> array = factory->NewFixedArray(3); | |
| 4893 Handle<HeapNumber> y0 = factory->NewHeapNumber(y[0]); | |
| 4894 Handle<HeapNumber> y1 = factory->NewHeapNumber(y[1]); | |
| 4895 array->set(0, Smi::FromInt(n)); | |
| 4896 array->set(1, *y0); | |
| 4897 array->set(2, *y1); | |
| 4898 return *factory->NewJSArrayWithElements(array); | |
| 4899 } | |
| 4900 | |
| 4901 | |
| 4902 static const double kPiDividedBy4 = 0.78539816339744830962; | |
| 4903 | |
| 4904 | |
| 4905 RUNTIME_FUNCTION(Runtime_MathAtan2) { | |
| 4906 HandleScope scope(isolate); | |
| 4907 DCHECK(args.length() == 2); | |
| 4908 isolate->counters()->math_atan2()->Increment(); | |
| 4909 | |
| 4910 CONVERT_DOUBLE_ARG_CHECKED(x, 0); | |
| 4911 CONVERT_DOUBLE_ARG_CHECKED(y, 1); | |
| 4912 double result; | |
| 4913 if (std::isinf(x) && std::isinf(y)) { | |
| 4914 // Make sure that the result in case of two infinite arguments | |
| 4915 // is a multiple of Pi / 4. The sign of the result is determined | |
| 4916 // by the first argument (x) and the sign of the second argument | |
| 4917 // determines the multiplier: one or three. | |
| 4918 int multiplier = (x < 0) ? -1 : 1; | |
| 4919 if (y < 0) multiplier *= 3; | |
| 4920 result = multiplier * kPiDividedBy4; | |
| 4921 } else { | |
| 4922 result = std::atan2(x, y); | |
| 4923 } | |
| 4924 return *isolate->factory()->NewNumber(result); | |
| 4925 } | |
| 4926 | |
| 4927 | |
| 4928 RUNTIME_FUNCTION(Runtime_MathExpRT) { | |
| 4929 HandleScope scope(isolate); | |
| 4930 DCHECK(args.length() == 1); | |
| 4931 isolate->counters()->math_exp()->Increment(); | |
| 4932 | |
| 4933 CONVERT_DOUBLE_ARG_CHECKED(x, 0); | |
| 4934 lazily_initialize_fast_exp(); | |
| 4935 return *isolate->factory()->NewNumber(fast_exp(x)); | |
| 4936 } | |
| 4937 | |
| 4938 | |
| 4939 RUNTIME_FUNCTION(Runtime_MathFloorRT) { | |
| 4940 HandleScope scope(isolate); | |
| 4941 DCHECK(args.length() == 1); | |
| 4942 isolate->counters()->math_floor()->Increment(); | |
| 4943 | |
| 4944 CONVERT_DOUBLE_ARG_CHECKED(x, 0); | |
| 4945 return *isolate->factory()->NewNumber(Floor(x)); | |
| 4946 } | |
| 4947 | |
| 4948 | |
| 4949 // Slow version of Math.pow. We check for fast paths for special cases. | |
| 4950 // Used if VFP3 is not available. | |
| 4951 RUNTIME_FUNCTION(Runtime_MathPowSlow) { | |
| 4952 HandleScope scope(isolate); | |
| 4953 DCHECK(args.length() == 2); | |
| 4954 isolate->counters()->math_pow()->Increment(); | |
| 4955 | |
| 4956 CONVERT_DOUBLE_ARG_CHECKED(x, 0); | |
| 4957 | |
| 4958 // If the second argument is a smi, it is much faster to call the | |
| 4959 // custom powi() function than the generic pow(). | |
| 4960 if (args[1]->IsSmi()) { | |
| 4961 int y = args.smi_at(1); | |
| 4962 return *isolate->factory()->NewNumber(power_double_int(x, y)); | |
| 4963 } | |
| 4964 | |
| 4965 CONVERT_DOUBLE_ARG_CHECKED(y, 1); | |
| 4966 double result = power_helper(x, y); | |
| 4967 if (std::isnan(result)) return isolate->heap()->nan_value(); | |
| 4968 return *isolate->factory()->NewNumber(result); | |
| 4969 } | |
| 4970 | |
| 4971 | |
| 4972 // Fast version of Math.pow if we know that y is not an integer and y is not | |
| 4973 // -0.5 or 0.5. Used as slow case from full codegen. | |
| 4974 RUNTIME_FUNCTION(Runtime_MathPowRT) { | |
| 4975 HandleScope scope(isolate); | |
| 4976 DCHECK(args.length() == 2); | |
| 4977 isolate->counters()->math_pow()->Increment(); | |
| 4978 | |
| 4979 CONVERT_DOUBLE_ARG_CHECKED(x, 0); | |
| 4980 CONVERT_DOUBLE_ARG_CHECKED(y, 1); | |
| 4981 if (y == 0) { | |
| 4982 return Smi::FromInt(1); | |
| 4983 } else { | |
| 4984 double result = power_double_double(x, y); | |
| 4985 if (std::isnan(result)) return isolate->heap()->nan_value(); | |
| 4986 return *isolate->factory()->NewNumber(result); | |
| 4987 } | |
| 4988 } | |
| 4989 | |
| 4990 | |
| 4991 RUNTIME_FUNCTION(Runtime_RoundNumber) { | |
| 4992 HandleScope scope(isolate); | |
| 4993 DCHECK(args.length() == 1); | |
| 4994 CONVERT_NUMBER_ARG_HANDLE_CHECKED(input, 0); | |
| 4995 isolate->counters()->math_round()->Increment(); | |
| 4996 | |
| 4997 if (!input->IsHeapNumber()) { | |
| 4998 DCHECK(input->IsSmi()); | |
| 4999 return *input; | |
| 5000 } | |
| 5001 | |
| 5002 Handle<HeapNumber> number = Handle<HeapNumber>::cast(input); | |
| 5003 | |
| 5004 double value = number->value(); | |
| 5005 int exponent = number->get_exponent(); | |
| 5006 int sign = number->get_sign(); | |
| 5007 | |
| 5008 if (exponent < -1) { | |
| 5009 // Number in range ]-0.5..0.5[. These always round to +/-zero. | |
| 5010 if (sign) return isolate->heap()->minus_zero_value(); | |
| 5011 return Smi::FromInt(0); | |
| 5012 } | |
| 5013 | |
| 5014 // We compare with kSmiValueSize - 2 because (2^30 - 0.1) has exponent 29 and | |
| 5015 // should be rounded to 2^30, which is not smi (for 31-bit smis, similar | |
| 5016 // argument holds for 32-bit smis). | |
| 5017 if (!sign && exponent < kSmiValueSize - 2) { | |
| 5018 return Smi::FromInt(static_cast<int>(value + 0.5)); | |
| 5019 } | |
| 5020 | |
| 5021 // If the magnitude is big enough, there's no place for fraction part. If we | |
| 5022 // try to add 0.5 to this number, 1.0 will be added instead. | |
| 5023 if (exponent >= 52) { | |
| 5024 return *number; | |
| 5025 } | |
| 5026 | |
| 5027 if (sign && value >= -0.5) return isolate->heap()->minus_zero_value(); | |
| 5028 | |
| 5029 // Do not call NumberFromDouble() to avoid extra checks. | |
| 5030 return *isolate->factory()->NewNumber(Floor(value + 0.5)); | |
| 5031 } | |
| 5032 | |
| 5033 | |
| 5034 RUNTIME_FUNCTION(Runtime_MathSqrtRT) { | |
| 5035 HandleScope scope(isolate); | |
| 5036 DCHECK(args.length() == 1); | |
| 5037 isolate->counters()->math_sqrt()->Increment(); | |
| 5038 | |
| 5039 CONVERT_DOUBLE_ARG_CHECKED(x, 0); | |
| 5040 return *isolate->factory()->NewNumber(fast_sqrt(x)); | |
| 5041 } | |
| 5042 | |
| 5043 | |
| 5044 RUNTIME_FUNCTION(Runtime_MathFround) { | |
| 5045 HandleScope scope(isolate); | |
| 5046 DCHECK(args.length() == 1); | |
| 5047 | |
| 5048 CONVERT_DOUBLE_ARG_CHECKED(x, 0); | |
| 5049 float xf = DoubleToFloat32(x); | |
| 5050 return *isolate->factory()->NewNumber(xf); | |
| 5051 } | |
| 5052 | 3229 |
| 5053 | 3230 |
| 5054 RUNTIME_FUNCTION(Runtime_DateMakeDay) { | 3231 RUNTIME_FUNCTION(Runtime_DateMakeDay) { |
| 5055 SealHandleScope shs(isolate); | 3232 SealHandleScope shs(isolate); |
| 5056 DCHECK(args.length() == 2); | 3233 DCHECK(args.length() == 2); |
| 5057 | 3234 |
| 5058 CONVERT_SMI_ARG_CHECKED(year, 0); | 3235 CONVERT_SMI_ARG_CHECKED(year, 0); |
| 5059 CONVERT_SMI_ARG_CHECKED(month, 1); | 3236 CONVERT_SMI_ARG_CHECKED(month, 1); |
| 5060 | 3237 |
| 5061 int days = isolate->date_cache()->DaysFromYearMonth(year, month); | 3238 int days = isolate->date_cache()->DaysFromYearMonth(year, month); |
| (...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5535 RUNTIME_FUNCTION(Runtime_FinalizeInstanceSize) { | 3712 RUNTIME_FUNCTION(Runtime_FinalizeInstanceSize) { |
| 5536 HandleScope scope(isolate); | 3713 HandleScope scope(isolate); |
| 5537 DCHECK(args.length() == 1); | 3714 DCHECK(args.length() == 1); |
| 5538 | 3715 |
| 5539 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); | 3716 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); |
| 5540 function->CompleteInobjectSlackTracking(); | 3717 function->CompleteInobjectSlackTracking(); |
| 5541 | 3718 |
| 5542 return isolate->heap()->undefined_value(); | 3719 return isolate->heap()->undefined_value(); |
| 5543 } | 3720 } |
| 5544 | 3721 |
| 5545 | |
| 5546 RUNTIME_FUNCTION(Runtime_CompileLazy) { | |
| 5547 HandleScope scope(isolate); | |
| 5548 DCHECK(args.length() == 1); | |
| 5549 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); | |
| 5550 #ifdef DEBUG | |
| 5551 if (FLAG_trace_lazy && !function->shared()->is_compiled()) { | |
| 5552 PrintF("[unoptimized: "); | |
| 5553 function->PrintName(); | |
| 5554 PrintF("]\n"); | |
| 5555 } | |
| 5556 #endif | |
| 5557 | |
| 5558 // Compile the target function. | |
| 5559 DCHECK(function->shared()->allows_lazy_compilation()); | |
| 5560 | |
| 5561 Handle<Code> code; | |
| 5562 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, code, | |
| 5563 Compiler::GetLazyCode(function)); | |
| 5564 DCHECK(code->kind() == Code::FUNCTION || | |
| 5565 code->kind() == Code::OPTIMIZED_FUNCTION); | |
| 5566 function->ReplaceCode(*code); | |
| 5567 return *code; | |
| 5568 } | |
| 5569 | |
| 5570 | |
| 5571 RUNTIME_FUNCTION(Runtime_CompileOptimized) { | |
| 5572 HandleScope scope(isolate); | |
| 5573 DCHECK(args.length() == 2); | |
| 5574 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); | |
| 5575 CONVERT_BOOLEAN_ARG_CHECKED(concurrent, 1); | |
| 5576 | |
| 5577 Handle<Code> unoptimized(function->shared()->code()); | |
| 5578 if (!isolate->use_crankshaft() || | |
| 5579 function->shared()->optimization_disabled() || | |
| 5580 isolate->DebuggerHasBreakPoints()) { | |
| 5581 // If the function is not optimizable or debugger is active continue | |
| 5582 // using the code from the full compiler. | |
| 5583 if (FLAG_trace_opt) { | |
| 5584 PrintF("[failed to optimize "); | |
| 5585 function->PrintName(); | |
| 5586 PrintF(": is code optimizable: %s, is debugger enabled: %s]\n", | |
| 5587 function->shared()->optimization_disabled() ? "F" : "T", | |
| 5588 isolate->DebuggerHasBreakPoints() ? "T" : "F"); | |
| 5589 } | |
| 5590 function->ReplaceCode(*unoptimized); | |
| 5591 return function->code(); | |
| 5592 } | |
| 5593 | |
| 5594 Compiler::ConcurrencyMode mode = | |
| 5595 concurrent ? Compiler::CONCURRENT : Compiler::NOT_CONCURRENT; | |
| 5596 Handle<Code> code; | |
| 5597 if (Compiler::GetOptimizedCode(function, unoptimized, mode).ToHandle(&code)) { | |
| 5598 function->ReplaceCode(*code); | |
| 5599 } else { | |
| 5600 function->ReplaceCode(function->shared()->code()); | |
| 5601 } | |
| 5602 | |
| 5603 DCHECK(function->code()->kind() == Code::FUNCTION || | |
| 5604 function->code()->kind() == Code::OPTIMIZED_FUNCTION || | |
| 5605 function->IsInOptimizationQueue()); | |
| 5606 return function->code(); | |
| 5607 } | |
| 5608 | |
| 5609 | |
| 5610 class ActivationsFinder : public ThreadVisitor { | |
| 5611 public: | |
| 5612 Code* code_; | |
| 5613 bool has_code_activations_; | |
| 5614 | |
| 5615 explicit ActivationsFinder(Code* code) | |
| 5616 : code_(code), has_code_activations_(false) {} | |
| 5617 | |
| 5618 void VisitThread(Isolate* isolate, ThreadLocalTop* top) { | |
| 5619 JavaScriptFrameIterator it(isolate, top); | |
| 5620 VisitFrames(&it); | |
| 5621 } | |
| 5622 | |
| 5623 void VisitFrames(JavaScriptFrameIterator* it) { | |
| 5624 for (; !it->done(); it->Advance()) { | |
| 5625 JavaScriptFrame* frame = it->frame(); | |
| 5626 if (code_->contains(frame->pc())) has_code_activations_ = true; | |
| 5627 } | |
| 5628 } | |
| 5629 }; | |
| 5630 | |
| 5631 | |
| 5632 RUNTIME_FUNCTION(Runtime_NotifyStubFailure) { | |
| 5633 HandleScope scope(isolate); | |
| 5634 DCHECK(args.length() == 0); | |
| 5635 Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate); | |
| 5636 DCHECK(AllowHeapAllocation::IsAllowed()); | |
| 5637 delete deoptimizer; | |
| 5638 return isolate->heap()->undefined_value(); | |
| 5639 } | |
| 5640 | |
| 5641 | |
| 5642 RUNTIME_FUNCTION(Runtime_NotifyDeoptimized) { | |
| 5643 HandleScope scope(isolate); | |
| 5644 DCHECK(args.length() == 1); | |
| 5645 CONVERT_SMI_ARG_CHECKED(type_arg, 0); | |
| 5646 Deoptimizer::BailoutType type = | |
| 5647 static_cast<Deoptimizer::BailoutType>(type_arg); | |
| 5648 Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate); | |
| 5649 DCHECK(AllowHeapAllocation::IsAllowed()); | |
| 5650 | |
| 5651 Handle<JSFunction> function = deoptimizer->function(); | |
| 5652 Handle<Code> optimized_code = deoptimizer->compiled_code(); | |
| 5653 | |
| 5654 DCHECK(optimized_code->kind() == Code::OPTIMIZED_FUNCTION); | |
| 5655 DCHECK(type == deoptimizer->bailout_type()); | |
| 5656 | |
| 5657 // Make sure to materialize objects before causing any allocation. | |
| 5658 JavaScriptFrameIterator it(isolate); | |
| 5659 deoptimizer->MaterializeHeapObjects(&it); | |
| 5660 delete deoptimizer; | |
| 5661 | |
| 5662 JavaScriptFrame* frame = it.frame(); | |
| 5663 RUNTIME_ASSERT(frame->function()->IsJSFunction()); | |
| 5664 DCHECK(frame->function() == *function); | |
| 5665 | |
| 5666 // Avoid doing too much work when running with --always-opt and keep | |
| 5667 // the optimized code around. | |
| 5668 if (FLAG_always_opt || type == Deoptimizer::LAZY) { | |
| 5669 return isolate->heap()->undefined_value(); | |
| 5670 } | |
| 5671 | |
| 5672 // Search for other activations of the same function and code. | |
| 5673 ActivationsFinder activations_finder(*optimized_code); | |
| 5674 activations_finder.VisitFrames(&it); | |
| 5675 isolate->thread_manager()->IterateArchivedThreads(&activations_finder); | |
| 5676 | |
| 5677 if (!activations_finder.has_code_activations_) { | |
| 5678 if (function->code() == *optimized_code) { | |
| 5679 if (FLAG_trace_deopt) { | |
| 5680 PrintF("[removing optimized code for: "); | |
| 5681 function->PrintName(); | |
| 5682 PrintF("]\n"); | |
| 5683 } | |
| 5684 function->ReplaceCode(function->shared()->code()); | |
| 5685 // Evict optimized code for this function from the cache so that it | |
| 5686 // doesn't get used for new closures. | |
| 5687 function->shared()->EvictFromOptimizedCodeMap(*optimized_code, | |
| 5688 "notify deoptimized"); | |
| 5689 } | |
| 5690 } else { | |
| 5691 // TODO(titzer): we should probably do DeoptimizeCodeList(code) | |
| 5692 // unconditionally if the code is not already marked for deoptimization. | |
| 5693 // If there is an index by shared function info, all the better. | |
| 5694 Deoptimizer::DeoptimizeFunction(*function); | |
| 5695 } | |
| 5696 | |
| 5697 return isolate->heap()->undefined_value(); | |
| 5698 } | |
| 5699 | |
| 5700 | |
| 5701 RUNTIME_FUNCTION(Runtime_DeoptimizeFunction) { | |
| 5702 HandleScope scope(isolate); | |
| 5703 DCHECK(args.length() == 1); | |
| 5704 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); | |
| 5705 if (!function->IsOptimized()) return isolate->heap()->undefined_value(); | |
| 5706 | |
| 5707 // TODO(turbofan): Deoptimization is not supported yet. | |
| 5708 if (function->code()->is_turbofanned() && !FLAG_turbo_deoptimization) { | |
| 5709 return isolate->heap()->undefined_value(); | |
| 5710 } | |
| 5711 | |
| 5712 Deoptimizer::DeoptimizeFunction(*function); | |
| 5713 | |
| 5714 return isolate->heap()->undefined_value(); | |
| 5715 } | |
| 5716 | |
| 5717 | |
| 5718 RUNTIME_FUNCTION(Runtime_ClearFunctionTypeFeedback) { | |
| 5719 HandleScope scope(isolate); | |
| 5720 DCHECK(args.length() == 1); | |
| 5721 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); | |
| 5722 function->shared()->ClearTypeFeedbackInfo(); | |
| 5723 Code* unoptimized = function->shared()->code(); | |
| 5724 if (unoptimized->kind() == Code::FUNCTION) { | |
| 5725 unoptimized->ClearInlineCaches(); | |
| 5726 } | |
| 5727 return isolate->heap()->undefined_value(); | |
| 5728 } | |
| 5729 | |
| 5730 | |
| 5731 RUNTIME_FUNCTION(Runtime_RunningInSimulator) { | |
| 5732 SealHandleScope shs(isolate); | |
| 5733 DCHECK(args.length() == 0); | |
| 5734 #if defined(USE_SIMULATOR) | |
| 5735 return isolate->heap()->true_value(); | |
| 5736 #else | |
| 5737 return isolate->heap()->false_value(); | |
| 5738 #endif | |
| 5739 } | |
| 5740 | |
| 5741 | |
| 5742 RUNTIME_FUNCTION(Runtime_IsConcurrentRecompilationSupported) { | |
| 5743 SealHandleScope shs(isolate); | |
| 5744 DCHECK(args.length() == 0); | |
| 5745 return isolate->heap()->ToBoolean( | |
| 5746 isolate->concurrent_recompilation_enabled()); | |
| 5747 } | |
| 5748 | |
| 5749 | |
| 5750 RUNTIME_FUNCTION(Runtime_OptimizeFunctionOnNextCall) { | |
| 5751 HandleScope scope(isolate); | |
| 5752 RUNTIME_ASSERT(args.length() == 1 || args.length() == 2); | |
| 5753 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); | |
| 5754 // The following two assertions are lifted from the DCHECKs inside | |
| 5755 // JSFunction::MarkForOptimization(). | |
| 5756 RUNTIME_ASSERT(!function->shared()->is_generator()); | |
| 5757 RUNTIME_ASSERT(function->shared()->allows_lazy_compilation() || | |
| 5758 (function->code()->kind() == Code::FUNCTION && | |
| 5759 function->code()->optimizable())); | |
| 5760 | |
| 5761 // If the function is optimized, just return. | |
| 5762 if (function->IsOptimized()) return isolate->heap()->undefined_value(); | |
| 5763 | |
| 5764 function->MarkForOptimization(); | |
| 5765 | |
| 5766 Code* unoptimized = function->shared()->code(); | |
| 5767 if (args.length() == 2 && unoptimized->kind() == Code::FUNCTION) { | |
| 5768 CONVERT_ARG_HANDLE_CHECKED(String, type, 1); | |
| 5769 if (type->IsOneByteEqualTo(STATIC_CHAR_VECTOR("osr")) && FLAG_use_osr) { | |
| 5770 // Start patching from the currently patched loop nesting level. | |
| 5771 DCHECK(BackEdgeTable::Verify(isolate, unoptimized)); | |
| 5772 isolate->runtime_profiler()->AttemptOnStackReplacement( | |
| 5773 *function, Code::kMaxLoopNestingMarker); | |
| 5774 } else if (type->IsOneByteEqualTo(STATIC_CHAR_VECTOR("concurrent")) && | |
| 5775 isolate->concurrent_recompilation_enabled()) { | |
| 5776 function->MarkForConcurrentOptimization(); | |
| 5777 } | |
| 5778 } | |
| 5779 | |
| 5780 return isolate->heap()->undefined_value(); | |
| 5781 } | |
| 5782 | |
| 5783 | |
| 5784 RUNTIME_FUNCTION(Runtime_NeverOptimizeFunction) { | |
| 5785 HandleScope scope(isolate); | |
| 5786 DCHECK(args.length() == 1); | |
| 5787 CONVERT_ARG_CHECKED(JSFunction, function, 0); | |
| 5788 function->shared()->set_optimization_disabled(true); | |
| 5789 return isolate->heap()->undefined_value(); | |
| 5790 } | |
| 5791 | |
| 5792 | |
| 5793 RUNTIME_FUNCTION(Runtime_GetOptimizationStatus) { | |
| 5794 HandleScope scope(isolate); | |
| 5795 RUNTIME_ASSERT(args.length() == 1 || args.length() == 2); | |
| 5796 if (!isolate->use_crankshaft()) { | |
| 5797 return Smi::FromInt(4); // 4 == "never". | |
| 5798 } | |
| 5799 bool sync_with_compiler_thread = true; | |
| 5800 if (args.length() == 2) { | |
| 5801 CONVERT_ARG_HANDLE_CHECKED(String, sync, 1); | |
| 5802 if (sync->IsOneByteEqualTo(STATIC_CHAR_VECTOR("no sync"))) { | |
| 5803 sync_with_compiler_thread = false; | |
| 5804 } | |
| 5805 } | |
| 5806 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); | |
| 5807 if (isolate->concurrent_recompilation_enabled() && | |
| 5808 sync_with_compiler_thread) { | |
| 5809 while (function->IsInOptimizationQueue()) { | |
| 5810 isolate->optimizing_compiler_thread()->InstallOptimizedFunctions(); | |
| 5811 base::OS::Sleep(50); | |
| 5812 } | |
| 5813 } | |
| 5814 if (FLAG_always_opt) { | |
| 5815 // We may have always opt, but that is more best-effort than a real | |
| 5816 // promise, so we still say "no" if it is not optimized. | |
| 5817 return function->IsOptimized() ? Smi::FromInt(3) // 3 == "always". | |
| 5818 : Smi::FromInt(2); // 2 == "no". | |
| 5819 } | |
| 5820 if (FLAG_deopt_every_n_times) { | |
| 5821 return Smi::FromInt(6); // 6 == "maybe deopted". | |
| 5822 } | |
| 5823 if (function->IsOptimized() && function->code()->is_turbofanned()) { | |
| 5824 return Smi::FromInt(7); // 7 == "TurboFan compiler". | |
| 5825 } | |
| 5826 return function->IsOptimized() ? Smi::FromInt(1) // 1 == "yes". | |
| 5827 : Smi::FromInt(2); // 2 == "no". | |
| 5828 } | |
| 5829 | |
| 5830 | |
| 5831 RUNTIME_FUNCTION(Runtime_UnblockConcurrentRecompilation) { | |
| 5832 DCHECK(args.length() == 0); | |
| 5833 RUNTIME_ASSERT(FLAG_block_concurrent_recompilation); | |
| 5834 RUNTIME_ASSERT(isolate->concurrent_recompilation_enabled()); | |
| 5835 isolate->optimizing_compiler_thread()->Unblock(); | |
| 5836 return isolate->heap()->undefined_value(); | |
| 5837 } | |
| 5838 | |
| 5839 | |
| 5840 RUNTIME_FUNCTION(Runtime_GetOptimizationCount) { | |
| 5841 HandleScope scope(isolate); | |
| 5842 DCHECK(args.length() == 1); | |
| 5843 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); | |
| 5844 return Smi::FromInt(function->shared()->opt_count()); | |
| 5845 } | |
| 5846 | |
| 5847 | |
| 5848 static bool IsSuitableForOnStackReplacement(Isolate* isolate, | |
| 5849 Handle<JSFunction> function, | |
| 5850 Handle<Code> current_code) { | |
| 5851 // Keep track of whether we've succeeded in optimizing. | |
| 5852 if (!isolate->use_crankshaft() || !current_code->optimizable()) return false; | |
| 5853 // If we are trying to do OSR when there are already optimized | |
| 5854 // activations of the function, it means (a) the function is directly or | |
| 5855 // indirectly recursive and (b) an optimized invocation has been | |
| 5856 // deoptimized so that we are currently in an unoptimized activation. | |
| 5857 // Check for optimized activations of this function. | |
| 5858 for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) { | |
| 5859 JavaScriptFrame* frame = it.frame(); | |
| 5860 if (frame->is_optimized() && frame->function() == *function) return false; | |
| 5861 } | |
| 5862 | |
| 5863 return true; | |
| 5864 } | |
| 5865 | |
| 5866 | |
| 5867 RUNTIME_FUNCTION(Runtime_CompileForOnStackReplacement) { | |
| 5868 HandleScope scope(isolate); | |
| 5869 DCHECK(args.length() == 1); | |
| 5870 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); | |
| 5871 Handle<Code> caller_code(function->shared()->code()); | |
| 5872 | |
| 5873 // We're not prepared to handle a function with arguments object. | |
| 5874 DCHECK(!function->shared()->uses_arguments()); | |
| 5875 | |
| 5876 RUNTIME_ASSERT(FLAG_use_osr); | |
| 5877 | |
| 5878 // Passing the PC in the javascript frame from the caller directly is | |
| 5879 // not GC safe, so we walk the stack to get it. | |
| 5880 JavaScriptFrameIterator it(isolate); | |
| 5881 JavaScriptFrame* frame = it.frame(); | |
| 5882 if (!caller_code->contains(frame->pc())) { | |
| 5883 // Code on the stack may not be the code object referenced by the shared | |
| 5884 // function info. It may have been replaced to include deoptimization data. | |
| 5885 caller_code = Handle<Code>(frame->LookupCode()); | |
| 5886 } | |
| 5887 | |
| 5888 uint32_t pc_offset = | |
| 5889 static_cast<uint32_t>(frame->pc() - caller_code->instruction_start()); | |
| 5890 | |
| 5891 #ifdef DEBUG | |
| 5892 DCHECK_EQ(frame->function(), *function); | |
| 5893 DCHECK_EQ(frame->LookupCode(), *caller_code); | |
| 5894 DCHECK(caller_code->contains(frame->pc())); | |
| 5895 #endif // DEBUG | |
| 5896 | |
| 5897 | |
| 5898 BailoutId ast_id = caller_code->TranslatePcOffsetToAstId(pc_offset); | |
| 5899 DCHECK(!ast_id.IsNone()); | |
| 5900 | |
| 5901 Compiler::ConcurrencyMode mode = | |
| 5902 isolate->concurrent_osr_enabled() && | |
| 5903 (function->shared()->ast_node_count() > 512) | |
| 5904 ? Compiler::CONCURRENT | |
| 5905 : Compiler::NOT_CONCURRENT; | |
| 5906 Handle<Code> result = Handle<Code>::null(); | |
| 5907 | |
| 5908 OptimizedCompileJob* job = NULL; | |
| 5909 if (mode == Compiler::CONCURRENT) { | |
| 5910 // Gate the OSR entry with a stack check. | |
| 5911 BackEdgeTable::AddStackCheck(caller_code, pc_offset); | |
| 5912 // Poll already queued compilation jobs. | |
| 5913 OptimizingCompilerThread* thread = isolate->optimizing_compiler_thread(); | |
| 5914 if (thread->IsQueuedForOSR(function, ast_id)) { | |
| 5915 if (FLAG_trace_osr) { | |
| 5916 PrintF("[OSR - Still waiting for queued: "); | |
| 5917 function->PrintName(); | |
| 5918 PrintF(" at AST id %d]\n", ast_id.ToInt()); | |
| 5919 } | |
| 5920 return NULL; | |
| 5921 } | |
| 5922 | |
| 5923 job = thread->FindReadyOSRCandidate(function, ast_id); | |
| 5924 } | |
| 5925 | |
| 5926 if (job != NULL) { | |
| 5927 if (FLAG_trace_osr) { | |
| 5928 PrintF("[OSR - Found ready: "); | |
| 5929 function->PrintName(); | |
| 5930 PrintF(" at AST id %d]\n", ast_id.ToInt()); | |
| 5931 } | |
| 5932 result = Compiler::GetConcurrentlyOptimizedCode(job); | |
| 5933 } else if (IsSuitableForOnStackReplacement(isolate, function, caller_code)) { | |
| 5934 if (FLAG_trace_osr) { | |
| 5935 PrintF("[OSR - Compiling: "); | |
| 5936 function->PrintName(); | |
| 5937 PrintF(" at AST id %d]\n", ast_id.ToInt()); | |
| 5938 } | |
| 5939 MaybeHandle<Code> maybe_result = | |
| 5940 Compiler::GetOptimizedCode(function, caller_code, mode, ast_id); | |
| 5941 if (maybe_result.ToHandle(&result) && | |
| 5942 result.is_identical_to(isolate->builtins()->InOptimizationQueue())) { | |
| 5943 // Optimization is queued. Return to check later. | |
| 5944 return NULL; | |
| 5945 } | |
| 5946 } | |
| 5947 | |
| 5948 // Revert the patched back edge table, regardless of whether OSR succeeds. | |
| 5949 BackEdgeTable::Revert(isolate, *caller_code); | |
| 5950 | |
| 5951 // Check whether we ended up with usable optimized code. | |
| 5952 if (!result.is_null() && result->kind() == Code::OPTIMIZED_FUNCTION) { | |
| 5953 DeoptimizationInputData* data = | |
| 5954 DeoptimizationInputData::cast(result->deoptimization_data()); | |
| 5955 | |
| 5956 if (data->OsrPcOffset()->value() >= 0) { | |
| 5957 DCHECK(BailoutId(data->OsrAstId()->value()) == ast_id); | |
| 5958 if (FLAG_trace_osr) { | |
| 5959 PrintF("[OSR - Entry at AST id %d, offset %d in optimized code]\n", | |
| 5960 ast_id.ToInt(), data->OsrPcOffset()->value()); | |
| 5961 } | |
| 5962 // TODO(titzer): this is a massive hack to make the deopt counts | |
| 5963 // match. Fix heuristics for reenabling optimizations! | |
| 5964 function->shared()->increment_deopt_count(); | |
| 5965 | |
| 5966 // TODO(titzer): Do not install code into the function. | |
| 5967 function->ReplaceCode(*result); | |
| 5968 return *result; | |
| 5969 } | |
| 5970 } | |
| 5971 | |
| 5972 // Failed. | |
| 5973 if (FLAG_trace_osr) { | |
| 5974 PrintF("[OSR - Failed: "); | |
| 5975 function->PrintName(); | |
| 5976 PrintF(" at AST id %d]\n", ast_id.ToInt()); | |
| 5977 } | |
| 5978 | |
| 5979 if (!function->IsOptimized()) { | |
| 5980 function->ReplaceCode(function->shared()->code()); | |
| 5981 } | |
| 5982 return NULL; | |
| 5983 } | |
| 5984 | |
| 5985 | |
| 5986 RUNTIME_FUNCTION(Runtime_SetAllocationTimeout) { | |
| 5987 SealHandleScope shs(isolate); | |
| 5988 DCHECK(args.length() == 2 || args.length() == 3); | |
| 5989 #ifdef DEBUG | |
| 5990 CONVERT_SMI_ARG_CHECKED(interval, 0); | |
| 5991 CONVERT_SMI_ARG_CHECKED(timeout, 1); | |
| 5992 isolate->heap()->set_allocation_timeout(timeout); | |
| 5993 FLAG_gc_interval = interval; | |
| 5994 if (args.length() == 3) { | |
| 5995 // Enable/disable inline allocation if requested. | |
| 5996 CONVERT_BOOLEAN_ARG_CHECKED(inline_allocation, 2); | |
| 5997 if (inline_allocation) { | |
| 5998 isolate->heap()->EnableInlineAllocation(); | |
| 5999 } else { | |
| 6000 isolate->heap()->DisableInlineAllocation(); | |
| 6001 } | |
| 6002 } | |
| 6003 #endif | |
| 6004 return isolate->heap()->undefined_value(); | |
| 6005 } | |
| 6006 | |
| 6007 | 3722 |
| 6008 RUNTIME_FUNCTION(Runtime_CheckIsBootstrapping) { | 3723 RUNTIME_FUNCTION(Runtime_CheckIsBootstrapping) { |
| 6009 SealHandleScope shs(isolate); | 3724 SealHandleScope shs(isolate); |
| 6010 DCHECK(args.length() == 0); | 3725 DCHECK(args.length() == 0); |
| 6011 RUNTIME_ASSERT(isolate->bootstrapper()->IsActive()); | 3726 RUNTIME_ASSERT(isolate->bootstrapper()->IsActive()); |
| 6012 return isolate->heap()->undefined_value(); | 3727 return isolate->heap()->undefined_value(); |
| 6013 } | 3728 } |
| 6014 | 3729 |
| 6015 | 3730 |
| 6016 RUNTIME_FUNCTION(Runtime_GetRootNaN) { | 3731 RUNTIME_FUNCTION(Runtime_GetRootNaN) { |
| (...skipping 581 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6598 // First check if this is a real stack overflow. | 4313 // First check if this is a real stack overflow. |
| 6599 StackLimitCheck check(isolate); | 4314 StackLimitCheck check(isolate); |
| 6600 if (check.JsHasOverflowed()) { | 4315 if (check.JsHasOverflowed()) { |
| 6601 return isolate->StackOverflow(); | 4316 return isolate->StackOverflow(); |
| 6602 } | 4317 } |
| 6603 | 4318 |
| 6604 return isolate->stack_guard()->HandleInterrupts(); | 4319 return isolate->stack_guard()->HandleInterrupts(); |
| 6605 } | 4320 } |
| 6606 | 4321 |
| 6607 | 4322 |
| 6608 RUNTIME_FUNCTION(Runtime_TryInstallOptimizedCode) { | |
| 6609 HandleScope scope(isolate); | |
| 6610 DCHECK(args.length() == 1); | |
| 6611 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); | |
| 6612 | |
| 6613 // First check if this is a real stack overflow. | |
| 6614 StackLimitCheck check(isolate); | |
| 6615 if (check.JsHasOverflowed()) { | |
| 6616 SealHandleScope shs(isolate); | |
| 6617 return isolate->StackOverflow(); | |
| 6618 } | |
| 6619 | |
| 6620 isolate->optimizing_compiler_thread()->InstallOptimizedFunctions(); | |
| 6621 return (function->IsOptimized()) ? function->code() | |
| 6622 : function->shared()->code(); | |
| 6623 } | |
| 6624 | |
| 6625 | |
| 6626 RUNTIME_FUNCTION(Runtime_Interrupt) { | 4323 RUNTIME_FUNCTION(Runtime_Interrupt) { |
| 6627 SealHandleScope shs(isolate); | 4324 SealHandleScope shs(isolate); |
| 6628 DCHECK(args.length() == 0); | 4325 DCHECK(args.length() == 0); |
| 6629 return isolate->stack_guard()->HandleInterrupts(); | 4326 return isolate->stack_guard()->HandleInterrupts(); |
| 6630 } | 4327 } |
| 6631 | 4328 |
| 6632 | 4329 |
| 6633 static int StackSize(Isolate* isolate) { | 4330 static int StackSize(Isolate* isolate) { |
| 6634 int n = 0; | 4331 int n = 0; |
| 6635 for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) n++; | 4332 for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) n++; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6670 | 4367 |
| 6671 RUNTIME_FUNCTION(Runtime_TraceExit) { | 4368 RUNTIME_FUNCTION(Runtime_TraceExit) { |
| 6672 SealHandleScope shs(isolate); | 4369 SealHandleScope shs(isolate); |
| 6673 DCHECK(args.length() == 1); | 4370 DCHECK(args.length() == 1); |
| 6674 CONVERT_ARG_CHECKED(Object, obj, 0); | 4371 CONVERT_ARG_CHECKED(Object, obj, 0); |
| 6675 PrintTransition(isolate, obj); | 4372 PrintTransition(isolate, obj); |
| 6676 return obj; // return TOS | 4373 return obj; // return TOS |
| 6677 } | 4374 } |
| 6678 | 4375 |
| 6679 | 4376 |
| 6680 RUNTIME_FUNCTION(Runtime_DebugPrint) { | |
| 6681 SealHandleScope shs(isolate); | |
| 6682 DCHECK(args.length() == 1); | |
| 6683 | |
| 6684 OFStream os(stdout); | |
| 6685 #ifdef DEBUG | |
| 6686 if (args[0]->IsString()) { | |
| 6687 // If we have a string, assume it's a code "marker" | |
| 6688 // and print some interesting cpu debugging info. | |
| 6689 JavaScriptFrameIterator it(isolate); | |
| 6690 JavaScriptFrame* frame = it.frame(); | |
| 6691 os << "fp = " << frame->fp() << ", sp = " << frame->sp() | |
| 6692 << ", caller_sp = " << frame->caller_sp() << ": "; | |
| 6693 } else { | |
| 6694 os << "DebugPrint: "; | |
| 6695 } | |
| 6696 args[0]->Print(os); | |
| 6697 if (args[0]->IsHeapObject()) { | |
| 6698 os << "\n"; | |
| 6699 HeapObject::cast(args[0])->map()->Print(os); | |
| 6700 } | |
| 6701 #else | |
| 6702 // ShortPrint is available in release mode. Print is not. | |
| 6703 os << Brief(args[0]); | |
| 6704 #endif | |
| 6705 os << endl; | |
| 6706 | |
| 6707 return args[0]; // return TOS | |
| 6708 } | |
| 6709 | |
| 6710 | |
| 6711 RUNTIME_FUNCTION(Runtime_DebugTrace) { | |
| 6712 SealHandleScope shs(isolate); | |
| 6713 DCHECK(args.length() == 0); | |
| 6714 isolate->PrintStack(stdout); | |
| 6715 return isolate->heap()->undefined_value(); | |
| 6716 } | |
| 6717 | |
| 6718 | |
| 6719 RUNTIME_FUNCTION(Runtime_DateCurrentTime) { | 4377 RUNTIME_FUNCTION(Runtime_DateCurrentTime) { |
| 6720 HandleScope scope(isolate); | 4378 HandleScope scope(isolate); |
| 6721 DCHECK(args.length() == 0); | 4379 DCHECK(args.length() == 0); |
| 6722 if (FLAG_log_timer_events) LOG(isolate, CurrentTimeEvent()); | 4380 if (FLAG_log_timer_events) LOG(isolate, CurrentTimeEvent()); |
| 6723 | 4381 |
| 6724 // According to ECMA-262, section 15.9.1, page 117, the precision of | 4382 // According to ECMA-262, section 15.9.1, page 117, the precision of |
| 6725 // the number in a Date object representing a particular instant in | 4383 // the number in a Date object representing a particular instant in |
| 6726 // time is milliseconds. Therefore, we floor the result of getting | 4384 // time is milliseconds. Therefore, we floor the result of getting |
| 6727 // the OS time. | 4385 // the OS time. |
| 6728 double millis; | 4386 double millis; |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6831 RUNTIME_FUNCTION(Runtime_IsAttachedGlobal) { | 4489 RUNTIME_FUNCTION(Runtime_IsAttachedGlobal) { |
| 6832 SealHandleScope shs(isolate); | 4490 SealHandleScope shs(isolate); |
| 6833 DCHECK(args.length() == 1); | 4491 DCHECK(args.length() == 1); |
| 6834 CONVERT_ARG_CHECKED(Object, global, 0); | 4492 CONVERT_ARG_CHECKED(Object, global, 0); |
| 6835 if (!global->IsJSGlobalObject()) return isolate->heap()->false_value(); | 4493 if (!global->IsJSGlobalObject()) return isolate->heap()->false_value(); |
| 6836 return isolate->heap()->ToBoolean( | 4494 return isolate->heap()->ToBoolean( |
| 6837 !JSGlobalObject::cast(global)->IsDetached()); | 4495 !JSGlobalObject::cast(global)->IsDetached()); |
| 6838 } | 4496 } |
| 6839 | 4497 |
| 6840 | 4498 |
| 6841 bool CodeGenerationFromStringsAllowed(Isolate* isolate, | |
| 6842 Handle<Context> context) { | |
| 6843 DCHECK(context->allow_code_gen_from_strings()->IsFalse()); | |
| 6844 // Check with callback if set. | |
| 6845 AllowCodeGenerationFromStringsCallback callback = | |
| 6846 isolate->allow_code_gen_callback(); | |
| 6847 if (callback == NULL) { | |
| 6848 // No callback set and code generation disallowed. | |
| 6849 return false; | |
| 6850 } else { | |
| 6851 // Callback set. Let it decide if code generation is allowed. | |
| 6852 VMState<EXTERNAL> state(isolate); | |
| 6853 return callback(v8::Utils::ToLocal(context)); | |
| 6854 } | |
| 6855 } | |
| 6856 | |
| 6857 | |
| 6858 RUNTIME_FUNCTION(Runtime_CompileString) { | |
| 6859 HandleScope scope(isolate); | |
| 6860 DCHECK(args.length() == 2); | |
| 6861 CONVERT_ARG_HANDLE_CHECKED(String, source, 0); | |
| 6862 CONVERT_BOOLEAN_ARG_CHECKED(function_literal_only, 1); | |
| 6863 | |
| 6864 // Extract native context. | |
| 6865 Handle<Context> context(isolate->native_context()); | |
| 6866 | |
| 6867 // Check if native context allows code generation from | |
| 6868 // strings. Throw an exception if it doesn't. | |
| 6869 if (context->allow_code_gen_from_strings()->IsFalse() && | |
| 6870 !CodeGenerationFromStringsAllowed(isolate, context)) { | |
| 6871 Handle<Object> error_message = | |
| 6872 context->ErrorMessageForCodeGenerationFromStrings(); | |
| 6873 THROW_NEW_ERROR_RETURN_FAILURE( | |
| 6874 isolate, NewEvalError("code_gen_from_strings", | |
| 6875 HandleVector<Object>(&error_message, 1))); | |
| 6876 } | |
| 6877 | |
| 6878 // Compile source string in the native context. | |
| 6879 ParseRestriction restriction = function_literal_only | |
| 6880 ? ONLY_SINGLE_FUNCTION_LITERAL | |
| 6881 : NO_PARSE_RESTRICTION; | |
| 6882 Handle<JSFunction> fun; | |
| 6883 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | |
| 6884 isolate, fun, | |
| 6885 Compiler::GetFunctionFromEval(source, context, SLOPPY, restriction, | |
| 6886 RelocInfo::kNoPosition)); | |
| 6887 return *fun; | |
| 6888 } | |
| 6889 | |
| 6890 | |
| 6891 static ObjectPair CompileGlobalEval(Isolate* isolate, Handle<String> source, | |
| 6892 Handle<Object> receiver, | |
| 6893 StrictMode strict_mode, | |
| 6894 int scope_position) { | |
| 6895 Handle<Context> context = Handle<Context>(isolate->context()); | |
| 6896 Handle<Context> native_context = Handle<Context>(context->native_context()); | |
| 6897 | |
| 6898 // Check if native context allows code generation from | |
| 6899 // strings. Throw an exception if it doesn't. | |
| 6900 if (native_context->allow_code_gen_from_strings()->IsFalse() && | |
| 6901 !CodeGenerationFromStringsAllowed(isolate, native_context)) { | |
| 6902 Handle<Object> error_message = | |
| 6903 native_context->ErrorMessageForCodeGenerationFromStrings(); | |
| 6904 Handle<Object> error; | |
| 6905 MaybeHandle<Object> maybe_error = isolate->factory()->NewEvalError( | |
| 6906 "code_gen_from_strings", HandleVector<Object>(&error_message, 1)); | |
| 6907 if (maybe_error.ToHandle(&error)) isolate->Throw(*error); | |
| 6908 return MakePair(isolate->heap()->exception(), NULL); | |
| 6909 } | |
| 6910 | |
| 6911 // Deal with a normal eval call with a string argument. Compile it | |
| 6912 // and return the compiled function bound in the local context. | |
| 6913 static const ParseRestriction restriction = NO_PARSE_RESTRICTION; | |
| 6914 Handle<JSFunction> compiled; | |
| 6915 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | |
| 6916 isolate, compiled, | |
| 6917 Compiler::GetFunctionFromEval(source, context, strict_mode, restriction, | |
| 6918 scope_position), | |
| 6919 MakePair(isolate->heap()->exception(), NULL)); | |
| 6920 return MakePair(*compiled, *receiver); | |
| 6921 } | |
| 6922 | |
| 6923 | |
| 6924 RUNTIME_FUNCTION_RETURN_PAIR(Runtime_ResolvePossiblyDirectEval) { | |
| 6925 HandleScope scope(isolate); | |
| 6926 DCHECK(args.length() == 5); | |
| 6927 | |
| 6928 Handle<Object> callee = args.at<Object>(0); | |
| 6929 | |
| 6930 // If "eval" didn't refer to the original GlobalEval, it's not a | |
| 6931 // direct call to eval. | |
| 6932 // (And even if it is, but the first argument isn't a string, just let | |
| 6933 // execution default to an indirect call to eval, which will also return | |
| 6934 // the first argument without doing anything). | |
| 6935 if (*callee != isolate->native_context()->global_eval_fun() || | |
| 6936 !args[1]->IsString()) { | |
| 6937 return MakePair(*callee, isolate->heap()->undefined_value()); | |
| 6938 } | |
| 6939 | |
| 6940 DCHECK(args[3]->IsSmi()); | |
| 6941 DCHECK(args.smi_at(3) == SLOPPY || args.smi_at(3) == STRICT); | |
| 6942 StrictMode strict_mode = static_cast<StrictMode>(args.smi_at(3)); | |
| 6943 DCHECK(args[4]->IsSmi()); | |
| 6944 return CompileGlobalEval(isolate, args.at<String>(1), args.at<Object>(2), | |
| 6945 strict_mode, args.smi_at(4)); | |
| 6946 } | |
| 6947 | |
| 6948 | |
| 6949 RUNTIME_FUNCTION(Runtime_AllocateInNewSpace) { | 4499 RUNTIME_FUNCTION(Runtime_AllocateInNewSpace) { |
| 6950 HandleScope scope(isolate); | 4500 HandleScope scope(isolate); |
| 6951 DCHECK(args.length() == 1); | 4501 DCHECK(args.length() == 1); |
| 6952 CONVERT_SMI_ARG_CHECKED(size, 0); | 4502 CONVERT_SMI_ARG_CHECKED(size, 0); |
| 6953 RUNTIME_ASSERT(IsAligned(size, kPointerSize)); | 4503 RUNTIME_ASSERT(IsAligned(size, kPointerSize)); |
| 6954 RUNTIME_ASSERT(size > 0); | 4504 RUNTIME_ASSERT(size > 0); |
| 6955 RUNTIME_ASSERT(size <= Page::kMaxRegularHeapObjectSize); | 4505 RUNTIME_ASSERT(size <= Page::kMaxRegularHeapObjectSize); |
| 6956 return *isolate->factory()->NewFillerObject(size, false, NEW_SPACE); | 4506 return *isolate->factory()->NewFillerObject(size, false, NEW_SPACE); |
| 6957 } | 4507 } |
| 6958 | 4508 |
| (...skipping 721 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7680 | 5230 |
| 7681 if (visitor.exceeds_array_limit()) { | 5231 if (visitor.exceeds_array_limit()) { |
| 7682 THROW_NEW_ERROR_RETURN_FAILURE( | 5232 THROW_NEW_ERROR_RETURN_FAILURE( |
| 7683 isolate, | 5233 isolate, |
| 7684 NewRangeError("invalid_array_length", HandleVector<Object>(NULL, 0))); | 5234 NewRangeError("invalid_array_length", HandleVector<Object>(NULL, 0))); |
| 7685 } | 5235 } |
| 7686 return *visitor.ToArray(); | 5236 return *visitor.ToArray(); |
| 7687 } | 5237 } |
| 7688 | 5238 |
| 7689 | 5239 |
| 7690 // This will not allocate (flatten the string), but it may run | |
| 7691 // very slowly for very deeply nested ConsStrings. For debugging use only. | |
| 7692 RUNTIME_FUNCTION(Runtime_GlobalPrint) { | |
| 7693 SealHandleScope shs(isolate); | |
| 7694 DCHECK(args.length() == 1); | |
| 7695 | |
| 7696 CONVERT_ARG_CHECKED(String, string, 0); | |
| 7697 ConsStringIteratorOp op; | |
| 7698 StringCharacterStream stream(string, &op); | |
| 7699 while (stream.HasMore()) { | |
| 7700 uint16_t character = stream.GetNext(); | |
| 7701 PrintF("%c", character); | |
| 7702 } | |
| 7703 return string; | |
| 7704 } | |
| 7705 | |
| 7706 | |
| 7707 // Moves all own elements of an object, that are below a limit, to positions | 5240 // Moves all own elements of an object, that are below a limit, to positions |
| 7708 // starting at zero. All undefined values are placed after non-undefined values, | 5241 // starting at zero. All undefined values are placed after non-undefined values, |
| 7709 // and are followed by non-existing element. Does not change the length | 5242 // and are followed by non-existing element. Does not change the length |
| 7710 // property. | 5243 // property. |
| 7711 // Returns the number of non-undefined elements collected. | 5244 // Returns the number of non-undefined elements collected. |
| 7712 // Returns -1 if hole removal is not supported by this method. | 5245 // Returns -1 if hole removal is not supported by this method. |
| 7713 RUNTIME_FUNCTION(Runtime_RemoveArrayHoles) { | 5246 RUNTIME_FUNCTION(Runtime_RemoveArrayHoles) { |
| 7714 HandleScope scope(isolate); | 5247 HandleScope scope(isolate); |
| 7715 DCHECK(args.length() == 2); | 5248 DCHECK(args.length() == 2); |
| 7716 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); | 5249 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); |
| (...skipping 2586 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10303 Handle<Script> script(Script::cast(script_wrapper->value())); | 7836 Handle<Script> script(Script::cast(script_wrapper->value())); |
| 10304 | 7837 |
| 10305 int compilation_state = script->compilation_state(); | 7838 int compilation_state = script->compilation_state(); |
| 10306 RUNTIME_ASSERT(compilation_state == Script::COMPILATION_STATE_INITIAL); | 7839 RUNTIME_ASSERT(compilation_state == Script::COMPILATION_STATE_INITIAL); |
| 10307 script->set_source(*source); | 7840 script->set_source(*source); |
| 10308 | 7841 |
| 10309 return isolate->heap()->undefined_value(); | 7842 return isolate->heap()->undefined_value(); |
| 10310 } | 7843 } |
| 10311 | 7844 |
| 10312 | 7845 |
| 10313 RUNTIME_FUNCTION(Runtime_SystemBreak) { | |
| 10314 SealHandleScope shs(isolate); | |
| 10315 DCHECK(args.length() == 0); | |
| 10316 base::OS::DebugBreak(); | |
| 10317 return isolate->heap()->undefined_value(); | |
| 10318 } | |
| 10319 | |
| 10320 | |
| 10321 RUNTIME_FUNCTION(Runtime_DebugDisassembleFunction) { | 7846 RUNTIME_FUNCTION(Runtime_DebugDisassembleFunction) { |
| 10322 HandleScope scope(isolate); | 7847 HandleScope scope(isolate); |
| 10323 #ifdef DEBUG | 7848 #ifdef DEBUG |
| 10324 DCHECK(args.length() == 1); | 7849 DCHECK(args.length() == 1); |
| 10325 // Get the function and make sure it is compiled. | 7850 // Get the function and make sure it is compiled. |
| 10326 CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0); | 7851 CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0); |
| 10327 if (!Compiler::EnsureCompiled(func, KEEP_EXCEPTION)) { | 7852 if (!Compiler::EnsureCompiled(func, KEEP_EXCEPTION)) { |
| 10328 return isolate->heap()->exception(); | 7853 return isolate->heap()->exception(); |
| 10329 } | 7854 } |
| 10330 OFStream os(stdout); | 7855 OFStream os(stdout); |
| (...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10692 DebugScope debug_scope(isolate->debug()); | 8217 DebugScope debug_scope(isolate->debug()); |
| 10693 maybe_result = Execution::Call(isolate, function, | 8218 maybe_result = Execution::Call(isolate, function, |
| 10694 handle(function->global_proxy()), 0, NULL); | 8219 handle(function->global_proxy()), 0, NULL); |
| 10695 } | 8220 } |
| 10696 Handle<Object> result; | 8221 Handle<Object> result; |
| 10697 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, maybe_result); | 8222 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, maybe_result); |
| 10698 return *result; | 8223 return *result; |
| 10699 } | 8224 } |
| 10700 | 8225 |
| 10701 | 8226 |
| 10702 // Sets a v8 flag. | |
| 10703 RUNTIME_FUNCTION(Runtime_SetFlags) { | |
| 10704 SealHandleScope shs(isolate); | |
| 10705 DCHECK(args.length() == 1); | |
| 10706 CONVERT_ARG_CHECKED(String, arg, 0); | |
| 10707 SmartArrayPointer<char> flags = | |
| 10708 arg->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL); | |
| 10709 FlagList::SetFlagsFromString(flags.get(), StrLength(flags.get())); | |
| 10710 return isolate->heap()->undefined_value(); | |
| 10711 } | |
| 10712 | |
| 10713 | |
| 10714 // Performs a GC. | 8227 // Performs a GC. |
| 10715 // Presently, it only does a full GC. | 8228 // Presently, it only does a full GC. |
| 10716 RUNTIME_FUNCTION(Runtime_CollectGarbage) { | 8229 RUNTIME_FUNCTION(Runtime_CollectGarbage) { |
| 10717 SealHandleScope shs(isolate); | 8230 SealHandleScope shs(isolate); |
| 10718 DCHECK(args.length() == 1); | 8231 DCHECK(args.length() == 1); |
| 10719 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, "%CollectGarbage"); | 8232 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, "%CollectGarbage"); |
| 10720 return isolate->heap()->undefined_value(); | 8233 return isolate->heap()->undefined_value(); |
| 10721 } | 8234 } |
| 10722 | 8235 |
| 10723 | 8236 |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10866 RUNTIME_ASSERT(0 <= offset && offset < code->Size()); | 8379 RUNTIME_ASSERT(0 <= offset && offset < code->Size()); |
| 10867 Address pc = code->address() + offset; | 8380 Address pc = code->address() + offset; |
| 10868 | 8381 |
| 10869 return Smi::FromInt(code->SourcePosition(pc)); | 8382 return Smi::FromInt(code->SourcePosition(pc)); |
| 10870 } | 8383 } |
| 10871 | 8384 |
| 10872 return isolate->heap()->undefined_value(); | 8385 return isolate->heap()->undefined_value(); |
| 10873 } | 8386 } |
| 10874 | 8387 |
| 10875 | 8388 |
| 10876 RUNTIME_FUNCTION(Runtime_Abort) { | |
| 10877 SealHandleScope shs(isolate); | |
| 10878 DCHECK(args.length() == 1); | |
| 10879 CONVERT_SMI_ARG_CHECKED(message_id, 0); | |
| 10880 const char* message = | |
| 10881 GetBailoutReason(static_cast<BailoutReason>(message_id)); | |
| 10882 base::OS::PrintError("abort: %s\n", message); | |
| 10883 isolate->PrintStack(stderr); | |
| 10884 base::OS::Abort(); | |
| 10885 UNREACHABLE(); | |
| 10886 return NULL; | |
| 10887 } | |
| 10888 | |
| 10889 | |
| 10890 RUNTIME_FUNCTION(Runtime_AbortJS) { | |
| 10891 HandleScope scope(isolate); | |
| 10892 DCHECK(args.length() == 1); | |
| 10893 CONVERT_ARG_HANDLE_CHECKED(String, message, 0); | |
| 10894 base::OS::PrintError("abort: %s\n", message->ToCString().get()); | |
| 10895 isolate->PrintStack(stderr); | |
| 10896 base::OS::Abort(); | |
| 10897 UNREACHABLE(); | |
| 10898 return NULL; | |
| 10899 } | |
| 10900 | |
| 10901 | |
| 10902 RUNTIME_FUNCTION(Runtime_FlattenString) { | |
| 10903 HandleScope scope(isolate); | |
| 10904 DCHECK(args.length() == 1); | |
| 10905 CONVERT_ARG_HANDLE_CHECKED(String, str, 0); | |
| 10906 return *String::Flatten(str); | |
| 10907 } | |
| 10908 | |
| 10909 | |
| 10910 RUNTIME_FUNCTION(Runtime_NotifyContextDisposed) { | |
| 10911 HandleScope scope(isolate); | |
| 10912 DCHECK(args.length() == 0); | |
| 10913 isolate->heap()->NotifyContextDisposed(); | |
| 10914 return isolate->heap()->undefined_value(); | |
| 10915 } | |
| 10916 | |
| 10917 | |
| 10918 RUNTIME_FUNCTION(Runtime_LoadMutableDouble) { | 8389 RUNTIME_FUNCTION(Runtime_LoadMutableDouble) { |
| 10919 HandleScope scope(isolate); | 8390 HandleScope scope(isolate); |
| 10920 DCHECK(args.length() == 2); | 8391 DCHECK(args.length() == 2); |
| 10921 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); | 8392 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); |
| 10922 CONVERT_ARG_HANDLE_CHECKED(Smi, index, 1); | 8393 CONVERT_ARG_HANDLE_CHECKED(Smi, index, 1); |
| 10923 RUNTIME_ASSERT((index->value() & 1) == 1); | 8394 RUNTIME_ASSERT((index->value() & 1) == 1); |
| 10924 FieldIndex field_index = | 8395 FieldIndex field_index = |
| 10925 FieldIndex::ForLoadByFieldIndex(object->map(), index->value()); | 8396 FieldIndex::ForLoadByFieldIndex(object->map(), index->value()); |
| 10926 if (field_index.is_inobject()) { | 8397 if (field_index.is_inobject()) { |
| 10927 RUNTIME_ASSERT(field_index.property_index() < | 8398 RUNTIME_ASSERT(field_index.property_index() < |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11107 } | 8578 } |
| 11108 #endif | 8579 #endif |
| 11109 | 8580 |
| 11110 | 8581 |
| 11111 RUNTIME_FUNCTION(Runtime_IS_VAR) { | 8582 RUNTIME_FUNCTION(Runtime_IS_VAR) { |
| 11112 UNREACHABLE(); // implemented as macro in the parser | 8583 UNREACHABLE(); // implemented as macro in the parser |
| 11113 return NULL; | 8584 return NULL; |
| 11114 } | 8585 } |
| 11115 | 8586 |
| 11116 | 8587 |
| 11117 #define ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(Name) \ | |
| 11118 RUNTIME_FUNCTION(Runtime_Has##Name) { \ | |
| 11119 CONVERT_ARG_CHECKED(JSObject, obj, 0); \ | |
| 11120 return isolate->heap()->ToBoolean(obj->Has##Name()); \ | |
| 11121 } | |
| 11122 | |
| 11123 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiElements) | |
| 11124 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastObjectElements) | |
| 11125 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiOrObjectElements) | |
| 11126 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastDoubleElements) | |
| 11127 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastHoleyElements) | |
| 11128 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(DictionaryElements) | |
| 11129 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(SloppyArgumentsElements) | |
| 11130 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalArrayElements) | |
| 11131 // Properties test sitting with elements tests - not fooling anyone. | |
| 11132 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastProperties) | |
| 11133 | |
| 11134 #undef ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION | |
| 11135 | |
| 11136 | |
| 11137 #define TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION(Type, type, TYPE, ctype, size) \ | 8588 #define TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION(Type, type, TYPE, ctype, size) \ |
| 11138 RUNTIME_FUNCTION(Runtime_HasExternal##Type##Elements) { \ | 8589 RUNTIME_FUNCTION(Runtime_HasExternal##Type##Elements) { \ |
| 11139 CONVERT_ARG_CHECKED(JSObject, obj, 0); \ | 8590 CONVERT_ARG_CHECKED(JSObject, obj, 0); \ |
| 11140 return isolate->heap()->ToBoolean(obj->HasExternal##Type##Elements()); \ | 8591 return isolate->heap()->ToBoolean(obj->HasExternal##Type##Elements()); \ |
| 11141 } | 8592 } |
| 11142 | 8593 |
| 11143 TYPED_ARRAYS(TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION) | 8594 TYPED_ARRAYS(TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION) |
| 11144 | 8595 |
| 11145 #undef TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION | 8596 #undef TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION |
| 11146 | 8597 |
| 11147 | 8598 |
| 11148 #define FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION(Type, type, TYPE, ctype, s) \ | 8599 #define FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION(Type, type, TYPE, ctype, s) \ |
| 11149 RUNTIME_FUNCTION(Runtime_HasFixed##Type##Elements) { \ | 8600 RUNTIME_FUNCTION(Runtime_HasFixed##Type##Elements) { \ |
| 11150 CONVERT_ARG_CHECKED(JSObject, obj, 0); \ | 8601 CONVERT_ARG_CHECKED(JSObject, obj, 0); \ |
| 11151 return isolate->heap()->ToBoolean(obj->HasFixed##Type##Elements()); \ | 8602 return isolate->heap()->ToBoolean(obj->HasFixed##Type##Elements()); \ |
| 11152 } | 8603 } |
| 11153 | 8604 |
| 11154 TYPED_ARRAYS(FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION) | 8605 TYPED_ARRAYS(FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION) |
| 11155 | 8606 |
| 11156 #undef FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION | 8607 #undef FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION |
| 11157 | 8608 |
| 11158 | 8609 |
| 11159 RUNTIME_FUNCTION(Runtime_HaveSameMap) { | |
| 11160 SealHandleScope shs(isolate); | |
| 11161 DCHECK(args.length() == 2); | |
| 11162 CONVERT_ARG_CHECKED(JSObject, obj1, 0); | |
| 11163 CONVERT_ARG_CHECKED(JSObject, obj2, 1); | |
| 11164 return isolate->heap()->ToBoolean(obj1->map() == obj2->map()); | |
| 11165 } | |
| 11166 | |
| 11167 | |
| 11168 RUNTIME_FUNCTION(Runtime_IsJSGlobalProxy) { | 8610 RUNTIME_FUNCTION(Runtime_IsJSGlobalProxy) { |
| 11169 SealHandleScope shs(isolate); | 8611 SealHandleScope shs(isolate); |
| 11170 DCHECK(args.length() == 1); | 8612 DCHECK(args.length() == 1); |
| 11171 CONVERT_ARG_CHECKED(Object, obj, 0); | 8613 CONVERT_ARG_CHECKED(Object, obj, 0); |
| 11172 return isolate->heap()->ToBoolean(obj->IsJSGlobalProxy()); | 8614 return isolate->heap()->ToBoolean(obj->IsJSGlobalProxy()); |
| 11173 } | 8615 } |
| 11174 | 8616 |
| 11175 | 8617 |
| 11176 RUNTIME_FUNCTION(Runtime_IsObserved) { | 8618 RUNTIME_FUNCTION(Runtime_IsObserved) { |
| 11177 SealHandleScope shs(isolate); | 8619 SealHandleScope shs(isolate); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11215 } | 8657 } |
| 11216 | 8658 |
| 11217 | 8659 |
| 11218 RUNTIME_FUNCTION(Runtime_GetObservationState) { | 8660 RUNTIME_FUNCTION(Runtime_GetObservationState) { |
| 11219 SealHandleScope shs(isolate); | 8661 SealHandleScope shs(isolate); |
| 11220 DCHECK(args.length() == 0); | 8662 DCHECK(args.length() == 0); |
| 11221 return isolate->heap()->observation_state(); | 8663 return isolate->heap()->observation_state(); |
| 11222 } | 8664 } |
| 11223 | 8665 |
| 11224 | 8666 |
| 11225 RUNTIME_FUNCTION(Runtime_ObservationWeakMapCreate) { | |
| 11226 HandleScope scope(isolate); | |
| 11227 DCHECK(args.length() == 0); | |
| 11228 // TODO(adamk): Currently this runtime function is only called three times per | |
| 11229 // isolate. If it's called more often, the map should be moved into the | |
| 11230 // strong root list. | |
| 11231 Handle<Map> map = | |
| 11232 isolate->factory()->NewMap(JS_WEAK_MAP_TYPE, JSWeakMap::kSize); | |
| 11233 Handle<JSWeakMap> weakmap = | |
| 11234 Handle<JSWeakMap>::cast(isolate->factory()->NewJSObjectFromMap(map)); | |
| 11235 return *WeakCollectionInitialize(isolate, weakmap); | |
| 11236 } | |
| 11237 | |
| 11238 | |
| 11239 static bool ContextsHaveSameOrigin(Handle<Context> context1, | 8667 static bool ContextsHaveSameOrigin(Handle<Context> context1, |
| 11240 Handle<Context> context2) { | 8668 Handle<Context> context2) { |
| 11241 return context1->security_token() == context2->security_token(); | 8669 return context1->security_token() == context2->security_token(); |
| 11242 } | 8670 } |
| 11243 | 8671 |
| 11244 | 8672 |
| 11245 RUNTIME_FUNCTION(Runtime_ObserverObjectAndRecordHaveSameOrigin) { | 8673 RUNTIME_FUNCTION(Runtime_ObserverObjectAndRecordHaveSameOrigin) { |
| 11246 HandleScope scope(isolate); | 8674 HandleScope scope(isolate); |
| 11247 DCHECK(args.length() == 3); | 8675 DCHECK(args.length() == 3); |
| 11248 CONVERT_ARG_HANDLE_CHECKED(JSFunction, observer, 0); | 8676 CONVERT_ARG_HANDLE_CHECKED(JSFunction, observer, 0); |
| (...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11694 | 9122 |
| 11695 | 9123 |
| 11696 RUNTIME_FUNCTION(RuntimeReference_IsSpecObject) { | 9124 RUNTIME_FUNCTION(RuntimeReference_IsSpecObject) { |
| 11697 SealHandleScope shs(isolate); | 9125 SealHandleScope shs(isolate); |
| 11698 DCHECK(args.length() == 1); | 9126 DCHECK(args.length() == 1); |
| 11699 CONVERT_ARG_CHECKED(Object, obj, 0); | 9127 CONVERT_ARG_CHECKED(Object, obj, 0); |
| 11700 return isolate->heap()->ToBoolean(obj->IsSpecObject()); | 9128 return isolate->heap()->ToBoolean(obj->IsSpecObject()); |
| 11701 } | 9129 } |
| 11702 | 9130 |
| 11703 | 9131 |
| 11704 RUNTIME_FUNCTION(RuntimeReference_MathPow) { | |
| 11705 SealHandleScope shs(isolate); | |
| 11706 return __RT_impl_Runtime_MathPowSlow(args, isolate); | |
| 11707 } | |
| 11708 | |
| 11709 | |
| 11710 RUNTIME_FUNCTION(RuntimeReference_IsMinusZero) { | |
| 11711 SealHandleScope shs(isolate); | |
| 11712 DCHECK(args.length() == 1); | |
| 11713 CONVERT_ARG_CHECKED(Object, obj, 0); | |
| 11714 if (!obj->IsHeapNumber()) return isolate->heap()->false_value(); | |
| 11715 HeapNumber* number = HeapNumber::cast(obj); | |
| 11716 return isolate->heap()->ToBoolean(IsMinusZero(number->value())); | |
| 11717 } | |
| 11718 | |
| 11719 | |
| 11720 RUNTIME_FUNCTION(RuntimeReference_HasCachedArrayIndex) { | 9132 RUNTIME_FUNCTION(RuntimeReference_HasCachedArrayIndex) { |
| 11721 SealHandleScope shs(isolate); | 9133 SealHandleScope shs(isolate); |
| 11722 DCHECK(args.length() == 1); | 9134 DCHECK(args.length() == 1); |
| 11723 return isolate->heap()->false_value(); | 9135 return isolate->heap()->false_value(); |
| 11724 } | 9136 } |
| 11725 | 9137 |
| 11726 | 9138 |
| 11727 RUNTIME_FUNCTION(RuntimeReference_GetCachedArrayIndex) { | 9139 RUNTIME_FUNCTION(RuntimeReference_GetCachedArrayIndex) { |
| 11728 SealHandleScope shs(isolate); | 9140 SealHandleScope shs(isolate); |
| 11729 DCHECK(args.length() == 1); | 9141 DCHECK(args.length() == 1); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11761 | 9173 |
| 11762 RUNTIME_FUNCTION(RuntimeReference_GetFromCache) { | 9174 RUNTIME_FUNCTION(RuntimeReference_GetFromCache) { |
| 11763 HandleScope scope(isolate); | 9175 HandleScope scope(isolate); |
| 11764 DCHECK(args.length() == 2); | 9176 DCHECK(args.length() == 2); |
| 11765 CONVERT_SMI_ARG_CHECKED(id, 0); | 9177 CONVERT_SMI_ARG_CHECKED(id, 0); |
| 11766 args[0] = isolate->native_context()->jsfunction_result_caches()->get(id); | 9178 args[0] = isolate->native_context()->jsfunction_result_caches()->get(id); |
| 11767 return __RT_impl_Runtime_GetFromCache(args, isolate); | 9179 return __RT_impl_Runtime_GetFromCache(args, isolate); |
| 11768 } | 9180 } |
| 11769 | 9181 |
| 11770 | 9182 |
| 11771 RUNTIME_FUNCTION(RuntimeReference_NumberToString) { | |
| 11772 SealHandleScope shs(isolate); | |
| 11773 return __RT_impl_Runtime_NumberToStringRT(args, isolate); | |
| 11774 } | |
| 11775 | |
| 11776 | |
| 11777 RUNTIME_FUNCTION(RuntimeReference_DebugIsActive) { | 9183 RUNTIME_FUNCTION(RuntimeReference_DebugIsActive) { |
| 11778 SealHandleScope shs(isolate); | 9184 SealHandleScope shs(isolate); |
| 11779 return Smi::FromInt(isolate->debug()->is_active()); | 9185 return Smi::FromInt(isolate->debug()->is_active()); |
| 11780 } | 9186 } |
| 11781 | 9187 |
| 11782 | 9188 |
| 11783 // ---------------------------------------------------------------------------- | 9189 // ---------------------------------------------------------------------------- |
| 11784 // Implementation of Runtime | 9190 // Implementation of Runtime |
| 11785 | 9191 |
| 11786 #define F(name, number_of_args, result_size) \ | 9192 #define F(name, number_of_args, result_size) \ |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11853 } | 9259 } |
| 11854 return NULL; | 9260 return NULL; |
| 11855 } | 9261 } |
| 11856 | 9262 |
| 11857 | 9263 |
| 11858 const Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) { | 9264 const Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) { |
| 11859 return &(kIntrinsicFunctions[static_cast<int>(id)]); | 9265 return &(kIntrinsicFunctions[static_cast<int>(id)]); |
| 11860 } | 9266 } |
| 11861 } | 9267 } |
| 11862 } // namespace v8::internal | 9268 } // namespace v8::internal |
| OLD | NEW |