OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 2250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2261 FieldOperand(rcx, JSRegExp::kIrregexpCaptureCountOffset)); | 2261 FieldOperand(rcx, JSRegExp::kIrregexpCaptureCountOffset)); |
2262 // Calculate number of capture registers (number_of_captures + 1) * 2. | 2262 // Calculate number of capture registers (number_of_captures + 1) * 2. |
2263 __ leal(rdx, Operand(rdx, rdx, times_1, 2)); | 2263 __ leal(rdx, Operand(rdx, rdx, times_1, 2)); |
2264 // Check that the static offsets vector buffer is large enough. | 2264 // Check that the static offsets vector buffer is large enough. |
2265 __ cmpl(rdx, Immediate(OffsetsVector::kStaticOffsetsVectorSize)); | 2265 __ cmpl(rdx, Immediate(OffsetsVector::kStaticOffsetsVectorSize)); |
2266 __ j(above, &runtime); | 2266 __ j(above, &runtime); |
2267 | 2267 |
2268 // rcx: RegExp data (FixedArray) | 2268 // rcx: RegExp data (FixedArray) |
2269 // rdx: Number of capture registers | 2269 // rdx: Number of capture registers |
2270 // Check that the second argument is a string. | 2270 // Check that the second argument is a string. |
2271 __ movq(rax, Operand(rsp, kSubjectOffset)); | 2271 __ movq(rdi, Operand(rsp, kSubjectOffset)); |
2272 __ JumpIfSmi(rax, &runtime); | 2272 __ JumpIfSmi(rdi, &runtime); |
2273 Condition is_string = masm->IsObjectStringType(rax, rbx, rbx); | 2273 Condition is_string = masm->IsObjectStringType(rdi, rbx, rbx); |
2274 __ j(NegateCondition(is_string), &runtime); | 2274 __ j(NegateCondition(is_string), &runtime); |
2275 | 2275 |
2276 // rax: Subject string. | 2276 // rdi: Subject string. |
2277 // rcx: RegExp data (FixedArray). | 2277 // rax: RegExp data (FixedArray). |
2278 // rdx: Number of capture registers. | 2278 // rdx: Number of capture registers. |
2279 // Check that the third argument is a positive smi less than the string | 2279 // Check that the third argument is a positive smi less than the string |
2280 // length. A negative value will be greater (unsigned comparison). | 2280 // length. A negative value will be greater (unsigned comparison). |
2281 __ movq(rbx, Operand(rsp, kPreviousIndexOffset)); | 2281 __ movq(rbx, Operand(rsp, kPreviousIndexOffset)); |
2282 __ JumpIfNotSmi(rbx, &runtime); | 2282 __ JumpIfNotSmi(rbx, &runtime); |
2283 __ SmiCompare(rbx, FieldOperand(rax, String::kLengthOffset)); | 2283 __ SmiCompare(rbx, FieldOperand(rdi, String::kLengthOffset)); |
2284 __ j(above_equal, &runtime); | 2284 __ j(above_equal, &runtime); |
2285 | 2285 |
2286 // rcx: RegExp data (FixedArray) | 2286 // rax: RegExp data (FixedArray) |
2287 // rdx: Number of capture registers | 2287 // rdx: Number of capture registers |
2288 // Check that the fourth object is a JSArray object. | 2288 // Check that the fourth object is a JSArray object. |
2289 __ movq(rax, Operand(rsp, kLastMatchInfoOffset)); | 2289 __ movq(rdi, Operand(rsp, kLastMatchInfoOffset)); |
2290 __ JumpIfSmi(rax, &runtime); | 2290 __ JumpIfSmi(rdi, &runtime); |
2291 __ CmpObjectType(rax, JS_ARRAY_TYPE, kScratchRegister); | 2291 __ CmpObjectType(rdi, JS_ARRAY_TYPE, kScratchRegister); |
2292 __ j(not_equal, &runtime); | 2292 __ j(not_equal, &runtime); |
2293 // Check that the JSArray is in fast case. | 2293 // Check that the JSArray is in fast case. |
2294 __ movq(rbx, FieldOperand(rax, JSArray::kElementsOffset)); | 2294 __ movq(rbx, FieldOperand(rdi, JSArray::kElementsOffset)); |
2295 __ movq(rax, FieldOperand(rbx, HeapObject::kMapOffset)); | 2295 __ movq(rdi, FieldOperand(rbx, HeapObject::kMapOffset)); |
2296 __ Cmp(rax, Factory::fixed_array_map()); | 2296 __ Cmp(rdi, Factory::fixed_array_map()); |
2297 __ j(not_equal, &runtime); | 2297 __ j(not_equal, &runtime); |
2298 // Check that the last match info has space for the capture registers and the | 2298 // Check that the last match info has space for the capture registers and the |
2299 // additional information. Ensure no overflow in add. | 2299 // additional information. Ensure no overflow in add. |
2300 STATIC_ASSERT(FixedArray::kMaxLength < kMaxInt - FixedArray::kLengthOffset); | 2300 STATIC_ASSERT(FixedArray::kMaxLength < kMaxInt - FixedArray::kLengthOffset); |
2301 __ SmiToInteger32(rax, FieldOperand(rbx, FixedArray::kLengthOffset)); | 2301 __ SmiToInteger32(rdi, FieldOperand(rbx, FixedArray::kLengthOffset)); |
2302 __ addl(rdx, Immediate(RegExpImpl::kLastMatchOverhead)); | 2302 __ addl(rdx, Immediate(RegExpImpl::kLastMatchOverhead)); |
2303 __ cmpl(rdx, rax); | 2303 __ cmpl(rdx, rdi); |
2304 __ j(greater, &runtime); | 2304 __ j(greater, &runtime); |
2305 | 2305 |
2306 // rcx: RegExp data (FixedArray) | 2306 // rax: RegExp data (FixedArray) |
2307 // Check the representation and encoding of the subject string. | 2307 // Check the representation and encoding of the subject string. |
2308 NearLabel seq_ascii_string, seq_two_byte_string, check_code; | 2308 NearLabel seq_ascii_string, seq_two_byte_string, check_code; |
2309 __ movq(rax, Operand(rsp, kSubjectOffset)); | 2309 __ movq(rdi, Operand(rsp, kSubjectOffset)); |
2310 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); | 2310 __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); |
2311 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); | 2311 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); |
2312 // First check for flat two byte string. | 2312 // First check for flat two byte string. |
2313 __ andb(rbx, Immediate( | 2313 __ andb(rbx, Immediate( |
2314 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask)); | 2314 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask)); |
2315 STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0); | 2315 STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0); |
2316 __ j(zero, &seq_two_byte_string); | 2316 __ j(zero, &seq_two_byte_string); |
2317 // Any other flat string must be a flat ascii string. | 2317 // Any other flat string must be a flat ascii string. |
2318 __ testb(rbx, Immediate(kIsNotStringMask | kStringRepresentationMask)); | 2318 __ testb(rbx, Immediate(kIsNotStringMask | kStringRepresentationMask)); |
2319 __ j(zero, &seq_ascii_string); | 2319 __ j(zero, &seq_ascii_string); |
2320 | 2320 |
2321 // Check for flat cons string. | 2321 // Check for flat cons string. |
2322 // A flat cons string is a cons string where the second part is the empty | 2322 // A flat cons string is a cons string where the second part is the empty |
2323 // string. In that case the subject string is just the first part of the cons | 2323 // string. In that case the subject string is just the first part of the cons |
2324 // string. Also in this case the first part of the cons string is known to be | 2324 // string. Also in this case the first part of the cons string is known to be |
2325 // a sequential string or an external string. | 2325 // a sequential string or an external string. |
2326 STATIC_ASSERT(kExternalStringTag !=0); | 2326 STATIC_ASSERT(kExternalStringTag !=0); |
2327 STATIC_ASSERT((kConsStringTag & kExternalStringTag) == 0); | 2327 STATIC_ASSERT((kConsStringTag & kExternalStringTag) == 0); |
2328 __ testb(rbx, Immediate(kIsNotStringMask | kExternalStringTag)); | 2328 __ testb(rbx, Immediate(kIsNotStringMask | kExternalStringTag)); |
2329 __ j(not_zero, &runtime); | 2329 __ j(not_zero, &runtime); |
2330 // String is a cons string. | 2330 // String is a cons string. |
2331 __ movq(rdx, FieldOperand(rax, ConsString::kSecondOffset)); | 2331 __ movq(rdx, FieldOperand(rdi, ConsString::kSecondOffset)); |
2332 __ Cmp(rdx, Factory::empty_string()); | 2332 __ Cmp(rdx, Factory::empty_string()); |
2333 __ j(not_equal, &runtime); | 2333 __ j(not_equal, &runtime); |
2334 __ movq(rax, FieldOperand(rax, ConsString::kFirstOffset)); | 2334 __ movq(rdi, FieldOperand(rdi, ConsString::kFirstOffset)); |
2335 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); | 2335 __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); |
2336 // String is a cons string with empty second part. | 2336 // String is a cons string with empty second part. |
2337 // rax: first part of cons string. | 2337 // rdi: first part of cons string. |
2338 // rbx: map of first part of cons string. | 2338 // rbx: map of first part of cons string. |
2339 // Is first part a flat two byte string? | 2339 // Is first part a flat two byte string? |
2340 __ testb(FieldOperand(rbx, Map::kInstanceTypeOffset), | 2340 __ testb(FieldOperand(rbx, Map::kInstanceTypeOffset), |
2341 Immediate(kStringRepresentationMask | kStringEncodingMask)); | 2341 Immediate(kStringRepresentationMask | kStringEncodingMask)); |
2342 STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0); | 2342 STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0); |
2343 __ j(zero, &seq_two_byte_string); | 2343 __ j(zero, &seq_two_byte_string); |
2344 // Any other flat string must be ascii. | 2344 // Any other flat string must be ascii. |
2345 __ testb(FieldOperand(rbx, Map::kInstanceTypeOffset), | 2345 __ testb(FieldOperand(rbx, Map::kInstanceTypeOffset), |
2346 Immediate(kStringRepresentationMask)); | 2346 Immediate(kStringRepresentationMask)); |
2347 __ j(not_zero, &runtime); | 2347 __ j(not_zero, &runtime); |
2348 | 2348 |
2349 __ bind(&seq_ascii_string); | 2349 __ bind(&seq_ascii_string); |
2350 // rax: subject string (sequential ascii) | 2350 // rdi: subject string (sequential ascii) |
2351 // rcx: RegExp data (FixedArray) | 2351 // rax: RegExp data (FixedArray) |
2352 __ movq(r11, FieldOperand(rcx, JSRegExp::kDataAsciiCodeOffset)); | 2352 __ movq(r11, FieldOperand(rax, JSRegExp::kDataAsciiCodeOffset)); |
2353 __ Set(rdi, 1); // Type is ascii. | 2353 __ Set(rcx, 1); // Type is ascii. |
2354 __ jmp(&check_code); | 2354 __ jmp(&check_code); |
2355 | 2355 |
2356 __ bind(&seq_two_byte_string); | 2356 __ bind(&seq_two_byte_string); |
2357 // rax: subject string (flat two-byte) | 2357 // rdi: subject string (flat two-byte) |
2358 // rcx: RegExp data (FixedArray) | 2358 // rax: RegExp data (FixedArray) |
2359 __ movq(r11, FieldOperand(rcx, JSRegExp::kDataUC16CodeOffset)); | 2359 __ movq(r11, FieldOperand(rax, JSRegExp::kDataUC16CodeOffset)); |
2360 __ Set(rdi, 0); // Type is two byte. | 2360 __ Set(rcx, 0); // Type is two byte. |
2361 | 2361 |
2362 __ bind(&check_code); | 2362 __ bind(&check_code); |
2363 // Check that the irregexp code has been generated for the actual string | 2363 // Check that the irregexp code has been generated for the actual string |
2364 // encoding. If it has, the field contains a code object otherwise it contains | 2364 // encoding. If it has, the field contains a code object otherwise it contains |
2365 // the hole. | 2365 // the hole. |
2366 __ CmpObjectType(r11, CODE_TYPE, kScratchRegister); | 2366 __ CmpObjectType(r11, CODE_TYPE, kScratchRegister); |
2367 __ j(not_equal, &runtime); | 2367 __ j(not_equal, &runtime); |
2368 | 2368 |
2369 // rax: subject string | 2369 // rdi: subject string |
2370 // rdi: encoding of subject string (1 if ascii, 0 if two_byte); | 2370 // rcx: encoding of subject string (1 if ascii, 0 if two_byte); |
2371 // r11: code | 2371 // r11: code |
2372 // Load used arguments before starting to push arguments for call to native | 2372 // Load used arguments before starting to push arguments for call to native |
2373 // RegExp code to avoid handling changing stack height. | 2373 // RegExp code to avoid handling changing stack height. |
2374 __ SmiToInteger64(rbx, Operand(rsp, kPreviousIndexOffset)); | 2374 __ SmiToInteger64(rbx, Operand(rsp, kPreviousIndexOffset)); |
2375 | 2375 |
2376 // rax: subject string | 2376 // rdi: subject string |
2377 // rbx: previous index | 2377 // rbx: previous index |
2378 // rdi: encoding of subject string (1 if ascii 0 if two_byte); | 2378 // rcx: encoding of subject string (1 if ascii 0 if two_byte); |
2379 // r11: code | 2379 // r11: code |
2380 // All checks done. Now push arguments for native regexp code. | 2380 // All checks done. Now push arguments for native regexp code. |
2381 __ IncrementCounter(&Counters::regexp_entry_native, 1); | 2381 __ IncrementCounter(&Counters::regexp_entry_native, 1); |
2382 | 2382 |
2383 // rsi is caller save on Windows and used to pass parameter on Linux. | |
2384 __ push(rsi); | |
2385 | |
2386 static const int kRegExpExecuteArguments = 7; | 2383 static const int kRegExpExecuteArguments = 7; |
2387 __ PrepareCallCFunction(kRegExpExecuteArguments); | |
2388 int argument_slots_on_stack = | 2384 int argument_slots_on_stack = |
2389 masm->ArgumentStackSlotsForCFunctionCall(kRegExpExecuteArguments); | 2385 masm->ArgumentStackSlotsForCFunctionCall(kRegExpExecuteArguments); |
| 2386 __ EnterApiExitFrame(argument_slots_on_stack); // Clobbers rax! |
2390 | 2387 |
2391 // Argument 7: Indicate that this is a direct call from JavaScript. | 2388 // Argument 7: Indicate that this is a direct call from JavaScript. |
2392 __ movq(Operand(rsp, (argument_slots_on_stack - 1) * kPointerSize), | 2389 __ movq(Operand(rsp, (argument_slots_on_stack - 1) * kPointerSize), |
2393 Immediate(1)); | 2390 Immediate(1)); |
2394 | 2391 |
2395 // Argument 6: Start (high end) of backtracking stack memory area. | 2392 // Argument 6: Start (high end) of backtracking stack memory area. |
2396 __ movq(kScratchRegister, address_of_regexp_stack_memory_address); | 2393 __ movq(kScratchRegister, address_of_regexp_stack_memory_address); |
2397 __ movq(r9, Operand(kScratchRegister, 0)); | 2394 __ movq(r9, Operand(kScratchRegister, 0)); |
2398 __ movq(kScratchRegister, address_of_regexp_stack_memory_size); | 2395 __ movq(kScratchRegister, address_of_regexp_stack_memory_size); |
2399 __ addq(r9, Operand(kScratchRegister, 0)); | 2396 __ addq(r9, Operand(kScratchRegister, 0)); |
(...skipping 16 matching lines...) Expand all Loading... |
2416 Register arg2 = rdx; | 2413 Register arg2 = rdx; |
2417 Register arg1 = rcx; | 2414 Register arg1 = rcx; |
2418 #else | 2415 #else |
2419 Register arg4 = rcx; | 2416 Register arg4 = rcx; |
2420 Register arg3 = rdx; | 2417 Register arg3 = rdx; |
2421 Register arg2 = rsi; | 2418 Register arg2 = rsi; |
2422 Register arg1 = rdi; | 2419 Register arg1 = rdi; |
2423 #endif | 2420 #endif |
2424 | 2421 |
2425 // Keep track on aliasing between argX defined above and the registers used. | 2422 // Keep track on aliasing between argX defined above and the registers used. |
2426 // rax: subject string | 2423 // rdi: subject string |
2427 // rbx: previous index | 2424 // rbx: previous index |
2428 // rdi: encoding of subject string (1 if ascii 0 if two_byte); | 2425 // rcx: encoding of subject string (1 if ascii 0 if two_byte); |
2429 // r11: code | 2426 // r11: code |
2430 | 2427 |
2431 // Argument 4: End of string data | 2428 // Argument 4: End of string data |
2432 // Argument 3: Start of string data | 2429 // Argument 3: Start of string data |
2433 NearLabel setup_two_byte, setup_rest; | 2430 NearLabel setup_two_byte, setup_rest; |
2434 __ testb(rdi, rdi); | 2431 __ testb(rcx, rcx); // Last use of rcx as encoding of subject string. |
2435 __ j(zero, &setup_two_byte); | 2432 __ j(zero, &setup_two_byte); |
2436 __ SmiToInteger32(rdi, FieldOperand(rax, String::kLengthOffset)); | 2433 __ SmiToInteger32(rcx, FieldOperand(rdi, String::kLengthOffset)); |
2437 __ lea(arg4, FieldOperand(rax, rdi, times_1, SeqAsciiString::kHeaderSize)); | 2434 __ lea(arg4, FieldOperand(rdi, rcx, times_1, SeqAsciiString::kHeaderSize)); |
2438 __ lea(arg3, FieldOperand(rax, rbx, times_1, SeqAsciiString::kHeaderSize)); | 2435 __ lea(arg3, FieldOperand(rdi, rbx, times_1, SeqAsciiString::kHeaderSize)); |
2439 __ jmp(&setup_rest); | 2436 __ jmp(&setup_rest); |
2440 __ bind(&setup_two_byte); | 2437 __ bind(&setup_two_byte); |
2441 __ SmiToInteger32(rdi, FieldOperand(rax, String::kLengthOffset)); | 2438 __ SmiToInteger32(rcx, FieldOperand(rdi, String::kLengthOffset)); |
2442 __ lea(arg4, FieldOperand(rax, rdi, times_2, SeqTwoByteString::kHeaderSize)); | 2439 __ lea(arg4, FieldOperand(rdi, rcx, times_2, SeqTwoByteString::kHeaderSize)); |
2443 __ lea(arg3, FieldOperand(rax, rbx, times_2, SeqTwoByteString::kHeaderSize)); | 2440 __ lea(arg3, FieldOperand(rdi, rbx, times_2, SeqTwoByteString::kHeaderSize)); |
2444 | 2441 |
2445 __ bind(&setup_rest); | 2442 __ bind(&setup_rest); |
2446 // Argument 2: Previous index. | 2443 // Argument 2: Previous index. |
2447 __ movq(arg2, rbx); | 2444 __ movq(arg2, rbx); |
2448 | 2445 |
2449 // Argument 1: Subject string. | 2446 // Argument 1: Subject string. |
2450 __ movq(arg1, rax); | 2447 #ifdef WIN64_ |
| 2448 __ movq(arg1, rdi); |
| 2449 #else |
| 2450 // Already there in AMD64 calling convention. |
| 2451 ASSERT(arg1.is(rdi)); |
| 2452 #endif |
2451 | 2453 |
2452 // Locate the code entry and call it. | 2454 // Locate the code entry and call it. |
2453 __ addq(r11, Immediate(Code::kHeaderSize - kHeapObjectTag)); | 2455 __ addq(r11, Immediate(Code::kHeaderSize - kHeapObjectTag)); |
2454 __ CallCFunction(r11, kRegExpExecuteArguments); | 2456 __ call(r11); |
2455 | 2457 |
2456 // rsi is caller save, as it is used to pass parameter. | 2458 __ LeaveApiExitFrame(); |
2457 __ pop(rsi); | |
2458 | 2459 |
2459 // Check the result. | 2460 // Check the result. |
2460 NearLabel success; | 2461 NearLabel success; |
| 2462 Label exception; |
2461 __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::SUCCESS)); | 2463 __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::SUCCESS)); |
2462 __ j(equal, &success); | 2464 __ j(equal, &success); |
2463 NearLabel failure; | 2465 __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::EXCEPTION)); |
| 2466 __ j(equal, &exception); |
2464 __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::FAILURE)); | 2467 __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::FAILURE)); |
2465 __ j(equal, &failure); | 2468 // If none of the above, it can only be retry. |
2466 __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::EXCEPTION)); | 2469 // Handle that in the runtime system. |
2467 // If not exception it can only be retry. Handle that in the runtime system. | |
2468 __ j(not_equal, &runtime); | 2470 __ j(not_equal, &runtime); |
2469 // Result must now be exception. If there is no pending exception already a | 2471 |
2470 // stack overflow (on the backtrack stack) was detected in RegExp code but | 2472 // For failure return null. |
2471 // haven't created the exception yet. Handle that in the runtime system. | 2473 __ LoadRoot(rax, Heap::kNullValueRootIndex); |
2472 // TODO(592): Rerunning the RegExp to get the stack overflow exception. | |
2473 ExternalReference pending_exception_address(Top::k_pending_exception_address); | |
2474 __ movq(kScratchRegister, pending_exception_address); | |
2475 __ Cmp(kScratchRegister, Factory::the_hole_value()); | |
2476 __ j(equal, &runtime); | |
2477 __ bind(&failure); | |
2478 // For failure and exception return null. | |
2479 __ Move(rax, Factory::null_value()); | |
2480 __ ret(4 * kPointerSize); | 2474 __ ret(4 * kPointerSize); |
2481 | 2475 |
2482 // Load RegExp data. | 2476 // Load RegExp data. |
2483 __ bind(&success); | 2477 __ bind(&success); |
2484 __ movq(rax, Operand(rsp, kJSRegExpOffset)); | 2478 __ movq(rax, Operand(rsp, kJSRegExpOffset)); |
2485 __ movq(rcx, FieldOperand(rax, JSRegExp::kDataOffset)); | 2479 __ movq(rcx, FieldOperand(rax, JSRegExp::kDataOffset)); |
2486 __ SmiToInteger32(rax, | 2480 __ SmiToInteger32(rax, |
2487 FieldOperand(rcx, JSRegExp::kIrregexpCaptureCountOffset)); | 2481 FieldOperand(rcx, JSRegExp::kIrregexpCaptureCountOffset)); |
2488 // Calculate number of capture registers (number_of_captures + 1) * 2. | 2482 // Calculate number of capture registers (number_of_captures + 1) * 2. |
2489 __ leal(rdx, Operand(rax, rax, times_1, 2)); | 2483 __ leal(rdx, Operand(rax, rax, times_1, 2)); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2530 times_pointer_size, | 2524 times_pointer_size, |
2531 RegExpImpl::kFirstCaptureOffset), | 2525 RegExpImpl::kFirstCaptureOffset), |
2532 rdi); | 2526 rdi); |
2533 __ jmp(&next_capture); | 2527 __ jmp(&next_capture); |
2534 __ bind(&done); | 2528 __ bind(&done); |
2535 | 2529 |
2536 // Return last match info. | 2530 // Return last match info. |
2537 __ movq(rax, Operand(rsp, kLastMatchInfoOffset)); | 2531 __ movq(rax, Operand(rsp, kLastMatchInfoOffset)); |
2538 __ ret(4 * kPointerSize); | 2532 __ ret(4 * kPointerSize); |
2539 | 2533 |
| 2534 __ bind(&exception); |
| 2535 // Result must now be exception. If there is no pending exception already a |
| 2536 // stack overflow (on the backtrack stack) was detected in RegExp code but |
| 2537 // haven't created the exception yet. Handle that in the runtime system. |
| 2538 // TODO(592): Rerunning the RegExp to get the stack overflow exception. |
| 2539 ExternalReference pending_exception_address(Top::k_pending_exception_address); |
| 2540 __ movq(rbx, pending_exception_address); |
| 2541 __ movq(rax, Operand(rbx, 0)); |
| 2542 __ LoadRoot(rdx, Heap::kTheHoleValueRootIndex); |
| 2543 __ cmpq(rax, rdx); |
| 2544 __ j(equal, &runtime); |
| 2545 __ movq(Operand(rbx, 0), rdx); |
| 2546 |
| 2547 __ CompareRoot(rax, Heap::kTerminationExceptionRootIndex); |
| 2548 NearLabel termination_exception; |
| 2549 __ j(equal, &termination_exception); |
| 2550 __ Throw(rax); |
| 2551 |
| 2552 __ bind(&termination_exception); |
| 2553 __ ThrowUncatchable(TERMINATION, rax); |
| 2554 |
2540 // Do the runtime call to execute the regexp. | 2555 // Do the runtime call to execute the regexp. |
2541 __ bind(&runtime); | 2556 __ bind(&runtime); |
2542 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); | 2557 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); |
2543 #endif // V8_INTERPRETED_REGEXP | 2558 #endif // V8_INTERPRETED_REGEXP |
2544 } | 2559 } |
2545 | 2560 |
2546 | 2561 |
2547 void RegExpConstructResultStub::Generate(MacroAssembler* masm) { | 2562 void RegExpConstructResultStub::Generate(MacroAssembler* masm) { |
2548 const int kMaxInlineLength = 100; | 2563 const int kMaxInlineLength = 100; |
2549 Label slowcase; | 2564 Label slowcase; |
(...skipping 528 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3078 __ movq(Operand(rsp, (argc_ + 1) * kPointerSize), rdi); | 3093 __ movq(Operand(rsp, (argc_ + 1) * kPointerSize), rdi); |
3079 __ Set(rax, argc_); | 3094 __ Set(rax, argc_); |
3080 __ Set(rbx, 0); | 3095 __ Set(rbx, 0); |
3081 __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION); | 3096 __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION); |
3082 Handle<Code> adaptor(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)); | 3097 Handle<Code> adaptor(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)); |
3083 __ Jump(adaptor, RelocInfo::CODE_TARGET); | 3098 __ Jump(adaptor, RelocInfo::CODE_TARGET); |
3084 } | 3099 } |
3085 | 3100 |
3086 | 3101 |
3087 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { | 3102 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { |
3088 // Check that stack should contain next handler, frame pointer, state and | 3103 // Throw exception in eax. |
3089 // return address in that order. | 3104 __ Throw(rax); |
3090 STATIC_ASSERT(StackHandlerConstants::kFPOffset + kPointerSize == | |
3091 StackHandlerConstants::kStateOffset); | |
3092 STATIC_ASSERT(StackHandlerConstants::kStateOffset + kPointerSize == | |
3093 StackHandlerConstants::kPCOffset); | |
3094 | |
3095 ExternalReference handler_address(Top::k_handler_address); | |
3096 __ movq(kScratchRegister, handler_address); | |
3097 __ movq(rsp, Operand(kScratchRegister, 0)); | |
3098 // get next in chain | |
3099 __ pop(rcx); | |
3100 __ movq(Operand(kScratchRegister, 0), rcx); | |
3101 __ pop(rbp); // pop frame pointer | |
3102 __ pop(rdx); // remove state | |
3103 | |
3104 // Before returning we restore the context from the frame pointer if not NULL. | |
3105 // The frame pointer is NULL in the exception handler of a JS entry frame. | |
3106 __ Set(rsi, 0); // Tentatively set context pointer to NULL | |
3107 NearLabel skip; | |
3108 __ cmpq(rbp, Immediate(0)); | |
3109 __ j(equal, &skip); | |
3110 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | |
3111 __ bind(&skip); | |
3112 __ ret(0); | |
3113 } | 3105 } |
3114 | 3106 |
3115 | 3107 |
3116 void CEntryStub::GenerateCore(MacroAssembler* masm, | 3108 void CEntryStub::GenerateCore(MacroAssembler* masm, |
3117 Label* throw_normal_exception, | 3109 Label* throw_normal_exception, |
3118 Label* throw_termination_exception, | 3110 Label* throw_termination_exception, |
3119 Label* throw_out_of_memory_exception, | 3111 Label* throw_out_of_memory_exception, |
3120 bool do_gc, | 3112 bool do_gc, |
3121 bool always_allocate_scope) { | 3113 bool always_allocate_scope) { |
3122 // rax: result parameter for PerformGC, if any. | 3114 // rax: result parameter for PerformGC, if any. |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3244 // Handle normal exception. | 3236 // Handle normal exception. |
3245 __ jmp(throw_normal_exception); | 3237 __ jmp(throw_normal_exception); |
3246 | 3238 |
3247 // Retry. | 3239 // Retry. |
3248 __ bind(&retry); | 3240 __ bind(&retry); |
3249 } | 3241 } |
3250 | 3242 |
3251 | 3243 |
3252 void CEntryStub::GenerateThrowUncatchable(MacroAssembler* masm, | 3244 void CEntryStub::GenerateThrowUncatchable(MacroAssembler* masm, |
3253 UncatchableExceptionType type) { | 3245 UncatchableExceptionType type) { |
3254 // Fetch top stack handler. | 3246 __ ThrowUncatchable(type, rax); |
3255 ExternalReference handler_address(Top::k_handler_address); | |
3256 __ movq(kScratchRegister, handler_address); | |
3257 __ movq(rsp, Operand(kScratchRegister, 0)); | |
3258 | |
3259 // Unwind the handlers until the ENTRY handler is found. | |
3260 NearLabel loop, done; | |
3261 __ bind(&loop); | |
3262 // Load the type of the current stack handler. | |
3263 const int kStateOffset = StackHandlerConstants::kStateOffset; | |
3264 __ cmpq(Operand(rsp, kStateOffset), Immediate(StackHandler::ENTRY)); | |
3265 __ j(equal, &done); | |
3266 // Fetch the next handler in the list. | |
3267 const int kNextOffset = StackHandlerConstants::kNextOffset; | |
3268 __ movq(rsp, Operand(rsp, kNextOffset)); | |
3269 __ jmp(&loop); | |
3270 __ bind(&done); | |
3271 | |
3272 // Set the top handler address to next handler past the current ENTRY handler. | |
3273 __ movq(kScratchRegister, handler_address); | |
3274 __ pop(Operand(kScratchRegister, 0)); | |
3275 | |
3276 if (type == OUT_OF_MEMORY) { | |
3277 // Set external caught exception to false. | |
3278 ExternalReference external_caught(Top::k_external_caught_exception_address); | |
3279 __ movq(rax, Immediate(false)); | |
3280 __ store_rax(external_caught); | |
3281 | |
3282 // Set pending exception and rax to out of memory exception. | |
3283 ExternalReference pending_exception(Top::k_pending_exception_address); | |
3284 __ movq(rax, Failure::OutOfMemoryException(), RelocInfo::NONE); | |
3285 __ store_rax(pending_exception); | |
3286 } | |
3287 | |
3288 // Clear the context pointer. | |
3289 __ Set(rsi, 0); | |
3290 | |
3291 // Restore registers from handler. | |
3292 STATIC_ASSERT(StackHandlerConstants::kNextOffset + kPointerSize == | |
3293 StackHandlerConstants::kFPOffset); | |
3294 __ pop(rbp); // FP | |
3295 STATIC_ASSERT(StackHandlerConstants::kFPOffset + kPointerSize == | |
3296 StackHandlerConstants::kStateOffset); | |
3297 __ pop(rdx); // State | |
3298 | |
3299 STATIC_ASSERT(StackHandlerConstants::kStateOffset + kPointerSize == | |
3300 StackHandlerConstants::kPCOffset); | |
3301 __ ret(0); | |
3302 } | 3247 } |
3303 | 3248 |
3304 | 3249 |
3305 void CEntryStub::Generate(MacroAssembler* masm) { | 3250 void CEntryStub::Generate(MacroAssembler* masm) { |
3306 // rax: number of arguments including receiver | 3251 // rax: number of arguments including receiver |
3307 // rbx: pointer to C function (C callee-saved) | 3252 // rbx: pointer to C function (C callee-saved) |
3308 // rbp: frame pointer of calling JS frame (restored after C call) | 3253 // rbp: frame pointer of calling JS frame (restored after C call) |
3309 // rsp: stack pointer (restored after C call) | 3254 // rsp: stack pointer (restored after C call) |
3310 // rsi: current context (restored) | 3255 // rsi: current context (restored) |
3311 | 3256 |
(...skipping 1469 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4781 __ Integer32ToSmi(result, result); | 4726 __ Integer32ToSmi(result, result); |
4782 __ ret(0); | 4727 __ ret(0); |
4783 } | 4728 } |
4784 | 4729 |
4785 | 4730 |
4786 #undef __ | 4731 #undef __ |
4787 | 4732 |
4788 } } // namespace v8::internal | 4733 } } // namespace v8::internal |
4789 | 4734 |
4790 #endif // V8_TARGET_ARCH_X64 | 4735 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |