Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(155)

Side by Side Diff: src/arm/code-stubs-arm.cc

Issue 139973004: A64: Synchronize with r15814. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/arm/code-stubs-arm.h ('k') | src/arm/codegen-arm.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 20 matching lines...) Expand all
31 31
32 #include "bootstrapper.h" 32 #include "bootstrapper.h"
33 #include "code-stubs.h" 33 #include "code-stubs.h"
34 #include "regexp-macro-assembler.h" 34 #include "regexp-macro-assembler.h"
35 #include "stub-cache.h" 35 #include "stub-cache.h"
36 36
37 namespace v8 { 37 namespace v8 {
38 namespace internal { 38 namespace internal {
39 39
40 40
41 void ToNumberStub::InitializeInterfaceDescriptor(
42 Isolate* isolate,
43 CodeStubInterfaceDescriptor* descriptor) {
44 static Register registers[] = { r0 };
45 descriptor->register_param_count_ = 1;
46 descriptor->register_params_ = registers;
47 descriptor->deoptimization_handler_ = NULL;
48 }
49
50
41 void FastCloneShallowArrayStub::InitializeInterfaceDescriptor( 51 void FastCloneShallowArrayStub::InitializeInterfaceDescriptor(
42 Isolate* isolate, 52 Isolate* isolate,
43 CodeStubInterfaceDescriptor* descriptor) { 53 CodeStubInterfaceDescriptor* descriptor) {
44 static Register registers[] = { r3, r2, r1 }; 54 static Register registers[] = { r3, r2, r1 };
45 descriptor->register_param_count_ = 3; 55 descriptor->register_param_count_ = 3;
46 descriptor->register_params_ = registers; 56 descriptor->register_params_ = registers;
47 descriptor->deoptimization_handler_ = 57 descriptor->deoptimization_handler_ =
48 Runtime::FunctionForId(Runtime::kCreateArrayLiteralShallow)->entry; 58 Runtime::FunctionForId(Runtime::kCreateArrayLiteralShallow)->entry;
49 } 59 }
50 60
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
251 Isolate* isolate, 261 Isolate* isolate,
252 CodeStubInterfaceDescriptor* descriptor) { 262 CodeStubInterfaceDescriptor* descriptor) {
253 static Register registers[] = { r1, r2, r0 }; 263 static Register registers[] = { r1, r2, r0 };
254 descriptor->register_param_count_ = 3; 264 descriptor->register_param_count_ = 3;
255 descriptor->register_params_ = registers; 265 descriptor->register_params_ = registers;
256 descriptor->deoptimization_handler_ = 266 descriptor->deoptimization_handler_ =
257 FUNCTION_ADDR(StoreIC_MissFromStubFailure); 267 FUNCTION_ADDR(StoreIC_MissFromStubFailure);
258 } 268 }
259 269
260 270
271 void ElementsTransitionAndStoreStub::InitializeInterfaceDescriptor(
272 Isolate* isolate,
273 CodeStubInterfaceDescriptor* descriptor) {
274 static Register registers[] = { r0, r3, r1, r2 };
275 descriptor->register_param_count_ = 4;
276 descriptor->register_params_ = registers;
277 descriptor->deoptimization_handler_ =
278 FUNCTION_ADDR(ElementsTransitionAndStoreIC_Miss);
279 }
280
281
261 #define __ ACCESS_MASM(masm) 282 #define __ ACCESS_MASM(masm)
262 283
263 284
264 static void EmitIdenticalObjectComparison(MacroAssembler* masm, 285 static void EmitIdenticalObjectComparison(MacroAssembler* masm,
265 Label* slow, 286 Label* slow,
266 Condition cond); 287 Condition cond);
267 static void EmitSmiNonsmiComparison(MacroAssembler* masm, 288 static void EmitSmiNonsmiComparison(MacroAssembler* masm,
268 Register lhs, 289 Register lhs,
269 Register rhs, 290 Register rhs,
270 Label* lhs_not_nan, 291 Label* lhs_not_nan,
271 Label* slow, 292 Label* slow,
272 bool strict); 293 bool strict);
273 static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm, 294 static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm,
274 Register lhs, 295 Register lhs,
275 Register rhs); 296 Register rhs);
276 297
277 298
278 // Check if the operand is a heap number.
279 static void EmitCheckForHeapNumber(MacroAssembler* masm, Register operand,
280 Register scratch1, Register scratch2,
281 Label* not_a_heap_number) {
282 __ ldr(scratch1, FieldMemOperand(operand, HeapObject::kMapOffset));
283 __ LoadRoot(scratch2, Heap::kHeapNumberMapRootIndex);
284 __ cmp(scratch1, scratch2);
285 __ b(ne, not_a_heap_number);
286 }
287
288
289 void HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm) { 299 void HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm) {
290 // Update the static counter each time a new code stub is generated. 300 // Update the static counter each time a new code stub is generated.
291 Isolate* isolate = masm->isolate(); 301 Isolate* isolate = masm->isolate();
292 isolate->counters()->code_stubs()->Increment(); 302 isolate->counters()->code_stubs()->Increment();
293 303
294 CodeStubInterfaceDescriptor* descriptor = GetInterfaceDescriptor(isolate); 304 CodeStubInterfaceDescriptor* descriptor = GetInterfaceDescriptor(isolate);
295 int param_count = descriptor->register_param_count_; 305 int param_count = descriptor->register_param_count_;
296 { 306 {
297 // Call the runtime system in a fresh internal frame. 307 // Call the runtime system in a fresh internal frame.
298 FrameScope scope(masm, StackFrame::INTERNAL); 308 FrameScope scope(masm, StackFrame::INTERNAL);
299 ASSERT(descriptor->register_param_count_ == 0 || 309 ASSERT(descriptor->register_param_count_ == 0 ||
300 r0.is(descriptor->register_params_[param_count - 1])); 310 r0.is(descriptor->register_params_[param_count - 1]));
301 // Push arguments 311 // Push arguments
302 for (int i = 0; i < param_count; ++i) { 312 for (int i = 0; i < param_count; ++i) {
303 __ push(descriptor->register_params_[i]); 313 __ push(descriptor->register_params_[i]);
304 } 314 }
305 ExternalReference miss = descriptor->miss_handler(); 315 ExternalReference miss = descriptor->miss_handler();
306 __ CallExternalReference(miss, descriptor->register_param_count_); 316 __ CallExternalReference(miss, descriptor->register_param_count_);
307 } 317 }
308 318
309 __ Ret(); 319 __ Ret();
310 } 320 }
311 321
312 322
313 void ToNumberStub::Generate(MacroAssembler* masm) {
314 // The ToNumber stub takes one argument in eax.
315 Label check_heap_number, call_builtin;
316 __ JumpIfNotSmi(r0, &check_heap_number);
317 __ Ret();
318
319 __ bind(&check_heap_number);
320 EmitCheckForHeapNumber(masm, r0, r1, ip, &call_builtin);
321 __ Ret();
322
323 __ bind(&call_builtin);
324 __ push(r0);
325 __ InvokeBuiltin(Builtins::TO_NUMBER, JUMP_FUNCTION);
326 }
327
328
329 void FastNewClosureStub::Generate(MacroAssembler* masm) { 323 void FastNewClosureStub::Generate(MacroAssembler* masm) {
330 // Create a new closure from the given function info in new 324 // Create a new closure from the given function info in new
331 // space. Set the context to the current context in cp. 325 // space. Set the context to the current context in cp.
332 Counters* counters = masm->isolate()->counters(); 326 Counters* counters = masm->isolate()->counters();
333 327
334 Label gc; 328 Label gc;
335 329
336 // Pop the function info from the stack. 330 // Pop the function info from the stack.
337 __ pop(r3); 331 __ pop(r3);
338 332
(...skipping 579 matching lines...) Expand 10 before | Expand all | Expand 10 after
918 912
919 __ CompareObjectType(lhs, r3, r3, FIRST_SPEC_OBJECT_TYPE); 913 __ CompareObjectType(lhs, r3, r3, FIRST_SPEC_OBJECT_TYPE);
920 __ b(ge, &return_not_equal); 914 __ b(ge, &return_not_equal);
921 915
922 // Check for oddballs: true, false, null, undefined. 916 // Check for oddballs: true, false, null, undefined.
923 __ cmp(r3, Operand(ODDBALL_TYPE)); 917 __ cmp(r3, Operand(ODDBALL_TYPE));
924 __ b(eq, &return_not_equal); 918 __ b(eq, &return_not_equal);
925 919
926 // Now that we have the types we might as well check for 920 // Now that we have the types we might as well check for
927 // internalized-internalized. 921 // internalized-internalized.
928 Label not_internalized; 922 STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
929 STATIC_ASSERT(kInternalizedTag != 0); 923 __ orr(r2, r2, Operand(r3));
930 __ and_(r2, r2, Operand(kIsNotStringMask | kIsInternalizedMask)); 924 __ tst(r2, Operand(kIsNotStringMask | kIsNotInternalizedMask));
931 __ cmp(r2, Operand(kInternalizedTag | kStringTag)); 925 __ b(eq, &return_not_equal);
932 __ b(ne, &not_internalized); // r2 (rhs) is not an internalized string
933
934 __ and_(r3, r3, Operand(kIsNotStringMask | kIsInternalizedMask));
935 __ cmp(r3, Operand(kInternalizedTag | kStringTag));
936 __ b(eq, &return_not_equal); // both rhs and lhs are internalized strings
937
938 __ bind(&not_internalized);
939 } 926 }
940 927
941 928
942 // See comment at call site. 929 // See comment at call site.
943 static void EmitCheckForTwoHeapNumbers(MacroAssembler* masm, 930 static void EmitCheckForTwoHeapNumbers(MacroAssembler* masm,
944 Register lhs, 931 Register lhs,
945 Register rhs, 932 Register rhs,
946 Label* both_loaded_as_doubles, 933 Label* both_loaded_as_doubles,
947 Label* not_heap_numbers, 934 Label* not_heap_numbers,
948 Label* slow) { 935 Label* slow) {
(...skipping 20 matching lines...) Expand all
969 static void EmitCheckForInternalizedStringsOrObjects(MacroAssembler* masm, 956 static void EmitCheckForInternalizedStringsOrObjects(MacroAssembler* masm,
970 Register lhs, 957 Register lhs,
971 Register rhs, 958 Register rhs,
972 Label* possible_strings, 959 Label* possible_strings,
973 Label* not_both_strings) { 960 Label* not_both_strings) {
974 ASSERT((lhs.is(r0) && rhs.is(r1)) || 961 ASSERT((lhs.is(r0) && rhs.is(r1)) ||
975 (lhs.is(r1) && rhs.is(r0))); 962 (lhs.is(r1) && rhs.is(r0)));
976 963
977 // r2 is object type of rhs. 964 // r2 is object type of rhs.
978 Label object_test; 965 Label object_test;
979 STATIC_ASSERT(kInternalizedTag != 0); 966 STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
980 __ tst(r2, Operand(kIsNotStringMask)); 967 __ tst(r2, Operand(kIsNotStringMask));
981 __ b(ne, &object_test); 968 __ b(ne, &object_test);
982 __ tst(r2, Operand(kIsInternalizedMask)); 969 __ tst(r2, Operand(kIsNotInternalizedMask));
983 __ b(eq, possible_strings); 970 __ b(ne, possible_strings);
984 __ CompareObjectType(lhs, r3, r3, FIRST_NONSTRING_TYPE); 971 __ CompareObjectType(lhs, r3, r3, FIRST_NONSTRING_TYPE);
985 __ b(ge, not_both_strings); 972 __ b(ge, not_both_strings);
986 __ tst(r3, Operand(kIsInternalizedMask)); 973 __ tst(r3, Operand(kIsNotInternalizedMask));
987 __ b(eq, possible_strings); 974 __ b(ne, possible_strings);
988 975
989 // Both are internalized. We already checked they weren't the same pointer 976 // Both are internalized. We already checked they weren't the same pointer
990 // so they are not equal. 977 // so they are not equal.
991 __ mov(r0, Operand(NOT_EQUAL)); 978 __ mov(r0, Operand(NOT_EQUAL));
992 __ Ret(); 979 __ Ret();
993 980
994 __ bind(&object_test); 981 __ bind(&object_test);
995 __ cmp(r2, Operand(FIRST_SPEC_OBJECT_TYPE)); 982 __ cmp(r2, Operand(FIRST_SPEC_OBJECT_TYPE));
996 __ b(lt, not_both_strings); 983 __ b(lt, not_both_strings);
997 __ CompareObjectType(lhs, r2, r3, FIRST_SPEC_OBJECT_TYPE); 984 __ CompareObjectType(lhs, r2, r3, FIRST_SPEC_OBJECT_TYPE);
(...skipping 10 matching lines...) Expand all
1008 __ Ret(); 995 __ Ret();
1009 } 996 }
1010 997
1011 998
1012 void NumberToStringStub::GenerateLookupNumberStringCache(MacroAssembler* masm, 999 void NumberToStringStub::GenerateLookupNumberStringCache(MacroAssembler* masm,
1013 Register object, 1000 Register object,
1014 Register result, 1001 Register result,
1015 Register scratch1, 1002 Register scratch1,
1016 Register scratch2, 1003 Register scratch2,
1017 Register scratch3, 1004 Register scratch3,
1018 bool object_is_smi,
1019 Label* not_found) { 1005 Label* not_found) {
1020 // Use of registers. Register result is used as a temporary. 1006 // Use of registers. Register result is used as a temporary.
1021 Register number_string_cache = result; 1007 Register number_string_cache = result;
1022 Register mask = scratch3; 1008 Register mask = scratch3;
1023 1009
1024 // Load the number string cache. 1010 // Load the number string cache.
1025 __ LoadRoot(number_string_cache, Heap::kNumberStringCacheRootIndex); 1011 __ LoadRoot(number_string_cache, Heap::kNumberStringCacheRootIndex);
1026 1012
1027 // Make the hash mask from the length of the number string cache. It 1013 // Make the hash mask from the length of the number string cache. It
1028 // contains two elements (number and string) for each cache entry. 1014 // contains two elements (number and string) for each cache entry.
1029 __ ldr(mask, FieldMemOperand(number_string_cache, FixedArray::kLengthOffset)); 1015 __ ldr(mask, FieldMemOperand(number_string_cache, FixedArray::kLengthOffset));
1030 // Divide length by two (length is a smi). 1016 // Divide length by two (length is a smi).
1031 __ mov(mask, Operand(mask, ASR, kSmiTagSize + 1)); 1017 __ mov(mask, Operand(mask, ASR, kSmiTagSize + 1));
1032 __ sub(mask, mask, Operand(1)); // Make mask. 1018 __ sub(mask, mask, Operand(1)); // Make mask.
1033 1019
1034 // Calculate the entry in the number string cache. The hash value in the 1020 // Calculate the entry in the number string cache. The hash value in the
1035 // number string cache for smis is just the smi value, and the hash for 1021 // number string cache for smis is just the smi value, and the hash for
1036 // doubles is the xor of the upper and lower words. See 1022 // doubles is the xor of the upper and lower words. See
1037 // Heap::GetNumberStringCache. 1023 // Heap::GetNumberStringCache.
1038 Isolate* isolate = masm->isolate(); 1024 Isolate* isolate = masm->isolate();
1039 Label is_smi; 1025 Label is_smi;
1040 Label load_result_from_cache; 1026 Label load_result_from_cache;
1041 if (!object_is_smi) { 1027 __ JumpIfSmi(object, &is_smi);
1042 __ JumpIfSmi(object, &is_smi); 1028 __ CheckMap(object,
1043 __ CheckMap(object, 1029 scratch1,
1044 scratch1, 1030 Heap::kHeapNumberMapRootIndex,
1045 Heap::kHeapNumberMapRootIndex, 1031 not_found,
1046 not_found, 1032 DONT_DO_SMI_CHECK);
1047 DONT_DO_SMI_CHECK);
1048 1033
1049 STATIC_ASSERT(8 == kDoubleSize); 1034 STATIC_ASSERT(8 == kDoubleSize);
1050 __ add(scratch1, 1035 __ add(scratch1,
1051 object, 1036 object,
1052 Operand(HeapNumber::kValueOffset - kHeapObjectTag)); 1037 Operand(HeapNumber::kValueOffset - kHeapObjectTag));
1053 __ ldm(ia, scratch1, scratch1.bit() | scratch2.bit()); 1038 __ ldm(ia, scratch1, scratch1.bit() | scratch2.bit());
1054 __ eor(scratch1, scratch1, Operand(scratch2)); 1039 __ eor(scratch1, scratch1, Operand(scratch2));
1055 __ and_(scratch1, scratch1, Operand(mask)); 1040 __ and_(scratch1, scratch1, Operand(mask));
1056 1041
1057 // Calculate address of entry in string cache: each entry consists 1042 // Calculate address of entry in string cache: each entry consists
1058 // of two pointer sized fields. 1043 // of two pointer sized fields.
1059 __ add(scratch1, 1044 __ add(scratch1,
1060 number_string_cache, 1045 number_string_cache,
1061 Operand(scratch1, LSL, kPointerSizeLog2 + 1)); 1046 Operand(scratch1, LSL, kPointerSizeLog2 + 1));
1062 1047
1063 Register probe = mask; 1048 Register probe = mask;
1064 __ ldr(probe, 1049 __ ldr(probe,
1065 FieldMemOperand(scratch1, FixedArray::kHeaderSize)); 1050 FieldMemOperand(scratch1, FixedArray::kHeaderSize));
1066 __ JumpIfSmi(probe, not_found); 1051 __ JumpIfSmi(probe, not_found);
1067 __ sub(scratch2, object, Operand(kHeapObjectTag)); 1052 __ sub(scratch2, object, Operand(kHeapObjectTag));
1068 __ vldr(d0, scratch2, HeapNumber::kValueOffset); 1053 __ vldr(d0, scratch2, HeapNumber::kValueOffset);
1069 __ sub(probe, probe, Operand(kHeapObjectTag)); 1054 __ sub(probe, probe, Operand(kHeapObjectTag));
1070 __ vldr(d1, probe, HeapNumber::kValueOffset); 1055 __ vldr(d1, probe, HeapNumber::kValueOffset);
1071 __ VFPCompareAndSetFlags(d0, d1); 1056 __ VFPCompareAndSetFlags(d0, d1);
1072 __ b(ne, not_found); // The cache did not contain this value. 1057 __ b(ne, not_found); // The cache did not contain this value.
1073 __ b(&load_result_from_cache); 1058 __ b(&load_result_from_cache);
1074 }
1075 1059
1076 __ bind(&is_smi); 1060 __ bind(&is_smi);
1077 Register scratch = scratch1; 1061 Register scratch = scratch1;
1078 __ and_(scratch, mask, Operand(object, ASR, 1)); 1062 __ and_(scratch, mask, Operand(object, ASR, 1));
1079 // Calculate address of entry in string cache: each entry consists 1063 // Calculate address of entry in string cache: each entry consists
1080 // of two pointer sized fields. 1064 // of two pointer sized fields.
1081 __ add(scratch, 1065 __ add(scratch,
1082 number_string_cache, 1066 number_string_cache,
1083 Operand(scratch, LSL, kPointerSizeLog2 + 1)); 1067 Operand(scratch, LSL, kPointerSizeLog2 + 1));
1084 1068
1085 // Check if the entry is the smi we are looking for. 1069 // Check if the entry is the smi we are looking for.
1086 Register probe = mask;
1087 __ ldr(probe, FieldMemOperand(scratch, FixedArray::kHeaderSize)); 1070 __ ldr(probe, FieldMemOperand(scratch, FixedArray::kHeaderSize));
1088 __ cmp(object, probe); 1071 __ cmp(object, probe);
1089 __ b(ne, not_found); 1072 __ b(ne, not_found);
1090 1073
1091 // Get the result from the cache. 1074 // Get the result from the cache.
1092 __ bind(&load_result_from_cache); 1075 __ bind(&load_result_from_cache);
1093 __ ldr(result, 1076 __ ldr(result,
1094 FieldMemOperand(scratch, FixedArray::kHeaderSize + kPointerSize)); 1077 FieldMemOperand(scratch, FixedArray::kHeaderSize + kPointerSize));
1095 __ IncrementCounter(isolate->counters()->number_to_string_native(), 1078 __ IncrementCounter(isolate->counters()->number_to_string_native(),
1096 1, 1079 1,
1097 scratch1, 1080 scratch1,
1098 scratch2); 1081 scratch2);
1099 } 1082 }
1100 1083
1101 1084
1102 void NumberToStringStub::Generate(MacroAssembler* masm) { 1085 void NumberToStringStub::Generate(MacroAssembler* masm) {
1103 Label runtime; 1086 Label runtime;
1104 1087
1105 __ ldr(r1, MemOperand(sp, 0)); 1088 __ ldr(r1, MemOperand(sp, 0));
1106 1089
1107 // Generate code to lookup number in the number string cache. 1090 // Generate code to lookup number in the number string cache.
1108 GenerateLookupNumberStringCache(masm, r1, r0, r2, r3, r4, false, &runtime); 1091 GenerateLookupNumberStringCache(masm, r1, r0, r2, r3, r4, &runtime);
1109 __ add(sp, sp, Operand(1 * kPointerSize)); 1092 __ add(sp, sp, Operand(1 * kPointerSize));
1110 __ Ret(); 1093 __ Ret();
1111 1094
1112 __ bind(&runtime); 1095 __ bind(&runtime);
1113 // Handle number to string in the runtime system if not found in the cache. 1096 // Handle number to string in the runtime system if not found in the cache.
1114 __ TailCallRuntime(Runtime::kNumberToStringSkipCache, 1, 1); 1097 __ TailCallRuntime(Runtime::kNumberToStringSkipCache, 1, 1);
1115 } 1098 }
1116 1099
1117 1100
1118 static void ICCompareStub_CheckInputType(MacroAssembler* masm, 1101 static void ICCompareStub_CheckInputType(MacroAssembler* masm,
(...skipping 771 matching lines...) Expand 10 before | Expand all | Expand 10 after
1890 // Test if left operand is a string. 1873 // Test if left operand is a string.
1891 __ JumpIfSmi(left, &call_runtime); 1874 __ JumpIfSmi(left, &call_runtime);
1892 __ CompareObjectType(left, r2, r2, FIRST_NONSTRING_TYPE); 1875 __ CompareObjectType(left, r2, r2, FIRST_NONSTRING_TYPE);
1893 __ b(ge, &call_runtime); 1876 __ b(ge, &call_runtime);
1894 1877
1895 // Test if right operand is a string. 1878 // Test if right operand is a string.
1896 __ JumpIfSmi(right, &call_runtime); 1879 __ JumpIfSmi(right, &call_runtime);
1897 __ CompareObjectType(right, r2, r2, FIRST_NONSTRING_TYPE); 1880 __ CompareObjectType(right, r2, r2, FIRST_NONSTRING_TYPE);
1898 __ b(ge, &call_runtime); 1881 __ b(ge, &call_runtime);
1899 1882
1900 StringAddStub string_add_stub((StringAddFlags) 1883 StringAddStub string_add_stub(
1901 (ERECT_FRAME | NO_STRING_CHECK_IN_STUB)); 1884 (StringAddFlags)(STRING_ADD_CHECK_NONE | STRING_ADD_ERECT_FRAME));
1902 GenerateRegisterArgsPush(masm); 1885 GenerateRegisterArgsPush(masm);
1903 __ TailCallStub(&string_add_stub); 1886 __ TailCallStub(&string_add_stub);
1904 1887
1905 __ bind(&call_runtime); 1888 __ bind(&call_runtime);
1906 GenerateTypeTransition(masm); 1889 GenerateTypeTransition(masm);
1907 } 1890 }
1908 1891
1909 1892
1910 void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { 1893 void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
1911 ASSERT(Max(left_type_, right_type_) == BinaryOpIC::INT32); 1894 ASSERT(Max(left_type_, right_type_) == BinaryOpIC::INT32);
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after
2249 Label left_not_string, call_runtime; 2232 Label left_not_string, call_runtime;
2250 2233
2251 Register left = r1; 2234 Register left = r1;
2252 Register right = r0; 2235 Register right = r0;
2253 2236
2254 // Check if left argument is a string. 2237 // Check if left argument is a string.
2255 __ JumpIfSmi(left, &left_not_string); 2238 __ JumpIfSmi(left, &left_not_string);
2256 __ CompareObjectType(left, r2, r2, FIRST_NONSTRING_TYPE); 2239 __ CompareObjectType(left, r2, r2, FIRST_NONSTRING_TYPE);
2257 __ b(ge, &left_not_string); 2240 __ b(ge, &left_not_string);
2258 2241
2259 StringAddStub string_add_left_stub((StringAddFlags) 2242 StringAddStub string_add_left_stub(
2260 (ERECT_FRAME | NO_STRING_CHECK_LEFT_IN_STUB)); 2243 (StringAddFlags)(STRING_ADD_CHECK_RIGHT | STRING_ADD_ERECT_FRAME));
2261 GenerateRegisterArgsPush(masm); 2244 GenerateRegisterArgsPush(masm);
2262 __ TailCallStub(&string_add_left_stub); 2245 __ TailCallStub(&string_add_left_stub);
2263 2246
2264 // Left operand is not a string, test right. 2247 // Left operand is not a string, test right.
2265 __ bind(&left_not_string); 2248 __ bind(&left_not_string);
2266 __ JumpIfSmi(right, &call_runtime); 2249 __ JumpIfSmi(right, &call_runtime);
2267 __ CompareObjectType(right, r2, r2, FIRST_NONSTRING_TYPE); 2250 __ CompareObjectType(right, r2, r2, FIRST_NONSTRING_TYPE);
2268 __ b(ge, &call_runtime); 2251 __ b(ge, &call_runtime);
2269 2252
2270 StringAddStub string_add_right_stub((StringAddFlags) 2253 StringAddStub string_add_right_stub(
2271 (ERECT_FRAME | NO_STRING_CHECK_RIGHT_IN_STUB)); 2254 (StringAddFlags)(STRING_ADD_CHECK_LEFT | STRING_ADD_ERECT_FRAME));
2272 GenerateRegisterArgsPush(masm); 2255 GenerateRegisterArgsPush(masm);
2273 __ TailCallStub(&string_add_right_stub); 2256 __ TailCallStub(&string_add_right_stub);
2274 2257
2275 // At least one argument is not a string. 2258 // At least one argument is not a string.
2276 __ bind(&call_runtime); 2259 __ bind(&call_runtime);
2277 } 2260 }
2278 2261
2279 2262
2280 void BinaryOpStub_GenerateHeapResultAllocation(MacroAssembler* masm, 2263 void BinaryOpStub_GenerateHeapResultAllocation(MacroAssembler* masm,
2281 Register result, 2264 Register result,
(...skipping 3205 matching lines...) Expand 10 before | Expand all | Expand 10 after
5487 5470
5488 // Stack on entry: 5471 // Stack on entry:
5489 // sp[0]: second argument (right). 5472 // sp[0]: second argument (right).
5490 // sp[4]: first argument (left). 5473 // sp[4]: first argument (left).
5491 5474
5492 // Load the two arguments. 5475 // Load the two arguments.
5493 __ ldr(r0, MemOperand(sp, 1 * kPointerSize)); // First argument. 5476 __ ldr(r0, MemOperand(sp, 1 * kPointerSize)); // First argument.
5494 __ ldr(r1, MemOperand(sp, 0 * kPointerSize)); // Second argument. 5477 __ ldr(r1, MemOperand(sp, 0 * kPointerSize)); // Second argument.
5495 5478
5496 // Make sure that both arguments are strings if not known in advance. 5479 // Make sure that both arguments are strings if not known in advance.
5497 if ((flags_ & NO_STRING_ADD_FLAGS) != 0) { 5480 // Otherwise, at least one of the arguments is definitely a string,
5481 // and we convert the one that is not known to be a string.
5482 if ((flags_ & STRING_ADD_CHECK_BOTH) == STRING_ADD_CHECK_BOTH) {
5483 ASSERT((flags_ & STRING_ADD_CHECK_LEFT) == STRING_ADD_CHECK_LEFT);
5484 ASSERT((flags_ & STRING_ADD_CHECK_RIGHT) == STRING_ADD_CHECK_RIGHT);
5498 __ JumpIfEitherSmi(r0, r1, &call_runtime); 5485 __ JumpIfEitherSmi(r0, r1, &call_runtime);
5499 // Load instance types. 5486 // Load instance types.
5500 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); 5487 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset));
5501 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset)); 5488 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset));
5502 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); 5489 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset));
5503 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); 5490 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset));
5504 STATIC_ASSERT(kStringTag == 0); 5491 STATIC_ASSERT(kStringTag == 0);
5505 // If either is not a string, go to runtime. 5492 // If either is not a string, go to runtime.
5506 __ tst(r4, Operand(kIsNotStringMask)); 5493 __ tst(r4, Operand(kIsNotStringMask));
5507 __ tst(r5, Operand(kIsNotStringMask), eq); 5494 __ tst(r5, Operand(kIsNotStringMask), eq);
5508 __ b(ne, &call_runtime); 5495 __ b(ne, &call_runtime);
5509 } else { 5496 } else if ((flags_ & STRING_ADD_CHECK_LEFT) == STRING_ADD_CHECK_LEFT) {
5510 // Here at least one of the arguments is definitely a string. 5497 ASSERT((flags_ & STRING_ADD_CHECK_RIGHT) == 0);
5511 // We convert the one that is not known to be a string. 5498 GenerateConvertArgument(
5512 if ((flags_ & NO_STRING_CHECK_LEFT_IN_STUB) == 0) { 5499 masm, 1 * kPointerSize, r0, r2, r3, r4, r5, &call_builtin);
5513 ASSERT((flags_ & NO_STRING_CHECK_RIGHT_IN_STUB) != 0); 5500 builtin_id = Builtins::STRING_ADD_RIGHT;
5514 GenerateConvertArgument( 5501 } else if ((flags_ & STRING_ADD_CHECK_RIGHT) == STRING_ADD_CHECK_RIGHT) {
5515 masm, 1 * kPointerSize, r0, r2, r3, r4, r5, &call_builtin); 5502 ASSERT((flags_ & STRING_ADD_CHECK_LEFT) == 0);
5516 builtin_id = Builtins::STRING_ADD_RIGHT; 5503 GenerateConvertArgument(
5517 } else if ((flags_ & NO_STRING_CHECK_RIGHT_IN_STUB) == 0) { 5504 masm, 0 * kPointerSize, r1, r2, r3, r4, r5, &call_builtin);
5518 ASSERT((flags_ & NO_STRING_CHECK_LEFT_IN_STUB) != 0); 5505 builtin_id = Builtins::STRING_ADD_LEFT;
5519 GenerateConvertArgument(
5520 masm, 0 * kPointerSize, r1, r2, r3, r4, r5, &call_builtin);
5521 builtin_id = Builtins::STRING_ADD_LEFT;
5522 }
5523 } 5506 }
5524 5507
5525 // Both arguments are strings. 5508 // Both arguments are strings.
5526 // r0: first string 5509 // r0: first string
5527 // r1: second string 5510 // r1: second string
5528 // r4: first string instance type (if flags_ == NO_STRING_ADD_FLAGS) 5511 // r4: first string instance type (if flags_ == NO_STRING_ADD_FLAGS)
5529 // r5: second string instance type (if flags_ == NO_STRING_ADD_FLAGS) 5512 // r5: second string instance type (if flags_ == NO_STRING_ADD_FLAGS)
5530 { 5513 {
5531 Label strings_not_empty; 5514 Label strings_not_empty;
5532 // Check if either of the strings are empty. In that case return the other. 5515 // Check if either of the strings are empty. In that case return the other.
(...skipping 27 matching lines...) Expand all
5560 Label string_add_flat_result, longer_than_two; 5543 Label string_add_flat_result, longer_than_two;
5561 // Adding two lengths can't overflow. 5544 // Adding two lengths can't overflow.
5562 STATIC_ASSERT(String::kMaxLength < String::kMaxLength * 2); 5545 STATIC_ASSERT(String::kMaxLength < String::kMaxLength * 2);
5563 __ add(r6, r2, Operand(r3)); 5546 __ add(r6, r2, Operand(r3));
5564 // Use the string table when adding two one character strings, as it 5547 // Use the string table when adding two one character strings, as it
5565 // helps later optimizations to return a string here. 5548 // helps later optimizations to return a string here.
5566 __ cmp(r6, Operand(2)); 5549 __ cmp(r6, Operand(2));
5567 __ b(ne, &longer_than_two); 5550 __ b(ne, &longer_than_two);
5568 5551
5569 // Check that both strings are non-external ASCII strings. 5552 // Check that both strings are non-external ASCII strings.
5570 if (flags_ != NO_STRING_ADD_FLAGS) { 5553 if ((flags_ & STRING_ADD_CHECK_BOTH) != STRING_ADD_CHECK_BOTH) {
5571 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); 5554 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset));
5572 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset)); 5555 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset));
5573 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); 5556 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset));
5574 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); 5557 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset));
5575 } 5558 }
5576 __ JumpIfBothInstanceTypesAreNotSequentialAscii(r4, r5, r6, r7, 5559 __ JumpIfBothInstanceTypesAreNotSequentialAscii(r4, r5, r6, r7,
5577 &call_runtime); 5560 &call_runtime);
5578 5561
5579 // Get the two characters forming the sub string. 5562 // Get the two characters forming the sub string.
5580 __ ldrb(r2, FieldMemOperand(r0, SeqOneByteString::kHeaderSize)); 5563 __ ldrb(r2, FieldMemOperand(r0, SeqOneByteString::kHeaderSize));
(...skipping 27 matching lines...) Expand all
5608 __ b(lt, &string_add_flat_result); 5591 __ b(lt, &string_add_flat_result);
5609 // Handle exceptionally long strings in the runtime system. 5592 // Handle exceptionally long strings in the runtime system.
5610 STATIC_ASSERT((String::kMaxLength & 0x80000000) == 0); 5593 STATIC_ASSERT((String::kMaxLength & 0x80000000) == 0);
5611 ASSERT(IsPowerOf2(String::kMaxLength + 1)); 5594 ASSERT(IsPowerOf2(String::kMaxLength + 1));
5612 // kMaxLength + 1 is representable as shifted literal, kMaxLength is not. 5595 // kMaxLength + 1 is representable as shifted literal, kMaxLength is not.
5613 __ cmp(r6, Operand(String::kMaxLength + 1)); 5596 __ cmp(r6, Operand(String::kMaxLength + 1));
5614 __ b(hs, &call_runtime); 5597 __ b(hs, &call_runtime);
5615 5598
5616 // If result is not supposed to be flat, allocate a cons string object. 5599 // If result is not supposed to be flat, allocate a cons string object.
5617 // If both strings are ASCII the result is an ASCII cons string. 5600 // If both strings are ASCII the result is an ASCII cons string.
5618 if (flags_ != NO_STRING_ADD_FLAGS) { 5601 if ((flags_ & STRING_ADD_CHECK_BOTH) != STRING_ADD_CHECK_BOTH) {
5619 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); 5602 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset));
5620 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset)); 5603 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset));
5621 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); 5604 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset));
5622 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); 5605 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset));
5623 } 5606 }
5624 Label non_ascii, allocated, ascii_data; 5607 Label non_ascii, allocated, ascii_data;
5625 STATIC_ASSERT(kTwoByteStringTag == 0); 5608 STATIC_ASSERT(kTwoByteStringTag == 0);
5626 __ tst(r4, Operand(kStringEncodingMask)); 5609 __ tst(r4, Operand(kStringEncodingMask));
5627 __ tst(r5, Operand(kStringEncodingMask), ne); 5610 __ tst(r5, Operand(kStringEncodingMask), ne);
5628 __ b(eq, &non_ascii); 5611 __ b(eq, &non_ascii);
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
5691 // Locate the first characters' locations. 5674 // Locate the first characters' locations.
5692 // r0: first string 5675 // r0: first string
5693 // r1: second string 5676 // r1: second string
5694 // r2: length of first string 5677 // r2: length of first string
5695 // r3: length of second string 5678 // r3: length of second string
5696 // r4: first string instance type (if flags_ == NO_STRING_ADD_FLAGS) 5679 // r4: first string instance type (if flags_ == NO_STRING_ADD_FLAGS)
5697 // r5: second string instance type (if flags_ == NO_STRING_ADD_FLAGS) 5680 // r5: second string instance type (if flags_ == NO_STRING_ADD_FLAGS)
5698 // r6: sum of lengths. 5681 // r6: sum of lengths.
5699 Label first_prepared, second_prepared; 5682 Label first_prepared, second_prepared;
5700 __ bind(&string_add_flat_result); 5683 __ bind(&string_add_flat_result);
5701 if (flags_ != NO_STRING_ADD_FLAGS) { 5684 if ((flags_ & STRING_ADD_CHECK_BOTH) != STRING_ADD_CHECK_BOTH) {
5702 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); 5685 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset));
5703 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset)); 5686 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset));
5704 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); 5687 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset));
5705 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); 5688 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset));
5706 } 5689 }
5707 5690
5708 // Check whether both strings have same encoding 5691 // Check whether both strings have same encoding
5709 __ eor(r7, r4, Operand(r5)); 5692 __ eor(r7, r4, Operand(r5));
5710 __ tst(r7, Operand(kStringEncodingMask)); 5693 __ tst(r7, Operand(kStringEncodingMask));
5711 __ b(ne, &call_runtime); 5694 __ b(ne, &call_runtime);
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
5779 // r6: first character of result. 5762 // r6: first character of result.
5780 StringHelper::GenerateCopyCharacters(masm, r6, r7, r2, r4, false); 5763 StringHelper::GenerateCopyCharacters(masm, r6, r7, r2, r4, false);
5781 // r6: next character of result. 5764 // r6: next character of result.
5782 StringHelper::GenerateCopyCharacters(masm, r6, r1, r3, r4, false); 5765 StringHelper::GenerateCopyCharacters(masm, r6, r1, r3, r4, false);
5783 __ IncrementCounter(counters->string_add_native(), 1, r2, r3); 5766 __ IncrementCounter(counters->string_add_native(), 1, r2, r3);
5784 __ add(sp, sp, Operand(2 * kPointerSize)); 5767 __ add(sp, sp, Operand(2 * kPointerSize));
5785 __ Ret(); 5768 __ Ret();
5786 5769
5787 // Just jump to runtime to add the two strings. 5770 // Just jump to runtime to add the two strings.
5788 __ bind(&call_runtime); 5771 __ bind(&call_runtime);
5789 if ((flags_ & ERECT_FRAME) != 0) { 5772 if ((flags_ & STRING_ADD_ERECT_FRAME) != 0) {
5790 GenerateRegisterArgsPop(masm); 5773 GenerateRegisterArgsPop(masm);
5791 // Build a frame 5774 // Build a frame
5792 { 5775 {
5793 FrameScope scope(masm, StackFrame::INTERNAL); 5776 FrameScope scope(masm, StackFrame::INTERNAL);
5794 GenerateRegisterArgsPush(masm); 5777 GenerateRegisterArgsPush(masm);
5795 __ CallRuntime(Runtime::kStringAdd, 2); 5778 __ CallRuntime(Runtime::kStringAdd, 2);
5796 } 5779 }
5797 __ Ret(); 5780 __ Ret();
5798 } else { 5781 } else {
5799 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); 5782 __ TailCallRuntime(Runtime::kStringAdd, 2, 1);
5800 } 5783 }
5801 5784
5802 if (call_builtin.is_linked()) { 5785 if (call_builtin.is_linked()) {
5803 __ bind(&call_builtin); 5786 __ bind(&call_builtin);
5804 if ((flags_ & ERECT_FRAME) != 0) { 5787 if ((flags_ & STRING_ADD_ERECT_FRAME) != 0) {
5805 GenerateRegisterArgsPop(masm); 5788 GenerateRegisterArgsPop(masm);
5806 // Build a frame 5789 // Build a frame
5807 { 5790 {
5808 FrameScope scope(masm, StackFrame::INTERNAL); 5791 FrameScope scope(masm, StackFrame::INTERNAL);
5809 GenerateRegisterArgsPush(masm); 5792 GenerateRegisterArgsPush(masm);
5810 __ InvokeBuiltin(builtin_id, CALL_FUNCTION); 5793 __ InvokeBuiltin(builtin_id, CALL_FUNCTION);
5811 } 5794 }
5812 __ Ret(); 5795 __ Ret();
5813 } else { 5796 } else {
5814 __ InvokeBuiltin(builtin_id, JUMP_FUNCTION); 5797 __ InvokeBuiltin(builtin_id, JUMP_FUNCTION);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
5846 // Check the number to string cache. 5829 // Check the number to string cache.
5847 Label not_cached; 5830 Label not_cached;
5848 __ bind(&not_string); 5831 __ bind(&not_string);
5849 // Puts the cached result into scratch1. 5832 // Puts the cached result into scratch1.
5850 NumberToStringStub::GenerateLookupNumberStringCache(masm, 5833 NumberToStringStub::GenerateLookupNumberStringCache(masm,
5851 arg, 5834 arg,
5852 scratch1, 5835 scratch1,
5853 scratch2, 5836 scratch2,
5854 scratch3, 5837 scratch3,
5855 scratch4, 5838 scratch4,
5856 false,
5857 &not_cached); 5839 &not_cached);
5858 __ mov(arg, scratch1); 5840 __ mov(arg, scratch1);
5859 __ str(arg, MemOperand(sp, stack_offset)); 5841 __ str(arg, MemOperand(sp, stack_offset));
5860 __ jmp(&done); 5842 __ jmp(&done);
5861 5843
5862 // Check if the argument is a safe string wrapper. 5844 // Check if the argument is a safe string wrapper.
5863 __ bind(&not_cached); 5845 __ bind(&not_cached);
5864 __ JumpIfSmi(arg, slow); 5846 __ JumpIfSmi(arg, slow);
5865 __ CompareObjectType( 5847 __ CompareObjectType(
5866 arg, scratch1, scratch2, JS_VALUE_TYPE); // map -> scratch1. 5848 arg, scratch1, scratch2, JS_VALUE_TYPE); // map -> scratch1.
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
5987 Register tmp2 = r3; 5969 Register tmp2 = r3;
5988 5970
5989 // Check that both operands are heap objects. 5971 // Check that both operands are heap objects.
5990 __ JumpIfEitherSmi(left, right, &miss); 5972 __ JumpIfEitherSmi(left, right, &miss);
5991 5973
5992 // Check that both operands are internalized strings. 5974 // Check that both operands are internalized strings.
5993 __ ldr(tmp1, FieldMemOperand(left, HeapObject::kMapOffset)); 5975 __ ldr(tmp1, FieldMemOperand(left, HeapObject::kMapOffset));
5994 __ ldr(tmp2, FieldMemOperand(right, HeapObject::kMapOffset)); 5976 __ ldr(tmp2, FieldMemOperand(right, HeapObject::kMapOffset));
5995 __ ldrb(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset)); 5977 __ ldrb(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset));
5996 __ ldrb(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset)); 5978 __ ldrb(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset));
5997 STATIC_ASSERT(kInternalizedTag != 0); 5979 STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
5998 5980 __ orr(tmp1, tmp1, Operand(tmp2));
5999 __ and_(tmp1, tmp1, Operand(kIsNotStringMask | kIsInternalizedMask)); 5981 __ tst(tmp1, Operand(kIsNotStringMask | kIsNotInternalizedMask));
6000 __ cmp(tmp1, Operand(kInternalizedTag | kStringTag));
6001 __ b(ne, &miss);
6002
6003 __ and_(tmp2, tmp2, Operand(kIsNotStringMask | kIsInternalizedMask));
6004 __ cmp(tmp2, Operand(kInternalizedTag | kStringTag));
6005 __ b(ne, &miss); 5982 __ b(ne, &miss);
6006 5983
6007 // Internalized strings are compared by identity. 5984 // Internalized strings are compared by identity.
6008 __ cmp(left, right); 5985 __ cmp(left, right);
6009 // Make sure r0 is non-zero. At this point input operands are 5986 // Make sure r0 is non-zero. At this point input operands are
6010 // guaranteed to be non-zero. 5987 // guaranteed to be non-zero.
6011 ASSERT(right.is(r0)); 5988 ASSERT(right.is(r0));
6012 STATIC_ASSERT(EQUAL == 0); 5989 STATIC_ASSERT(EQUAL == 0);
6013 STATIC_ASSERT(kSmiTag == 0); 5990 STATIC_ASSERT(kSmiTag == 0);
6014 __ mov(r0, Operand(Smi::FromInt(EQUAL)), LeaveCC, eq); 5991 __ mov(r0, Operand(Smi::FromInt(EQUAL)), LeaveCC, eq);
(...skipping 13 matching lines...) Expand all
6028 Register left = r1; 6005 Register left = r1;
6029 Register right = r0; 6006 Register right = r0;
6030 Register tmp1 = r2; 6007 Register tmp1 = r2;
6031 Register tmp2 = r3; 6008 Register tmp2 = r3;
6032 6009
6033 // Check that both operands are heap objects. 6010 // Check that both operands are heap objects.
6034 __ JumpIfEitherSmi(left, right, &miss); 6011 __ JumpIfEitherSmi(left, right, &miss);
6035 6012
6036 // Check that both operands are unique names. This leaves the instance 6013 // Check that both operands are unique names. This leaves the instance
6037 // types loaded in tmp1 and tmp2. 6014 // types loaded in tmp1 and tmp2.
6038 STATIC_ASSERT(kInternalizedTag != 0);
6039 __ ldr(tmp1, FieldMemOperand(left, HeapObject::kMapOffset)); 6015 __ ldr(tmp1, FieldMemOperand(left, HeapObject::kMapOffset));
6040 __ ldr(tmp2, FieldMemOperand(right, HeapObject::kMapOffset)); 6016 __ ldr(tmp2, FieldMemOperand(right, HeapObject::kMapOffset));
6041 __ ldrb(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset)); 6017 __ ldrb(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset));
6042 __ ldrb(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset)); 6018 __ ldrb(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset));
6043 6019
6044 __ JumpIfNotUniqueName(tmp1, &miss); 6020 __ JumpIfNotUniqueName(tmp1, &miss);
6045 __ JumpIfNotUniqueName(tmp2, &miss); 6021 __ JumpIfNotUniqueName(tmp2, &miss);
6046 6022
6047 // Unique names are compared by identity. 6023 // Unique names are compared by identity.
6048 __ cmp(left, right); 6024 __ cmp(left, right);
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
6094 __ mov(r0, Operand(Smi::FromInt(EQUAL)), LeaveCC, eq); 6070 __ mov(r0, Operand(Smi::FromInt(EQUAL)), LeaveCC, eq);
6095 __ Ret(eq); 6071 __ Ret(eq);
6096 6072
6097 // Handle not identical strings. 6073 // Handle not identical strings.
6098 6074
6099 // Check that both strings are internalized strings. If they are, we're done 6075 // Check that both strings are internalized strings. If they are, we're done
6100 // because we already know they are not identical. We know they are both 6076 // because we already know they are not identical. We know they are both
6101 // strings. 6077 // strings.
6102 if (equality) { 6078 if (equality) {
6103 ASSERT(GetCondition() == eq); 6079 ASSERT(GetCondition() == eq);
6104 STATIC_ASSERT(kInternalizedTag != 0); 6080 STATIC_ASSERT(kInternalizedTag == 0);
6105 __ and_(tmp3, tmp1, Operand(tmp2)); 6081 __ orr(tmp3, tmp1, Operand(tmp2));
6106 __ tst(tmp3, Operand(kIsInternalizedMask)); 6082 __ tst(tmp3, Operand(kIsNotInternalizedMask));
6107 // Make sure r0 is non-zero. At this point input operands are 6083 // Make sure r0 is non-zero. At this point input operands are
6108 // guaranteed to be non-zero. 6084 // guaranteed to be non-zero.
6109 ASSERT(right.is(r0)); 6085 ASSERT(right.is(r0));
6110 __ Ret(ne); 6086 __ Ret(eq);
6111 } 6087 }
6112 6088
6113 // Check that both strings are sequential ASCII. 6089 // Check that both strings are sequential ASCII.
6114 Label runtime; 6090 Label runtime;
6115 __ JumpIfBothInstanceTypesAreNotSequentialAscii( 6091 __ JumpIfBothInstanceTypesAreNotSequentialAscii(
6116 tmp1, tmp2, tmp3, tmp4, &runtime); 6092 tmp1, tmp2, tmp3, tmp4, &runtime);
6117 6093
6118 // Compare flat ASCII strings. Returns when done. 6094 // Compare flat ASCII strings. Returns when done.
6119 if (equality) { 6095 if (equality) {
6120 StringCompareStub::GenerateFlatAsciiStringEquals( 6096 StringCompareStub::GenerateFlatAsciiStringEquals(
(...skipping 1078 matching lines...) Expand 10 before | Expand all | Expand 10 after
7199 __ bind(&fast_elements_case); 7175 __ bind(&fast_elements_case);
7200 GenerateCase(masm, FAST_ELEMENTS); 7176 GenerateCase(masm, FAST_ELEMENTS);
7201 } 7177 }
7202 7178
7203 7179
7204 #undef __ 7180 #undef __
7205 7181
7206 } } // namespace v8::internal 7182 } } // namespace v8::internal
7207 7183
7208 #endif // V8_TARGET_ARCH_ARM 7184 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/arm/code-stubs-arm.h ('k') | src/arm/codegen-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698