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

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

Issue 2738413002: [regexp] Port RegExpExecStub to CSA (mostly) (Closed)
Patch Set: Rebase Created 3 years, 9 months 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 | « src/runtime/runtime-regexp.cc ('k') | src/s390/interface-descriptors-s390.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 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
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(&not_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(&not_seq_nor_cons);
1602 // Compare flags are still set.
1603 __ bgt(&not_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(&not_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
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
OLDNEW
« no previous file with comments | « src/runtime/runtime-regexp.cc ('k') | src/s390/interface-descriptors-s390.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698