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

Side by Side Diff: src/arm/code-stubs-arm.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 | « no previous file | src/arm/interface-descriptors-arm.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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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_ARM 5 #if V8_TARGET_ARCH_ARM
6 6
7 #include "src/code-stubs.h" 7 #include "src/code-stubs.h"
8 8
9 #include "src/api-arguments.h" 9 #include "src/api-arguments.h"
10 #include "src/assembler-inl.h" 10 #include "src/assembler-inl.h"
(...skipping 1135 matching lines...) Expand 10 before | Expand all | Expand 10 after
1146 } 1146 }
1147 #endif 1147 #endif
1148 1148
1149 // Restore callee-saved vfp registers. 1149 // Restore callee-saved vfp registers.
1150 __ vldm(ia_w, sp, kFirstCalleeSavedDoubleReg, kLastCalleeSavedDoubleReg); 1150 __ vldm(ia_w, sp, kFirstCalleeSavedDoubleReg, kLastCalleeSavedDoubleReg);
1151 1151
1152 __ ldm(ia_w, sp, kCalleeSaved | pc.bit()); 1152 __ ldm(ia_w, sp, kCalleeSaved | pc.bit());
1153 } 1153 }
1154 1154
1155 void RegExpExecStub::Generate(MacroAssembler* masm) { 1155 void RegExpExecStub::Generate(MacroAssembler* masm) {
1156 // Just jump directly to runtime if native RegExp is not selected at compile
1157 // time or if regexp entry in generated code is turned off runtime switch or
1158 // at compilation.
1159 #ifdef V8_INTERPRETED_REGEXP 1156 #ifdef V8_INTERPRETED_REGEXP
1160 __ TailCallRuntime(Runtime::kRegExpExec); 1157 // This case is handled prior to the RegExpExecStub call.
1158 __ Abort(kUnexpectedRegExpExecCall);
1161 #else // V8_INTERPRETED_REGEXP 1159 #else // V8_INTERPRETED_REGEXP
1162
1163 // Stack frame on entry.
1164 // sp[0]: last_match_info (expected JSArray)
1165 // sp[4]: previous index
1166 // sp[8]: subject string
1167 // sp[12]: JSRegExp object
1168
1169 const int kLastMatchInfoOffset = 0 * kPointerSize;
1170 const int kPreviousIndexOffset = 1 * kPointerSize;
1171 const int kSubjectOffset = 2 * kPointerSize;
1172 const int kJSRegExpOffset = 3 * kPointerSize;
1173
1174 Label runtime;
1175 // Allocation of registers for this function. These are in callee save
1176 // registers and will be preserved by the call to the native RegExp code, as
1177 // this code is called using the normal C calling convention. When calling
1178 // directly from generated code the native RegExp code will not do a GC and
1179 // therefore the content of these registers are safe to use after the call.
1180 Register subject = r4;
1181 Register regexp_data = r5;
1182 Register last_match_info_elements = no_reg; // will be r6;
1183
1184 // Ensure that a RegExp stack is allocated.
1185 ExternalReference address_of_regexp_stack_memory_address =
1186 ExternalReference::address_of_regexp_stack_memory_address(isolate());
1187 ExternalReference address_of_regexp_stack_memory_size =
1188 ExternalReference::address_of_regexp_stack_memory_size(isolate());
1189 __ mov(r0, Operand(address_of_regexp_stack_memory_size));
1190 __ ldr(r0, MemOperand(r0, 0));
1191 __ cmp(r0, Operand::Zero());
1192 __ b(eq, &runtime);
1193
1194 // Check that the first argument is a JSRegExp object.
1195 __ ldr(r0, MemOperand(sp, kJSRegExpOffset));
1196 __ JumpIfSmi(r0, &runtime);
1197 __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE);
1198 __ b(ne, &runtime);
1199
1200 // Check that the RegExp has been compiled (data contains a fixed array).
1201 __ ldr(regexp_data, FieldMemOperand(r0, JSRegExp::kDataOffset));
1202 if (FLAG_debug_code) {
1203 __ SmiTst(regexp_data);
1204 __ Check(ne, kUnexpectedTypeForRegExpDataFixedArrayExpected);
1205 __ CompareObjectType(regexp_data, r0, r0, FIXED_ARRAY_TYPE);
1206 __ Check(eq, kUnexpectedTypeForRegExpDataFixedArrayExpected);
1207 }
1208
1209 // regexp_data: RegExp data (FixedArray)
1210 // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP.
1211 __ ldr(r0, FieldMemOperand(regexp_data, JSRegExp::kDataTagOffset));
1212 __ cmp(r0, Operand(Smi::FromInt(JSRegExp::IRREGEXP)));
1213 __ b(ne, &runtime);
1214
1215 // regexp_data: RegExp data (FixedArray)
1216 // Check that the number of captures fit in the static offsets vector buffer.
1217 __ ldr(r2,
1218 FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset));
1219 // Check (number_of_captures + 1) * 2 <= offsets vector size
1220 // Or number_of_captures * 2 <= offsets vector size - 2
1221 // Multiplying by 2 comes for free since r2 is smi-tagged.
1222 STATIC_ASSERT(kSmiTag == 0);
1223 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
1224 STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2);
1225 __ cmp(r2, Operand(Isolate::kJSRegexpStaticOffsetsVectorSize - 2));
1226 __ b(hi, &runtime);
1227
1228 // Reset offset for possibly sliced string.
1229 __ mov(r9, Operand::Zero());
1230 __ ldr(subject, MemOperand(sp, kSubjectOffset));
1231 __ JumpIfSmi(subject, &runtime);
1232 __ mov(r3, subject); // Make a copy of the original subject string.
1233 // subject: subject string
1234 // r3: subject string
1235 // regexp_data: RegExp data (FixedArray)
1236 // Handle subject string according to its encoding and representation:
1237 // (1) Sequential string? If yes, go to (4).
1238 // (2) Sequential or cons? If not, go to (5).
1239 // (3) Cons string. If the string is flat, replace subject with first string
1240 // and go to (1). Otherwise bail out to runtime.
1241 // (4) Sequential string. Load regexp code according to encoding.
1242 // (E) Carry on.
1243 /// [...]
1244
1245 // Deferred code at the end of the stub:
1246 // (5) Long external string? If not, go to (7).
1247 // (6) External string. Make it, offset-wise, look like a sequential string.
1248 // Go to (4).
1249 // (7) Short external string or not a string? If yes, bail out to runtime.
1250 // (8) Sliced or thin string. Replace subject with parent. Go to (1).
1251
1252 Label seq_string /* 4 */, external_string /* 6 */, check_underlying /* 1 */,
1253 not_seq_nor_cons /* 5 */, not_long_external /* 7 */;
1254
1255 __ bind(&check_underlying);
1256 __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset));
1257 __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset));
1258
1259 // (1) Sequential string? If yes, go to (4).
1260 __ and_(r1,
1261 r0,
1262 Operand(kIsNotStringMask |
1263 kStringRepresentationMask |
1264 kShortExternalStringMask),
1265 SetCC);
1266 STATIC_ASSERT((kStringTag | kSeqStringTag) == 0);
1267 __ b(eq, &seq_string); // Go to (4).
1268
1269 // (2) Sequential or cons? If not, go to (5).
1270 STATIC_ASSERT(kConsStringTag < kExternalStringTag);
1271 STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
1272 STATIC_ASSERT(kThinStringTag > kExternalStringTag);
1273 STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
1274 STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
1275 __ cmp(r1, Operand(kExternalStringTag));
1276 __ b(ge, &not_seq_nor_cons); // Go to (5).
1277
1278 // (3) Cons string. Check that it's flat.
1279 // Replace subject with first string and reload instance type.
1280 __ ldr(r0, FieldMemOperand(subject, ConsString::kSecondOffset));
1281 __ CompareRoot(r0, Heap::kempty_stringRootIndex);
1282 __ b(ne, &runtime);
1283 __ ldr(subject, FieldMemOperand(subject, ConsString::kFirstOffset));
1284 __ jmp(&check_underlying);
1285
1286 // (4) Sequential string. Load regexp code according to encoding.
1287 __ bind(&seq_string);
1288 // subject: sequential subject string (or look-alike, external string)
1289 // r3: original subject string
1290 // Load previous index and check range before r3 is overwritten. We have to
1291 // use r3 instead of subject here because subject might have been only made
1292 // to look like a sequential string when it actually is an external string.
1293 __ ldr(r1, MemOperand(sp, kPreviousIndexOffset));
1294 __ JumpIfNotSmi(r1, &runtime);
1295 __ ldr(r3, FieldMemOperand(r3, String::kLengthOffset));
1296 __ cmp(r3, Operand(r1));
1297 __ b(ls, &runtime);
1298 __ SmiUntag(r1);
1299
1300 STATIC_ASSERT(8 == kOneByteStringTag);
1301 STATIC_ASSERT(kTwoByteStringTag == 0);
1302 __ and_(r0, r0, Operand(kStringEncodingMask));
1303 __ mov(r3, Operand(r0, ASR, 3), SetCC);
1304 __ ldr(r6, FieldMemOperand(regexp_data, JSRegExp::kDataOneByteCodeOffset),
1305 ne);
1306 __ ldr(r6, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset), eq);
1307
1308 // (E) Carry on. String handling is done.
1309 // r6: irregexp code
1310 // Check that the irregexp code has been generated for the actual string
1311 // encoding. If it has, the field contains a code object otherwise it contains
1312 // a smi (code flushing support).
1313 __ JumpIfSmi(r6, &runtime);
1314
1315 // r1: previous index
1316 // r3: encoding of subject string (1 if one_byte, 0 if two_byte);
1317 // r6: code
1318 // subject: Subject string
1319 // regexp_data: RegExp data (FixedArray)
1320 // All checks done. Now push arguments for native regexp code.
1321 __ IncrementCounter(isolate()->counters()->regexp_entry_native(), 1, r0, r2);
1322
1323 // Isolates: note we add an additional parameter here (isolate pointer). 1160 // Isolates: note we add an additional parameter here (isolate pointer).
1324 const int kRegExpExecuteArguments = 9; 1161 const int kRegExpExecuteArguments = 9;
1325 const int kParameterRegisters = 4; 1162 const int kParameterRegisters = 4;
1326 __ EnterExitFrame(false, kRegExpExecuteArguments - kParameterRegisters); 1163 __ EnterExitFrame(false, kRegExpExecuteArguments - kParameterRegisters);
1327 1164
1328 // Stack pointer now points to cell where return address is to be written. 1165 // Stack pointer now points to cell where return address is to be written.
1329 // Arguments are before that on the stack or in registers. 1166 // Arguments are before that on the stack or in registers.
1330 1167
1331 // Argument 9 (sp[20]): Pass current isolate address. 1168 // Argument 9 (sp[20]): Pass current isolate address.
1332 __ mov(r0, Operand(ExternalReference::isolate_address(isolate()))); 1169 __ mov(r5, Operand(ExternalReference::isolate_address(isolate())));
1333 __ str(r0, MemOperand(sp, 5 * kPointerSize)); 1170 __ str(r5, MemOperand(sp, 5 * kPointerSize));
1334 1171
1335 // Argument 8 (sp[16]): Indicate that this is a direct call from JavaScript. 1172 // Argument 8 (sp[16]): Indicate that this is a direct call from JavaScript.
1336 __ mov(r0, Operand(1)); 1173 __ mov(r5, Operand(1));
1337 __ str(r0, MemOperand(sp, 4 * kPointerSize)); 1174 __ str(r5, MemOperand(sp, 4 * kPointerSize));
1338 1175
1339 // Argument 7 (sp[12]): Start (high end) of backtracking stack memory area. 1176 // Argument 7 (sp[12]): Start (high end) of backtracking stack memory area.
1340 __ mov(r0, Operand(address_of_regexp_stack_memory_address)); 1177 ExternalReference address_of_regexp_stack_memory_address =
1341 __ ldr(r0, MemOperand(r0, 0)); 1178 ExternalReference::address_of_regexp_stack_memory_address(isolate());
1342 __ mov(r2, Operand(address_of_regexp_stack_memory_size)); 1179 ExternalReference address_of_regexp_stack_memory_size =
1343 __ ldr(r2, MemOperand(r2, 0)); 1180 ExternalReference::address_of_regexp_stack_memory_size(isolate());
1344 __ add(r0, r0, Operand(r2)); 1181 __ mov(r5, Operand(address_of_regexp_stack_memory_address));
1345 __ str(r0, MemOperand(sp, 3 * kPointerSize)); 1182 __ ldr(r5, MemOperand(r5, 0));
1183 __ mov(r6, Operand(address_of_regexp_stack_memory_size));
1184 __ ldr(r6, MemOperand(r6, 0));
1185 __ add(r5, r5, Operand(r6));
1186 __ str(r5, MemOperand(sp, 3 * kPointerSize));
1346 1187
1347 // Argument 6: Set the number of capture registers to zero to force global 1188 // Argument 6: Set the number of capture registers to zero to force global
1348 // regexps to behave as non-global. This does not affect non-global regexps. 1189 // regexps to behave as non-global. This does not affect non-global regexps.
1349 __ mov(r0, Operand::Zero()); 1190 __ mov(r5, Operand::Zero());
1350 __ str(r0, MemOperand(sp, 2 * kPointerSize)); 1191 __ str(r5, MemOperand(sp, 2 * kPointerSize));
1351 1192
1352 // Argument 5 (sp[4]): static offsets vector buffer. 1193 // Argument 5 (sp[4]): static offsets vector buffer.
1353 __ mov(r0, 1194 __ mov(
1354 Operand(ExternalReference::address_of_static_offsets_vector( 1195 r5,
1355 isolate()))); 1196 Operand(ExternalReference::address_of_static_offsets_vector(isolate())));
1356 __ str(r0, MemOperand(sp, 1 * kPointerSize)); 1197 __ str(r5, MemOperand(sp, 1 * kPointerSize));
1357 1198
1358 // For arguments 4 and 3 get string length, calculate start of string data and 1199 // Argument 4: End of string data
1359 // calculate the shift of the index (0 for one-byte and 1 for two-byte). 1200 // Argument 3: Start of string data
1360 __ add(r7, subject, Operand(SeqString::kHeaderSize - kHeapObjectTag)); 1201 CHECK(r3.is(RegExpExecDescriptor::StringEndRegister()));
1361 __ eor(r3, r3, Operand(1)); 1202 CHECK(r2.is(RegExpExecDescriptor::StringStartRegister()));
1362 // Load the length from the original subject string from the previous stack
1363 // frame. Therefore we have to use fp, which points exactly to two pointer
1364 // sizes below the previous sp. (Because creating a new stack frame pushes
1365 // the previous fp onto the stack and moves up sp by 2 * kPointerSize.)
1366 __ ldr(subject, MemOperand(fp, kSubjectOffset + 2 * kPointerSize));
1367 // If slice offset is not 0, load the length from the original sliced string.
1368 // Argument 4, r3: End of string data
1369 // Argument 3, r2: Start of string data
1370 // Prepare start and end index of the input.
1371 __ add(r9, r7, Operand(r9, LSL, r3));
1372 __ add(r2, r9, Operand(r1, LSL, r3));
1373
1374 __ ldr(r7, FieldMemOperand(subject, String::kLengthOffset));
1375 __ SmiUntag(r7);
1376 __ add(r3, r9, Operand(r7, LSL, r3));
1377 1203
1378 // Argument 2 (r1): Previous index. 1204 // Argument 2 (r1): Previous index.
1379 // Already there 1205 CHECK(r1.is(RegExpExecDescriptor::LastIndexRegister()));
1380 1206
1381 // Argument 1 (r0): Subject string. 1207 // Argument 1 (r0): Subject string.
1382 __ mov(r0, subject); 1208 CHECK(r0.is(RegExpExecDescriptor::StringRegister()));
1383 1209
1384 // Locate the code entry and call it. 1210 // Locate the code entry and call it.
1385 __ add(r6, r6, Operand(Code::kHeaderSize - kHeapObjectTag)); 1211 Register code_reg = RegExpExecDescriptor::CodeRegister();
1212 __ add(code_reg, code_reg, Operand(Code::kHeaderSize - kHeapObjectTag));
1213
1386 DirectCEntryStub stub(isolate()); 1214 DirectCEntryStub stub(isolate());
1387 stub.GenerateCall(masm, r6); 1215 stub.GenerateCall(masm, code_reg);
1388 1216
1389 __ LeaveExitFrame(false, no_reg, true); 1217 __ LeaveExitFrame(false, no_reg, true);
1390 1218
1391 last_match_info_elements = r6; 1219 __ SmiTag(r0);
1392
1393 // r0: result
1394 // subject: subject string (callee saved)
1395 // regexp_data: RegExp data (callee saved)
1396 // last_match_info_elements: Last match info elements (callee saved)
1397 // Check the result.
1398 Label success;
1399 __ cmp(r0, Operand(1));
1400 // We expect exactly one result since we force the called regexp to behave
1401 // as non-global.
1402 __ b(eq, &success);
1403 Label failure;
1404 __ cmp(r0, Operand(NativeRegExpMacroAssembler::FAILURE));
1405 __ b(eq, &failure);
1406 __ cmp(r0, Operand(NativeRegExpMacroAssembler::EXCEPTION));
1407 // If not exception it can only be retry. Handle that in the runtime system.
1408 __ b(ne, &runtime);
1409 // Result must now be exception. If there is no pending exception already a
1410 // stack overflow (on the backtrack stack) was detected in RegExp code but
1411 // haven't created the exception yet. Handle that in the runtime system.
1412 // TODO(592): Rerunning the RegExp to get the stack overflow exception.
1413 __ mov(r1, Operand(isolate()->factory()->the_hole_value()));
1414 __ mov(r2, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
1415 isolate())));
1416 __ ldr(r0, MemOperand(r2, 0));
1417 __ cmp(r0, r1);
1418 __ b(eq, &runtime);
1419
1420 // For exception, throw the exception again.
1421 __ TailCallRuntime(Runtime::kRegExpExecReThrow);
1422
1423 __ bind(&failure);
1424 // For failure and exception return null.
1425 __ mov(r0, Operand(isolate()->factory()->null_value()));
1426 __ add(sp, sp, Operand(4 * kPointerSize));
1427 __ Ret(); 1220 __ Ret();
1428
1429 // Process the result from the native regexp code.
1430 __ bind(&success);
1431 __ ldr(r1,
1432 FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset));
1433 // Calculate number of capture registers (number_of_captures + 1) * 2.
1434 // Multiplying by 2 comes for free since r1 is smi-tagged.
1435 STATIC_ASSERT(kSmiTag == 0);
1436 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
1437 __ add(r1, r1, Operand(2)); // r1 was a smi.
1438
1439 // Check that the last match info is a FixedArray.
1440 __ ldr(last_match_info_elements, MemOperand(sp, kLastMatchInfoOffset));
1441 __ JumpIfSmi(last_match_info_elements, &runtime);
1442 // Check that the object has fast elements.
1443 __ ldr(r0, FieldMemOperand(last_match_info_elements, HeapObject::kMapOffset));
1444 __ CompareRoot(r0, Heap::kFixedArrayMapRootIndex);
1445 __ b(ne, &runtime);
1446 // Check that the last match info has space for the capture registers and the
1447 // additional information.
1448 __ ldr(r0,
1449 FieldMemOperand(last_match_info_elements, FixedArray::kLengthOffset));
1450 __ add(r2, r1, Operand(RegExpMatchInfo::kLastMatchOverhead));
1451 __ cmp(r2, Operand::SmiUntag(r0));
1452 __ b(gt, &runtime);
1453
1454 // r1: number of capture registers
1455 // r4: subject string
1456 // Store the capture count.
1457 __ SmiTag(r2, r1);
1458 __ str(r2, FieldMemOperand(last_match_info_elements,
1459 RegExpMatchInfo::kNumberOfCapturesOffset));
1460 // Store last subject and last input.
1461 __ str(subject, FieldMemOperand(last_match_info_elements,
1462 RegExpMatchInfo::kLastSubjectOffset));
1463 __ mov(r2, subject);
1464 __ RecordWriteField(last_match_info_elements,
1465 RegExpMatchInfo::kLastSubjectOffset, subject, r3,
1466 kLRHasNotBeenSaved, kDontSaveFPRegs);
1467 __ mov(subject, r2);
1468 __ str(subject, FieldMemOperand(last_match_info_elements,
1469 RegExpMatchInfo::kLastInputOffset));
1470 __ RecordWriteField(last_match_info_elements,
1471 RegExpMatchInfo::kLastInputOffset, subject, r3,
1472 kLRHasNotBeenSaved, kDontSaveFPRegs);
1473
1474 // Get the static offsets vector filled by the native regexp code.
1475 ExternalReference address_of_static_offsets_vector =
1476 ExternalReference::address_of_static_offsets_vector(isolate());
1477 __ mov(r2, Operand(address_of_static_offsets_vector));
1478
1479 // r1: number of capture registers
1480 // r2: offsets vector
1481 Label next_capture, done;
1482 // Capture register counter starts from number of capture registers and
1483 // counts down until wrapping after zero.
1484 __ add(r0, last_match_info_elements,
1485 Operand(RegExpMatchInfo::kFirstCaptureOffset - kHeapObjectTag));
1486 __ bind(&next_capture);
1487 __ sub(r1, r1, Operand(1), SetCC);
1488 __ b(mi, &done);
1489 // Read the value from the static offsets vector buffer.
1490 __ ldr(r3, MemOperand(r2, kPointerSize, PostIndex));
1491 // Store the smi value in the last match info.
1492 __ SmiTag(r3);
1493 __ str(r3, MemOperand(r0, kPointerSize, PostIndex));
1494 __ jmp(&next_capture);
1495 __ bind(&done);
1496
1497 // Return last match info.
1498 __ mov(r0, last_match_info_elements);
1499 __ add(sp, sp, Operand(4 * kPointerSize));
1500 __ Ret();
1501
1502 // Do the runtime call to execute the regexp.
1503 __ bind(&runtime);
1504 __ TailCallRuntime(Runtime::kRegExpExec);
1505
1506 // Deferred code for string handling.
1507 // (5) Long external string? If not, go to (7).
1508 __ bind(&not_seq_nor_cons);
1509 // Compare flags are still set.
1510 __ b(gt, &not_long_external); // Go to (7).
1511
1512 // (6) External string. Make it, offset-wise, look like a sequential string.
1513 __ bind(&external_string);
1514 __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset));
1515 __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset));
1516 if (FLAG_debug_code) {
1517 // Assert that we do not have a cons or slice (indirect strings) here.
1518 // Sequential strings have already been ruled out.
1519 __ tst(r0, Operand(kIsIndirectStringMask));
1520 __ Assert(eq, kExternalStringExpectedButNotFound);
1521 }
1522 __ ldr(subject,
1523 FieldMemOperand(subject, ExternalString::kResourceDataOffset));
1524 // Move the pointer so that offset-wise, it looks like a sequential string.
1525 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
1526 __ sub(subject,
1527 subject,
1528 Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
1529 __ jmp(&seq_string); // Go to (4).
1530
1531 // (7) Short external string or not a string? If yes, bail out to runtime.
1532 __ bind(&not_long_external);
1533 STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0);
1534 __ tst(r1, Operand(kIsNotStringMask | kShortExternalStringMask));
1535 __ b(ne, &runtime);
1536
1537 // (8) Sliced or thin string. Replace subject with parent. Go to (4).
1538 Label thin_string;
1539 __ cmp(r1, Operand(kThinStringTag));
1540 __ b(eq, &thin_string);
1541 // Load offset into r9 and replace subject string with parent.
1542 __ ldr(r9, FieldMemOperand(subject, SlicedString::kOffsetOffset));
1543 __ SmiUntag(r9);
1544 __ ldr(subject, FieldMemOperand(subject, SlicedString::kParentOffset));
1545 __ jmp(&check_underlying); // Go to (4).
1546
1547 __ bind(&thin_string);
1548 __ ldr(subject, FieldMemOperand(subject, ThinString::kActualOffset));
1549 __ jmp(&check_underlying); // Go to (4).
1550 #endif // V8_INTERPRETED_REGEXP 1221 #endif // V8_INTERPRETED_REGEXP
1551 } 1222 }
1552 1223
1553
1554 static void CallStubInRecordCallTarget(MacroAssembler* masm, CodeStub* stub) { 1224 static void CallStubInRecordCallTarget(MacroAssembler* masm, CodeStub* stub) {
1555 // r0 : number of arguments to the construct function 1225 // r0 : number of arguments to the construct function
1556 // r1 : the function to call 1226 // r1 : the function to call
1557 // r2 : feedback vector 1227 // r2 : feedback vector
1558 // r3 : slot in feedback vector (Smi) 1228 // r3 : slot in feedback vector (Smi)
1559 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 1229 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
1560 1230
1561 // Number-of-arguments register must be smi-tagged to call out. 1231 // Number-of-arguments register must be smi-tagged to call out.
1562 __ SmiTag(r0); 1232 __ SmiTag(r0);
1563 __ Push(r3, r2, r1, r0); 1233 __ Push(r3, r2, r1, r0);
(...skipping 1762 matching lines...) Expand 10 before | Expand all | Expand 10 after
3326 CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, 2996 CallApiFunctionAndReturn(masm, api_function_address, thunk_ref,
3327 kStackUnwindSpace, NULL, return_value_operand, NULL); 2997 kStackUnwindSpace, NULL, return_value_operand, NULL);
3328 } 2998 }
3329 2999
3330 #undef __ 3000 #undef __
3331 3001
3332 } // namespace internal 3002 } // namespace internal
3333 } // namespace v8 3003 } // namespace v8
3334 3004
3335 #endif // V8_TARGET_ARCH_ARM 3005 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « no previous file | src/arm/interface-descriptors-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698