| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 // | 4 // |
| 5 // The intrinsic code below is executed before a method has built its frame. | 5 // The intrinsic code below is executed before a method has built its frame. |
| 6 // The return address is on the stack and the arguments below it. | 6 // The return address is on the stack and the arguments below it. |
| 7 // Registers EDX (arguments descriptor) and ECX (function) must be preserved. | 7 // Registers EDX (arguments descriptor) and ECX (function) must be preserved. |
| 8 // Each intrinsification method returns true if the corresponding | 8 // Each intrinsification method returns true if the corresponding |
| 9 // Dart method was intrinsified. | 9 // Dart method was intrinsified. |
| 10 | 10 |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 68 V(ObjectArray, [], Array_getIndexed) \ | 68 V(ObjectArray, [], Array_getIndexed) \ |
| 69 V(ObjectArray, []=, Array_setIndexed) \ | 69 V(ObjectArray, []=, Array_setIndexed) \ |
| 70 V(GrowableObjectArray, get:length, GrowableArray_getLength) \ | 70 V(GrowableObjectArray, get:length, GrowableArray_getLength) \ |
| 71 V(GrowableObjectArray, [], GrowableArray_getIndexed) \ | 71 V(GrowableObjectArray, [], GrowableArray_getIndexed) \ |
| 72 V(ImmutableArray, [], Array_getIndexed) \ | 72 V(ImmutableArray, [], Array_getIndexed) \ |
| 73 V(ImmutableArray, get:length, Array_getLength) \ | 73 V(ImmutableArray, get:length, Array_getLength) \ |
| 74 V(Math, sqrt, Math_sqrt) \ | 74 V(Math, sqrt, Math_sqrt) \ |
| 75 V(Object, ==, Object_equal) \ | 75 V(Object, ==, Object_equal) \ |
| 76 V(FixedSizeArrayIterator, next, FixedSizeArrayIterator_next) \ | 76 V(FixedSizeArrayIterator, next, FixedSizeArrayIterator_next) \ |
| 77 V(FixedSizeArrayIterator, hasNext, FixedSizeArrayIterator_hasNext) \ | 77 V(FixedSizeArrayIterator, hasNext, FixedSizeArrayIterator_hasNext) \ |
| 78 V(StringBase, get:length, String_getLength) \ |
| 79 V(StringBase, charCodeAt, String_charCodeAt) \ |
| 80 V(StringBase, hashCode, String_hashCode) \ |
| 78 | 81 |
| 79 #define __ assembler-> | 82 #define __ assembler-> |
| 80 | 83 |
| 81 static bool ObjectArray_Allocate(Assembler* assembler) { | 84 static bool ObjectArray_Allocate(Assembler* assembler) { |
| 82 // This snippet of inlined code uses the following registers: | 85 // This snippet of inlined code uses the following registers: |
| 83 // EAX, EBX, EDI | 86 // EAX, EBX, EDI |
| 84 // and the newly allocated object is returned in EAX. | 87 // and the newly allocated object is returned in EAX. |
| 85 const intptr_t kTypeArgumentsOffset = 2 * kWordSize; | 88 const intptr_t kTypeArgumentsOffset = 2 * kWordSize; |
| 86 const intptr_t kArrayLengthOffset = 1 * kWordSize; | 89 const intptr_t kArrayLengthOffset = 1 * kWordSize; |
| 87 Label fall_through; | 90 Label fall_through; |
| (...skipping 802 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 890 __ LoadObject(EAX, bool_false); | 893 __ LoadObject(EAX, bool_false); |
| 891 __ ret(); | 894 __ ret(); |
| 892 __ Bind(&is_true); | 895 __ Bind(&is_true); |
| 893 __ LoadObject(EAX, bool_true); | 896 __ LoadObject(EAX, bool_true); |
| 894 __ ret(); | 897 __ ret(); |
| 895 __ Bind(&fall_through); | 898 __ Bind(&fall_through); |
| 896 return false; | 899 return false; |
| 897 } | 900 } |
| 898 | 901 |
| 899 | 902 |
| 903 static bool String_getLength(Assembler* assembler) { |
| 904 __ movl(EAX, Address(ESP, + 1 * kWordSize)); // String object. |
| 905 __ movl(EAX, FieldAddress(EAX, String::length_offset())); |
| 906 __ ret(); |
| 907 return true; |
| 908 } |
| 909 |
| 910 |
| 911 // TODO(srdjan): Implement for two and four byte strings as well. |
| 912 static bool String_charCodeAt(Assembler* assembler) { |
| 913 ObjectStore* object_store = Isolate::Current()->object_store(); |
| 914 Label fall_through; |
| 915 __ movl(EBX, Address(ESP, + 1 * kWordSize)); // Index. |
| 916 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // String. |
| 917 __ testl(EBX, Immediate(kSmiTagMask)); |
| 918 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index. |
| 919 // Range check. |
| 920 __ cmpl(EBX, FieldAddress(EAX, String::length_offset())); |
| 921 // Runtime throws exception. |
| 922 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); |
| 923 __ movl(EDI, FieldAddress(EAX, Instance::class_offset())); |
| 924 __ CompareObject(EDI, |
| 925 Class::ZoneHandle(object_store->one_byte_string_class())); |
| 926 __ j(NOT_EQUAL, &fall_through); |
| 927 __ SmiUntag(EBX); |
| 928 __ movzxb(EAX, FieldAddress(EAX, EBX, TIMES_1, OneByteString::data_offset())); |
| 929 __ SmiTag(EAX); |
| 930 __ ret(); |
| 931 __ Bind(&fall_through); |
| 932 return false; |
| 933 } |
| 934 |
| 935 |
| 936 static bool String_hashCode(Assembler* assembler) { |
| 937 Label fall_through; |
| 938 __ movl(EAX, Address(ESP, + 1 * kWordSize)); // String object. |
| 939 __ movl(EAX, FieldAddress(EAX, String::hash_offset())); |
| 940 __ cmpl(EAX, Immediate(0)); |
| 941 __ j(EQUAL, &fall_through, Assembler::kNearJump); |
| 942 __ ret(); |
| 943 __ Bind(&fall_through); |
| 944 // Hash not yet computed. |
| 945 return false; |
| 946 } |
| 947 |
| 900 #undef __ | 948 #undef __ |
| 901 | 949 |
| 902 | 950 |
| 903 bool Intrinsifier::Intrinsify(const Function& function, Assembler* assembler) { | 951 bool Intrinsifier::Intrinsify(const Function& function, Assembler* assembler) { |
| 904 if (!FLAG_intrinsify) return false; | 952 if (!FLAG_intrinsify) return false; |
| 905 const char* function_name = String::Handle(function.name()).ToCString(); | 953 const char* function_name = String::Handle(function.name()).ToCString(); |
| 906 const Class& function_class = Class::Handle(function.owner()); | 954 const Class& function_class = Class::Handle(function.owner()); |
| 907 const char* class_name = String::Handle(function_class.Name()).ToCString(); | 955 const char* class_name = String::Handle(function_class.Name()).ToCString(); |
| 908 #define FIND_INTRINSICS(test_class_name, test_function_name, destination) \ | 956 #define FIND_INTRINSICS(test_class_name, test_function_name, destination) \ |
| 909 if ((strcmp(#test_function_name, function_name) == 0) && \ | 957 if ((strcmp(#test_function_name, function_name) == 0) && \ |
| 910 (strcmp(#test_class_name, class_name) == 0)) { \ | 958 (strcmp(#test_class_name, class_name) == 0)) { \ |
| 911 return destination(assembler); \ | 959 return destination(assembler); \ |
| 912 } \ | 960 } \ |
| 913 | 961 |
| 914 INTRINSIC_LIST(FIND_INTRINSICS); | 962 INTRINSIC_LIST(FIND_INTRINSICS); |
| 915 #undef FIND_INTRINSICS | 963 #undef FIND_INTRINSICS |
| 916 return false; | 964 return false; |
| 917 } | 965 } |
| 918 | 966 |
| 919 } // namespace dart | 967 } // namespace dart |
| 920 | 968 |
| 921 #endif // defined TARGET_ARCH_IA32 | 969 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |