OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #if V8_TARGET_ARCH_S390 | 5 #if V8_TARGET_ARCH_S390 |
6 | 6 |
7 #include "src/code-stubs.h" | 7 #include "src/code-stubs.h" |
8 #include "src/api-arguments.h" | 8 #include "src/api-arguments.h" |
9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
(...skipping 1196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1207 // http://refspecs.linuxbase.org/ELF/zSeries/lzsabi0_s390.html#AEN417 | 1207 // http://refspecs.linuxbase.org/ELF/zSeries/lzsabi0_s390.html#AEN417 |
1208 __ ld(d4, MemOperand(sp)); | 1208 __ ld(d4, MemOperand(sp)); |
1209 __ ld(d6, MemOperand(sp, kDoubleSize)); | 1209 __ ld(d6, MemOperand(sp, kDoubleSize)); |
1210 __ la(sp, MemOperand(sp, 2 * kDoubleSize)); | 1210 __ la(sp, MemOperand(sp, 2 * kDoubleSize)); |
1211 #endif | 1211 #endif |
1212 | 1212 |
1213 __ b(r14); | 1213 __ b(r14); |
1214 } | 1214 } |
1215 | 1215 |
1216 void RegExpExecStub::Generate(MacroAssembler* masm) { | 1216 void RegExpExecStub::Generate(MacroAssembler* masm) { |
1217 // Just jump directly to runtime if native RegExp is not selected at compile | |
1218 // time or if regexp entry in generated code is turned off runtime switch or | |
1219 // at compilation. | |
1220 #ifdef V8_INTERPRETED_REGEXP | 1217 #ifdef V8_INTERPRETED_REGEXP |
1221 __ TailCallRuntime(Runtime::kRegExpExec); | 1218 // This case is handled prior to the RegExpExecStub call. |
| 1219 __ Abort(kUnexpectedRegExpExecCall); |
1222 #else // V8_INTERPRETED_REGEXP | 1220 #else // V8_INTERPRETED_REGEXP |
1223 | |
1224 // Stack frame on entry. | |
1225 // sp[0]: last_match_info (expected JSArray) | |
1226 // sp[4]: previous index | |
1227 // sp[8]: subject string | |
1228 // sp[12]: JSRegExp object | |
1229 | |
1230 const int kLastMatchInfoOffset = 0 * kPointerSize; | |
1231 const int kPreviousIndexOffset = 1 * kPointerSize; | |
1232 const int kSubjectOffset = 2 * kPointerSize; | |
1233 const int kJSRegExpOffset = 3 * kPointerSize; | |
1234 | |
1235 Label runtime, br_over, encoding_type_UC16; | |
1236 | |
1237 // Allocation of registers for this function. These are in callee save | |
1238 // registers and will be preserved by the call to the native RegExp code, as | |
1239 // this code is called using the normal C calling convention. When calling | |
1240 // directly from generated code the native RegExp code will not do a GC and | |
1241 // therefore the content of these registers are safe to use after the call. | |
1242 Register subject = r6; | |
1243 Register regexp_data = r7; | |
1244 Register last_match_info_elements = r8; | |
1245 Register code = r9; | |
1246 | |
1247 __ CleanseP(r14); | 1221 __ CleanseP(r14); |
1248 | 1222 |
1249 // Ensure register assigments are consistent with callee save masks | |
1250 DCHECK(subject.bit() & kCalleeSaved); | |
1251 DCHECK(regexp_data.bit() & kCalleeSaved); | |
1252 DCHECK(last_match_info_elements.bit() & kCalleeSaved); | |
1253 DCHECK(code.bit() & kCalleeSaved); | |
1254 | |
1255 // Ensure that a RegExp stack is allocated. | |
1256 ExternalReference address_of_regexp_stack_memory_address = | |
1257 ExternalReference::address_of_regexp_stack_memory_address(isolate()); | |
1258 ExternalReference address_of_regexp_stack_memory_size = | |
1259 ExternalReference::address_of_regexp_stack_memory_size(isolate()); | |
1260 __ mov(r2, Operand(address_of_regexp_stack_memory_size)); | |
1261 __ LoadAndTestP(r2, MemOperand(r2)); | |
1262 __ beq(&runtime); | |
1263 | |
1264 // Check that the first argument is a JSRegExp object. | |
1265 __ LoadP(r2, MemOperand(sp, kJSRegExpOffset)); | |
1266 __ JumpIfSmi(r2, &runtime); | |
1267 __ CompareObjectType(r2, r3, r3, JS_REGEXP_TYPE); | |
1268 __ bne(&runtime); | |
1269 | |
1270 // Check that the RegExp has been compiled (data contains a fixed array). | |
1271 __ LoadP(regexp_data, FieldMemOperand(r2, JSRegExp::kDataOffset)); | |
1272 if (FLAG_debug_code) { | |
1273 __ TestIfSmi(regexp_data); | |
1274 __ Check(ne, kUnexpectedTypeForRegExpDataFixedArrayExpected, cr0); | |
1275 __ CompareObjectType(regexp_data, r2, r2, FIXED_ARRAY_TYPE); | |
1276 __ Check(eq, kUnexpectedTypeForRegExpDataFixedArrayExpected); | |
1277 } | |
1278 | |
1279 // regexp_data: RegExp data (FixedArray) | |
1280 // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP. | |
1281 __ LoadP(r2, FieldMemOperand(regexp_data, JSRegExp::kDataTagOffset)); | |
1282 // DCHECK(Smi::FromInt(JSRegExp::IRREGEXP) < (char *)0xffffu); | |
1283 __ CmpSmiLiteral(r2, Smi::FromInt(JSRegExp::IRREGEXP), r0); | |
1284 __ bne(&runtime); | |
1285 | |
1286 // regexp_data: RegExp data (FixedArray) | |
1287 // Check that the number of captures fit in the static offsets vector buffer. | |
1288 __ LoadP(r4, | |
1289 FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset)); | |
1290 // Check (number_of_captures + 1) * 2 <= offsets vector size | |
1291 // Or number_of_captures * 2 <= offsets vector size - 2 | |
1292 // SmiToShortArrayOffset accomplishes the multiplication by 2 and | |
1293 // SmiUntag (which is a nop for 32-bit). | |
1294 __ SmiToShortArrayOffset(r4, r4); | |
1295 STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2); | |
1296 __ CmpLogicalP(r4, Operand(Isolate::kJSRegexpStaticOffsetsVectorSize - 2)); | |
1297 __ bgt(&runtime); | |
1298 | |
1299 // Reset offset for possibly sliced string. | |
1300 __ LoadImmP(ip, Operand::Zero()); | |
1301 __ LoadP(subject, MemOperand(sp, kSubjectOffset)); | |
1302 __ JumpIfSmi(subject, &runtime); | |
1303 __ LoadRR(r5, subject); // Make a copy of the original subject string. | |
1304 // subject: subject string | |
1305 // r5: subject string | |
1306 // regexp_data: RegExp data (FixedArray) | |
1307 // Handle subject string according to its encoding and representation: | |
1308 // (1) Sequential string? If yes, go to (4). | |
1309 // (2) Sequential or cons? If not, go to (5). | |
1310 // (3) Cons string. If the string is flat, replace subject with first string | |
1311 // and go to (1). Otherwise bail out to runtime. | |
1312 // (4) Sequential string. Load regexp code according to encoding. | |
1313 // (E) Carry on. | |
1314 /// [...] | |
1315 | |
1316 // Deferred code at the end of the stub: | |
1317 // (5) Long external string? If not, go to (7). | |
1318 // (6) External string. Make it, offset-wise, look like a sequential string. | |
1319 // Go to (4). | |
1320 // (7) Short external string or not a string? If yes, bail out to runtime. | |
1321 // (8) Sliced or thin string. Replace subject with parent. Go to (1). | |
1322 | |
1323 Label seq_string /* 4 */, external_string /* 6 */, check_underlying /* 1 */, | |
1324 not_seq_nor_cons /* 5 */, not_long_external /* 7 */; | |
1325 | |
1326 __ bind(&check_underlying); | |
1327 __ LoadP(r2, FieldMemOperand(subject, HeapObject::kMapOffset)); | |
1328 __ LoadlB(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset)); | |
1329 | |
1330 // (1) Sequential string? If yes, go to (4). | |
1331 | |
1332 STATIC_ASSERT((kIsNotStringMask | kStringRepresentationMask | | |
1333 kShortExternalStringMask) == 0xa7); | |
1334 __ mov(r3, Operand(kIsNotStringMask | kStringRepresentationMask | | |
1335 kShortExternalStringMask)); | |
1336 __ AndP(r3, r2); | |
1337 STATIC_ASSERT((kStringTag | kSeqStringTag) == 0); | |
1338 __ beq(&seq_string, Label::kNear); // Go to (4). | |
1339 | |
1340 // (2) Sequential or cons? If not, go to (5). | |
1341 STATIC_ASSERT(kConsStringTag < kExternalStringTag); | |
1342 STATIC_ASSERT(kSlicedStringTag > kExternalStringTag); | |
1343 STATIC_ASSERT(kThinStringTag > kExternalStringTag); | |
1344 STATIC_ASSERT(kIsNotStringMask > kExternalStringTag); | |
1345 STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag); | |
1346 STATIC_ASSERT(kExternalStringTag < 0xffffu); | |
1347 __ CmpP(r3, Operand(kExternalStringTag)); | |
1348 __ bge(¬_seq_nor_cons); // Go to (5). | |
1349 | |
1350 // (3) Cons string. Check that it's flat. | |
1351 // Replace subject with first string and reload instance type. | |
1352 __ LoadP(r2, FieldMemOperand(subject, ConsString::kSecondOffset)); | |
1353 __ CompareRoot(r2, Heap::kempty_stringRootIndex); | |
1354 __ bne(&runtime); | |
1355 __ LoadP(subject, FieldMemOperand(subject, ConsString::kFirstOffset)); | |
1356 __ b(&check_underlying); | |
1357 | |
1358 // (4) Sequential string. Load regexp code according to encoding. | |
1359 __ bind(&seq_string); | |
1360 // subject: sequential subject string (or look-alike, external string) | |
1361 // r5: original subject string | |
1362 // Load previous index and check range before r5 is overwritten. We have to | |
1363 // use r5 instead of subject here because subject might have been only made | |
1364 // to look like a sequential string when it actually is an external string. | |
1365 __ LoadP(r3, MemOperand(sp, kPreviousIndexOffset)); | |
1366 __ JumpIfNotSmi(r3, &runtime); | |
1367 __ LoadP(r5, FieldMemOperand(r5, String::kLengthOffset)); | |
1368 __ CmpLogicalP(r5, r3); | |
1369 __ ble(&runtime); | |
1370 __ SmiUntag(r3); | |
1371 | |
1372 STATIC_ASSERT(8 == kOneByteStringTag); | |
1373 STATIC_ASSERT(kTwoByteStringTag == 0); | |
1374 STATIC_ASSERT(kStringEncodingMask == 8); | |
1375 __ ExtractBitMask(r5, r2, kStringEncodingMask, SetRC); | |
1376 __ beq(&encoding_type_UC16, Label::kNear); | |
1377 __ LoadP(code, | |
1378 FieldMemOperand(regexp_data, JSRegExp::kDataOneByteCodeOffset)); | |
1379 __ b(&br_over, Label::kNear); | |
1380 __ bind(&encoding_type_UC16); | |
1381 __ LoadP(code, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset)); | |
1382 __ bind(&br_over); | |
1383 | |
1384 // (E) Carry on. String handling is done. | |
1385 // code: irregexp code | |
1386 // Check that the irregexp code has been generated for the actual string | |
1387 // encoding. If it has, the field contains a code object otherwise it contains | |
1388 // a smi (code flushing support). | |
1389 __ JumpIfSmi(code, &runtime); | |
1390 | |
1391 // r3: previous index | |
1392 // r5: encoding of subject string (1 if one_byte, 0 if two_byte); | |
1393 // code: Address of generated regexp code | |
1394 // subject: Subject string | |
1395 // regexp_data: RegExp data (FixedArray) | |
1396 // All checks done. Now push arguments for native regexp code. | |
1397 __ IncrementCounter(isolate()->counters()->regexp_entry_native(), 1, r2, r4); | |
1398 | |
1399 // Isolates: note we add an additional parameter here (isolate pointer). | 1223 // Isolates: note we add an additional parameter here (isolate pointer). |
1400 const int kRegExpExecuteArguments = 10; | 1224 const int kRegExpExecuteArguments = 10; |
1401 const int kParameterRegisters = 5; | 1225 const int kParameterRegisters = 5; |
1402 __ EnterExitFrame(false, kRegExpExecuteArguments - kParameterRegisters); | 1226 __ EnterExitFrame(false, kRegExpExecuteArguments - kParameterRegisters); |
1403 | 1227 |
1404 // Stack pointer now points to cell where return address is to be written. | 1228 // Stack pointer now points to cell where return address is to be written. |
1405 // Arguments are before that on the stack or in registers. | 1229 // Arguments are before that on the stack or in registers. |
1406 | 1230 |
1407 // Argument 10 (in stack parameter area): Pass current isolate address. | 1231 // Argument 10 (in stack parameter area): Pass current isolate address. |
1408 __ mov(r2, Operand(ExternalReference::isolate_address(isolate()))); | 1232 __ mov(r6, Operand(ExternalReference::isolate_address(isolate()))); |
1409 __ StoreP(r2, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize + | 1233 __ StoreP(r6, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize + |
1410 4 * kPointerSize)); | 1234 4 * kPointerSize)); |
1411 | 1235 |
1412 // Argument 9 is a dummy that reserves the space used for | 1236 // Argument 9 is a dummy that reserves the space used for |
1413 // the return address added by the ExitFrame in native calls. | 1237 // the return address added by the ExitFrame in native calls. |
1414 __ mov(r2, Operand::Zero()); | 1238 __ mov(r6, Operand::Zero()); |
1415 __ StoreP(r2, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize + | 1239 __ StoreP(r6, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize + |
1416 3 * kPointerSize)); | 1240 3 * kPointerSize)); |
1417 | 1241 |
1418 // Argument 8: Indicate that this is a direct call from JavaScript. | 1242 // Argument 8: Indicate that this is a direct call from JavaScript. |
1419 __ mov(r2, Operand(1)); | 1243 __ mov(r6, Operand(1)); |
1420 __ StoreP(r2, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize + | 1244 __ StoreP(r6, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize + |
1421 2 * kPointerSize)); | 1245 2 * kPointerSize)); |
1422 | 1246 |
1423 // Argument 7: Start (high end) of backtracking stack memory area. | 1247 // Argument 7: Start (high end) of backtracking stack memory area. |
1424 __ mov(r2, Operand(address_of_regexp_stack_memory_address)); | 1248 ExternalReference address_of_regexp_stack_memory_address = |
1425 __ LoadP(r2, MemOperand(r2, 0)); | 1249 ExternalReference::address_of_regexp_stack_memory_address(isolate()); |
| 1250 ExternalReference address_of_regexp_stack_memory_size = |
| 1251 ExternalReference::address_of_regexp_stack_memory_size(isolate()); |
| 1252 __ mov(r6, Operand(address_of_regexp_stack_memory_address)); |
| 1253 __ LoadP(r6, MemOperand(r6, 0)); |
1426 __ mov(r1, Operand(address_of_regexp_stack_memory_size)); | 1254 __ mov(r1, Operand(address_of_regexp_stack_memory_size)); |
1427 __ LoadP(r1, MemOperand(r1, 0)); | 1255 __ LoadP(r1, MemOperand(r1, 0)); |
1428 __ AddP(r2, r1); | 1256 __ AddP(r6, r1); |
1429 __ StoreP(r2, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize + | 1257 __ StoreP(r6, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize + |
1430 1 * kPointerSize)); | 1258 1 * kPointerSize)); |
1431 | 1259 |
1432 // Argument 6: Set the number of capture registers to zero to force | 1260 // Argument 6: Set the number of capture registers to zero to force |
1433 // global egexps to behave as non-global. This does not affect non-global | 1261 // global egexps to behave as non-global. This does not affect non-global |
1434 // regexps. | 1262 // regexps. |
1435 __ mov(r2, Operand::Zero()); | 1263 __ mov(r6, Operand::Zero()); |
1436 __ StoreP(r2, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize + | 1264 __ StoreP(r6, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize + |
1437 0 * kPointerSize)); | 1265 0 * kPointerSize)); |
1438 | 1266 |
1439 // Argument 1 (r2): Subject string. | |
1440 // Load the length from the original subject string from the previous stack | |
1441 // frame. Therefore we have to use fp, which points exactly to 15 pointer | |
1442 // sizes below the previous sp. (Because creating a new stack frame pushes | |
1443 // the previous fp onto the stack and moves up sp by 2 * kPointerSize and | |
1444 // 13 registers saved on the stack previously) | |
1445 __ LoadP(r2, MemOperand(fp, kSubjectOffset + 2 * kPointerSize)); | |
1446 | |
1447 // Argument 2 (r3): Previous index. | |
1448 // Already there | |
1449 __ AddP(r1, subject, Operand(SeqString::kHeaderSize - kHeapObjectTag)); | |
1450 | |
1451 // Argument 5 (r6): static offsets vector buffer. | 1267 // Argument 5 (r6): static offsets vector buffer. |
1452 __ mov( | 1268 __ mov( |
1453 r6, | 1269 r6, |
1454 Operand(ExternalReference::address_of_static_offsets_vector(isolate()))); | 1270 Operand(ExternalReference::address_of_static_offsets_vector(isolate()))); |
1455 | 1271 |
1456 // For arguments 4 (r5) and 3 (r4) get string length, calculate start of data | 1272 // Argument 4, r5: End of string data |
1457 // and calculate the shift of the index (0 for one-byte and 1 for two byte). | |
1458 __ XorP(r5, Operand(1)); | |
1459 // If slice offset is not 0, load the length from the original sliced string. | |
1460 // Argument 3, r4: Start of string data | 1273 // Argument 3, r4: Start of string data |
1461 // Prepare start and end index of the input. | 1274 CHECK(r5.is(RegExpExecDescriptor::StringEndRegister())); |
1462 __ ShiftLeftP(ip, ip, r5); | 1275 CHECK(r4.is(RegExpExecDescriptor::StringStartRegister())); |
1463 __ AddP(ip, r1, ip); | |
1464 __ ShiftLeftP(r4, r3, r5); | |
1465 __ AddP(r4, ip, r4); | |
1466 | 1276 |
1467 // Argument 4, r5: End of string data | 1277 // Argument 2 (r3): Previous index. |
1468 __ LoadP(r1, FieldMemOperand(r2, String::kLengthOffset)); | 1278 CHECK(r3.is(RegExpExecDescriptor::LastIndexRegister())); |
1469 __ SmiUntag(r1); | 1279 |
1470 __ ShiftLeftP(r0, r1, r5); | 1280 // Argument 1 (r2): Subject string. |
1471 __ AddP(r5, ip, r0); | 1281 CHECK(r2.is(RegExpExecDescriptor::StringRegister())); |
1472 | 1282 |
1473 // Locate the code entry and call it. | 1283 // Locate the code entry and call it. |
1474 __ AddP(code, Operand(Code::kHeaderSize - kHeapObjectTag)); | 1284 Register code_reg = RegExpDescriptor::CodeRegister(); |
| 1285 __ AddP(code_reg, Operand(Code::kHeaderSize - kHeapObjectTag)); |
1475 | 1286 |
1476 DirectCEntryStub stub(isolate()); | 1287 DirectCEntryStub stub(isolate()); |
1477 stub.GenerateCall(masm, code); | 1288 stub.GenerateCall(masm, code_reg); |
1478 | 1289 |
1479 __ LeaveExitFrame(false, no_reg, true); | 1290 __ LeaveExitFrame(false, no_reg, true); |
1480 | 1291 |
1481 // r2: result (int32) | 1292 // Return the smi-tagged result. |
1482 // subject: subject string -- needed to reload | 1293 __ SmiTag(r2); |
1483 __ LoadP(subject, MemOperand(sp, kSubjectOffset)); | |
1484 | |
1485 // regexp_data: RegExp data (callee saved) | |
1486 // last_match_info_elements: Last match info elements (callee saved) | |
1487 // Check the result. | |
1488 Label success; | |
1489 __ Cmp32(r2, Operand(1)); | |
1490 // We expect exactly one result since we force the called regexp to behave | |
1491 // as non-global. | |
1492 __ beq(&success); | |
1493 Label failure; | |
1494 __ Cmp32(r2, Operand(NativeRegExpMacroAssembler::FAILURE)); | |
1495 __ beq(&failure); | |
1496 __ Cmp32(r2, Operand(NativeRegExpMacroAssembler::EXCEPTION)); | |
1497 // If not exception it can only be retry. Handle that in the runtime system. | |
1498 __ bne(&runtime); | |
1499 // Result must now be exception. If there is no pending exception already a | |
1500 // stack overflow (on the backtrack stack) was detected in RegExp code but | |
1501 // haven't created the exception yet. Handle that in the runtime system. | |
1502 // TODO(592): Rerunning the RegExp to get the stack overflow exception. | |
1503 __ mov(r3, Operand(isolate()->factory()->the_hole_value())); | |
1504 __ mov(r4, Operand(ExternalReference(Isolate::kPendingExceptionAddress, | |
1505 isolate()))); | |
1506 __ LoadP(r2, MemOperand(r4, 0)); | |
1507 __ CmpP(r2, r3); | |
1508 __ beq(&runtime); | |
1509 | |
1510 // For exception, throw the exception again. | |
1511 __ TailCallRuntime(Runtime::kRegExpExecReThrow); | |
1512 | |
1513 __ bind(&failure); | |
1514 // For failure and exception return null. | |
1515 __ mov(r2, Operand(isolate()->factory()->null_value())); | |
1516 __ la(sp, MemOperand(sp, (4 * kPointerSize))); | |
1517 __ Ret(); | 1294 __ Ret(); |
1518 | |
1519 // Process the result from the native regexp code. | |
1520 __ bind(&success); | |
1521 __ LoadP(r3, | |
1522 FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset)); | |
1523 // Calculate number of capture registers (number_of_captures + 1) * 2. | |
1524 // SmiToShortArrayOffset accomplishes the multiplication by 2 and | |
1525 // SmiUntag (which is a nop for 32-bit). | |
1526 __ SmiToShortArrayOffset(r3, r3); | |
1527 __ AddP(r3, Operand(2)); | |
1528 | |
1529 // Check that the last match info is a FixedArray. | |
1530 __ LoadP(last_match_info_elements, MemOperand(sp, kLastMatchInfoOffset)); | |
1531 __ JumpIfSmi(last_match_info_elements, &runtime); | |
1532 // Check that the object has fast elements. | |
1533 __ LoadP(r2, | |
1534 FieldMemOperand(last_match_info_elements, HeapObject::kMapOffset)); | |
1535 __ CompareRoot(r2, Heap::kFixedArrayMapRootIndex); | |
1536 __ bne(&runtime); | |
1537 // Check that the last match info has space for the capture registers and the | |
1538 // additional information. | |
1539 __ LoadP( | |
1540 r2, FieldMemOperand(last_match_info_elements, FixedArray::kLengthOffset)); | |
1541 __ AddP(r4, r3, Operand(RegExpMatchInfo::kLastMatchOverhead)); | |
1542 __ SmiUntag(r0, r2); | |
1543 __ CmpP(r4, r0); | |
1544 __ bgt(&runtime); | |
1545 | |
1546 // r3: number of capture registers | |
1547 // subject: subject string | |
1548 // Store the capture count. | |
1549 __ SmiTag(r4, r3); | |
1550 __ StoreP(r4, FieldMemOperand(last_match_info_elements, | |
1551 RegExpMatchInfo::kNumberOfCapturesOffset)); | |
1552 // Store last subject and last input. | |
1553 __ StoreP(subject, FieldMemOperand(last_match_info_elements, | |
1554 RegExpMatchInfo::kLastSubjectOffset)); | |
1555 __ LoadRR(r4, subject); | |
1556 __ RecordWriteField(last_match_info_elements, | |
1557 RegExpMatchInfo::kLastSubjectOffset, subject, r9, | |
1558 kLRHasNotBeenSaved, kDontSaveFPRegs); | |
1559 __ LoadRR(subject, r4); | |
1560 __ StoreP(subject, FieldMemOperand(last_match_info_elements, | |
1561 RegExpMatchInfo::kLastInputOffset)); | |
1562 __ RecordWriteField(last_match_info_elements, | |
1563 RegExpMatchInfo::kLastInputOffset, subject, r9, | |
1564 kLRHasNotBeenSaved, kDontSaveFPRegs); | |
1565 | |
1566 // Get the static offsets vector filled by the native regexp code. | |
1567 ExternalReference address_of_static_offsets_vector = | |
1568 ExternalReference::address_of_static_offsets_vector(isolate()); | |
1569 __ mov(r4, Operand(address_of_static_offsets_vector)); | |
1570 | |
1571 // r3: number of capture registers | |
1572 // r4: offsets vector | |
1573 Label next_capture; | |
1574 // Capture register counter starts from number of capture registers and | |
1575 // counts down until wrapping after zero. | |
1576 __ AddP(r2, last_match_info_elements, | |
1577 Operand(RegExpMatchInfo::kFirstCaptureOffset - kHeapObjectTag - | |
1578 kPointerSize)); | |
1579 __ AddP(r4, Operand(-kIntSize)); // bias down for lwzu | |
1580 __ bind(&next_capture); | |
1581 // Read the value from the static offsets vector buffer. | |
1582 __ ly(r5, MemOperand(r4, kIntSize)); | |
1583 __ lay(r4, MemOperand(r4, kIntSize)); | |
1584 // Store the smi value in the last match info. | |
1585 __ SmiTag(r5); | |
1586 __ StoreP(r5, MemOperand(r2, kPointerSize)); | |
1587 __ lay(r2, MemOperand(r2, kPointerSize)); | |
1588 __ BranchOnCount(r3, &next_capture); | |
1589 | |
1590 // Return last match info. | |
1591 __ LoadRR(r2, last_match_info_elements); | |
1592 __ la(sp, MemOperand(sp, (4 * kPointerSize))); | |
1593 __ Ret(); | |
1594 | |
1595 // Do the runtime call to execute the regexp. | |
1596 __ bind(&runtime); | |
1597 __ TailCallRuntime(Runtime::kRegExpExec); | |
1598 | |
1599 // Deferred code for string handling. | |
1600 // (5) Long external string? If not, go to (7). | |
1601 __ bind(¬_seq_nor_cons); | |
1602 // Compare flags are still set. | |
1603 __ bgt(¬_long_external, Label::kNear); // Go to (7). | |
1604 | |
1605 // (6) External string. Make it, offset-wise, look like a sequential string. | |
1606 __ bind(&external_string); | |
1607 __ LoadP(r2, FieldMemOperand(subject, HeapObject::kMapOffset)); | |
1608 __ LoadlB(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset)); | |
1609 if (FLAG_debug_code) { | |
1610 // Assert that we do not have a cons or slice (indirect strings) here. | |
1611 // Sequential strings have already been ruled out. | |
1612 STATIC_ASSERT(kIsIndirectStringMask == 1); | |
1613 __ tmll(r2, Operand(kIsIndirectStringMask)); | |
1614 __ Assert(eq, kExternalStringExpectedButNotFound, cr0); | |
1615 } | |
1616 __ LoadP(subject, | |
1617 FieldMemOperand(subject, ExternalString::kResourceDataOffset)); | |
1618 // Move the pointer so that offset-wise, it looks like a sequential string. | |
1619 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); | |
1620 __ SubP(subject, subject, | |
1621 Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); | |
1622 __ b(&seq_string); // Go to (4). | |
1623 | |
1624 // (7) Short external string or not a string? If yes, bail out to runtime. | |
1625 __ bind(¬_long_external); | |
1626 STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag != 0); | |
1627 __ mov(r0, Operand(kIsNotStringMask | kShortExternalStringMask)); | |
1628 __ AndP(r0, r3); | |
1629 __ bne(&runtime); | |
1630 | |
1631 // (8) Sliced or thin string. Replace subject with parent. Go to (4). | |
1632 Label thin_string; | |
1633 __ CmpP(r3, Operand(kThinStringTag)); | |
1634 __ beq(&thin_string); | |
1635 // Load offset into ip and replace subject string with parent. | |
1636 __ LoadP(ip, FieldMemOperand(subject, SlicedString::kOffsetOffset)); | |
1637 __ SmiUntag(ip); | |
1638 __ LoadP(subject, FieldMemOperand(subject, SlicedString::kParentOffset)); | |
1639 __ b(&check_underlying); // Go to (4). | |
1640 | |
1641 __ bind(&thin_string); | |
1642 __ LoadP(subject, FieldMemOperand(subject, ThinString::kActualOffset)); | |
1643 __ b(&check_underlying); // Go to (4). | |
1644 #endif // V8_INTERPRETED_REGEXP | 1295 #endif // V8_INTERPRETED_REGEXP |
1645 } | 1296 } |
1646 | 1297 |
1647 static void CallStubInRecordCallTarget(MacroAssembler* masm, CodeStub* stub) { | 1298 static void CallStubInRecordCallTarget(MacroAssembler* masm, CodeStub* stub) { |
1648 // r2 : number of arguments to the construct function | 1299 // r2 : number of arguments to the construct function |
1649 // r3 : the function to call | 1300 // r3 : the function to call |
1650 // r4 : feedback vector | 1301 // r4 : feedback vector |
1651 // r5 : slot in feedback vector (Smi) | 1302 // r5 : slot in feedback vector (Smi) |
1652 FrameScope scope(masm, StackFrame::INTERNAL); | 1303 FrameScope scope(masm, StackFrame::INTERNAL); |
1653 | 1304 |
(...skipping 1818 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3472 CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, | 3123 CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, |
3473 kStackUnwindSpace, NULL, return_value_operand, NULL); | 3124 kStackUnwindSpace, NULL, return_value_operand, NULL); |
3474 } | 3125 } |
3475 | 3126 |
3476 #undef __ | 3127 #undef __ |
3477 | 3128 |
3478 } // namespace internal | 3129 } // namespace internal |
3479 } // namespace v8 | 3130 } // namespace v8 |
3480 | 3131 |
3481 #endif // V8_TARGET_ARCH_S390 | 3132 #endif // V8_TARGET_ARCH_S390 |
OLD | NEW |