| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 6122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6133 GenerateCompareFlatAsciiStrings(masm, r1, r0, r2, r3, r4, r5); | 6133 GenerateCompareFlatAsciiStrings(masm, r1, r0, r2, r3, r4, r5); |
| 6134 | 6134 |
| 6135 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) | 6135 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) |
| 6136 // tagged as a small integer. | 6136 // tagged as a small integer. |
| 6137 __ bind(&runtime); | 6137 __ bind(&runtime); |
| 6138 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 6138 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
| 6139 } | 6139 } |
| 6140 | 6140 |
| 6141 | 6141 |
| 6142 void StringAddStub::Generate(MacroAssembler* masm) { | 6142 void StringAddStub::Generate(MacroAssembler* masm) { |
| 6143 Label string_add_runtime, call_builtin; | 6143 Label call_runtime, call_builtin; |
| 6144 Builtins::JavaScript builtin_id = Builtins::ADD; | 6144 Builtins::JavaScript builtin_id = Builtins::ADD; |
| 6145 | 6145 |
| 6146 Counters* counters = masm->isolate()->counters(); | 6146 Counters* counters = masm->isolate()->counters(); |
| 6147 | 6147 |
| 6148 // Stack on entry: | 6148 // Stack on entry: |
| 6149 // sp[0]: second argument (right). | 6149 // sp[0]: second argument (right). |
| 6150 // sp[4]: first argument (left). | 6150 // sp[4]: first argument (left). |
| 6151 | 6151 |
| 6152 // Load the two arguments. | 6152 // Load the two arguments. |
| 6153 __ ldr(r0, MemOperand(sp, 1 * kPointerSize)); // First argument. | 6153 __ ldr(r0, MemOperand(sp, 1 * kPointerSize)); // First argument. |
| 6154 __ ldr(r1, MemOperand(sp, 0 * kPointerSize)); // Second argument. | 6154 __ ldr(r1, MemOperand(sp, 0 * kPointerSize)); // Second argument. |
| 6155 | 6155 |
| 6156 // Make sure that both arguments are strings if not known in advance. | 6156 // Make sure that both arguments are strings if not known in advance. |
| 6157 if (flags_ == NO_STRING_ADD_FLAGS) { | 6157 if (flags_ == NO_STRING_ADD_FLAGS) { |
| 6158 __ JumpIfEitherSmi(r0, r1, &string_add_runtime); | 6158 __ JumpIfEitherSmi(r0, r1, &call_runtime); |
| 6159 // Load instance types. | 6159 // Load instance types. |
| 6160 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); | 6160 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); |
| 6161 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset)); | 6161 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset)); |
| 6162 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); | 6162 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); |
| 6163 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); | 6163 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); |
| 6164 STATIC_ASSERT(kStringTag == 0); | 6164 STATIC_ASSERT(kStringTag == 0); |
| 6165 // If either is not a string, go to runtime. | 6165 // If either is not a string, go to runtime. |
| 6166 __ tst(r4, Operand(kIsNotStringMask)); | 6166 __ tst(r4, Operand(kIsNotStringMask)); |
| 6167 __ tst(r5, Operand(kIsNotStringMask), eq); | 6167 __ tst(r5, Operand(kIsNotStringMask), eq); |
| 6168 __ b(ne, &string_add_runtime); | 6168 __ b(ne, &call_runtime); |
| 6169 } else { | 6169 } else { |
| 6170 // Here at least one of the arguments is definitely a string. | 6170 // Here at least one of the arguments is definitely a string. |
| 6171 // We convert the one that is not known to be a string. | 6171 // We convert the one that is not known to be a string. |
| 6172 if ((flags_ & NO_STRING_CHECK_LEFT_IN_STUB) == 0) { | 6172 if ((flags_ & NO_STRING_CHECK_LEFT_IN_STUB) == 0) { |
| 6173 ASSERT((flags_ & NO_STRING_CHECK_RIGHT_IN_STUB) != 0); | 6173 ASSERT((flags_ & NO_STRING_CHECK_RIGHT_IN_STUB) != 0); |
| 6174 GenerateConvertArgument( | 6174 GenerateConvertArgument( |
| 6175 masm, 1 * kPointerSize, r0, r2, r3, r4, r5, &call_builtin); | 6175 masm, 1 * kPointerSize, r0, r2, r3, r4, r5, &call_builtin); |
| 6176 builtin_id = Builtins::STRING_ADD_RIGHT; | 6176 builtin_id = Builtins::STRING_ADD_RIGHT; |
| 6177 } else if ((flags_ & NO_STRING_CHECK_RIGHT_IN_STUB) == 0) { | 6177 } else if ((flags_ & NO_STRING_CHECK_RIGHT_IN_STUB) == 0) { |
| 6178 ASSERT((flags_ & NO_STRING_CHECK_LEFT_IN_STUB) != 0); | 6178 ASSERT((flags_ & NO_STRING_CHECK_LEFT_IN_STUB) != 0); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6227 __ b(ne, &longer_than_two); | 6227 __ b(ne, &longer_than_two); |
| 6228 | 6228 |
| 6229 // Check that both strings are non-external ASCII strings. | 6229 // Check that both strings are non-external ASCII strings. |
| 6230 if (flags_ != NO_STRING_ADD_FLAGS) { | 6230 if (flags_ != NO_STRING_ADD_FLAGS) { |
| 6231 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); | 6231 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); |
| 6232 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset)); | 6232 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset)); |
| 6233 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); | 6233 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); |
| 6234 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); | 6234 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); |
| 6235 } | 6235 } |
| 6236 __ JumpIfBothInstanceTypesAreNotSequentialAscii(r4, r5, r6, r7, | 6236 __ JumpIfBothInstanceTypesAreNotSequentialAscii(r4, r5, r6, r7, |
| 6237 &string_add_runtime); | 6237 &call_runtime); |
| 6238 | 6238 |
| 6239 // Get the two characters forming the sub string. | 6239 // Get the two characters forming the sub string. |
| 6240 __ ldrb(r2, FieldMemOperand(r0, SeqAsciiString::kHeaderSize)); | 6240 __ ldrb(r2, FieldMemOperand(r0, SeqAsciiString::kHeaderSize)); |
| 6241 __ ldrb(r3, FieldMemOperand(r1, SeqAsciiString::kHeaderSize)); | 6241 __ ldrb(r3, FieldMemOperand(r1, SeqAsciiString::kHeaderSize)); |
| 6242 | 6242 |
| 6243 // Try to lookup two character string in symbol table. If it is not found | 6243 // Try to lookup two character string in symbol table. If it is not found |
| 6244 // just allocate a new one. | 6244 // just allocate a new one. |
| 6245 Label make_two_character_string; | 6245 Label make_two_character_string; |
| 6246 StringHelper::GenerateTwoCharacterSymbolTableProbe( | 6246 StringHelper::GenerateTwoCharacterSymbolTableProbe( |
| 6247 masm, r2, r3, r6, r7, r4, r5, r9, &make_two_character_string); | 6247 masm, r2, r3, r6, r7, r4, r5, r9, &make_two_character_string); |
| 6248 __ IncrementCounter(counters->string_add_native(), 1, r2, r3); | 6248 __ IncrementCounter(counters->string_add_native(), 1, r2, r3); |
| 6249 __ add(sp, sp, Operand(2 * kPointerSize)); | 6249 __ add(sp, sp, Operand(2 * kPointerSize)); |
| 6250 __ Ret(); | 6250 __ Ret(); |
| 6251 | 6251 |
| 6252 __ bind(&make_two_character_string); | 6252 __ bind(&make_two_character_string); |
| 6253 // Resulting string has length 2 and first chars of two strings | 6253 // Resulting string has length 2 and first chars of two strings |
| 6254 // are combined into single halfword in r2 register. | 6254 // are combined into single halfword in r2 register. |
| 6255 // So we can fill resulting string without two loops by a single | 6255 // So we can fill resulting string without two loops by a single |
| 6256 // halfword store instruction (which assumes that processor is | 6256 // halfword store instruction (which assumes that processor is |
| 6257 // in a little endian mode) | 6257 // in a little endian mode) |
| 6258 __ mov(r6, Operand(2)); | 6258 __ mov(r6, Operand(2)); |
| 6259 __ AllocateAsciiString(r0, r6, r4, r5, r9, &string_add_runtime); | 6259 __ AllocateAsciiString(r0, r6, r4, r5, r9, &call_runtime); |
| 6260 __ strh(r2, FieldMemOperand(r0, SeqAsciiString::kHeaderSize)); | 6260 __ strh(r2, FieldMemOperand(r0, SeqAsciiString::kHeaderSize)); |
| 6261 __ IncrementCounter(counters->string_add_native(), 1, r2, r3); | 6261 __ IncrementCounter(counters->string_add_native(), 1, r2, r3); |
| 6262 __ add(sp, sp, Operand(2 * kPointerSize)); | 6262 __ add(sp, sp, Operand(2 * kPointerSize)); |
| 6263 __ Ret(); | 6263 __ Ret(); |
| 6264 | 6264 |
| 6265 __ bind(&longer_than_two); | 6265 __ bind(&longer_than_two); |
| 6266 // Check if resulting string will be flat. | 6266 // Check if resulting string will be flat. |
| 6267 __ cmp(r6, Operand(String::kMinNonFlatLength)); | 6267 __ cmp(r6, Operand(String::kMinNonFlatLength)); |
| 6268 __ b(lt, &string_add_flat_result); | 6268 __ b(lt, &string_add_flat_result); |
| 6269 // Handle exceptionally long strings in the runtime system. | 6269 // Handle exceptionally long strings in the runtime system. |
| 6270 STATIC_ASSERT((String::kMaxLength & 0x80000000) == 0); | 6270 STATIC_ASSERT((String::kMaxLength & 0x80000000) == 0); |
| 6271 ASSERT(IsPowerOf2(String::kMaxLength + 1)); | 6271 ASSERT(IsPowerOf2(String::kMaxLength + 1)); |
| 6272 // kMaxLength + 1 is representable as shifted literal, kMaxLength is not. | 6272 // kMaxLength + 1 is representable as shifted literal, kMaxLength is not. |
| 6273 __ cmp(r6, Operand(String::kMaxLength + 1)); | 6273 __ cmp(r6, Operand(String::kMaxLength + 1)); |
| 6274 __ b(hs, &string_add_runtime); | 6274 __ b(hs, &call_runtime); |
| 6275 | 6275 |
| 6276 // If result is not supposed to be flat, allocate a cons string object. | 6276 // If result is not supposed to be flat, allocate a cons string object. |
| 6277 // If both strings are ASCII the result is an ASCII cons string. | 6277 // If both strings are ASCII the result is an ASCII cons string. |
| 6278 if (flags_ != NO_STRING_ADD_FLAGS) { | 6278 if (flags_ != NO_STRING_ADD_FLAGS) { |
| 6279 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); | 6279 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); |
| 6280 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset)); | 6280 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset)); |
| 6281 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); | 6281 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); |
| 6282 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); | 6282 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); |
| 6283 } | 6283 } |
| 6284 Label non_ascii, allocated, ascii_data; | 6284 Label non_ascii, allocated, ascii_data; |
| 6285 STATIC_ASSERT(kTwoByteStringTag == 0); | 6285 STATIC_ASSERT(kTwoByteStringTag == 0); |
| 6286 __ tst(r4, Operand(kStringEncodingMask)); | 6286 __ tst(r4, Operand(kStringEncodingMask)); |
| 6287 __ tst(r5, Operand(kStringEncodingMask), ne); | 6287 __ tst(r5, Operand(kStringEncodingMask), ne); |
| 6288 __ b(eq, &non_ascii); | 6288 __ b(eq, &non_ascii); |
| 6289 | 6289 |
| 6290 // Allocate an ASCII cons string. | 6290 // Allocate an ASCII cons string. |
| 6291 __ bind(&ascii_data); | 6291 __ bind(&ascii_data); |
| 6292 __ AllocateAsciiConsString(r7, r6, r4, r5, &string_add_runtime); | 6292 __ AllocateAsciiConsString(r7, r6, r4, r5, &call_runtime); |
| 6293 __ bind(&allocated); | 6293 __ bind(&allocated); |
| 6294 // Fill the fields of the cons string. | 6294 // Fill the fields of the cons string. |
| 6295 __ str(r0, FieldMemOperand(r7, ConsString::kFirstOffset)); | 6295 __ str(r0, FieldMemOperand(r7, ConsString::kFirstOffset)); |
| 6296 __ str(r1, FieldMemOperand(r7, ConsString::kSecondOffset)); | 6296 __ str(r1, FieldMemOperand(r7, ConsString::kSecondOffset)); |
| 6297 __ mov(r0, Operand(r7)); | 6297 __ mov(r0, Operand(r7)); |
| 6298 __ IncrementCounter(counters->string_add_native(), 1, r2, r3); | 6298 __ IncrementCounter(counters->string_add_native(), 1, r2, r3); |
| 6299 __ add(sp, sp, Operand(2 * kPointerSize)); | 6299 __ add(sp, sp, Operand(2 * kPointerSize)); |
| 6300 __ Ret(); | 6300 __ Ret(); |
| 6301 | 6301 |
| 6302 __ bind(&non_ascii); | 6302 __ bind(&non_ascii); |
| 6303 // At least one of the strings is two-byte. Check whether it happens | 6303 // At least one of the strings is two-byte. Check whether it happens |
| 6304 // to contain only ASCII characters. | 6304 // to contain only ASCII characters. |
| 6305 // r4: first instance type. | 6305 // r4: first instance type. |
| 6306 // r5: second instance type. | 6306 // r5: second instance type. |
| 6307 __ tst(r4, Operand(kAsciiDataHintMask)); | 6307 __ tst(r4, Operand(kAsciiDataHintMask)); |
| 6308 __ tst(r5, Operand(kAsciiDataHintMask), ne); | 6308 __ tst(r5, Operand(kAsciiDataHintMask), ne); |
| 6309 __ b(ne, &ascii_data); | 6309 __ b(ne, &ascii_data); |
| 6310 __ eor(r4, r4, Operand(r5)); | 6310 __ eor(r4, r4, Operand(r5)); |
| 6311 STATIC_ASSERT(kAsciiStringTag != 0 && kAsciiDataHintTag != 0); | 6311 STATIC_ASSERT(kAsciiStringTag != 0 && kAsciiDataHintTag != 0); |
| 6312 __ and_(r4, r4, Operand(kAsciiStringTag | kAsciiDataHintTag)); | 6312 __ and_(r4, r4, Operand(kAsciiStringTag | kAsciiDataHintTag)); |
| 6313 __ cmp(r4, Operand(kAsciiStringTag | kAsciiDataHintTag)); | 6313 __ cmp(r4, Operand(kAsciiStringTag | kAsciiDataHintTag)); |
| 6314 __ b(eq, &ascii_data); | 6314 __ b(eq, &ascii_data); |
| 6315 | 6315 |
| 6316 // Allocate a two byte cons string. | 6316 // Allocate a two byte cons string. |
| 6317 __ AllocateTwoByteConsString(r7, r6, r4, r5, &string_add_runtime); | 6317 __ AllocateTwoByteConsString(r7, r6, r4, r5, &call_runtime); |
| 6318 __ jmp(&allocated); | 6318 __ jmp(&allocated); |
| 6319 | 6319 |
| 6320 // Handle creating a flat result. First check that both strings are | 6320 // We cannot encounter sliced strings or cons strings here since: |
| 6321 // sequential and that they have the same encoding. | 6321 STATIC_ASSERT(SlicedString::kMinLength >= String::kMinNonFlatLength); |
| 6322 // Handle creating a flat result from either external or sequential strings. |
| 6323 // Locate the first characters' locations. |
| 6322 // r0: first string | 6324 // r0: first string |
| 6323 // r1: second string | 6325 // r1: second string |
| 6324 // r2: length of first string | 6326 // r2: length of first string |
| 6325 // r3: length of second string | 6327 // r3: length of second string |
| 6326 // r4: first string instance type (if flags_ == NO_STRING_ADD_FLAGS) | 6328 // r4: first string instance type (if flags_ == NO_STRING_ADD_FLAGS) |
| 6327 // r5: second string instance type (if flags_ == NO_STRING_ADD_FLAGS) | 6329 // r5: second string instance type (if flags_ == NO_STRING_ADD_FLAGS) |
| 6328 // r6: sum of lengths. | 6330 // r6: sum of lengths. |
| 6331 Label first_prepared, second_prepared; |
| 6329 __ bind(&string_add_flat_result); | 6332 __ bind(&string_add_flat_result); |
| 6330 if (flags_ != NO_STRING_ADD_FLAGS) { | 6333 if (flags_ != NO_STRING_ADD_FLAGS) { |
| 6331 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); | 6334 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); |
| 6332 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset)); | 6335 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset)); |
| 6333 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); | 6336 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); |
| 6334 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); | 6337 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); |
| 6335 } | 6338 } |
| 6336 // Check that both strings are sequential. | 6339 |
| 6340 // Check whether both strings have same encoding |
| 6341 __ eor(r7, r4, Operand(r5)); |
| 6342 __ tst(r7, Operand(kStringEncodingMask)); |
| 6343 __ b(ne, &call_runtime); |
| 6344 |
| 6337 STATIC_ASSERT(kSeqStringTag == 0); | 6345 STATIC_ASSERT(kSeqStringTag == 0); |
| 6338 __ tst(r4, Operand(kStringRepresentationMask)); | 6346 __ tst(r4, Operand(kStringRepresentationMask)); |
| 6339 __ tst(r5, Operand(kStringRepresentationMask), eq); | 6347 STATIC_ASSERT(SeqAsciiString::kHeaderSize == SeqTwoByteString::kHeaderSize); |
| 6340 __ b(ne, &string_add_runtime); | 6348 __ add(r7, |
| 6341 // Now check if both strings have the same encoding (ASCII/Two-byte). | 6349 r0, |
| 6342 // r0: first string. | 6350 Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag), |
| 6343 // r1: second string. | 6351 LeaveCC, |
| 6352 eq); |
| 6353 __ b(eq, &first_prepared); |
| 6354 // External string: rule out short external string and load string resource. |
| 6355 STATIC_ASSERT(kShortExternalStringTag != 0); |
| 6356 __ tst(r4, Operand(kShortExternalStringMask)); |
| 6357 __ b(ne, &call_runtime); |
| 6358 __ ldr(r7, FieldMemOperand(r0, ExternalString::kResourceDataOffset)); |
| 6359 __ bind(&first_prepared); |
| 6360 |
| 6361 STATIC_ASSERT(kSeqStringTag == 0); |
| 6362 __ tst(r5, Operand(kStringRepresentationMask)); |
| 6363 STATIC_ASSERT(SeqAsciiString::kHeaderSize == SeqTwoByteString::kHeaderSize); |
| 6364 __ add(r1, |
| 6365 r1, |
| 6366 Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag), |
| 6367 LeaveCC, |
| 6368 eq); |
| 6369 __ b(eq, &second_prepared); |
| 6370 // External string: rule out short external string and load string resource. |
| 6371 STATIC_ASSERT(kShortExternalStringTag != 0); |
| 6372 __ tst(r5, Operand(kShortExternalStringMask)); |
| 6373 __ b(ne, &call_runtime); |
| 6374 __ ldr(r1, FieldMemOperand(r1, ExternalString::kResourceDataOffset)); |
| 6375 __ bind(&second_prepared); |
| 6376 |
| 6377 Label non_ascii_string_add_flat_result; |
| 6378 // r7: first character of first string |
| 6379 // r1: first character of second string |
| 6344 // r2: length of first string. | 6380 // r2: length of first string. |
| 6345 // r3: length of second string. | 6381 // r3: length of second string. |
| 6346 // r6: sum of lengths.. | 6382 // r6: sum of lengths. |
| 6347 Label non_ascii_string_add_flat_result; | 6383 // Both strings have the same encoding. |
| 6348 ASSERT(IsPowerOf2(kStringEncodingMask)); // Just one bit to test. | 6384 STATIC_ASSERT(kTwoByteStringTag == 0); |
| 6349 __ eor(r7, r4, Operand(r5)); | 6385 __ tst(r5, Operand(kStringEncodingMask)); |
| 6350 __ tst(r7, Operand(kStringEncodingMask)); | |
| 6351 __ b(ne, &string_add_runtime); | |
| 6352 // And see if it's ASCII or two-byte. | |
| 6353 __ tst(r4, Operand(kStringEncodingMask)); | |
| 6354 __ b(eq, &non_ascii_string_add_flat_result); | 6386 __ b(eq, &non_ascii_string_add_flat_result); |
| 6355 | 6387 |
| 6356 // Both strings are sequential ASCII strings. We also know that they are | 6388 __ AllocateAsciiString(r0, r6, r4, r5, r9, &call_runtime); |
| 6357 // short (since the sum of the lengths is less than kMinNonFlatLength). | 6389 __ add(r6, r0, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); |
| 6358 // r6: length of resulting flat string | 6390 // r0: result string. |
| 6359 __ AllocateAsciiString(r7, r6, r4, r5, r9, &string_add_runtime); | 6391 // r7: first character of first string. |
| 6360 // Locate first character of result. | 6392 // r1: first character of second string. |
| 6361 __ add(r6, r7, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); | |
| 6362 // Locate first character of first argument. | |
| 6363 __ add(r0, r0, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); | |
| 6364 // r0: first character of first string. | |
| 6365 // r1: second string. | |
| 6366 // r2: length of first string. | 6393 // r2: length of first string. |
| 6367 // r3: length of second string. | 6394 // r3: length of second string. |
| 6368 // r6: first character of result. | 6395 // r6: first character of result. |
| 6369 // r7: result string. | 6396 StringHelper::GenerateCopyCharacters(masm, r6, r7, r2, r4, true); |
| 6370 StringHelper::GenerateCopyCharacters(masm, r6, r0, r2, r4, true); | |
| 6371 | |
| 6372 // Load second argument and locate first character. | |
| 6373 __ add(r1, r1, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); | |
| 6374 // r1: first character of second string. | |
| 6375 // r3: length of second string. | |
| 6376 // r6: next character of result. | 6397 // r6: next character of result. |
| 6377 // r7: result string. | |
| 6378 StringHelper::GenerateCopyCharacters(masm, r6, r1, r3, r4, true); | 6398 StringHelper::GenerateCopyCharacters(masm, r6, r1, r3, r4, true); |
| 6379 __ mov(r0, Operand(r7)); | |
| 6380 __ IncrementCounter(counters->string_add_native(), 1, r2, r3); | 6399 __ IncrementCounter(counters->string_add_native(), 1, r2, r3); |
| 6381 __ add(sp, sp, Operand(2 * kPointerSize)); | 6400 __ add(sp, sp, Operand(2 * kPointerSize)); |
| 6382 __ Ret(); | 6401 __ Ret(); |
| 6383 | 6402 |
| 6384 __ bind(&non_ascii_string_add_flat_result); | 6403 __ bind(&non_ascii_string_add_flat_result); |
| 6385 // Both strings are sequential two byte strings. | 6404 __ AllocateTwoByteString(r0, r6, r4, r5, r9, &call_runtime); |
| 6386 // r0: first string. | 6405 __ add(r6, r0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); |
| 6387 // r1: second string. | 6406 // r0: result string. |
| 6388 // r2: length of first string. | 6407 // r7: first character of first string. |
| 6389 // r3: length of second string. | 6408 // r1: first character of second string. |
| 6390 // r6: sum of length of strings. | |
| 6391 __ AllocateTwoByteString(r7, r6, r4, r5, r9, &string_add_runtime); | |
| 6392 // r0: first string. | |
| 6393 // r1: second string. | |
| 6394 // r2: length of first string. | |
| 6395 // r3: length of second string. | |
| 6396 // r7: result string. | |
| 6397 | |
| 6398 // Locate first character of result. | |
| 6399 __ add(r6, r7, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); | |
| 6400 // Locate first character of first argument. | |
| 6401 __ add(r0, r0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); | |
| 6402 | |
| 6403 // r0: first character of first string. | |
| 6404 // r1: second string. | |
| 6405 // r2: length of first string. | 6409 // r2: length of first string. |
| 6406 // r3: length of second string. | 6410 // r3: length of second string. |
| 6407 // r6: first character of result. | 6411 // r6: first character of result. |
| 6408 // r7: result string. | 6412 StringHelper::GenerateCopyCharacters(masm, r6, r7, r2, r4, false); |
| 6409 StringHelper::GenerateCopyCharacters(masm, r6, r0, r2, r4, false); | 6413 // r6: next character of result. |
| 6410 | |
| 6411 // Locate first character of second argument. | |
| 6412 __ add(r1, r1, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); | |
| 6413 | |
| 6414 // r1: first character of second string. | |
| 6415 // r3: length of second string. | |
| 6416 // r6: next character of result (after copy of first string). | |
| 6417 // r7: result string. | |
| 6418 StringHelper::GenerateCopyCharacters(masm, r6, r1, r3, r4, false); | 6414 StringHelper::GenerateCopyCharacters(masm, r6, r1, r3, r4, false); |
| 6419 | |
| 6420 __ mov(r0, Operand(r7)); | |
| 6421 __ IncrementCounter(counters->string_add_native(), 1, r2, r3); | 6415 __ IncrementCounter(counters->string_add_native(), 1, r2, r3); |
| 6422 __ add(sp, sp, Operand(2 * kPointerSize)); | 6416 __ add(sp, sp, Operand(2 * kPointerSize)); |
| 6423 __ Ret(); | 6417 __ Ret(); |
| 6424 | 6418 |
| 6425 // Just jump to runtime to add the two strings. | 6419 // Just jump to runtime to add the two strings. |
| 6426 __ bind(&string_add_runtime); | 6420 __ bind(&call_runtime); |
| 6427 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); | 6421 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); |
| 6428 | 6422 |
| 6429 if (call_builtin.is_linked()) { | 6423 if (call_builtin.is_linked()) { |
| 6430 __ bind(&call_builtin); | 6424 __ bind(&call_builtin); |
| 6431 __ InvokeBuiltin(builtin_id, JUMP_FUNCTION); | 6425 __ InvokeBuiltin(builtin_id, JUMP_FUNCTION); |
| 6432 } | 6426 } |
| 6433 } | 6427 } |
| 6434 | 6428 |
| 6435 | 6429 |
| 6436 void StringAddStub::GenerateConvertArgument(MacroAssembler* masm, | 6430 void StringAddStub::GenerateConvertArgument(MacroAssembler* masm, |
| (...skipping 879 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7316 __ StoreNumberToDoubleElements(r0, r3, r1, r5, r6, r7, r9, r10, | 7310 __ StoreNumberToDoubleElements(r0, r3, r1, r5, r6, r7, r9, r10, |
| 7317 &slow_elements); | 7311 &slow_elements); |
| 7318 __ Ret(); | 7312 __ Ret(); |
| 7319 } | 7313 } |
| 7320 | 7314 |
| 7321 #undef __ | 7315 #undef __ |
| 7322 | 7316 |
| 7323 } } // namespace v8::internal | 7317 } } // namespace v8::internal |
| 7324 | 7318 |
| 7325 #endif // V8_TARGET_ARCH_ARM | 7319 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |