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

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

Issue 8506024: MIPS: Simplify StringCharCodeAt in non-crankshaft codegen. (Closed)
Patch Set: Created 9 years, 1 month 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
« no previous file with comments | « no previous file | src/mips/full-codegen-mips.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 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 5225 matching lines...) Expand 10 before | Expand all | Expand 10 after
5236 } 5236 }
5237 5237
5238 5238
5239 // StringCharCodeAtGenerator. 5239 // StringCharCodeAtGenerator.
5240 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { 5240 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
5241 Label flat_string; 5241 Label flat_string;
5242 Label ascii_string; 5242 Label ascii_string;
5243 Label got_char_code; 5243 Label got_char_code;
5244 Label sliced_string; 5244 Label sliced_string;
5245 5245
5246 ASSERT(!t0.is(scratch_));
5247 ASSERT(!t0.is(index_)); 5246 ASSERT(!t0.is(index_));
5248 ASSERT(!t0.is(result_)); 5247 ASSERT(!t0.is(result_));
5249 ASSERT(!t0.is(object_)); 5248 ASSERT(!t0.is(object_));
5250 5249
5251 // If the receiver is a smi trigger the non-string case. 5250 // If the receiver is a smi trigger the non-string case.
5252 __ JumpIfSmi(object_, receiver_not_string_); 5251 __ JumpIfSmi(object_, receiver_not_string_);
5253 5252
5254 // Fetch the instance type of the receiver into result register. 5253 // Fetch the instance type of the receiver into result register.
5255 __ lw(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); 5254 __ lw(result_, FieldMemOperand(object_, HeapObject::kMapOffset));
5256 __ lbu(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); 5255 __ lbu(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset));
5257 // If the receiver is not a string trigger the non-string case. 5256 // If the receiver is not a string trigger the non-string case.
5258 __ And(t0, result_, Operand(kIsNotStringMask)); 5257 __ And(t0, result_, Operand(kIsNotStringMask));
5259 __ Branch(receiver_not_string_, ne, t0, Operand(zero_reg)); 5258 __ Branch(receiver_not_string_, ne, t0, Operand(zero_reg));
5260 5259
5261 // If the index is non-smi trigger the non-smi case. 5260 // If the index is non-smi trigger the non-smi case.
5262 __ JumpIfNotSmi(index_, &index_not_smi_); 5261 __ JumpIfNotSmi(index_, &index_not_smi_);
5263 5262
5264 // Put smi-tagged index into scratch register.
5265 __ mov(scratch_, index_);
5266 __ bind(&got_smi_index_); 5263 __ bind(&got_smi_index_);
5267 5264
5268 // Check for index out of range. 5265 // Check for index out of range.
5269 __ lw(t0, FieldMemOperand(object_, String::kLengthOffset)); 5266 __ lw(t0, FieldMemOperand(object_, String::kLengthOffset));
5270 __ Branch(index_out_of_range_, ls, t0, Operand(scratch_)); 5267 __ Branch(index_out_of_range_, ls, t0, Operand(index_));
5271 5268
5272 // We need special handling for non-flat strings. 5269 // We need special handling for non-flat strings.
5273 STATIC_ASSERT(kSeqStringTag == 0); 5270 STATIC_ASSERT(kSeqStringTag == 0);
5274 __ And(t0, result_, Operand(kStringRepresentationMask)); 5271 __ And(t0, result_, Operand(kStringRepresentationMask));
5275 __ Branch(&flat_string, eq, t0, Operand(zero_reg)); 5272 __ Branch(&flat_string, eq, t0, Operand(zero_reg));
5276 5273
5277 // Handle non-flat strings. 5274 // Handle non-flat strings.
5278 __ And(result_, result_, Operand(kStringRepresentationMask)); 5275 __ And(result_, result_, Operand(kStringRepresentationMask));
5279 STATIC_ASSERT(kConsStringTag < kExternalStringTag); 5276 STATIC_ASSERT(kConsStringTag < kExternalStringTag);
5280 STATIC_ASSERT(kSlicedStringTag > kExternalStringTag); 5277 STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
5281 __ Branch(&sliced_string, gt, result_, Operand(kExternalStringTag)); 5278 __ Branch(&sliced_string, gt, result_, Operand(kExternalStringTag));
5282 __ Branch(&call_runtime_, eq, result_, Operand(kExternalStringTag)); 5279 __ Branch(&call_runtime_, eq, result_, Operand(kExternalStringTag));
5283 5280
5284 // ConsString. 5281 // ConsString.
5285 // Check whether the right hand side is the empty string (i.e. if 5282 // Check whether the right hand side is the empty string (i.e. if
5286 // this is really a flat string in a cons string). If that is not 5283 // this is really a flat string in a cons string). If that is not
5287 // the case we would rather go to the runtime system now to flatten 5284 // the case we would rather go to the runtime system now to flatten
5288 // the string. 5285 // the string.
5289 Label assure_seq_string; 5286 Label assure_seq_string;
5290 __ lw(result_, FieldMemOperand(object_, ConsString::kSecondOffset)); 5287 __ lw(result_, FieldMemOperand(object_, ConsString::kSecondOffset));
5291 __ LoadRoot(t0, Heap::kEmptyStringRootIndex); 5288 __ LoadRoot(t0, Heap::kEmptyStringRootIndex);
5292 __ Branch(&call_runtime_, ne, result_, Operand(t0)); 5289 __ Branch(&call_runtime_, ne, result_, Operand(t0));
5293 5290
5294 // Get the first of the two strings and load its instance type. 5291 // Get the first of the two parts.
5295 __ lw(result_, FieldMemOperand(object_, ConsString::kFirstOffset)); 5292 __ lw(object_, FieldMemOperand(object_, ConsString::kFirstOffset));
5296 __ jmp(&assure_seq_string); 5293 __ jmp(&assure_seq_string);
5297 5294
5298 // SlicedString, unpack and add offset. 5295 // SlicedString, unpack and add offset.
5299 __ bind(&sliced_string); 5296 __ bind(&sliced_string);
5300 __ lw(result_, FieldMemOperand(object_, SlicedString::kOffsetOffset)); 5297 __ lw(result_, FieldMemOperand(object_, SlicedString::kOffsetOffset));
5301 __ addu(scratch_, scratch_, result_); 5298 __ Addu(index_, index_, result_);
5302 __ lw(result_, FieldMemOperand(object_, SlicedString::kParentOffset)); 5299 __ lw(object_, FieldMemOperand(object_, SlicedString::kParentOffset));
5303 5300
5304 // Assure that we are dealing with a sequential string. Go to runtime if not. 5301 // Assure that we are dealing with a sequential string. Go to runtime if not.
5305 __ bind(&assure_seq_string); 5302 __ bind(&assure_seq_string);
5306 __ lw(result_, FieldMemOperand(result_, HeapObject::kMapOffset)); 5303 __ lw(result_, FieldMemOperand(object_, HeapObject::kMapOffset));
5307 __ lbu(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); 5304 __ lbu(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset));
5308 // Check that parent is not an external string. Go to runtime otherwise. 5305 // Check that parent is not an external string. Go to runtime otherwise.
5306 // Note that if the original string is a cons or slice with an external
5307 // string as underlying string, we pass that unpacked underlying string with
5308 // the updated index to the runtime function.
5309 STATIC_ASSERT(kSeqStringTag == 0); 5309 STATIC_ASSERT(kSeqStringTag == 0);
5310 5310
5311 __ And(t0, result_, Operand(kStringRepresentationMask)); 5311 __ And(t0, result_, Operand(kStringRepresentationMask));
5312 __ Branch(&call_runtime_, ne, t0, Operand(zero_reg)); 5312 __ Branch(&call_runtime_, ne, t0, Operand(zero_reg));
5313 // Actually fetch the parent string if it is confirmed to be sequential.
5314 STATIC_ASSERT(SlicedString::kParentOffset == ConsString::kFirstOffset);
5315 __ lw(object_, FieldMemOperand(object_, SlicedString::kParentOffset));
5316 5313
5317 // Check for 1-byte or 2-byte string. 5314 // Check for 1-byte or 2-byte string.
5318 __ bind(&flat_string); 5315 __ bind(&flat_string);
5319 STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0); 5316 STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0);
5320 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0); 5317 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
5321 __ And(t0, result_, Operand(kStringEncodingMask)); 5318 __ And(t0, result_, Operand(kStringEncodingMask));
5322 __ Branch(&ascii_string, ne, t0, Operand(zero_reg)); 5319 __ Branch(&ascii_string, ne, t0, Operand(zero_reg));
5323 5320
5324 // 2-byte string. 5321 // 2-byte string.
5325 // Load the 2-byte character code into the result register. We can 5322 // Load the 2-byte character code into the result register. We can
5326 // add without shifting since the smi tag size is the log2 of the 5323 // add without shifting since the smi tag size is the log2 of the
5327 // number of bytes in a two-byte character. 5324 // number of bytes in a two-byte character.
5328 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1 && kSmiShiftSize == 0); 5325 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1 && kSmiShiftSize == 0);
5329 __ Addu(scratch_, object_, Operand(scratch_)); 5326 __ Addu(index_, object_, Operand(index_));
5330 __ lhu(result_, FieldMemOperand(scratch_, SeqTwoByteString::kHeaderSize)); 5327 __ lhu(result_, FieldMemOperand(index_, SeqTwoByteString::kHeaderSize));
5331 __ Branch(&got_char_code); 5328 __ Branch(&got_char_code);
5332 5329
5333 // ASCII string. 5330 // ASCII string.
5334 // Load the byte into the result register. 5331 // Load the byte into the result register.
5335 __ bind(&ascii_string); 5332 __ bind(&ascii_string);
5336 5333
5337 __ srl(t0, scratch_, kSmiTagSize); 5334 __ srl(t0, index_, kSmiTagSize);
5338 __ Addu(scratch_, object_, t0); 5335 __ Addu(index_, object_, t0);
5339 5336
5340 __ lbu(result_, FieldMemOperand(scratch_, SeqAsciiString::kHeaderSize)); 5337 __ lbu(result_, FieldMemOperand(index_, SeqAsciiString::kHeaderSize));
5341 5338
5342 __ bind(&got_char_code); 5339 __ bind(&got_char_code);
5343 __ sll(result_, result_, kSmiTagSize); 5340 __ sll(result_, result_, kSmiTagSize);
5344 __ bind(&exit_); 5341 __ bind(&exit_);
5345 } 5342 }
5346 5343
5347 5344
5348 void StringCharCodeAtGenerator::GenerateSlow( 5345 void StringCharCodeAtGenerator::GenerateSlow(
5349 MacroAssembler* masm, 5346 MacroAssembler* masm,
5350 const RuntimeCallHelper& call_helper) { 5347 const RuntimeCallHelper& call_helper) {
5351 __ Abort("Unexpected fallthrough to CharCodeAt slow case"); 5348 __ Abort("Unexpected fallthrough to CharCodeAt slow case");
5352 5349
5353 // Index is not a smi. 5350 // Index is not a smi.
5354 __ bind(&index_not_smi_); 5351 __ bind(&index_not_smi_);
5355 // If index is a heap number, try converting it to an integer. 5352 // If index is a heap number, try converting it to an integer.
5356 __ CheckMap(index_, 5353 __ CheckMap(index_,
5357 scratch_, 5354 result_,
5358 Heap::kHeapNumberMapRootIndex, 5355 Heap::kHeapNumberMapRootIndex,
5359 index_not_number_, 5356 index_not_number_,
5360 DONT_DO_SMI_CHECK); 5357 DONT_DO_SMI_CHECK);
5361 call_helper.BeforeCall(masm); 5358 call_helper.BeforeCall(masm);
5362 // Consumed by runtime conversion function: 5359 // Consumed by runtime conversion function:
5363 __ Push(object_, index_, index_); 5360 __ Push(object_, index_);
5364 if (index_flags_ == STRING_INDEX_IS_NUMBER) { 5361 if (index_flags_ == STRING_INDEX_IS_NUMBER) {
5365 __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1); 5362 __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1);
5366 } else { 5363 } else {
5367 ASSERT(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX); 5364 ASSERT(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX);
5368 // NumberToSmi discards numbers that are not exact integers. 5365 // NumberToSmi discards numbers that are not exact integers.
5369 __ CallRuntime(Runtime::kNumberToSmi, 1); 5366 __ CallRuntime(Runtime::kNumberToSmi, 1);
5370 } 5367 }
5371 5368
5372 // Save the conversion result before the pop instructions below 5369 // Save the conversion result before the pop instructions below
5373 // have a chance to overwrite it. 5370 // have a chance to overwrite it.
5374 5371
5375 __ Move(scratch_, v0); 5372 __ Move(index_, v0);
5376
5377 __ pop(index_);
5378 __ pop(object_); 5373 __ pop(object_);
5379 // Reload the instance type. 5374 // Reload the instance type.
5380 __ lw(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); 5375 __ lw(result_, FieldMemOperand(object_, HeapObject::kMapOffset));
5381 __ lbu(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); 5376 __ lbu(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset));
5382 call_helper.AfterCall(masm); 5377 call_helper.AfterCall(masm);
5383 // If index is still not a smi, it must be out of range. 5378 // If index is still not a smi, it must be out of range.
5384 __ JumpIfNotSmi(scratch_, index_out_of_range_); 5379 __ JumpIfNotSmi(index_, index_out_of_range_);
5385 // Otherwise, return to the fast path. 5380 // Otherwise, return to the fast path.
5386 __ Branch(&got_smi_index_); 5381 __ Branch(&got_smi_index_);
5387 5382
5388 // Call runtime. We get here when the receiver is a string and the 5383 // Call runtime. We get here when the receiver is a string and the
5389 // index is a number, but the code of getting the actual character 5384 // index is a number, but the code of getting the actual character
5390 // is too complex (e.g., when the string needs to be flattened). 5385 // is too complex (e.g., when the string needs to be flattened).
5391 __ bind(&call_runtime_); 5386 __ bind(&call_runtime_);
5392 call_helper.BeforeCall(masm); 5387 call_helper.BeforeCall(masm);
5393 __ Push(object_, index_); 5388 __ Push(object_, index_);
5394 __ CallRuntime(Runtime::kStringCharCodeAt, 2); 5389 __ CallRuntime(Runtime::kStringCharCodeAt, 2);
(...skipping 2069 matching lines...) Expand 10 before | Expand all | Expand 10 after
7464 7459
7465 // Fall through when we need to inform the incremental marker. 7460 // Fall through when we need to inform the incremental marker.
7466 } 7461 }
7467 7462
7468 7463
7469 #undef __ 7464 #undef __
7470 7465
7471 } } // namespace v8::internal 7466 } } // namespace v8::internal
7472 7467
7473 #endif // V8_TARGET_ARCH_MIPS 7468 #endif // V8_TARGET_ARCH_MIPS
OLDNEW
« no previous file with comments | « no previous file | src/mips/full-codegen-mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698