| 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 |