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 5250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5261 | 5261 |
5262 // If the index is non-smi trigger the non-smi case. | 5262 // If the index is non-smi trigger the non-smi case. |
5263 __ JumpIfNotSmi(index_, &index_not_smi_); | 5263 __ JumpIfNotSmi(index_, &index_not_smi_); |
5264 | 5264 |
5265 __ bind(&got_smi_index_); | 5265 __ bind(&got_smi_index_); |
5266 | 5266 |
5267 // Check for index out of range. | 5267 // Check for index out of range. |
5268 __ lw(t0, FieldMemOperand(object_, String::kLengthOffset)); | 5268 __ lw(t0, FieldMemOperand(object_, String::kLengthOffset)); |
5269 __ Branch(index_out_of_range_, ls, t0, Operand(index_)); | 5269 __ Branch(index_out_of_range_, ls, t0, Operand(index_)); |
5270 | 5270 |
5271 // We need special handling for non-flat strings. | 5271 __ sra(index_, index_, kSmiTagSize); |
5272 STATIC_ASSERT(kSeqStringTag == 0); | |
5273 __ And(t0, result_, Operand(kStringRepresentationMask)); | |
5274 __ Branch(&flat_string, eq, t0, Operand(zero_reg)); | |
5275 | 5272 |
5276 // Handle non-flat strings. | 5273 StringCharLoadGenerator::Generate(masm, |
5277 __ And(result_, result_, Operand(kStringRepresentationMask)); | 5274 object_, |
5278 STATIC_ASSERT(kConsStringTag < kExternalStringTag); | 5275 index_, |
5279 STATIC_ASSERT(kSlicedStringTag > kExternalStringTag); | 5276 result_, |
5280 __ Branch(&sliced_string, gt, result_, Operand(kExternalStringTag)); | 5277 &call_runtime_); |
5281 __ Branch(&call_runtime_, eq, result_, Operand(kExternalStringTag)); | |
5282 | 5278 |
5283 // ConsString. | |
5284 // Check whether the right hand side is the empty string (i.e. if | |
5285 // this is really a flat string in a cons string). If that is not | |
5286 // the case we would rather go to the runtime system now to flatten | |
5287 // the string. | |
5288 Label assure_seq_string; | |
5289 __ lw(result_, FieldMemOperand(object_, ConsString::kSecondOffset)); | |
5290 __ LoadRoot(t0, Heap::kEmptyStringRootIndex); | |
5291 __ Branch(&call_runtime_, ne, result_, Operand(t0)); | |
5292 | |
5293 // Get the first of the two parts. | |
5294 __ lw(object_, FieldMemOperand(object_, ConsString::kFirstOffset)); | |
5295 __ jmp(&assure_seq_string); | |
5296 | |
5297 // SlicedString, unpack and add offset. | |
5298 __ bind(&sliced_string); | |
5299 __ lw(result_, FieldMemOperand(object_, SlicedString::kOffsetOffset)); | |
5300 __ Addu(index_, index_, result_); | |
5301 __ lw(object_, FieldMemOperand(object_, SlicedString::kParentOffset)); | |
5302 | |
5303 // Assure that we are dealing with a sequential string. Go to runtime if not. | |
5304 __ bind(&assure_seq_string); | |
5305 __ lw(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); | |
5306 __ lbu(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); | |
5307 // Check that parent is not an external string. Go to runtime otherwise. | |
5308 // Note that if the original string is a cons or slice with an external | |
5309 // string as underlying string, we pass that unpacked underlying string with | |
5310 // the adjusted index to the runtime function. | |
5311 STATIC_ASSERT(kSeqStringTag == 0); | |
5312 | |
5313 __ And(t0, result_, Operand(kStringRepresentationMask)); | |
5314 __ Branch(&call_runtime_, ne, t0, Operand(zero_reg)); | |
5315 | |
5316 // Check for 1-byte or 2-byte string. | |
5317 __ bind(&flat_string); | |
5318 STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0); | |
5319 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0); | |
5320 __ And(t0, result_, Operand(kStringEncodingMask)); | |
5321 __ Branch(&ascii_string, ne, t0, Operand(zero_reg)); | |
5322 | |
5323 // 2-byte string. | |
5324 // Load the 2-byte character code into the result register. We can | |
5325 // add without shifting since the smi tag size is the log2 of the | |
5326 // number of bytes in a two-byte character. | |
5327 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1 && kSmiShiftSize == 0); | |
5328 __ Addu(index_, object_, Operand(index_)); | |
5329 __ lhu(result_, FieldMemOperand(index_, SeqTwoByteString::kHeaderSize)); | |
5330 __ Branch(&got_char_code); | |
5331 | |
5332 // ASCII string. | |
5333 // Load the byte into the result register. | |
5334 __ bind(&ascii_string); | |
5335 | |
5336 __ srl(t0, index_, kSmiTagSize); | |
5337 __ Addu(index_, object_, t0); | |
5338 | |
5339 __ lbu(result_, FieldMemOperand(index_, SeqAsciiString::kHeaderSize)); | |
5340 | |
5341 __ bind(&got_char_code); | |
5342 __ sll(result_, result_, kSmiTagSize); | 5279 __ sll(result_, result_, kSmiTagSize); |
5343 __ bind(&exit_); | 5280 __ bind(&exit_); |
5344 } | 5281 } |
5345 | 5282 |
5346 | 5283 |
5347 void StringCharCodeAtGenerator::GenerateSlow( | 5284 void StringCharCodeAtGenerator::GenerateSlow( |
5348 MacroAssembler* masm, | 5285 MacroAssembler* masm, |
5349 const RuntimeCallHelper& call_helper) { | 5286 const RuntimeCallHelper& call_helper) { |
5350 __ Abort("Unexpected fallthrough to CharCodeAt slow case"); | 5287 __ Abort("Unexpected fallthrough to CharCodeAt slow case"); |
5351 | 5288 |
(...skipping 28 matching lines...) Expand all Loading... |
5380 // If index is still not a smi, it must be out of range. | 5317 // If index is still not a smi, it must be out of range. |
5381 __ JumpIfNotSmi(index_, index_out_of_range_); | 5318 __ JumpIfNotSmi(index_, index_out_of_range_); |
5382 // Otherwise, return to the fast path. | 5319 // Otherwise, return to the fast path. |
5383 __ Branch(&got_smi_index_); | 5320 __ Branch(&got_smi_index_); |
5384 | 5321 |
5385 // Call runtime. We get here when the receiver is a string and the | 5322 // Call runtime. We get here when the receiver is a string and the |
5386 // index is a number, but the code of getting the actual character | 5323 // index is a number, but the code of getting the actual character |
5387 // is too complex (e.g., when the string needs to be flattened). | 5324 // is too complex (e.g., when the string needs to be flattened). |
5388 __ bind(&call_runtime_); | 5325 __ bind(&call_runtime_); |
5389 call_helper.BeforeCall(masm); | 5326 call_helper.BeforeCall(masm); |
| 5327 __ sll(index_, index_, kSmiTagSize); |
5390 __ Push(object_, index_); | 5328 __ Push(object_, index_); |
5391 __ CallRuntime(Runtime::kStringCharCodeAt, 2); | 5329 __ CallRuntime(Runtime::kStringCharCodeAt, 2); |
5392 | 5330 |
5393 __ Move(result_, v0); | 5331 __ Move(result_, v0); |
5394 | 5332 |
5395 call_helper.AfterCall(masm); | 5333 call_helper.AfterCall(masm); |
5396 __ jmp(&exit_); | 5334 __ jmp(&exit_); |
5397 | 5335 |
5398 __ Abort("Unexpected fallthrough from CharCodeAt slow case"); | 5336 __ Abort("Unexpected fallthrough from CharCodeAt slow case"); |
5399 } | 5337 } |
(...skipping 2061 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7461 &slow_elements); | 7399 &slow_elements); |
7462 __ Ret(); | 7400 __ Ret(); |
7463 } | 7401 } |
7464 | 7402 |
7465 | 7403 |
7466 #undef __ | 7404 #undef __ |
7467 | 7405 |
7468 } } // namespace v8::internal | 7406 } } // namespace v8::internal |
7469 | 7407 |
7470 #endif // V8_TARGET_ARCH_MIPS | 7408 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |