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 |