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 5089 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5100 __ mov(result_, FieldOperand(object_, HeapObject::kMapOffset)); | 5100 __ mov(result_, FieldOperand(object_, HeapObject::kMapOffset)); |
5101 __ movzx_b(result_, FieldOperand(result_, Map::kInstanceTypeOffset)); | 5101 __ movzx_b(result_, FieldOperand(result_, Map::kInstanceTypeOffset)); |
5102 // If the receiver is not a string trigger the non-string case. | 5102 // If the receiver is not a string trigger the non-string case. |
5103 __ test(result_, Immediate(kIsNotStringMask)); | 5103 __ test(result_, Immediate(kIsNotStringMask)); |
5104 __ j(not_zero, receiver_not_string_); | 5104 __ j(not_zero, receiver_not_string_); |
5105 | 5105 |
5106 // If the index is non-smi trigger the non-smi case. | 5106 // If the index is non-smi trigger the non-smi case. |
5107 STATIC_ASSERT(kSmiTag == 0); | 5107 STATIC_ASSERT(kSmiTag == 0); |
5108 __ JumpIfNotSmi(index_, &index_not_smi_); | 5108 __ JumpIfNotSmi(index_, &index_not_smi_); |
5109 | 5109 |
5110 // Put smi-tagged index into scratch register. | 5110 // Put smi-tagged index into scratch register. |
Lasse Reichstein
2011/11/09 12:48:11
Remove the comment too.
| |
5111 __ mov(scratch_, index_); | |
5112 __ bind(&got_smi_index_); | 5111 __ bind(&got_smi_index_); |
5113 | 5112 |
5114 // Check for index out of range. | 5113 // Check for index out of range. |
5115 __ cmp(scratch_, FieldOperand(object_, String::kLengthOffset)); | 5114 __ cmp(index_, FieldOperand(object_, String::kLengthOffset)); |
5116 __ j(above_equal, index_out_of_range_); | 5115 __ j(above_equal, index_out_of_range_); |
5117 | 5116 |
5118 // We need special handling for non-flat strings. | 5117 // We need special handling for non-flat strings. |
5119 STATIC_ASSERT(kSeqStringTag == 0); | 5118 STATIC_ASSERT(kSeqStringTag == 0); |
5120 __ test(result_, Immediate(kStringRepresentationMask)); | 5119 __ test(result_, Immediate(kStringRepresentationMask)); |
5121 __ j(zero, &flat_string); | 5120 __ j(zero, &flat_string); |
5122 | 5121 |
5123 // Handle non-flat strings. | 5122 // Handle non-flat strings. |
5124 __ and_(result_, kStringRepresentationMask); | 5123 __ and_(result_, kStringRepresentationMask); |
5125 STATIC_ASSERT(kConsStringTag < kExternalStringTag); | 5124 STATIC_ASSERT(kConsStringTag < kExternalStringTag); |
5126 STATIC_ASSERT(kSlicedStringTag > kExternalStringTag); | 5125 STATIC_ASSERT(kSlicedStringTag > kExternalStringTag); |
5127 __ cmp(result_, kExternalStringTag); | 5126 __ cmp(result_, kExternalStringTag); |
5128 __ j(greater, &sliced_string, Label::kNear); | 5127 __ j(greater, &sliced_string, Label::kNear); |
5129 __ j(equal, &call_runtime_); | 5128 __ j(equal, &call_runtime_); |
5130 | 5129 |
5131 // ConsString. | 5130 // ConsString. |
5132 // Check whether the right hand side is the empty string (i.e. if | 5131 // Check whether the right hand side is the empty string (i.e. if |
5133 // this is really a flat string in a cons string). If that is not | 5132 // this is really a flat string in a cons string). If that is not |
5134 // the case we would rather go to the runtime system now to flatten | 5133 // the case we would rather go to the runtime system now to flatten |
5135 // the string. | 5134 // the string. |
5136 Label assure_seq_string; | 5135 Label assure_seq_string; |
5137 __ cmp(FieldOperand(object_, ConsString::kSecondOffset), | 5136 __ cmp(FieldOperand(object_, ConsString::kSecondOffset), |
5138 Immediate(masm->isolate()->factory()->empty_string())); | 5137 Immediate(masm->isolate()->factory()->empty_string())); |
5139 __ j(not_equal, &call_runtime_); | 5138 __ j(not_equal, &call_runtime_); |
5140 // Get the first of the two strings and load its instance type. | 5139 // Get the first of the two parts. |
5141 __ mov(result_, FieldOperand(object_, ConsString::kFirstOffset)); | 5140 __ mov(object_, FieldOperand(object_, ConsString::kFirstOffset)); |
5142 __ jmp(&assure_seq_string, Label::kNear); | 5141 __ jmp(&assure_seq_string, Label::kNear); |
5143 | 5142 |
5144 // SlicedString, unpack and add offset. | 5143 // SlicedString, unpack and add offset. |
5145 __ bind(&sliced_string); | 5144 __ bind(&sliced_string); |
5146 __ add(scratch_, FieldOperand(object_, SlicedString::kOffsetOffset)); | 5145 __ add(index_, FieldOperand(object_, SlicedString::kOffsetOffset)); |
5147 __ mov(result_, FieldOperand(object_, SlicedString::kParentOffset)); | 5146 __ mov(object_, FieldOperand(object_, SlicedString::kParentOffset)); |
5148 | 5147 |
5149 // Assure that we are dealing with a sequential string. Go to runtime if not. | 5148 // Assure that we are dealing with a sequential string. Go to runtime if not. |
5149 // Note that if the original string is a cons or slice with an external | |
5150 // string as underlying string, we pass that unpacked underlying string with | |
5151 // the updated index to the runtime function. | |
5150 __ bind(&assure_seq_string); | 5152 __ bind(&assure_seq_string); |
5151 __ mov(result_, FieldOperand(result_, HeapObject::kMapOffset)); | 5153 __ mov(result_, FieldOperand(object_, HeapObject::kMapOffset)); |
5152 __ movzx_b(result_, FieldOperand(result_, Map::kInstanceTypeOffset)); | 5154 __ movzx_b(result_, FieldOperand(result_, Map::kInstanceTypeOffset)); |
5153 STATIC_ASSERT(kSeqStringTag == 0); | 5155 STATIC_ASSERT(kSeqStringTag == 0); |
5154 __ test(result_, Immediate(kStringRepresentationMask)); | 5156 __ test(result_, Immediate(kStringRepresentationMask)); |
5155 __ j(not_zero, &call_runtime_); | 5157 __ j(not_zero, &call_runtime_); |
5156 // Actually fetch the parent string if it is confirmed to be sequential. | |
5157 STATIC_ASSERT(SlicedString::kParentOffset == ConsString::kFirstOffset); | |
5158 __ mov(object_, FieldOperand(object_, SlicedString::kParentOffset)); | |
5159 | 5158 |
5160 // Check for 1-byte or 2-byte string. | 5159 // Check for 1-byte or 2-byte string. |
5161 __ bind(&flat_string); | 5160 __ bind(&flat_string); |
5162 STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0); | 5161 STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0); |
5163 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0); | 5162 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0); |
5164 __ test(result_, Immediate(kStringEncodingMask)); | 5163 __ test(result_, Immediate(kStringEncodingMask)); |
5165 __ j(not_zero, &ascii_string, Label::kNear); | 5164 __ j(not_zero, &ascii_string, Label::kNear); |
5166 | 5165 |
5167 // 2-byte string. | 5166 // 2-byte string. |
5168 // Load the 2-byte character code into the result register. | 5167 // Load the 2-byte character code into the result register. |
5169 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1); | 5168 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1); |
5170 __ movzx_w(result_, FieldOperand(object_, | 5169 __ movzx_w(result_, FieldOperand(object_, |
5171 scratch_, times_1, // Scratch is smi-tagged. | 5170 index_, times_1, // Scratch is smi-tagged. |
5172 SeqTwoByteString::kHeaderSize)); | 5171 SeqTwoByteString::kHeaderSize)); |
5173 __ jmp(&got_char_code, Label::kNear); | 5172 __ jmp(&got_char_code, Label::kNear); |
5174 | 5173 |
5175 // ASCII string. | 5174 // ASCII string. |
5176 // Load the byte into the result register. | 5175 // Load the byte into the result register. |
5177 __ bind(&ascii_string); | 5176 __ bind(&ascii_string); |
5178 __ SmiUntag(scratch_); | 5177 __ SmiUntag(index_); |
5179 __ movzx_b(result_, FieldOperand(object_, | 5178 __ movzx_b(result_, FieldOperand(object_, |
5180 scratch_, times_1, | 5179 index_, times_1, |
5181 SeqAsciiString::kHeaderSize)); | 5180 SeqAsciiString::kHeaderSize)); |
5182 __ bind(&got_char_code); | 5181 __ bind(&got_char_code); |
5183 __ SmiTag(result_); | 5182 __ SmiTag(result_); |
5184 __ bind(&exit_); | 5183 __ bind(&exit_); |
5185 } | 5184 } |
5186 | 5185 |
5187 | 5186 |
5188 void StringCharCodeAtGenerator::GenerateSlow( | 5187 void StringCharCodeAtGenerator::GenerateSlow( |
5189 MacroAssembler* masm, | 5188 MacroAssembler* masm, |
5190 const RuntimeCallHelper& call_helper) { | 5189 const RuntimeCallHelper& call_helper) { |
5191 __ Abort("Unexpected fallthrough to CharCodeAt slow case"); | 5190 __ Abort("Unexpected fallthrough to CharCodeAt slow case"); |
5192 | 5191 |
5193 // Index is not a smi. | 5192 // Index is not a smi. |
5194 __ bind(&index_not_smi_); | 5193 __ bind(&index_not_smi_); |
5195 // If index is a heap number, try converting it to an integer. | 5194 // If index is a heap number, try converting it to an integer. |
5196 __ CheckMap(index_, | 5195 __ CheckMap(index_, |
5197 masm->isolate()->factory()->heap_number_map(), | 5196 masm->isolate()->factory()->heap_number_map(), |
5198 index_not_number_, | 5197 index_not_number_, |
5199 DONT_DO_SMI_CHECK); | 5198 DONT_DO_SMI_CHECK); |
5200 call_helper.BeforeCall(masm); | 5199 call_helper.BeforeCall(masm); |
5201 __ push(object_); | 5200 __ push(object_); |
5202 __ push(index_); | |
5203 __ push(index_); // Consumed by runtime conversion function. | 5201 __ push(index_); // Consumed by runtime conversion function. |
5204 if (index_flags_ == STRING_INDEX_IS_NUMBER) { | 5202 if (index_flags_ == STRING_INDEX_IS_NUMBER) { |
5205 __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1); | 5203 __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1); |
5206 } else { | 5204 } else { |
5207 ASSERT(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX); | 5205 ASSERT(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX); |
5208 // NumberToSmi discards numbers that are not exact integers. | 5206 // NumberToSmi discards numbers that are not exact integers. |
5209 __ CallRuntime(Runtime::kNumberToSmi, 1); | 5207 __ CallRuntime(Runtime::kNumberToSmi, 1); |
5210 } | 5208 } |
5211 if (!scratch_.is(eax)) { | 5209 if (!index_.is(eax)) { |
5212 // Save the conversion result before the pop instructions below | 5210 // Save the conversion result before the pop instructions below |
5213 // have a chance to overwrite it. | 5211 // have a chance to overwrite it. |
5214 __ mov(scratch_, eax); | 5212 __ mov(index_, eax); |
5215 } | 5213 } |
5216 __ pop(index_); | |
5217 __ pop(object_); | 5214 __ pop(object_); |
5218 // Reload the instance type. | 5215 // Reload the instance type. |
5219 __ mov(result_, FieldOperand(object_, HeapObject::kMapOffset)); | 5216 __ mov(result_, FieldOperand(object_, HeapObject::kMapOffset)); |
5220 __ movzx_b(result_, FieldOperand(result_, Map::kInstanceTypeOffset)); | 5217 __ movzx_b(result_, FieldOperand(result_, Map::kInstanceTypeOffset)); |
5221 call_helper.AfterCall(masm); | 5218 call_helper.AfterCall(masm); |
5222 // If index is still not a smi, it must be out of range. | 5219 // If index is still not a smi, it must be out of range. |
5223 STATIC_ASSERT(kSmiTag == 0); | 5220 STATIC_ASSERT(kSmiTag == 0); |
5224 __ JumpIfNotSmi(scratch_, index_out_of_range_); | 5221 __ JumpIfNotSmi(index_, index_out_of_range_); |
5225 // Otherwise, return to the fast path. | 5222 // Otherwise, return to the fast path. |
5226 __ jmp(&got_smi_index_); | 5223 __ jmp(&got_smi_index_); |
5227 | 5224 |
5228 // Call runtime. We get here when the receiver is a string and the | 5225 // Call runtime. We get here when the receiver is a string and the |
5229 // index is a number, but the code of getting the actual character | 5226 // index is a number, but the code of getting the actual character |
5230 // is too complex (e.g., when the string needs to be flattened). | 5227 // is too complex (e.g., when the string needs to be flattened). |
5231 __ bind(&call_runtime_); | 5228 __ bind(&call_runtime_); |
5232 call_helper.BeforeCall(masm); | 5229 call_helper.BeforeCall(masm); |
5233 __ push(object_); | 5230 __ push(object_); |
5234 __ push(index_); | 5231 __ push(index_); |
(...skipping 1878 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7113 __ bind(&element_done); | 7110 __ bind(&element_done); |
7114 __ ret(0); | 7111 __ ret(0); |
7115 } | 7112 } |
7116 } | 7113 } |
7117 | 7114 |
7118 #undef __ | 7115 #undef __ |
7119 | 7116 |
7120 } } // namespace v8::internal | 7117 } } // namespace v8::internal |
7121 | 7118 |
7122 #endif // V8_TARGET_ARCH_IA32 | 7119 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |