| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 1958 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1969 __ bind(&miss); | 1969 __ bind(&miss); |
| 1970 | 1970 |
| 1971 StubCompiler::TailCallBuiltin( | 1971 StubCompiler::TailCallBuiltin( |
| 1972 masm, BaseLoadStoreStubCompiler::MissBuiltin(kind())); | 1972 masm, BaseLoadStoreStubCompiler::MissBuiltin(kind())); |
| 1973 } | 1973 } |
| 1974 | 1974 |
| 1975 | 1975 |
| 1976 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { | 1976 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { |
| 1977 // The key is in rdx and the parameter count is in rax. | 1977 // The key is in rdx and the parameter count is in rax. |
| 1978 | 1978 |
| 1979 // The displacement is used for skipping the frame pointer on the | |
| 1980 // stack. It is the offset of the last parameter (if any) relative | |
| 1981 // to the frame pointer. | |
| 1982 static const int kDisplacement = 1 * kPointerSize; | |
| 1983 | |
| 1984 // Check that the key is a smi. | 1979 // Check that the key is a smi. |
| 1985 Label slow; | 1980 Label slow; |
| 1986 __ JumpIfNotSmi(rdx, &slow); | 1981 __ JumpIfNotSmi(rdx, &slow); |
| 1987 | 1982 |
| 1988 // Check if the calling frame is an arguments adaptor frame. We look at the | 1983 // Check if the calling frame is an arguments adaptor frame. We look at the |
| 1989 // context offset, and if the frame is not a regular one, then we find a | 1984 // context offset, and if the frame is not a regular one, then we find a |
| 1990 // Smi instead of the context. We can't use SmiCompare here, because that | 1985 // Smi instead of the context. We can't use SmiCompare here, because that |
| 1991 // only works for comparing two smis. | 1986 // only works for comparing two smis. |
| 1992 Label adaptor; | 1987 Label adaptor; |
| 1993 __ movq(rbx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); | 1988 __ movq(rbx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); |
| 1994 __ Cmp(Operand(rbx, StandardFrameConstants::kContextOffset), | 1989 __ Cmp(Operand(rbx, StandardFrameConstants::kContextOffset), |
| 1995 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); | 1990 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); |
| 1996 __ j(equal, &adaptor); | 1991 __ j(equal, &adaptor); |
| 1997 | 1992 |
| 1998 // Check index against formal parameters count limit passed in | 1993 // Check index against formal parameters count limit passed in |
| 1999 // through register rax. Use unsigned comparison to get negative | 1994 // through register rax. Use unsigned comparison to get negative |
| 2000 // check for free. | 1995 // check for free. |
| 2001 __ cmpq(rdx, rax); | 1996 __ cmpq(rdx, rax); |
| 2002 __ j(above_equal, &slow); | 1997 __ j(above_equal, &slow); |
| 2003 | 1998 |
| 2004 // Read the argument from the stack and return it. | 1999 // Read the argument from the stack and return it. |
| 2005 SmiIndex index = masm->SmiToIndex(rax, rax, kPointerSizeLog2); | 2000 __ SmiSub(rax, rax, rdx); |
| 2006 __ lea(rbx, Operand(rbp, index.reg, index.scale, 0)); | 2001 __ SmiToInteger32(rax, rax); |
| 2007 index = masm->SmiToNegativeIndex(rdx, rdx, kPointerSizeLog2); | 2002 StackArgumentsAccessor args(rbp, rax, ARGUMENTS_DONT_CONTAIN_RECEIVER); |
| 2008 __ movq(rax, Operand(rbx, index.reg, index.scale, kDisplacement)); | 2003 __ movq(rax, args.GetArgumentOperand(0)); |
| 2009 __ Ret(); | 2004 __ Ret(); |
| 2010 | 2005 |
| 2011 // Arguments adaptor case: Check index against actual arguments | 2006 // Arguments adaptor case: Check index against actual arguments |
| 2012 // limit found in the arguments adaptor frame. Use unsigned | 2007 // limit found in the arguments adaptor frame. Use unsigned |
| 2013 // comparison to get negative check for free. | 2008 // comparison to get negative check for free. |
| 2014 __ bind(&adaptor); | 2009 __ bind(&adaptor); |
| 2015 __ movq(rcx, Operand(rbx, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 2010 __ movq(rcx, Operand(rbx, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| 2016 __ cmpq(rdx, rcx); | 2011 __ cmpq(rdx, rcx); |
| 2017 __ j(above_equal, &slow); | 2012 __ j(above_equal, &slow); |
| 2018 | 2013 |
| 2019 // Read the argument from the stack and return it. | 2014 // Read the argument from the stack and return it. |
| 2020 index = masm->SmiToIndex(rax, rcx, kPointerSizeLog2); | 2015 __ SmiSub(rcx, rcx, rdx); |
| 2021 __ lea(rbx, Operand(rbx, index.reg, index.scale, 0)); | 2016 __ SmiToInteger32(rcx, rcx); |
| 2022 index = masm->SmiToNegativeIndex(rdx, rdx, kPointerSizeLog2); | 2017 StackArgumentsAccessor adaptor_args(rbx, rcx, |
| 2023 __ movq(rax, Operand(rbx, index.reg, index.scale, kDisplacement)); | 2018 ARGUMENTS_DONT_CONTAIN_RECEIVER); |
| 2019 __ movq(rax, adaptor_args.GetArgumentOperand(0)); |
| 2024 __ Ret(); | 2020 __ Ret(); |
| 2025 | 2021 |
| 2026 // Slow-case: Handle non-smi or out-of-bounds access to arguments | 2022 // Slow-case: Handle non-smi or out-of-bounds access to arguments |
| 2027 // by calling the runtime system. | 2023 // by calling the runtime system. |
| 2028 __ bind(&slow); | 2024 __ bind(&slow); |
| 2029 __ PopReturnAddressTo(rbx); | 2025 __ PopReturnAddressTo(rbx); |
| 2030 __ push(rdx); | 2026 __ push(rdx); |
| 2031 __ PushReturnAddressFrom(rbx); | 2027 __ PushReturnAddressFrom(rbx); |
| 2032 __ TailCallRuntime(Runtime::kGetArgumentsProperty, 1, 1); | 2028 __ TailCallRuntime(Runtime::kGetArgumentsProperty, 1, 1); |
| 2033 } | 2029 } |
| (...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2387 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); | 2383 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); |
| 2388 #else // V8_INTERPRETED_REGEXP | 2384 #else // V8_INTERPRETED_REGEXP |
| 2389 | 2385 |
| 2390 // Stack frame on entry. | 2386 // Stack frame on entry. |
| 2391 // rsp[0] : return address | 2387 // rsp[0] : return address |
| 2392 // rsp[8] : last_match_info (expected JSArray) | 2388 // rsp[8] : last_match_info (expected JSArray) |
| 2393 // rsp[16] : previous index | 2389 // rsp[16] : previous index |
| 2394 // rsp[24] : subject string | 2390 // rsp[24] : subject string |
| 2395 // rsp[32] : JSRegExp object | 2391 // rsp[32] : JSRegExp object |
| 2396 | 2392 |
| 2397 static const int kLastMatchInfoOffset = 1 * kPointerSize; | 2393 enum RegExpExecStubArgumentIndices { |
| 2398 static const int kPreviousIndexOffset = 2 * kPointerSize; | 2394 JS_REG_EXP_OBJECT_ARGUMENT_INDEX, |
| 2399 static const int kSubjectOffset = 3 * kPointerSize; | 2395 SUBJECT_STRING_ARGUMENT_INDEX, |
| 2400 static const int kJSRegExpOffset = 4 * kPointerSize; | 2396 PREVIOUS_INDEX_ARGUMENT_INDEX, |
| 2397 LAST_MATCH_INFO_ARGUMENT_INDEX, |
| 2398 REG_EXP_EXEC_ARGUMENT_COUNT |
| 2399 }; |
| 2401 | 2400 |
| 2401 StackArgumentsAccessor args(rsp, REG_EXP_EXEC_ARGUMENT_COUNT, |
| 2402 ARGUMENTS_DONT_CONTAIN_RECEIVER); |
| 2402 Label runtime; | 2403 Label runtime; |
| 2403 // Ensure that a RegExp stack is allocated. | 2404 // Ensure that a RegExp stack is allocated. |
| 2404 Isolate* isolate = masm->isolate(); | 2405 Isolate* isolate = masm->isolate(); |
| 2405 ExternalReference address_of_regexp_stack_memory_address = | 2406 ExternalReference address_of_regexp_stack_memory_address = |
| 2406 ExternalReference::address_of_regexp_stack_memory_address(isolate); | 2407 ExternalReference::address_of_regexp_stack_memory_address(isolate); |
| 2407 ExternalReference address_of_regexp_stack_memory_size = | 2408 ExternalReference address_of_regexp_stack_memory_size = |
| 2408 ExternalReference::address_of_regexp_stack_memory_size(isolate); | 2409 ExternalReference::address_of_regexp_stack_memory_size(isolate); |
| 2409 __ Load(kScratchRegister, address_of_regexp_stack_memory_size); | 2410 __ Load(kScratchRegister, address_of_regexp_stack_memory_size); |
| 2410 __ testq(kScratchRegister, kScratchRegister); | 2411 __ testq(kScratchRegister, kScratchRegister); |
| 2411 __ j(zero, &runtime); | 2412 __ j(zero, &runtime); |
| 2412 | 2413 |
| 2413 // Check that the first argument is a JSRegExp object. | 2414 // Check that the first argument is a JSRegExp object. |
| 2414 __ movq(rax, Operand(rsp, kJSRegExpOffset)); | 2415 __ movq(rax, args.GetArgumentOperand(JS_REG_EXP_OBJECT_ARGUMENT_INDEX)); |
| 2415 __ JumpIfSmi(rax, &runtime); | 2416 __ JumpIfSmi(rax, &runtime); |
| 2416 __ CmpObjectType(rax, JS_REGEXP_TYPE, kScratchRegister); | 2417 __ CmpObjectType(rax, JS_REGEXP_TYPE, kScratchRegister); |
| 2417 __ j(not_equal, &runtime); | 2418 __ j(not_equal, &runtime); |
| 2418 | 2419 |
| 2419 // Check that the RegExp has been compiled (data contains a fixed array). | 2420 // Check that the RegExp has been compiled (data contains a fixed array). |
| 2420 __ movq(rax, FieldOperand(rax, JSRegExp::kDataOffset)); | 2421 __ movq(rax, FieldOperand(rax, JSRegExp::kDataOffset)); |
| 2421 if (FLAG_debug_code) { | 2422 if (FLAG_debug_code) { |
| 2422 Condition is_smi = masm->CheckSmi(rax); | 2423 Condition is_smi = masm->CheckSmi(rax); |
| 2423 __ Check(NegateCondition(is_smi), | 2424 __ Check(NegateCondition(is_smi), |
| 2424 kUnexpectedTypeForRegExpDataFixedArrayExpected); | 2425 kUnexpectedTypeForRegExpDataFixedArrayExpected); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 2437 __ SmiToInteger32(rdx, | 2438 __ SmiToInteger32(rdx, |
| 2438 FieldOperand(rax, JSRegExp::kIrregexpCaptureCountOffset)); | 2439 FieldOperand(rax, JSRegExp::kIrregexpCaptureCountOffset)); |
| 2439 // Check (number_of_captures + 1) * 2 <= offsets vector size | 2440 // Check (number_of_captures + 1) * 2 <= offsets vector size |
| 2440 // Or number_of_captures <= offsets vector size / 2 - 1 | 2441 // Or number_of_captures <= offsets vector size / 2 - 1 |
| 2441 STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2); | 2442 STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2); |
| 2442 __ cmpl(rdx, Immediate(Isolate::kJSRegexpStaticOffsetsVectorSize / 2 - 1)); | 2443 __ cmpl(rdx, Immediate(Isolate::kJSRegexpStaticOffsetsVectorSize / 2 - 1)); |
| 2443 __ j(above, &runtime); | 2444 __ j(above, &runtime); |
| 2444 | 2445 |
| 2445 // Reset offset for possibly sliced string. | 2446 // Reset offset for possibly sliced string. |
| 2446 __ Set(r14, 0); | 2447 __ Set(r14, 0); |
| 2447 __ movq(rdi, Operand(rsp, kSubjectOffset)); | 2448 __ movq(rdi, args.GetArgumentOperand(SUBJECT_STRING_ARGUMENT_INDEX)); |
| 2448 __ JumpIfSmi(rdi, &runtime); | 2449 __ JumpIfSmi(rdi, &runtime); |
| 2449 __ movq(r15, rdi); // Make a copy of the original subject string. | 2450 __ movq(r15, rdi); // Make a copy of the original subject string. |
| 2450 __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); | 2451 __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); |
| 2451 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); | 2452 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); |
| 2452 // rax: RegExp data (FixedArray) | 2453 // rax: RegExp data (FixedArray) |
| 2453 // rdi: subject string | 2454 // rdi: subject string |
| 2454 // r15: subject string | 2455 // r15: subject string |
| 2455 // Handle subject string according to its encoding and representation: | 2456 // Handle subject string according to its encoding and representation: |
| 2456 // (1) Sequential two byte? If yes, go to (9). | 2457 // (1) Sequential two byte? If yes, go to (9). |
| 2457 // (2) Sequential one byte? If yes, go to (6). | 2458 // (2) Sequential one byte? If yes, go to (6). |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2539 | 2540 |
| 2540 // rdi: sequential subject string (or look-alike, external string) | 2541 // rdi: sequential subject string (or look-alike, external string) |
| 2541 // r15: original subject string | 2542 // r15: original subject string |
| 2542 // rcx: encoding of subject string (1 if ASCII, 0 if two_byte); | 2543 // rcx: encoding of subject string (1 if ASCII, 0 if two_byte); |
| 2543 // r11: code | 2544 // r11: code |
| 2544 // Load used arguments before starting to push arguments for call to native | 2545 // Load used arguments before starting to push arguments for call to native |
| 2545 // RegExp code to avoid handling changing stack height. | 2546 // RegExp code to avoid handling changing stack height. |
| 2546 // We have to use r15 instead of rdi to load the length because rdi might | 2547 // We have to use r15 instead of rdi to load the length because rdi might |
| 2547 // have been only made to look like a sequential string when it actually | 2548 // have been only made to look like a sequential string when it actually |
| 2548 // is an external string. | 2549 // is an external string. |
| 2549 __ movq(rbx, Operand(rsp, kPreviousIndexOffset)); | 2550 __ movq(rbx, args.GetArgumentOperand(PREVIOUS_INDEX_ARGUMENT_INDEX)); |
| 2550 __ JumpIfNotSmi(rbx, &runtime); | 2551 __ JumpIfNotSmi(rbx, &runtime); |
| 2551 __ SmiCompare(rbx, FieldOperand(r15, String::kLengthOffset)); | 2552 __ SmiCompare(rbx, FieldOperand(r15, String::kLengthOffset)); |
| 2552 __ j(above_equal, &runtime); | 2553 __ j(above_equal, &runtime); |
| 2553 __ SmiToInteger64(rbx, rbx); | 2554 __ SmiToInteger64(rbx, rbx); |
| 2554 | 2555 |
| 2555 // rdi: subject string | 2556 // rdi: subject string |
| 2556 // rbx: previous index | 2557 // rbx: previous index |
| 2557 // rcx: encoding of subject string (1 if ASCII 0 if two_byte); | 2558 // rcx: encoding of subject string (1 if ASCII 0 if two_byte); |
| 2558 // r11: code | 2559 // r11: code |
| 2559 // All checks done. Now push arguments for native regexp code. | 2560 // All checks done. Now push arguments for native regexp code. |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2659 __ j(equal, &success, Label::kNear); | 2660 __ j(equal, &success, Label::kNear); |
| 2660 __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::EXCEPTION)); | 2661 __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::EXCEPTION)); |
| 2661 __ j(equal, &exception); | 2662 __ j(equal, &exception); |
| 2662 __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::FAILURE)); | 2663 __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::FAILURE)); |
| 2663 // If none of the above, it can only be retry. | 2664 // If none of the above, it can only be retry. |
| 2664 // Handle that in the runtime system. | 2665 // Handle that in the runtime system. |
| 2665 __ j(not_equal, &runtime); | 2666 __ j(not_equal, &runtime); |
| 2666 | 2667 |
| 2667 // For failure return null. | 2668 // For failure return null. |
| 2668 __ LoadRoot(rax, Heap::kNullValueRootIndex); | 2669 __ LoadRoot(rax, Heap::kNullValueRootIndex); |
| 2669 __ ret(4 * kPointerSize); | 2670 __ ret(REG_EXP_EXEC_ARGUMENT_COUNT * kPointerSize); |
| 2670 | 2671 |
| 2671 // Load RegExp data. | 2672 // Load RegExp data. |
| 2672 __ bind(&success); | 2673 __ bind(&success); |
| 2673 __ movq(rax, Operand(rsp, kJSRegExpOffset)); | 2674 __ movq(rax, args.GetArgumentOperand(JS_REG_EXP_OBJECT_ARGUMENT_INDEX)); |
| 2674 __ movq(rcx, FieldOperand(rax, JSRegExp::kDataOffset)); | 2675 __ movq(rcx, FieldOperand(rax, JSRegExp::kDataOffset)); |
| 2675 __ SmiToInteger32(rax, | 2676 __ SmiToInteger32(rax, |
| 2676 FieldOperand(rcx, JSRegExp::kIrregexpCaptureCountOffset)); | 2677 FieldOperand(rcx, JSRegExp::kIrregexpCaptureCountOffset)); |
| 2677 // Calculate number of capture registers (number_of_captures + 1) * 2. | 2678 // Calculate number of capture registers (number_of_captures + 1) * 2. |
| 2678 __ leal(rdx, Operand(rax, rax, times_1, 2)); | 2679 __ leal(rdx, Operand(rax, rax, times_1, 2)); |
| 2679 | 2680 |
| 2680 // rdx: Number of capture registers | 2681 // rdx: Number of capture registers |
| 2681 // Check that the fourth object is a JSArray object. | 2682 // Check that the fourth object is a JSArray object. |
| 2682 __ movq(r15, Operand(rsp, kLastMatchInfoOffset)); | 2683 __ movq(r15, args.GetArgumentOperand(LAST_MATCH_INFO_ARGUMENT_INDEX)); |
| 2683 __ JumpIfSmi(r15, &runtime); | 2684 __ JumpIfSmi(r15, &runtime); |
| 2684 __ CmpObjectType(r15, JS_ARRAY_TYPE, kScratchRegister); | 2685 __ CmpObjectType(r15, JS_ARRAY_TYPE, kScratchRegister); |
| 2685 __ j(not_equal, &runtime); | 2686 __ j(not_equal, &runtime); |
| 2686 // Check that the JSArray is in fast case. | 2687 // Check that the JSArray is in fast case. |
| 2687 __ movq(rbx, FieldOperand(r15, JSArray::kElementsOffset)); | 2688 __ movq(rbx, FieldOperand(r15, JSArray::kElementsOffset)); |
| 2688 __ movq(rax, FieldOperand(rbx, HeapObject::kMapOffset)); | 2689 __ movq(rax, FieldOperand(rbx, HeapObject::kMapOffset)); |
| 2689 __ CompareRoot(rax, Heap::kFixedArrayMapRootIndex); | 2690 __ CompareRoot(rax, Heap::kFixedArrayMapRootIndex); |
| 2690 __ j(not_equal, &runtime); | 2691 __ j(not_equal, &runtime); |
| 2691 // Check that the last match info has space for the capture registers and the | 2692 // Check that the last match info has space for the capture registers and the |
| 2692 // additional information. Ensure no overflow in add. | 2693 // additional information. Ensure no overflow in add. |
| 2693 STATIC_ASSERT(FixedArray::kMaxLength < kMaxInt - FixedArray::kLengthOffset); | 2694 STATIC_ASSERT(FixedArray::kMaxLength < kMaxInt - FixedArray::kLengthOffset); |
| 2694 __ SmiToInteger32(rax, FieldOperand(rbx, FixedArray::kLengthOffset)); | 2695 __ SmiToInteger32(rax, FieldOperand(rbx, FixedArray::kLengthOffset)); |
| 2695 __ subl(rax, Immediate(RegExpImpl::kLastMatchOverhead)); | 2696 __ subl(rax, Immediate(RegExpImpl::kLastMatchOverhead)); |
| 2696 __ cmpl(rdx, rax); | 2697 __ cmpl(rdx, rax); |
| 2697 __ j(greater, &runtime); | 2698 __ j(greater, &runtime); |
| 2698 | 2699 |
| 2699 // rbx: last_match_info backing store (FixedArray) | 2700 // rbx: last_match_info backing store (FixedArray) |
| 2700 // rdx: number of capture registers | 2701 // rdx: number of capture registers |
| 2701 // Store the capture count. | 2702 // Store the capture count. |
| 2702 __ Integer32ToSmi(kScratchRegister, rdx); | 2703 __ Integer32ToSmi(kScratchRegister, rdx); |
| 2703 __ movq(FieldOperand(rbx, RegExpImpl::kLastCaptureCountOffset), | 2704 __ movq(FieldOperand(rbx, RegExpImpl::kLastCaptureCountOffset), |
| 2704 kScratchRegister); | 2705 kScratchRegister); |
| 2705 // Store last subject and last input. | 2706 // Store last subject and last input. |
| 2706 __ movq(rax, Operand(rsp, kSubjectOffset)); | 2707 __ movq(rax, args.GetArgumentOperand(SUBJECT_STRING_ARGUMENT_INDEX)); |
| 2707 __ movq(FieldOperand(rbx, RegExpImpl::kLastSubjectOffset), rax); | 2708 __ movq(FieldOperand(rbx, RegExpImpl::kLastSubjectOffset), rax); |
| 2708 __ movq(rcx, rax); | 2709 __ movq(rcx, rax); |
| 2709 __ RecordWriteField(rbx, | 2710 __ RecordWriteField(rbx, |
| 2710 RegExpImpl::kLastSubjectOffset, | 2711 RegExpImpl::kLastSubjectOffset, |
| 2711 rax, | 2712 rax, |
| 2712 rdi, | 2713 rdi, |
| 2713 kDontSaveFPRegs); | 2714 kDontSaveFPRegs); |
| 2714 __ movq(rax, rcx); | 2715 __ movq(rax, rcx); |
| 2715 __ movq(FieldOperand(rbx, RegExpImpl::kLastInputOffset), rax); | 2716 __ movq(FieldOperand(rbx, RegExpImpl::kLastInputOffset), rax); |
| 2716 __ RecordWriteField(rbx, | 2717 __ RecordWriteField(rbx, |
| (...skipping 22 matching lines...) Expand all Loading... |
| 2739 __ movq(FieldOperand(rbx, | 2740 __ movq(FieldOperand(rbx, |
| 2740 rdx, | 2741 rdx, |
| 2741 times_pointer_size, | 2742 times_pointer_size, |
| 2742 RegExpImpl::kFirstCaptureOffset), | 2743 RegExpImpl::kFirstCaptureOffset), |
| 2743 rdi); | 2744 rdi); |
| 2744 __ jmp(&next_capture); | 2745 __ jmp(&next_capture); |
| 2745 __ bind(&done); | 2746 __ bind(&done); |
| 2746 | 2747 |
| 2747 // Return last match info. | 2748 // Return last match info. |
| 2748 __ movq(rax, r15); | 2749 __ movq(rax, r15); |
| 2749 __ ret(4 * kPointerSize); | 2750 __ ret(REG_EXP_EXEC_ARGUMENT_COUNT * kPointerSize); |
| 2750 | 2751 |
| 2751 __ bind(&exception); | 2752 __ bind(&exception); |
| 2752 // Result must now be exception. If there is no pending exception already a | 2753 // Result must now be exception. If there is no pending exception already a |
| 2753 // stack overflow (on the backtrack stack) was detected in RegExp code but | 2754 // stack overflow (on the backtrack stack) was detected in RegExp code but |
| 2754 // haven't created the exception yet. Handle that in the runtime system. | 2755 // haven't created the exception yet. Handle that in the runtime system. |
| 2755 // TODO(592): Rerunning the RegExp to get the stack overflow exception. | 2756 // TODO(592): Rerunning the RegExp to get the stack overflow exception. |
| 2756 ExternalReference pending_exception_address( | 2757 ExternalReference pending_exception_address( |
| 2757 Isolate::kPendingExceptionAddress, isolate); | 2758 Isolate::kPendingExceptionAddress, isolate); |
| 2758 Operand pending_exception_operand = | 2759 Operand pending_exception_operand = |
| 2759 masm->ExternalOperand(pending_exception_address, rbx); | 2760 masm->ExternalOperand(pending_exception_address, rbx); |
| (...skipping 2074 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4834 | 4835 |
| 4835 void SubStringStub::Generate(MacroAssembler* masm) { | 4836 void SubStringStub::Generate(MacroAssembler* masm) { |
| 4836 Label runtime; | 4837 Label runtime; |
| 4837 | 4838 |
| 4838 // Stack frame on entry. | 4839 // Stack frame on entry. |
| 4839 // rsp[0] : return address | 4840 // rsp[0] : return address |
| 4840 // rsp[8] : to | 4841 // rsp[8] : to |
| 4841 // rsp[16] : from | 4842 // rsp[16] : from |
| 4842 // rsp[24] : string | 4843 // rsp[24] : string |
| 4843 | 4844 |
| 4844 const int kToOffset = 1 * kPointerSize; | 4845 enum SubStringStubArgumentIndices { |
| 4845 const int kFromOffset = kToOffset + kPointerSize; | 4846 STRING_ARGUMENT_INDEX, |
| 4846 const int kStringOffset = kFromOffset + kPointerSize; | 4847 FROM_ARGUMENT_INDEX, |
| 4847 const int kArgumentsSize = (kStringOffset + kPointerSize) - kToOffset; | 4848 TO_ARGUMENT_INDEX, |
| 4849 SUB_STRING_ARGUMENT_COUNT |
| 4850 }; |
| 4851 |
| 4852 StackArgumentsAccessor args(rsp, SUB_STRING_ARGUMENT_COUNT, |
| 4853 ARGUMENTS_DONT_CONTAIN_RECEIVER); |
| 4848 | 4854 |
| 4849 // Make sure first argument is a string. | 4855 // Make sure first argument is a string. |
| 4850 __ movq(rax, Operand(rsp, kStringOffset)); | 4856 __ movq(rax, args.GetArgumentOperand(STRING_ARGUMENT_INDEX)); |
| 4851 STATIC_ASSERT(kSmiTag == 0); | 4857 STATIC_ASSERT(kSmiTag == 0); |
| 4852 __ testl(rax, Immediate(kSmiTagMask)); | 4858 __ testl(rax, Immediate(kSmiTagMask)); |
| 4853 __ j(zero, &runtime); | 4859 __ j(zero, &runtime); |
| 4854 Condition is_string = masm->IsObjectStringType(rax, rbx, rbx); | 4860 Condition is_string = masm->IsObjectStringType(rax, rbx, rbx); |
| 4855 __ j(NegateCondition(is_string), &runtime); | 4861 __ j(NegateCondition(is_string), &runtime); |
| 4856 | 4862 |
| 4857 // rax: string | 4863 // rax: string |
| 4858 // rbx: instance type | 4864 // rbx: instance type |
| 4859 // Calculate length of sub string using the smi values. | 4865 // Calculate length of sub string using the smi values. |
| 4860 __ movq(rcx, Operand(rsp, kToOffset)); | 4866 __ movq(rcx, args.GetArgumentOperand(TO_ARGUMENT_INDEX)); |
| 4861 __ movq(rdx, Operand(rsp, kFromOffset)); | 4867 __ movq(rdx, args.GetArgumentOperand(FROM_ARGUMENT_INDEX)); |
| 4862 __ JumpUnlessBothNonNegativeSmi(rcx, rdx, &runtime); | 4868 __ JumpUnlessBothNonNegativeSmi(rcx, rdx, &runtime); |
| 4863 | 4869 |
| 4864 __ SmiSub(rcx, rcx, rdx); // Overflow doesn't happen. | 4870 __ SmiSub(rcx, rcx, rdx); // Overflow doesn't happen. |
| 4865 __ cmpq(rcx, FieldOperand(rax, String::kLengthOffset)); | 4871 __ cmpq(rcx, FieldOperand(rax, String::kLengthOffset)); |
| 4866 Label not_original_string; | 4872 Label not_original_string; |
| 4867 // Shorter than original string's length: an actual substring. | 4873 // Shorter than original string's length: an actual substring. |
| 4868 __ j(below, ¬_original_string, Label::kNear); | 4874 __ j(below, ¬_original_string, Label::kNear); |
| 4869 // Longer than original string's length or negative: unsafe arguments. | 4875 // Longer than original string's length or negative: unsafe arguments. |
| 4870 __ j(above, &runtime); | 4876 __ j(above, &runtime); |
| 4871 // Return original string. | 4877 // Return original string. |
| 4872 Counters* counters = masm->isolate()->counters(); | 4878 Counters* counters = masm->isolate()->counters(); |
| 4873 __ IncrementCounter(counters->sub_string_native(), 1); | 4879 __ IncrementCounter(counters->sub_string_native(), 1); |
| 4874 __ ret(kArgumentsSize); | 4880 __ ret(SUB_STRING_ARGUMENT_COUNT * kPointerSize); |
| 4875 __ bind(¬_original_string); | 4881 __ bind(¬_original_string); |
| 4876 | 4882 |
| 4877 Label single_char; | 4883 Label single_char; |
| 4878 __ SmiCompare(rcx, Smi::FromInt(1)); | 4884 __ SmiCompare(rcx, Smi::FromInt(1)); |
| 4879 __ j(equal, &single_char); | 4885 __ j(equal, &single_char); |
| 4880 | 4886 |
| 4881 __ SmiToInteger32(rcx, rcx); | 4887 __ SmiToInteger32(rcx, rcx); |
| 4882 | 4888 |
| 4883 // rax: string | 4889 // rax: string |
| 4884 // rbx: instance type | 4890 // rbx: instance type |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4947 __ bind(&two_byte_slice); | 4953 __ bind(&two_byte_slice); |
| 4948 __ AllocateTwoByteSlicedString(rax, rbx, r14, &runtime); | 4954 __ AllocateTwoByteSlicedString(rax, rbx, r14, &runtime); |
| 4949 __ bind(&set_slice_header); | 4955 __ bind(&set_slice_header); |
| 4950 __ Integer32ToSmi(rcx, rcx); | 4956 __ Integer32ToSmi(rcx, rcx); |
| 4951 __ movq(FieldOperand(rax, SlicedString::kLengthOffset), rcx); | 4957 __ movq(FieldOperand(rax, SlicedString::kLengthOffset), rcx); |
| 4952 __ movq(FieldOperand(rax, SlicedString::kHashFieldOffset), | 4958 __ movq(FieldOperand(rax, SlicedString::kHashFieldOffset), |
| 4953 Immediate(String::kEmptyHashField)); | 4959 Immediate(String::kEmptyHashField)); |
| 4954 __ movq(FieldOperand(rax, SlicedString::kParentOffset), rdi); | 4960 __ movq(FieldOperand(rax, SlicedString::kParentOffset), rdi); |
| 4955 __ movq(FieldOperand(rax, SlicedString::kOffsetOffset), rdx); | 4961 __ movq(FieldOperand(rax, SlicedString::kOffsetOffset), rdx); |
| 4956 __ IncrementCounter(counters->sub_string_native(), 1); | 4962 __ IncrementCounter(counters->sub_string_native(), 1); |
| 4957 __ ret(kArgumentsSize); | 4963 __ ret(3 * kPointerSize); |
| 4958 | 4964 |
| 4959 __ bind(©_routine); | 4965 __ bind(©_routine); |
| 4960 } | 4966 } |
| 4961 | 4967 |
| 4962 // rdi: underlying subject string | 4968 // rdi: underlying subject string |
| 4963 // rbx: instance type of underlying subject string | 4969 // rbx: instance type of underlying subject string |
| 4964 // rdx: adjusted start index (smi) | 4970 // rdx: adjusted start index (smi) |
| 4965 // rcx: length | 4971 // rcx: length |
| 4966 // The subject string can only be external or sequential string of either | 4972 // The subject string can only be external or sequential string of either |
| 4967 // encoding at this point. | 4973 // encoding at this point. |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5001 __ lea(rdi, FieldOperand(rax, SeqOneByteString::kHeaderSize)); | 5007 __ lea(rdi, FieldOperand(rax, SeqOneByteString::kHeaderSize)); |
| 5002 | 5008 |
| 5003 // rax: result string | 5009 // rax: result string |
| 5004 // rcx: result length | 5010 // rcx: result length |
| 5005 // rdi: first character of result | 5011 // rdi: first character of result |
| 5006 // rsi: character of sub string start | 5012 // rsi: character of sub string start |
| 5007 // r14: original value of rsi | 5013 // r14: original value of rsi |
| 5008 StringHelper::GenerateCopyCharactersREP(masm, rdi, rsi, rcx, true); | 5014 StringHelper::GenerateCopyCharactersREP(masm, rdi, rsi, rcx, true); |
| 5009 __ movq(rsi, r14); // Restore rsi. | 5015 __ movq(rsi, r14); // Restore rsi. |
| 5010 __ IncrementCounter(counters->sub_string_native(), 1); | 5016 __ IncrementCounter(counters->sub_string_native(), 1); |
| 5011 __ ret(kArgumentsSize); | 5017 __ ret(SUB_STRING_ARGUMENT_COUNT * kPointerSize); |
| 5012 | 5018 |
| 5013 __ bind(&two_byte_sequential); | 5019 __ bind(&two_byte_sequential); |
| 5014 // Allocate the result. | 5020 // Allocate the result. |
| 5015 __ AllocateTwoByteString(rax, rcx, r11, r14, r15, &runtime); | 5021 __ AllocateTwoByteString(rax, rcx, r11, r14, r15, &runtime); |
| 5016 | 5022 |
| 5017 // rax: result string | 5023 // rax: result string |
| 5018 // rcx: result string length | 5024 // rcx: result string length |
| 5019 __ movq(r14, rsi); // esi used by following code. | 5025 __ movq(r14, rsi); // esi used by following code. |
| 5020 { // Locate character of sub string start. | 5026 { // Locate character of sub string start. |
| 5021 SmiIndex smi_as_index = masm->SmiToIndex(rdx, rdx, times_2); | 5027 SmiIndex smi_as_index = masm->SmiToIndex(rdx, rdx, times_2); |
| 5022 __ lea(rsi, Operand(rdi, smi_as_index.reg, smi_as_index.scale, | 5028 __ lea(rsi, Operand(rdi, smi_as_index.reg, smi_as_index.scale, |
| 5023 SeqOneByteString::kHeaderSize - kHeapObjectTag)); | 5029 SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
| 5024 } | 5030 } |
| 5025 // Locate first character of result. | 5031 // Locate first character of result. |
| 5026 __ lea(rdi, FieldOperand(rax, SeqTwoByteString::kHeaderSize)); | 5032 __ lea(rdi, FieldOperand(rax, SeqTwoByteString::kHeaderSize)); |
| 5027 | 5033 |
| 5028 // rax: result string | 5034 // rax: result string |
| 5029 // rcx: result length | 5035 // rcx: result length |
| 5030 // rdi: first character of result | 5036 // rdi: first character of result |
| 5031 // rsi: character of sub string start | 5037 // rsi: character of sub string start |
| 5032 // r14: original value of rsi | 5038 // r14: original value of rsi |
| 5033 StringHelper::GenerateCopyCharactersREP(masm, rdi, rsi, rcx, false); | 5039 StringHelper::GenerateCopyCharactersREP(masm, rdi, rsi, rcx, false); |
| 5034 __ movq(rsi, r14); // Restore esi. | 5040 __ movq(rsi, r14); // Restore esi. |
| 5035 __ IncrementCounter(counters->sub_string_native(), 1); | 5041 __ IncrementCounter(counters->sub_string_native(), 1); |
| 5036 __ ret(kArgumentsSize); | 5042 __ ret(SUB_STRING_ARGUMENT_COUNT * kPointerSize); |
| 5037 | 5043 |
| 5038 // Just jump to runtime to create the sub string. | 5044 // Just jump to runtime to create the sub string. |
| 5039 __ bind(&runtime); | 5045 __ bind(&runtime); |
| 5040 __ TailCallRuntime(Runtime::kSubString, 3, 1); | 5046 __ TailCallRuntime(Runtime::kSubString, 3, 1); |
| 5041 | 5047 |
| 5042 __ bind(&single_char); | 5048 __ bind(&single_char); |
| 5043 // rax: string | 5049 // rax: string |
| 5044 // rbx: instance type | 5050 // rbx: instance type |
| 5045 // rcx: sub string length (smi) | 5051 // rcx: sub string length (smi) |
| 5046 // rdx: from index (smi) | 5052 // rdx: from index (smi) |
| 5047 StringCharAtGenerator generator( | 5053 StringCharAtGenerator generator( |
| 5048 rax, rdx, rcx, rax, &runtime, &runtime, &runtime, STRING_INDEX_IS_NUMBER); | 5054 rax, rdx, rcx, rax, &runtime, &runtime, &runtime, STRING_INDEX_IS_NUMBER); |
| 5049 generator.GenerateFast(masm); | 5055 generator.GenerateFast(masm); |
| 5050 __ ret(kArgumentsSize); | 5056 __ ret(SUB_STRING_ARGUMENT_COUNT * kPointerSize); |
| 5051 generator.SkipSlow(masm, &runtime); | 5057 generator.SkipSlow(masm, &runtime); |
| 5052 } | 5058 } |
| 5053 | 5059 |
| 5054 | 5060 |
| 5055 void StringCompareStub::GenerateFlatAsciiStringEquals(MacroAssembler* masm, | 5061 void StringCompareStub::GenerateFlatAsciiStringEquals(MacroAssembler* masm, |
| 5056 Register left, | 5062 Register left, |
| 5057 Register right, | 5063 Register right, |
| 5058 Register scratch1, | 5064 Register scratch1, |
| 5059 Register scratch2) { | 5065 Register scratch2) { |
| 5060 Register length = scratch1; | 5066 Register length = scratch1; |
| (...skipping 1485 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6546 __ bind(&fast_elements_case); | 6552 __ bind(&fast_elements_case); |
| 6547 GenerateCase(masm, FAST_ELEMENTS); | 6553 GenerateCase(masm, FAST_ELEMENTS); |
| 6548 } | 6554 } |
| 6549 | 6555 |
| 6550 | 6556 |
| 6551 #undef __ | 6557 #undef __ |
| 6552 | 6558 |
| 6553 } } // namespace v8::internal | 6559 } } // namespace v8::internal |
| 6554 | 6560 |
| 6555 #endif // V8_TARGET_ARCH_X64 | 6561 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |