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