| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 5064 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5075 // sp[0]: last_match_info (expected JSArray) | 5075 // sp[0]: last_match_info (expected JSArray) |
| 5076 // sp[4]: previous index | 5076 // sp[4]: previous index |
| 5077 // sp[8]: subject string | 5077 // sp[8]: subject string |
| 5078 // sp[12]: JSRegExp object | 5078 // sp[12]: JSRegExp object |
| 5079 | 5079 |
| 5080 const int kLastMatchInfoOffset = 0 * kPointerSize; | 5080 const int kLastMatchInfoOffset = 0 * kPointerSize; |
| 5081 const int kPreviousIndexOffset = 1 * kPointerSize; | 5081 const int kPreviousIndexOffset = 1 * kPointerSize; |
| 5082 const int kSubjectOffset = 2 * kPointerSize; | 5082 const int kSubjectOffset = 2 * kPointerSize; |
| 5083 const int kJSRegExpOffset = 3 * kPointerSize; | 5083 const int kJSRegExpOffset = 3 * kPointerSize; |
| 5084 | 5084 |
| 5085 Label runtime, invoke_regexp; | 5085 Label runtime; |
| 5086 | |
| 5087 // Allocation of registers for this function. These are in callee save | 5086 // Allocation of registers for this function. These are in callee save |
| 5088 // registers and will be preserved by the call to the native RegExp code, as | 5087 // registers and will be preserved by the call to the native RegExp code, as |
| 5089 // this code is called using the normal C calling convention. When calling | 5088 // this code is called using the normal C calling convention. When calling |
| 5090 // directly from generated code the native RegExp code will not do a GC and | 5089 // directly from generated code the native RegExp code will not do a GC and |
| 5091 // therefore the content of these registers are safe to use after the call. | 5090 // therefore the content of these registers are safe to use after the call. |
| 5092 Register subject = r4; | 5091 Register subject = r4; |
| 5093 Register regexp_data = r5; | 5092 Register regexp_data = r5; |
| 5094 Register last_match_info_elements = r6; | 5093 Register last_match_info_elements = r6; |
| 5095 | 5094 |
| 5096 // Ensure that a RegExp stack is allocated. | 5095 // Ensure that a RegExp stack is allocated. |
| (...skipping 26 matching lines...) Expand all Loading... |
| 5123 // regexp_data: RegExp data (FixedArray) | 5122 // regexp_data: RegExp data (FixedArray) |
| 5124 // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP. | 5123 // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP. |
| 5125 __ ldr(r0, FieldMemOperand(regexp_data, JSRegExp::kDataTagOffset)); | 5124 __ ldr(r0, FieldMemOperand(regexp_data, JSRegExp::kDataTagOffset)); |
| 5126 __ cmp(r0, Operand(Smi::FromInt(JSRegExp::IRREGEXP))); | 5125 __ cmp(r0, Operand(Smi::FromInt(JSRegExp::IRREGEXP))); |
| 5127 __ b(ne, &runtime); | 5126 __ b(ne, &runtime); |
| 5128 | 5127 |
| 5129 // regexp_data: RegExp data (FixedArray) | 5128 // regexp_data: RegExp data (FixedArray) |
| 5130 // Check that the number of captures fit in the static offsets vector buffer. | 5129 // Check that the number of captures fit in the static offsets vector buffer. |
| 5131 __ ldr(r2, | 5130 __ ldr(r2, |
| 5132 FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset)); | 5131 FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset)); |
| 5133 // Calculate number of capture registers (number_of_captures + 1) * 2. This | 5132 // Check (number_of_captures + 1) * 2 <= offsets vector size |
| 5134 // uses the asumption that smis are 2 * their untagged value. | 5133 // Or number_of_captures * 2 <= offsets vector size - 2 |
| 5134 // Multiplying by 2 comes for free since r2 is smi-tagged. |
| 5135 STATIC_ASSERT(kSmiTag == 0); | 5135 STATIC_ASSERT(kSmiTag == 0); |
| 5136 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); | 5136 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); |
| 5137 __ add(r2, r2, Operand(2)); // r2 was a smi. | 5137 STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2); |
| 5138 // Check that the static offsets vector buffer is large enough. | 5138 __ cmp(r2, Operand(Isolate::kJSRegexpStaticOffsetsVectorSize - 2)); |
| 5139 __ cmp(r2, Operand(Isolate::kJSRegexpStaticOffsetsVectorSize)); | |
| 5140 __ b(hi, &runtime); | 5139 __ b(hi, &runtime); |
| 5141 | 5140 |
| 5142 // r2: Number of capture registers | |
| 5143 // regexp_data: RegExp data (FixedArray) | |
| 5144 // Check that the second argument is a string. | |
| 5145 __ ldr(subject, MemOperand(sp, kSubjectOffset)); | |
| 5146 __ JumpIfSmi(subject, &runtime); | |
| 5147 Condition is_string = masm->IsObjectStringType(subject, r0); | |
| 5148 __ b(NegateCondition(is_string), &runtime); | |
| 5149 // Get the length of the string to r3. | |
| 5150 __ ldr(r3, FieldMemOperand(subject, String::kLengthOffset)); | |
| 5151 | |
| 5152 // r2: Number of capture registers | |
| 5153 // r3: Length of subject string as a smi | |
| 5154 // subject: Subject string | |
| 5155 // regexp_data: RegExp data (FixedArray) | |
| 5156 // Check that the third argument is a positive smi less than the subject | |
| 5157 // string length. A negative value will be greater (unsigned comparison). | |
| 5158 __ ldr(r0, MemOperand(sp, kPreviousIndexOffset)); | |
| 5159 __ JumpIfNotSmi(r0, &runtime); | |
| 5160 __ cmp(r3, Operand(r0)); | |
| 5161 __ b(ls, &runtime); | |
| 5162 | |
| 5163 // r2: Number of capture registers | |
| 5164 // subject: Subject string | |
| 5165 // regexp_data: RegExp data (FixedArray) | |
| 5166 // Check that the fourth object is a JSArray object. | |
| 5167 __ ldr(r0, MemOperand(sp, kLastMatchInfoOffset)); | |
| 5168 __ JumpIfSmi(r0, &runtime); | |
| 5169 __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE); | |
| 5170 __ b(ne, &runtime); | |
| 5171 // Check that the JSArray is in fast case. | |
| 5172 __ ldr(last_match_info_elements, | |
| 5173 FieldMemOperand(r0, JSArray::kElementsOffset)); | |
| 5174 __ ldr(r0, FieldMemOperand(last_match_info_elements, HeapObject::kMapOffset)); | |
| 5175 __ CompareRoot(r0, Heap::kFixedArrayMapRootIndex); | |
| 5176 __ b(ne, &runtime); | |
| 5177 // Check that the last match info has space for the capture registers and the | |
| 5178 // additional information. | |
| 5179 __ ldr(r0, | |
| 5180 FieldMemOperand(last_match_info_elements, FixedArray::kLengthOffset)); | |
| 5181 __ add(r2, r2, Operand(RegExpImpl::kLastMatchOverhead)); | |
| 5182 __ cmp(r2, Operand(r0, ASR, kSmiTagSize)); | |
| 5183 __ b(gt, &runtime); | |
| 5184 | |
| 5185 // Reset offset for possibly sliced string. | 5141 // Reset offset for possibly sliced string. |
| 5186 __ mov(r9, Operand::Zero()); | 5142 __ mov(r9, Operand::Zero()); |
| 5187 // subject: Subject string | 5143 __ ldr(subject, MemOperand(sp, kSubjectOffset)); |
| 5188 // regexp_data: RegExp data (FixedArray) | 5144 __ JumpIfSmi(subject, &runtime); |
| 5189 // Check the representation and encoding of the subject string. | 5145 __ mov(r3, subject); // Make a copy of the original subject string. |
| 5190 Label seq_string; | |
| 5191 __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset)); | 5146 __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset)); |
| 5192 __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset)); | 5147 __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset)); |
| 5193 // First check for flat string. None of the following string type tests will | 5148 // subject: subject string |
| 5194 // succeed if subject is not a string or a short external string. | 5149 // r3: subject string |
| 5150 // r0: subject string instance type |
| 5151 // regexp_data: RegExp data (FixedArray) |
| 5152 // Handle subject string according to its encoding and representation: |
| 5153 // (1) Sequential string? If yes, go to (5). |
| 5154 // (2) Anything but sequential or cons? If yes, go to (6). |
| 5155 // (3) Cons string. If the string is flat, replace subject with first string. |
| 5156 // Otherwise bailout. |
| 5157 // (4) Is subject external? If yes, go to (7). |
| 5158 // (5) Sequential string. Load regexp code according to encoding. |
| 5159 // (E) Carry on. |
| 5160 /// [...] |
| 5161 |
| 5162 // Deferred code at the end of the stub: |
| 5163 // (6) Not a long external string? If yes, go to (8). |
| 5164 // (7) External string. Make it, offset-wise, look like a sequential string. |
| 5165 // Go to (5). |
| 5166 // (8) Short external string or not a string? If yes, bail out to runtime. |
| 5167 // (9) Sliced string. Replace subject with parent. Go to (4). |
| 5168 |
| 5169 Label seq_string /* 5 */, external_string /* 7 */, |
| 5170 check_underlying /* 4 */, not_seq_nor_cons /* 6 */, |
| 5171 not_long_external /* 8 */; |
| 5172 |
| 5173 // (1) Sequential string? If yes, go to (5). |
| 5195 __ and_(r1, | 5174 __ and_(r1, |
| 5196 r0, | 5175 r0, |
| 5197 Operand(kIsNotStringMask | | 5176 Operand(kIsNotStringMask | |
| 5198 kStringRepresentationMask | | 5177 kStringRepresentationMask | |
| 5199 kShortExternalStringMask), | 5178 kShortExternalStringMask), |
| 5200 SetCC); | 5179 SetCC); |
| 5201 STATIC_ASSERT((kStringTag | kSeqStringTag) == 0); | 5180 STATIC_ASSERT((kStringTag | kSeqStringTag) == 0); |
| 5202 __ b(eq, &seq_string); | 5181 __ b(eq, &seq_string); // Go to (5). |
| 5203 | 5182 |
| 5204 // subject: Subject string | 5183 // (2) Anything but sequential or cons? If yes, go to (6). |
| 5205 // regexp_data: RegExp data (FixedArray) | |
| 5206 // r1: whether subject is a string and if yes, its string representation | |
| 5207 // Check for flat cons string or sliced string. | |
| 5208 // A flat cons string is a cons string where the second part is the empty | |
| 5209 // string. In that case the subject string is just the first part of the cons | |
| 5210 // string. Also in this case the first part of the cons string is known to be | |
| 5211 // a sequential string or an external string. | |
| 5212 // In the case of a sliced string its offset has to be taken into account. | |
| 5213 Label cons_string, external_string, check_encoding; | |
| 5214 STATIC_ASSERT(kConsStringTag < kExternalStringTag); | 5184 STATIC_ASSERT(kConsStringTag < kExternalStringTag); |
| 5215 STATIC_ASSERT(kSlicedStringTag > kExternalStringTag); | 5185 STATIC_ASSERT(kSlicedStringTag > kExternalStringTag); |
| 5216 STATIC_ASSERT(kIsNotStringMask > kExternalStringTag); | 5186 STATIC_ASSERT(kIsNotStringMask > kExternalStringTag); |
| 5217 STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag); | 5187 STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag); |
| 5218 __ cmp(r1, Operand(kExternalStringTag)); | 5188 __ cmp(r1, Operand(kExternalStringTag)); |
| 5219 __ b(lt, &cons_string); | 5189 __ b(ge, ¬_seq_nor_cons); // Go to (6). |
| 5220 __ b(eq, &external_string); | |
| 5221 | 5190 |
| 5222 // Catch non-string subject or short external string. | 5191 // (3) Cons string. Check that it's flat. |
| 5223 STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0); | 5192 // Replace subject with first string and reload instance type. |
| 5224 __ tst(r1, Operand(kIsNotStringMask | kShortExternalStringMask)); | |
| 5225 __ b(ne, &runtime); | |
| 5226 | |
| 5227 // String is sliced. | |
| 5228 __ ldr(r9, FieldMemOperand(subject, SlicedString::kOffsetOffset)); | |
| 5229 __ mov(r9, Operand(r9, ASR, kSmiTagSize)); | |
| 5230 __ ldr(subject, FieldMemOperand(subject, SlicedString::kParentOffset)); | |
| 5231 // r9: offset of sliced string, smi-tagged. | |
| 5232 __ jmp(&check_encoding); | |
| 5233 // String is a cons string, check whether it is flat. | |
| 5234 __ bind(&cons_string); | |
| 5235 __ ldr(r0, FieldMemOperand(subject, ConsString::kSecondOffset)); | 5193 __ ldr(r0, FieldMemOperand(subject, ConsString::kSecondOffset)); |
| 5236 __ CompareRoot(r0, Heap::kEmptyStringRootIndex); | 5194 __ CompareRoot(r0, Heap::kEmptyStringRootIndex); |
| 5237 __ b(ne, &runtime); | 5195 __ b(ne, &runtime); |
| 5238 __ ldr(subject, FieldMemOperand(subject, ConsString::kFirstOffset)); | 5196 __ ldr(subject, FieldMemOperand(subject, ConsString::kFirstOffset)); |
| 5239 // Is first part of cons or parent of slice a flat string? | 5197 |
| 5240 __ bind(&check_encoding); | 5198 // (4) Is subject external? If yes, go to (7). |
| 5199 __ bind(&check_underlying); |
| 5241 __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset)); | 5200 __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset)); |
| 5242 __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset)); | 5201 __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset)); |
| 5243 STATIC_ASSERT(kSeqStringTag == 0); | 5202 STATIC_ASSERT(kSeqStringTag == 0); |
| 5244 __ tst(r0, Operand(kStringRepresentationMask)); | 5203 __ tst(r0, Operand(kStringRepresentationMask)); |
| 5245 __ b(ne, &external_string); | 5204 // The underlying external string is never a short external string. |
| 5205 STATIC_CHECK(ExternalString::kMaxShortLength < ConsString::kMinLength); |
| 5206 STATIC_CHECK(ExternalString::kMaxShortLength < SlicedString::kMinLength); |
| 5207 __ b(ne, &external_string); // Go to (7). |
| 5246 | 5208 |
| 5209 // (5) Sequential string. Load regexp code according to encoding. |
| 5247 __ bind(&seq_string); | 5210 __ bind(&seq_string); |
| 5248 // subject: Subject string | 5211 // subject: sequential subject string (or look-alike, external string) |
| 5249 // regexp_data: RegExp data (FixedArray) | 5212 // r3: original subject string |
| 5250 // r0: Instance type of subject string | 5213 // Load previous index and check range before r3 is overwritten. We have to |
| 5214 // use r3 instead of subject here because subject might have been only made |
| 5215 // to look like a sequential string when it actually is an external string. |
| 5216 __ ldr(r1, MemOperand(sp, kPreviousIndexOffset)); |
| 5217 __ JumpIfNotSmi(r1, &runtime); |
| 5218 __ ldr(r3, FieldMemOperand(r3, String::kLengthOffset)); |
| 5219 __ cmp(r3, Operand(r1)); |
| 5220 __ b(ls, &runtime); |
| 5221 __ mov(r1, Operand(r1, ASR, kSmiTagSize)); |
| 5222 |
| 5251 STATIC_ASSERT(4 == kOneByteStringTag); | 5223 STATIC_ASSERT(4 == kOneByteStringTag); |
| 5252 STATIC_ASSERT(kTwoByteStringTag == 0); | 5224 STATIC_ASSERT(kTwoByteStringTag == 0); |
| 5253 // Find the code object based on the assumptions above. | |
| 5254 __ and_(r0, r0, Operand(kStringEncodingMask)); | 5225 __ and_(r0, r0, Operand(kStringEncodingMask)); |
| 5255 __ mov(r3, Operand(r0, ASR, 2), SetCC); | 5226 __ mov(r3, Operand(r0, ASR, 2), SetCC); |
| 5256 __ ldr(r7, FieldMemOperand(regexp_data, JSRegExp::kDataAsciiCodeOffset), ne); | 5227 __ ldr(r7, FieldMemOperand(regexp_data, JSRegExp::kDataAsciiCodeOffset), ne); |
| 5257 __ ldr(r7, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset), eq); | 5228 __ ldr(r7, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset), eq); |
| 5258 | 5229 |
| 5230 // (E) Carry on. String handling is done. |
| 5231 // r7: irregexp code |
| 5259 // Check that the irregexp code has been generated for the actual string | 5232 // Check that the irregexp code has been generated for the actual string |
| 5260 // encoding. If it has, the field contains a code object otherwise it contains | 5233 // encoding. If it has, the field contains a code object otherwise it contains |
| 5261 // a smi (code flushing support). | 5234 // a smi (code flushing support). |
| 5262 __ JumpIfSmi(r7, &runtime); | 5235 __ JumpIfSmi(r7, &runtime); |
| 5263 | 5236 |
| 5264 // r3: encoding of subject string (1 if ASCII, 0 if two_byte); | |
| 5265 // r7: code | |
| 5266 // subject: Subject string | |
| 5267 // regexp_data: RegExp data (FixedArray) | |
| 5268 // Load used arguments before starting to push arguments for call to native | |
| 5269 // RegExp code to avoid handling changing stack height. | |
| 5270 __ ldr(r1, MemOperand(sp, kPreviousIndexOffset)); | |
| 5271 __ mov(r1, Operand(r1, ASR, kSmiTagSize)); | |
| 5272 | |
| 5273 // r1: previous index | 5237 // r1: previous index |
| 5274 // r3: encoding of subject string (1 if ASCII, 0 if two_byte); | 5238 // r3: encoding of subject string (1 if ASCII, 0 if two_byte); |
| 5275 // r7: code | 5239 // r7: code |
| 5276 // subject: Subject string | 5240 // subject: Subject string |
| 5277 // regexp_data: RegExp data (FixedArray) | 5241 // regexp_data: RegExp data (FixedArray) |
| 5278 // All checks done. Now push arguments for native regexp code. | 5242 // All checks done. Now push arguments for native regexp code. |
| 5279 __ IncrementCounter(isolate->counters()->regexp_entry_native(), 1, r0, r2); | 5243 __ IncrementCounter(isolate->counters()->regexp_entry_native(), 1, r0, r2); |
| 5280 | 5244 |
| 5281 // Isolates: note we add an additional parameter here (isolate pointer). | 5245 // Isolates: note we add an additional parameter here (isolate pointer). |
| 5282 const int kRegExpExecuteArguments = 9; | 5246 const int kRegExpExecuteArguments = 9; |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5342 __ add(r7, r7, Operand(Code::kHeaderSize - kHeapObjectTag)); | 5306 __ add(r7, r7, Operand(Code::kHeaderSize - kHeapObjectTag)); |
| 5343 DirectCEntryStub stub; | 5307 DirectCEntryStub stub; |
| 5344 stub.GenerateCall(masm, r7); | 5308 stub.GenerateCall(masm, r7); |
| 5345 | 5309 |
| 5346 __ LeaveExitFrame(false, no_reg); | 5310 __ LeaveExitFrame(false, no_reg); |
| 5347 | 5311 |
| 5348 // r0: result | 5312 // r0: result |
| 5349 // subject: subject string (callee saved) | 5313 // subject: subject string (callee saved) |
| 5350 // regexp_data: RegExp data (callee saved) | 5314 // regexp_data: RegExp data (callee saved) |
| 5351 // last_match_info_elements: Last match info elements (callee saved) | 5315 // last_match_info_elements: Last match info elements (callee saved) |
| 5352 | |
| 5353 // Check the result. | 5316 // Check the result. |
| 5354 Label success; | 5317 Label success; |
| 5355 | |
| 5356 __ cmp(r0, Operand(1)); | 5318 __ cmp(r0, Operand(1)); |
| 5357 // We expect exactly one result since we force the called regexp to behave | 5319 // We expect exactly one result since we force the called regexp to behave |
| 5358 // as non-global. | 5320 // as non-global. |
| 5359 __ b(eq, &success); | 5321 __ b(eq, &success); |
| 5360 Label failure; | 5322 Label failure; |
| 5361 __ cmp(r0, Operand(NativeRegExpMacroAssembler::FAILURE)); | 5323 __ cmp(r0, Operand(NativeRegExpMacroAssembler::FAILURE)); |
| 5362 __ b(eq, &failure); | 5324 __ b(eq, &failure); |
| 5363 __ cmp(r0, Operand(NativeRegExpMacroAssembler::EXCEPTION)); | 5325 __ cmp(r0, Operand(NativeRegExpMacroAssembler::EXCEPTION)); |
| 5364 // If not exception it can only be retry. Handle that in the runtime system. | 5326 // If not exception it can only be retry. Handle that in the runtime system. |
| 5365 __ b(ne, &runtime); | 5327 __ b(ne, &runtime); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 5391 // For failure and exception return null. | 5353 // For failure and exception return null. |
| 5392 __ mov(r0, Operand(masm->isolate()->factory()->null_value())); | 5354 __ mov(r0, Operand(masm->isolate()->factory()->null_value())); |
| 5393 __ add(sp, sp, Operand(4 * kPointerSize)); | 5355 __ add(sp, sp, Operand(4 * kPointerSize)); |
| 5394 __ Ret(); | 5356 __ Ret(); |
| 5395 | 5357 |
| 5396 // Process the result from the native regexp code. | 5358 // Process the result from the native regexp code. |
| 5397 __ bind(&success); | 5359 __ bind(&success); |
| 5398 __ ldr(r1, | 5360 __ ldr(r1, |
| 5399 FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset)); | 5361 FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset)); |
| 5400 // Calculate number of capture registers (number_of_captures + 1) * 2. | 5362 // Calculate number of capture registers (number_of_captures + 1) * 2. |
| 5363 // Multiplying by 2 comes for free since r1 is smi-tagged. |
| 5401 STATIC_ASSERT(kSmiTag == 0); | 5364 STATIC_ASSERT(kSmiTag == 0); |
| 5402 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); | 5365 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); |
| 5403 __ add(r1, r1, Operand(2)); // r1 was a smi. | 5366 __ add(r1, r1, Operand(2)); // r1 was a smi. |
| 5404 | 5367 |
| 5368 __ ldr(r0, MemOperand(sp, kLastMatchInfoOffset)); |
| 5369 __ JumpIfSmi(r0, &runtime); |
| 5370 __ CompareObjectType(r0, r2, r2, JS_ARRAY_TYPE); |
| 5371 __ b(ne, &runtime); |
| 5372 // Check that the JSArray is in fast case. |
| 5373 __ ldr(last_match_info_elements, |
| 5374 FieldMemOperand(r0, JSArray::kElementsOffset)); |
| 5375 __ ldr(r0, FieldMemOperand(last_match_info_elements, HeapObject::kMapOffset)); |
| 5376 __ CompareRoot(r0, Heap::kFixedArrayMapRootIndex); |
| 5377 __ b(ne, &runtime); |
| 5378 // Check that the last match info has space for the capture registers and the |
| 5379 // additional information. |
| 5380 __ ldr(r0, |
| 5381 FieldMemOperand(last_match_info_elements, FixedArray::kLengthOffset)); |
| 5382 __ add(r2, r1, Operand(RegExpImpl::kLastMatchOverhead)); |
| 5383 __ cmp(r2, Operand(r0, ASR, kSmiTagSize)); |
| 5384 __ b(gt, &runtime); |
| 5385 |
| 5405 // r1: number of capture registers | 5386 // r1: number of capture registers |
| 5406 // r4: subject string | 5387 // r4: subject string |
| 5407 // Store the capture count. | 5388 // Store the capture count. |
| 5408 __ mov(r2, Operand(r1, LSL, kSmiTagSize + kSmiShiftSize)); // To smi. | 5389 __ mov(r2, Operand(r1, LSL, kSmiTagSize + kSmiShiftSize)); // To smi. |
| 5409 __ str(r2, FieldMemOperand(last_match_info_elements, | 5390 __ str(r2, FieldMemOperand(last_match_info_elements, |
| 5410 RegExpImpl::kLastCaptureCountOffset)); | 5391 RegExpImpl::kLastCaptureCountOffset)); |
| 5411 // Store last subject and last input. | 5392 // Store last subject and last input. |
| 5412 __ str(subject, | 5393 __ str(subject, |
| 5413 FieldMemOperand(last_match_info_elements, | 5394 FieldMemOperand(last_match_info_elements, |
| 5414 RegExpImpl::kLastSubjectOffset)); | 5395 RegExpImpl::kLastSubjectOffset)); |
| 5415 __ mov(r2, subject); | 5396 __ mov(r2, subject); |
| 5416 __ RecordWriteField(last_match_info_elements, | 5397 __ RecordWriteField(last_match_info_elements, |
| 5417 RegExpImpl::kLastSubjectOffset, | 5398 RegExpImpl::kLastSubjectOffset, |
| 5418 r2, | 5399 subject, |
| 5419 r7, | 5400 r7, |
| 5420 kLRHasNotBeenSaved, | 5401 kLRHasNotBeenSaved, |
| 5421 kDontSaveFPRegs); | 5402 kDontSaveFPRegs); |
| 5403 __ mov(subject, r2); |
| 5422 __ str(subject, | 5404 __ str(subject, |
| 5423 FieldMemOperand(last_match_info_elements, | 5405 FieldMemOperand(last_match_info_elements, |
| 5424 RegExpImpl::kLastInputOffset)); | 5406 RegExpImpl::kLastInputOffset)); |
| 5425 __ RecordWriteField(last_match_info_elements, | 5407 __ RecordWriteField(last_match_info_elements, |
| 5426 RegExpImpl::kLastInputOffset, | 5408 RegExpImpl::kLastInputOffset, |
| 5427 subject, | 5409 subject, |
| 5428 r7, | 5410 r7, |
| 5429 kLRHasNotBeenSaved, | 5411 kLRHasNotBeenSaved, |
| 5430 kDontSaveFPRegs); | 5412 kDontSaveFPRegs); |
| 5431 | 5413 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 5451 __ mov(r3, Operand(r3, LSL, kSmiTagSize)); | 5433 __ mov(r3, Operand(r3, LSL, kSmiTagSize)); |
| 5452 __ str(r3, MemOperand(r0, kPointerSize, PostIndex)); | 5434 __ str(r3, MemOperand(r0, kPointerSize, PostIndex)); |
| 5453 __ jmp(&next_capture); | 5435 __ jmp(&next_capture); |
| 5454 __ bind(&done); | 5436 __ bind(&done); |
| 5455 | 5437 |
| 5456 // Return last match info. | 5438 // Return last match info. |
| 5457 __ ldr(r0, MemOperand(sp, kLastMatchInfoOffset)); | 5439 __ ldr(r0, MemOperand(sp, kLastMatchInfoOffset)); |
| 5458 __ add(sp, sp, Operand(4 * kPointerSize)); | 5440 __ add(sp, sp, Operand(4 * kPointerSize)); |
| 5459 __ Ret(); | 5441 __ Ret(); |
| 5460 | 5442 |
| 5461 // External string. Short external strings have already been ruled out. | 5443 // Do the runtime call to execute the regexp. |
| 5462 // r0: scratch | 5444 __ bind(&runtime); |
| 5445 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); |
| 5446 |
| 5447 // Deferred code for string handling. |
| 5448 // (6) Not a long external string? If yes, go to (8). |
| 5449 __ bind(¬_seq_nor_cons); |
| 5450 // Compare flags are still set. |
| 5451 __ b(gt, ¬_long_external); // Go to (8). |
| 5452 |
| 5453 // (7) External string. Make it, offset-wise, look like a sequential string. |
| 5463 __ bind(&external_string); | 5454 __ bind(&external_string); |
| 5464 __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset)); | 5455 __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset)); |
| 5465 __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset)); | 5456 __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset)); |
| 5466 if (FLAG_debug_code) { | 5457 if (FLAG_debug_code) { |
| 5467 // Assert that we do not have a cons or slice (indirect strings) here. | 5458 // Assert that we do not have a cons or slice (indirect strings) here. |
| 5468 // Sequential strings have already been ruled out. | 5459 // Sequential strings have already been ruled out. |
| 5469 __ tst(r0, Operand(kIsIndirectStringMask)); | 5460 __ tst(r0, Operand(kIsIndirectStringMask)); |
| 5470 __ Assert(eq, "external string expected, but not found"); | 5461 __ Assert(eq, "external string expected, but not found"); |
| 5471 } | 5462 } |
| 5472 __ ldr(subject, | 5463 __ ldr(subject, |
| 5473 FieldMemOperand(subject, ExternalString::kResourceDataOffset)); | 5464 FieldMemOperand(subject, ExternalString::kResourceDataOffset)); |
| 5474 // Move the pointer so that offset-wise, it looks like a sequential string. | 5465 // Move the pointer so that offset-wise, it looks like a sequential string. |
| 5475 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); | 5466 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); |
| 5476 __ sub(subject, | 5467 __ sub(subject, |
| 5477 subject, | 5468 subject, |
| 5478 Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); | 5469 Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); |
| 5479 __ jmp(&seq_string); | 5470 __ jmp(&seq_string); // Go to (5). |
| 5480 | 5471 |
| 5481 // Do the runtime call to execute the regexp. | 5472 // (8) Short external string or not a string? If yes, bail out to runtime. |
| 5482 __ bind(&runtime); | 5473 __ bind(¬_long_external); |
| 5483 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); | 5474 STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0); |
| 5475 __ tst(r1, Operand(kIsNotStringMask | kShortExternalStringMask)); |
| 5476 __ b(ne, &runtime); |
| 5477 |
| 5478 // (9) Sliced string. Replace subject with parent. Go to (4). |
| 5479 // Load offset into r9 and replace subject string with parent. |
| 5480 __ ldr(r9, FieldMemOperand(subject, SlicedString::kOffsetOffset)); |
| 5481 __ mov(r9, Operand(r9, ASR, kSmiTagSize)); |
| 5482 __ ldr(subject, FieldMemOperand(subject, SlicedString::kParentOffset)); |
| 5483 __ jmp(&check_underlying); // Go to (4). |
| 5484 #endif // V8_INTERPRETED_REGEXP | 5484 #endif // V8_INTERPRETED_REGEXP |
| 5485 } | 5485 } |
| 5486 | 5486 |
| 5487 | 5487 |
| 5488 void RegExpConstructResultStub::Generate(MacroAssembler* masm) { | 5488 void RegExpConstructResultStub::Generate(MacroAssembler* masm) { |
| 5489 const int kMaxInlineLength = 100; | 5489 const int kMaxInlineLength = 100; |
| 5490 Label slowcase; | 5490 Label slowcase; |
| 5491 Label done; | 5491 Label done; |
| 5492 Factory* factory = masm->isolate()->factory(); | 5492 Factory* factory = masm->isolate()->factory(); |
| 5493 | 5493 |
| (...skipping 2031 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7525 struct AheadOfTimeWriteBarrierStubList { | 7525 struct AheadOfTimeWriteBarrierStubList { |
| 7526 Register object, value, address; | 7526 Register object, value, address; |
| 7527 RememberedSetAction action; | 7527 RememberedSetAction action; |
| 7528 }; | 7528 }; |
| 7529 | 7529 |
| 7530 #define REG(Name) { kRegister_ ## Name ## _Code } | 7530 #define REG(Name) { kRegister_ ## Name ## _Code } |
| 7531 | 7531 |
| 7532 static const AheadOfTimeWriteBarrierStubList kAheadOfTime[] = { | 7532 static const AheadOfTimeWriteBarrierStubList kAheadOfTime[] = { |
| 7533 // Used in RegExpExecStub. | 7533 // Used in RegExpExecStub. |
| 7534 { REG(r6), REG(r4), REG(r7), EMIT_REMEMBERED_SET }, | 7534 { REG(r6), REG(r4), REG(r7), EMIT_REMEMBERED_SET }, |
| 7535 { REG(r6), REG(r2), REG(r7), EMIT_REMEMBERED_SET }, | |
| 7536 // Used in CompileArrayPushCall. | 7535 // Used in CompileArrayPushCall. |
| 7537 // Also used in StoreIC::GenerateNormal via GenerateDictionaryStore. | 7536 // Also used in StoreIC::GenerateNormal via GenerateDictionaryStore. |
| 7538 // Also used in KeyedStoreIC::GenerateGeneric. | 7537 // Also used in KeyedStoreIC::GenerateGeneric. |
| 7539 { REG(r3), REG(r4), REG(r5), EMIT_REMEMBERED_SET }, | 7538 { REG(r3), REG(r4), REG(r5), EMIT_REMEMBERED_SET }, |
| 7540 // Used in CompileStoreGlobal. | 7539 // Used in CompileStoreGlobal. |
| 7541 { REG(r4), REG(r1), REG(r2), OMIT_REMEMBERED_SET }, | 7540 { REG(r4), REG(r1), REG(r2), OMIT_REMEMBERED_SET }, |
| 7542 // Used in StoreStubCompiler::CompileStoreField via GenerateStoreField. | 7541 // Used in StoreStubCompiler::CompileStoreField via GenerateStoreField. |
| 7543 { REG(r1), REG(r2), REG(r3), EMIT_REMEMBERED_SET }, | 7542 { REG(r1), REG(r2), REG(r3), EMIT_REMEMBERED_SET }, |
| 7544 { REG(r3), REG(r2), REG(r1), EMIT_REMEMBERED_SET }, | 7543 { REG(r3), REG(r2), REG(r1), EMIT_REMEMBERED_SET }, |
| 7545 // Used in KeyedStoreStubCompiler::CompileStoreField via GenerateStoreField. | 7544 // Used in KeyedStoreStubCompiler::CompileStoreField via GenerateStoreField. |
| (...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7946 | 7945 |
| 7947 __ Pop(lr, r5, r1); | 7946 __ Pop(lr, r5, r1); |
| 7948 __ Ret(); | 7947 __ Ret(); |
| 7949 } | 7948 } |
| 7950 | 7949 |
| 7951 #undef __ | 7950 #undef __ |
| 7952 | 7951 |
| 7953 } } // namespace v8::internal | 7952 } } // namespace v8::internal |
| 7954 | 7953 |
| 7955 #endif // V8_TARGET_ARCH_ARM | 7954 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |