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

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

Issue 8513010: Add pointer cache field to external string for access in generated code. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
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 | Annotate | Revision Log
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 5071 matching lines...) Expand 10 before | Expand all | Expand 10 after
5082 if (never_nan_nan_ && is_equality) stream->Add("_NO_NAN"); 5082 if (never_nan_nan_ && is_equality) stream->Add("_NO_NAN");
5083 if (!include_number_compare_) stream->Add("_NO_NUMBER"); 5083 if (!include_number_compare_) stream->Add("_NO_NUMBER");
5084 if (!include_smi_compare_) stream->Add("_NO_SMI"); 5084 if (!include_smi_compare_) stream->Add("_NO_SMI");
5085 } 5085 }
5086 5086
5087 5087
5088 // ------------------------------------------------------------------------- 5088 // -------------------------------------------------------------------------
5089 // StringCharCodeAtGenerator 5089 // StringCharCodeAtGenerator
5090 5090
5091 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { 5091 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
5092 Label flat_string;
5093 Label ascii_string;
5094 Label got_char_code;
5095 Label sliced_string;
5096
5097 // If the receiver is a smi trigger the non-string case. 5092 // If the receiver is a smi trigger the non-string case.
5098 STATIC_ASSERT(kSmiTag == 0); 5093 STATIC_ASSERT(kSmiTag == 0);
5099 __ JumpIfSmi(object_, receiver_not_string_); 5094 __ JumpIfSmi(object_, receiver_not_string_);
5100 5095
5101 // Fetch the instance type of the receiver into result register. 5096 // Fetch the instance type of the receiver into result register.
5102 __ mov(result_, FieldOperand(object_, HeapObject::kMapOffset)); 5097 __ mov(result_, FieldOperand(object_, HeapObject::kMapOffset));
5103 __ movzx_b(result_, FieldOperand(result_, Map::kInstanceTypeOffset)); 5098 __ movzx_b(result_, FieldOperand(result_, Map::kInstanceTypeOffset));
5104 // If the receiver is not a string trigger the non-string case. 5099 // If the receiver is not a string trigger the non-string case.
5105 __ test(result_, Immediate(kIsNotStringMask)); 5100 __ test(result_, Immediate(kIsNotStringMask));
5106 __ j(not_zero, receiver_not_string_); 5101 __ j(not_zero, receiver_not_string_);
5107 5102
5108 // If the index is non-smi trigger the non-smi case. 5103 // If the index is non-smi trigger the non-smi case.
5109 STATIC_ASSERT(kSmiTag == 0); 5104 STATIC_ASSERT(kSmiTag == 0);
5110 __ JumpIfNotSmi(index_, &index_not_smi_); 5105 __ JumpIfNotSmi(index_, &index_not_smi_);
5111 __ bind(&got_smi_index_); 5106 __ bind(&got_smi_index_);
5112 5107
5113 // Check for index out of range. 5108 // Check for index out of range.
5114 __ cmp(index_, FieldOperand(object_, String::kLengthOffset)); 5109 __ cmp(index_, FieldOperand(object_, String::kLengthOffset));
5115 __ j(above_equal, index_out_of_range_); 5110 __ j(above_equal, index_out_of_range_);
5116 5111
5117 // We need special handling for non-flat strings. 5112 __ SmiUntag(index_);
5118 STATIC_ASSERT(kSeqStringTag == 0);
5119 __ test(result_, Immediate(kStringRepresentationMask));
5120 __ j(zero, &flat_string);
5121 5113
5122 // Handle non-flat strings. 5114 Factory* factory = masm->isolate()->factory();
5123 __ and_(result_, kStringRepresentationMask); 5115 GenerateCharLoad(masm, factory, object_, index_, result_, &call_runtime_);
5124 STATIC_ASSERT(kConsStringTag < kExternalStringTag);
5125 STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
5126 __ cmp(result_, kExternalStringTag);
5127 __ j(greater, &sliced_string, Label::kNear);
5128 __ j(equal, &call_runtime_);
5129 5116
5130 // ConsString.
5131 // Check whether the right hand side is the empty string (i.e. if
5132 // this is really a flat string in a cons string). If that is not
5133 // the case we would rather go to the runtime system now to flatten
5134 // the string.
5135 Label assure_seq_string;
5136 __ cmp(FieldOperand(object_, ConsString::kSecondOffset),
5137 Immediate(masm->isolate()->factory()->empty_string()));
5138 __ j(not_equal, &call_runtime_);
5139 // Get the first of the two parts.
5140 __ mov(object_, FieldOperand(object_, ConsString::kFirstOffset));
5141 __ jmp(&assure_seq_string, Label::kNear);
5142
5143 // SlicedString, unpack and add offset.
5144 __ bind(&sliced_string);
5145 __ add(index_, FieldOperand(object_, SlicedString::kOffsetOffset));
5146 __ mov(object_, FieldOperand(object_, SlicedString::kParentOffset));
5147
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 adjusted index to the runtime function.
5152 __ bind(&assure_seq_string);
5153 __ mov(result_, FieldOperand(object_, HeapObject::kMapOffset));
5154 __ movzx_b(result_, FieldOperand(result_, Map::kInstanceTypeOffset));
5155 STATIC_ASSERT(kSeqStringTag == 0);
5156 __ test(result_, Immediate(kStringRepresentationMask));
5157 __ j(not_zero, &call_runtime_);
5158
5159 // Check for 1-byte or 2-byte string.
5160 __ bind(&flat_string);
5161 STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0);
5162 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
5163 __ test(result_, Immediate(kStringEncodingMask));
5164 __ j(not_zero, &ascii_string, Label::kNear);
5165
5166 // 2-byte string.
5167 // Load the 2-byte character code into the result register.
5168 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
5169 __ movzx_w(result_, FieldOperand(object_,
5170 index_, times_1, // Scratch is smi-tagged.
5171 SeqTwoByteString::kHeaderSize));
5172 __ jmp(&got_char_code, Label::kNear);
5173
5174 // ASCII string.
5175 // Load the byte into the result register.
5176 __ bind(&ascii_string);
5177 __ SmiUntag(index_);
5178 __ movzx_b(result_, FieldOperand(object_,
5179 index_, times_1,
5180 SeqAsciiString::kHeaderSize));
5181 __ bind(&got_char_code);
5182 __ SmiTag(result_); 5117 __ SmiTag(result_);
5183 __ bind(&exit_); 5118 __ bind(&exit_);
5184 } 5119 }
5185 5120
5186 5121
5122 void StringCharCodeAtGenerator::GenerateCharLoad(MacroAssembler* masm,
5123 Factory* factory,
5124 Register string,
5125 Register index,
5126 Register result,
5127 Label* call_runtime) {
5128 // Fetch the instance type of the receiver into result register.
5129 __ mov(result, FieldOperand(string, HeapObject::kMapOffset));
5130 __ movzx_b(result, FieldOperand(result, Map::kInstanceTypeOffset));
5131
5132 // We need special handling for indirect strings.
5133 Label check_sequential;
5134 __ test(result, Immediate(kIsIndirectStringMask));
5135 __ j(zero, &check_sequential);
5136
5137 // Dispatch on the indirect string shape: slice or cons.
5138 Label cons_string;
5139 __ test(result, Immediate(kSlicedNotConsMask));
5140 __ j(zero, &cons_string);
5141
5142 // Handle slices.
5143 Label indirect_string_loaded;
5144 __ mov(result, FieldOperand(string, SlicedString::kOffsetOffset));
5145 __ SmiUntag(result);
5146 __ add(index, result);
5147 __ mov(string, FieldOperand(string, SlicedString::kParentOffset));
5148 __ jmp(&indirect_string_loaded);
5149
5150 // Handle external strings.
5151 Label external_string, ascii_external, done;
5152 __ bind(&external_string);
5153 if (FLAG_debug_code) {
5154 // Assert that we do not have a cons or slice (indirect strings) here.
5155 __ test(result, Immediate(kIsIndirectStringMask));
5156 __ Assert(zero, "external string expected, but not found");
Lasse Reichstein 2011/11/17 13:40:18 This test checks for "indirect string" but reports
5157 }
5158 __ mov(result, FieldOperand(string, ExternalString::kResourceDataOffset));
5159 __ test(result, result);
5160 __ j(zero, call_runtime);
5161 __ cmp(FieldOperand(string, HeapObject::kMapOffset),
5162 Immediate(factory->external_ascii_string_map()));
5163 __ j(equal, &ascii_external, Label::kNear);
5164 __ cmp(FieldOperand(string, HeapObject::kMapOffset),
Lasse Reichstein 2011/11/17 13:40:18 Comparing against the same memory location twice i
Yang 2011/11/17 17:06:23 |string| is used as a temp register, so I can use
5165 Immediate(factory->external_ascii_symbol_map()));
5166 __ j(equal, &ascii_external, Label::kNear);
5167 // Two-byte string.
5168 __ movzx_w(result, Operand(result, index, times_2, 0));
5169 __ jmp(&done);
5170 __ bind(&ascii_external);
5171 // Ascii string.
5172 __ movzx_b(result, Operand(result, index, times_1, 0));
5173 __ jmp(&done);
5174
5175 // Handle conses.
5176 // Check whether the right hand side is the empty string (i.e. if
5177 // this is really a flat string in a cons string). If that is not
5178 // the case we would rather go to the runtime system now to flatten
5179 // the string.
5180 __ bind(&cons_string);
5181 __ cmp(FieldOperand(string, ConsString::kSecondOffset),
5182 Immediate(factory->empty_string()));
5183 __ j(not_equal, call_runtime);
5184 __ mov(string, FieldOperand(string, ConsString::kFirstOffset));
5185
5186 __ bind(&indirect_string_loaded);
5187 __ mov(result, FieldOperand(string, HeapObject::kMapOffset));
5188 __ movzx_b(result, FieldOperand(result, Map::kInstanceTypeOffset));
5189
5190 // Check whether the string is sequential. The only non-sequential
5191 // shapes we support have just been unwrapped above.
5192 // Note that if the original string is a cons or slice with an external
5193 // string as underlying string, we pass that unpacked underlying string with
5194 // the adjusted index to the runtime function.
5195 __ bind(&check_sequential);
5196 STATIC_ASSERT(kSeqStringTag == 0);
5197 __ test(result, Immediate(kStringRepresentationMask));
5198 __ j(not_zero, &external_string);
5199
5200 // Dispatch on the encoding: ASCII or two-byte.
5201 Label ascii_string;
5202 STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0);
5203 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
5204 __ test(result, Immediate(kStringEncodingMask));
5205 __ j(not_zero, &ascii_string, Label::kNear);
5206
5207 // Two-byte string.
5208 // Load the two-byte character code into the result register.
5209 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
5210 __ movzx_w(result, FieldOperand(string,
5211 index,
5212 times_2,
5213 SeqTwoByteString::kHeaderSize));
5214 __ jmp(&done, Label::kNear);
5215
5216 // Ascii string.
5217 // Load the byte into the result register.
5218 __ bind(&ascii_string);
5219 __ movzx_b(result, FieldOperand(string,
5220 index,
5221 times_1,
5222 SeqAsciiString::kHeaderSize));
5223 __ bind(&done);
5224 }
5225
5226
5187 void StringCharCodeAtGenerator::GenerateSlow( 5227 void StringCharCodeAtGenerator::GenerateSlow(
5188 MacroAssembler* masm, 5228 MacroAssembler* masm,
5189 const RuntimeCallHelper& call_helper) { 5229 const RuntimeCallHelper& call_helper) {
5190 __ Abort("Unexpected fallthrough to CharCodeAt slow case"); 5230 __ Abort("Unexpected fallthrough to CharCodeAt slow case");
5191 5231
5192 // Index is not a smi. 5232 // Index is not a smi.
5193 __ bind(&index_not_smi_); 5233 __ bind(&index_not_smi_);
5194 // If index is a heap number, try converting it to an integer. 5234 // If index is a heap number, try converting it to an integer.
5195 __ CheckMap(index_, 5235 __ CheckMap(index_,
5196 masm->isolate()->factory()->heap_number_map(), 5236 masm->isolate()->factory()->heap_number_map(),
(...skipping 24 matching lines...) Expand all
5221 __ JumpIfNotSmi(index_, index_out_of_range_); 5261 __ JumpIfNotSmi(index_, index_out_of_range_);
5222 // Otherwise, return to the fast path. 5262 // Otherwise, return to the fast path.
5223 __ jmp(&got_smi_index_); 5263 __ jmp(&got_smi_index_);
5224 5264
5225 // Call runtime. We get here when the receiver is a string and the 5265 // Call runtime. We get here when the receiver is a string and the
5226 // index is a number, but the code of getting the actual character 5266 // index is a number, but the code of getting the actual character
5227 // is too complex (e.g., when the string needs to be flattened). 5267 // is too complex (e.g., when the string needs to be flattened).
5228 __ bind(&call_runtime_); 5268 __ bind(&call_runtime_);
5229 call_helper.BeforeCall(masm); 5269 call_helper.BeforeCall(masm);
5230 __ push(object_); 5270 __ push(object_);
5271 __ SmiTag(index_);
5231 __ push(index_); 5272 __ push(index_);
5232 __ CallRuntime(Runtime::kStringCharCodeAt, 2); 5273 __ CallRuntime(Runtime::kStringCharCodeAt, 2);
5233 if (!result_.is(eax)) { 5274 if (!result_.is(eax)) {
5234 __ mov(result_, eax); 5275 __ mov(result_, eax);
5235 } 5276 }
5236 call_helper.AfterCall(masm); 5277 call_helper.AfterCall(masm);
5237 __ jmp(&exit_); 5278 __ jmp(&exit_);
5238 5279
5239 __ Abort("Unexpected fallthrough from CharCodeAt slow case"); 5280 __ Abort("Unexpected fallthrough from CharCodeAt slow case");
5240 } 5281 }
(...skipping 1866 matching lines...) Expand 10 before | Expand all | Expand 10 after
7107 false); 7148 false);
7108 __ pop(edx); 7149 __ pop(edx);
7109 __ ret(0); 7150 __ ret(0);
7110 } 7151 }
7111 7152
7112 #undef __ 7153 #undef __
7113 7154
7114 } } // namespace v8::internal 7155 } } // namespace v8::internal
7115 7156
7116 #endif // V8_TARGET_ARCH_IA32 7157 #endif // V8_TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698