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 1961 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1972 __ bind(&miss); | 1972 __ bind(&miss); |
1973 | 1973 |
1974 StubCompiler::TailCallBuiltin( | 1974 StubCompiler::TailCallBuiltin( |
1975 masm, BaseLoadStoreStubCompiler::MissBuiltin(kind())); | 1975 masm, BaseLoadStoreStubCompiler::MissBuiltin(kind())); |
1976 } | 1976 } |
1977 | 1977 |
1978 | 1978 |
1979 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { | 1979 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { |
1980 // The key is in rdx and the parameter count is in rax. | 1980 // The key is in rdx and the parameter count is in rax. |
1981 | 1981 |
1982 // The displacement is used for skipping the frame pointer on the | |
1983 // stack. It is the offset of the last parameter (if any) relative | |
1984 // to the frame pointer. | |
1985 static const int kDisplacement = 1 * kPointerSize; | |
1986 | |
1987 // Check that the key is a smi. | 1982 // Check that the key is a smi. |
1988 Label slow; | 1983 Label slow; |
1989 __ JumpIfNotSmi(rdx, &slow); | 1984 __ JumpIfNotSmi(rdx, &slow); |
1990 | 1985 |
1991 // Check if the calling frame is an arguments adaptor frame. We look at the | 1986 // Check if the calling frame is an arguments adaptor frame. We look at the |
1992 // context offset, and if the frame is not a regular one, then we find a | 1987 // context offset, and if the frame is not a regular one, then we find a |
1993 // Smi instead of the context. We can't use SmiCompare here, because that | 1988 // Smi instead of the context. We can't use SmiCompare here, because that |
1994 // only works for comparing two smis. | 1989 // only works for comparing two smis. |
1995 Label adaptor; | 1990 Label adaptor; |
1996 __ movq(rbx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); | 1991 __ movq(rbx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); |
1997 __ Cmp(Operand(rbx, StandardFrameConstants::kContextOffset), | 1992 __ Cmp(Operand(rbx, StandardFrameConstants::kContextOffset), |
1998 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); | 1993 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); |
1999 __ j(equal, &adaptor); | 1994 __ j(equal, &adaptor); |
2000 | 1995 |
2001 // Check index against formal parameters count limit passed in | 1996 // Check index against formal parameters count limit passed in |
2002 // through register rax. Use unsigned comparison to get negative | 1997 // through register rax. Use unsigned comparison to get negative |
2003 // check for free. | 1998 // check for free. |
2004 __ cmpq(rdx, rax); | 1999 __ cmpq(rdx, rax); |
2005 __ j(above_equal, &slow); | 2000 __ j(above_equal, &slow); |
2006 | 2001 |
2007 // Read the argument from the stack and return it. | 2002 // Read the argument from the stack and return it. |
2008 SmiIndex index = masm->SmiToIndex(rax, rax, kPointerSizeLog2); | 2003 __ SmiSub(rax, rax, rdx); |
2009 __ lea(rbx, Operand(rbp, index.reg, index.scale, 0)); | 2004 __ SmiToInteger32(rax, rax); |
2010 index = masm->SmiToNegativeIndex(rdx, rdx, kPointerSizeLog2); | 2005 StackArgumentsAccessor args(rbp, rax, ARGUMENTS_DONT_CONTAIN_RECEIVER); |
2011 __ movq(rax, Operand(rbx, index.reg, index.scale, kDisplacement)); | 2006 __ movq(rax, args.GetArgumentOperand(0)); |
2012 __ Ret(); | 2007 __ Ret(); |
2013 | 2008 |
2014 // Arguments adaptor case: Check index against actual arguments | 2009 // Arguments adaptor case: Check index against actual arguments |
2015 // limit found in the arguments adaptor frame. Use unsigned | 2010 // limit found in the arguments adaptor frame. Use unsigned |
2016 // comparison to get negative check for free. | 2011 // comparison to get negative check for free. |
2017 __ bind(&adaptor); | 2012 __ bind(&adaptor); |
2018 __ movq(rcx, Operand(rbx, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 2013 __ movq(rcx, Operand(rbx, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
2019 __ cmpq(rdx, rcx); | 2014 __ cmpq(rdx, rcx); |
2020 __ j(above_equal, &slow); | 2015 __ j(above_equal, &slow); |
2021 | 2016 |
2022 // Read the argument from the stack and return it. | 2017 // Read the argument from the stack and return it. |
2023 index = masm->SmiToIndex(rax, rcx, kPointerSizeLog2); | 2018 __ SmiSub(rcx, rcx, rdx); |
2024 __ lea(rbx, Operand(rbx, index.reg, index.scale, 0)); | 2019 __ SmiToInteger32(rcx, rcx); |
2025 index = masm->SmiToNegativeIndex(rdx, rdx, kPointerSizeLog2); | 2020 StackArgumentsAccessor adaptor_args(rbx, rcx, |
2026 __ movq(rax, Operand(rbx, index.reg, index.scale, kDisplacement)); | 2021 ARGUMENTS_DONT_CONTAIN_RECEIVER); |
2022 __ movq(rax, adaptor_args.GetArgumentOperand(0)); | |
2027 __ Ret(); | 2023 __ Ret(); |
2028 | 2024 |
2029 // Slow-case: Handle non-smi or out-of-bounds access to arguments | 2025 // Slow-case: Handle non-smi or out-of-bounds access to arguments |
2030 // by calling the runtime system. | 2026 // by calling the runtime system. |
2031 __ bind(&slow); | 2027 __ bind(&slow); |
2032 __ PopReturnAddressTo(rbx); | 2028 __ PopReturnAddressTo(rbx); |
2033 __ push(rdx); | 2029 __ push(rdx); |
2034 __ PushReturnAddressFrom(rbx); | 2030 __ PushReturnAddressFrom(rbx); |
2035 __ TailCallRuntime(Runtime::kGetArgumentsProperty, 1, 1); | 2031 __ TailCallRuntime(Runtime::kGetArgumentsProperty, 1, 1); |
2036 } | 2032 } |
(...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2390 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); | 2386 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); |
2391 #else // V8_INTERPRETED_REGEXP | 2387 #else // V8_INTERPRETED_REGEXP |
2392 | 2388 |
2393 // Stack frame on entry. | 2389 // Stack frame on entry. |
2394 // rsp[0] : return address | 2390 // rsp[0] : return address |
2395 // rsp[8] : last_match_info (expected JSArray) | 2391 // rsp[8] : last_match_info (expected JSArray) |
2396 // rsp[16] : previous index | 2392 // rsp[16] : previous index |
2397 // rsp[24] : subject string | 2393 // rsp[24] : subject string |
2398 // rsp[32] : JSRegExp object | 2394 // rsp[32] : JSRegExp object |
2399 | 2395 |
2400 static const int kLastMatchInfoOffset = 1 * kPointerSize; | 2396 StackArgumentsAccessor args(rsp, 4, ARGUMENTS_DONT_CONTAIN_RECEIVER); |
danno
2013/09/18 12:08:42
Since you are going through all the trouble to cle
haitao.feng
2013/09/22 08:16:00
Done.
| |
2401 static const int kPreviousIndexOffset = 2 * kPointerSize; | 2397 Operand StackOperandForJSRegExpObject = args.GetArgumentOperand(0); |
danno
2013/09/18 12:08:42
nit: these variable names should start with a lowe
haitao.feng
2013/09/22 08:16:00
Removed these variables.
On 2013/09/18 12:08:42, d
| |
2402 static const int kSubjectOffset = 3 * kPointerSize; | 2398 Operand StackOperandForSubjectString = args.GetArgumentOperand(1); |
2403 static const int kJSRegExpOffset = 4 * kPointerSize; | 2399 Operand StackOperandForPreviousIndex = args.GetArgumentOperand(2); |
2400 Operand StackOperandForLastMatchInfo = args.GetArgumentOperand(3); | |
2404 | 2401 |
2405 Label runtime; | 2402 Label runtime; |
2406 // Ensure that a RegExp stack is allocated. | 2403 // Ensure that a RegExp stack is allocated. |
2407 Isolate* isolate = masm->isolate(); | 2404 Isolate* isolate = masm->isolate(); |
2408 ExternalReference address_of_regexp_stack_memory_address = | 2405 ExternalReference address_of_regexp_stack_memory_address = |
2409 ExternalReference::address_of_regexp_stack_memory_address(isolate); | 2406 ExternalReference::address_of_regexp_stack_memory_address(isolate); |
2410 ExternalReference address_of_regexp_stack_memory_size = | 2407 ExternalReference address_of_regexp_stack_memory_size = |
2411 ExternalReference::address_of_regexp_stack_memory_size(isolate); | 2408 ExternalReference::address_of_regexp_stack_memory_size(isolate); |
2412 __ Load(kScratchRegister, address_of_regexp_stack_memory_size); | 2409 __ Load(kScratchRegister, address_of_regexp_stack_memory_size); |
2413 __ testq(kScratchRegister, kScratchRegister); | 2410 __ testq(kScratchRegister, kScratchRegister); |
2414 __ j(zero, &runtime); | 2411 __ j(zero, &runtime); |
2415 | 2412 |
2416 // Check that the first argument is a JSRegExp object. | 2413 // Check that the first argument is a JSRegExp object. |
2417 __ movq(rax, Operand(rsp, kJSRegExpOffset)); | 2414 __ movq(rax, StackOperandForJSRegExpObject); |
2418 __ JumpIfSmi(rax, &runtime); | 2415 __ JumpIfSmi(rax, &runtime); |
2419 __ CmpObjectType(rax, JS_REGEXP_TYPE, kScratchRegister); | 2416 __ CmpObjectType(rax, JS_REGEXP_TYPE, kScratchRegister); |
2420 __ j(not_equal, &runtime); | 2417 __ j(not_equal, &runtime); |
2421 | 2418 |
2422 // Check that the RegExp has been compiled (data contains a fixed array). | 2419 // Check that the RegExp has been compiled (data contains a fixed array). |
2423 __ movq(rax, FieldOperand(rax, JSRegExp::kDataOffset)); | 2420 __ movq(rax, FieldOperand(rax, JSRegExp::kDataOffset)); |
2424 if (FLAG_debug_code) { | 2421 if (FLAG_debug_code) { |
2425 Condition is_smi = masm->CheckSmi(rax); | 2422 Condition is_smi = masm->CheckSmi(rax); |
2426 __ Check(NegateCondition(is_smi), | 2423 __ Check(NegateCondition(is_smi), |
2427 kUnexpectedTypeForRegExpDataFixedArrayExpected); | 2424 kUnexpectedTypeForRegExpDataFixedArrayExpected); |
(...skipping 12 matching lines...) Expand all Loading... | |
2440 __ SmiToInteger32(rdx, | 2437 __ SmiToInteger32(rdx, |
2441 FieldOperand(rax, JSRegExp::kIrregexpCaptureCountOffset)); | 2438 FieldOperand(rax, JSRegExp::kIrregexpCaptureCountOffset)); |
2442 // Check (number_of_captures + 1) * 2 <= offsets vector size | 2439 // Check (number_of_captures + 1) * 2 <= offsets vector size |
2443 // Or number_of_captures <= offsets vector size / 2 - 1 | 2440 // Or number_of_captures <= offsets vector size / 2 - 1 |
2444 STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2); | 2441 STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2); |
2445 __ cmpl(rdx, Immediate(Isolate::kJSRegexpStaticOffsetsVectorSize / 2 - 1)); | 2442 __ cmpl(rdx, Immediate(Isolate::kJSRegexpStaticOffsetsVectorSize / 2 - 1)); |
2446 __ j(above, &runtime); | 2443 __ j(above, &runtime); |
2447 | 2444 |
2448 // Reset offset for possibly sliced string. | 2445 // Reset offset for possibly sliced string. |
2449 __ Set(r14, 0); | 2446 __ Set(r14, 0); |
2450 __ movq(rdi, Operand(rsp, kSubjectOffset)); | 2447 __ movq(rdi, StackOperandForSubjectString); |
2451 __ JumpIfSmi(rdi, &runtime); | 2448 __ JumpIfSmi(rdi, &runtime); |
2452 __ movq(r15, rdi); // Make a copy of the original subject string. | 2449 __ movq(r15, rdi); // Make a copy of the original subject string. |
2453 __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); | 2450 __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); |
2454 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); | 2451 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); |
2455 // rax: RegExp data (FixedArray) | 2452 // rax: RegExp data (FixedArray) |
2456 // rdi: subject string | 2453 // rdi: subject string |
2457 // r15: subject string | 2454 // r15: subject string |
2458 // Handle subject string according to its encoding and representation: | 2455 // Handle subject string according to its encoding and representation: |
2459 // (1) Sequential two byte? If yes, go to (9). | 2456 // (1) Sequential two byte? If yes, go to (9). |
2460 // (2) Sequential one byte? If yes, go to (6). | 2457 // (2) Sequential one byte? If yes, go to (6). |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2542 | 2539 |
2543 // rdi: sequential subject string (or look-alike, external string) | 2540 // rdi: sequential subject string (or look-alike, external string) |
2544 // r15: original subject string | 2541 // r15: original subject string |
2545 // rcx: encoding of subject string (1 if ASCII, 0 if two_byte); | 2542 // rcx: encoding of subject string (1 if ASCII, 0 if two_byte); |
2546 // r11: code | 2543 // r11: code |
2547 // Load used arguments before starting to push arguments for call to native | 2544 // Load used arguments before starting to push arguments for call to native |
2548 // RegExp code to avoid handling changing stack height. | 2545 // RegExp code to avoid handling changing stack height. |
2549 // We have to use r15 instead of rdi to load the length because rdi might | 2546 // We have to use r15 instead of rdi to load the length because rdi might |
2550 // have been only made to look like a sequential string when it actually | 2547 // have been only made to look like a sequential string when it actually |
2551 // is an external string. | 2548 // is an external string. |
2552 __ movq(rbx, Operand(rsp, kPreviousIndexOffset)); | 2549 __ movq(rbx, StackOperandForPreviousIndex); |
2553 __ JumpIfNotSmi(rbx, &runtime); | 2550 __ JumpIfNotSmi(rbx, &runtime); |
2554 __ SmiCompare(rbx, FieldOperand(r15, String::kLengthOffset)); | 2551 __ SmiCompare(rbx, FieldOperand(r15, String::kLengthOffset)); |
2555 __ j(above_equal, &runtime); | 2552 __ j(above_equal, &runtime); |
2556 __ SmiToInteger64(rbx, rbx); | 2553 __ SmiToInteger64(rbx, rbx); |
2557 | 2554 |
2558 // rdi: subject string | 2555 // rdi: subject string |
2559 // rbx: previous index | 2556 // rbx: previous index |
2560 // rcx: encoding of subject string (1 if ASCII 0 if two_byte); | 2557 // rcx: encoding of subject string (1 if ASCII 0 if two_byte); |
2561 // r11: code | 2558 // r11: code |
2562 // All checks done. Now push arguments for native regexp code. | 2559 // All checks done. Now push arguments for native regexp code. |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2666 // If none of the above, it can only be retry. | 2663 // If none of the above, it can only be retry. |
2667 // Handle that in the runtime system. | 2664 // Handle that in the runtime system. |
2668 __ j(not_equal, &runtime); | 2665 __ j(not_equal, &runtime); |
2669 | 2666 |
2670 // For failure return null. | 2667 // For failure return null. |
2671 __ LoadRoot(rax, Heap::kNullValueRootIndex); | 2668 __ LoadRoot(rax, Heap::kNullValueRootIndex); |
2672 __ ret(4 * kPointerSize); | 2669 __ ret(4 * kPointerSize); |
2673 | 2670 |
2674 // Load RegExp data. | 2671 // Load RegExp data. |
2675 __ bind(&success); | 2672 __ bind(&success); |
2676 __ movq(rax, Operand(rsp, kJSRegExpOffset)); | 2673 __ movq(rax, StackOperandForJSRegExpObject); |
2677 __ movq(rcx, FieldOperand(rax, JSRegExp::kDataOffset)); | 2674 __ movq(rcx, FieldOperand(rax, JSRegExp::kDataOffset)); |
2678 __ SmiToInteger32(rax, | 2675 __ SmiToInteger32(rax, |
2679 FieldOperand(rcx, JSRegExp::kIrregexpCaptureCountOffset)); | 2676 FieldOperand(rcx, JSRegExp::kIrregexpCaptureCountOffset)); |
2680 // Calculate number of capture registers (number_of_captures + 1) * 2. | 2677 // Calculate number of capture registers (number_of_captures + 1) * 2. |
2681 __ leal(rdx, Operand(rax, rax, times_1, 2)); | 2678 __ leal(rdx, Operand(rax, rax, times_1, 2)); |
2682 | 2679 |
2683 // rdx: Number of capture registers | 2680 // rdx: Number of capture registers |
2684 // Check that the fourth object is a JSArray object. | 2681 // Check that the fourth object is a JSArray object. |
2685 __ movq(r15, Operand(rsp, kLastMatchInfoOffset)); | 2682 __ movq(r15, StackOperandForLastMatchInfo); |
2686 __ JumpIfSmi(r15, &runtime); | 2683 __ JumpIfSmi(r15, &runtime); |
2687 __ CmpObjectType(r15, JS_ARRAY_TYPE, kScratchRegister); | 2684 __ CmpObjectType(r15, JS_ARRAY_TYPE, kScratchRegister); |
2688 __ j(not_equal, &runtime); | 2685 __ j(not_equal, &runtime); |
2689 // Check that the JSArray is in fast case. | 2686 // Check that the JSArray is in fast case. |
2690 __ movq(rbx, FieldOperand(r15, JSArray::kElementsOffset)); | 2687 __ movq(rbx, FieldOperand(r15, JSArray::kElementsOffset)); |
2691 __ movq(rax, FieldOperand(rbx, HeapObject::kMapOffset)); | 2688 __ movq(rax, FieldOperand(rbx, HeapObject::kMapOffset)); |
2692 __ CompareRoot(rax, Heap::kFixedArrayMapRootIndex); | 2689 __ CompareRoot(rax, Heap::kFixedArrayMapRootIndex); |
2693 __ j(not_equal, &runtime); | 2690 __ j(not_equal, &runtime); |
2694 // Check that the last match info has space for the capture registers and the | 2691 // Check that the last match info has space for the capture registers and the |
2695 // additional information. Ensure no overflow in add. | 2692 // additional information. Ensure no overflow in add. |
2696 STATIC_ASSERT(FixedArray::kMaxLength < kMaxInt - FixedArray::kLengthOffset); | 2693 STATIC_ASSERT(FixedArray::kMaxLength < kMaxInt - FixedArray::kLengthOffset); |
2697 __ SmiToInteger32(rax, FieldOperand(rbx, FixedArray::kLengthOffset)); | 2694 __ SmiToInteger32(rax, FieldOperand(rbx, FixedArray::kLengthOffset)); |
2698 __ subl(rax, Immediate(RegExpImpl::kLastMatchOverhead)); | 2695 __ subl(rax, Immediate(RegExpImpl::kLastMatchOverhead)); |
2699 __ cmpl(rdx, rax); | 2696 __ cmpl(rdx, rax); |
2700 __ j(greater, &runtime); | 2697 __ j(greater, &runtime); |
2701 | 2698 |
2702 // rbx: last_match_info backing store (FixedArray) | 2699 // rbx: last_match_info backing store (FixedArray) |
2703 // rdx: number of capture registers | 2700 // rdx: number of capture registers |
2704 // Store the capture count. | 2701 // Store the capture count. |
2705 __ Integer32ToSmi(kScratchRegister, rdx); | 2702 __ Integer32ToSmi(kScratchRegister, rdx); |
2706 __ movq(FieldOperand(rbx, RegExpImpl::kLastCaptureCountOffset), | 2703 __ movq(FieldOperand(rbx, RegExpImpl::kLastCaptureCountOffset), |
2707 kScratchRegister); | 2704 kScratchRegister); |
2708 // Store last subject and last input. | 2705 // Store last subject and last input. |
2709 __ movq(rax, Operand(rsp, kSubjectOffset)); | 2706 __ movq(rax, StackOperandForSubjectString); |
2710 __ movq(FieldOperand(rbx, RegExpImpl::kLastSubjectOffset), rax); | 2707 __ movq(FieldOperand(rbx, RegExpImpl::kLastSubjectOffset), rax); |
2711 __ movq(rcx, rax); | 2708 __ movq(rcx, rax); |
2712 __ RecordWriteField(rbx, | 2709 __ RecordWriteField(rbx, |
2713 RegExpImpl::kLastSubjectOffset, | 2710 RegExpImpl::kLastSubjectOffset, |
2714 rax, | 2711 rax, |
2715 rdi, | 2712 rdi, |
2716 kDontSaveFPRegs); | 2713 kDontSaveFPRegs); |
2717 __ movq(rax, rcx); | 2714 __ movq(rax, rcx); |
2718 __ movq(FieldOperand(rbx, RegExpImpl::kLastInputOffset), rax); | 2715 __ movq(FieldOperand(rbx, RegExpImpl::kLastInputOffset), rax); |
2719 __ RecordWriteField(rbx, | 2716 __ RecordWriteField(rbx, |
(...skipping 2224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4944 | 4941 |
4945 void SubStringStub::Generate(MacroAssembler* masm) { | 4942 void SubStringStub::Generate(MacroAssembler* masm) { |
4946 Label runtime; | 4943 Label runtime; |
4947 | 4944 |
4948 // Stack frame on entry. | 4945 // Stack frame on entry. |
4949 // rsp[0] : return address | 4946 // rsp[0] : return address |
4950 // rsp[8] : to | 4947 // rsp[8] : to |
4951 // rsp[16] : from | 4948 // rsp[16] : from |
4952 // rsp[24] : string | 4949 // rsp[24] : string |
4953 | 4950 |
4954 const int kToOffset = 1 * kPointerSize; | 4951 StackArgumentsAccessor args(rsp, 3, ARGUMENTS_DONT_CONTAIN_RECEIVER); |
danno
2013/09/18 12:08:42
See comment above about using constants.
haitao.feng
2013/09/22 08:16:00
Done.
| |
4955 const int kFromOffset = kToOffset + kPointerSize; | |
4956 const int kStringOffset = kFromOffset + kPointerSize; | |
4957 const int kArgumentsSize = (kStringOffset + kPointerSize) - kToOffset; | |
4958 | 4952 |
4959 // Make sure first argument is a string. | 4953 // Make sure first argument is a string. |
4960 __ movq(rax, Operand(rsp, kStringOffset)); | 4954 __ movq(rax, args.GetArgumentOperand(0)); |
4961 STATIC_ASSERT(kSmiTag == 0); | 4955 STATIC_ASSERT(kSmiTag == 0); |
4962 __ testl(rax, Immediate(kSmiTagMask)); | 4956 __ testl(rax, Immediate(kSmiTagMask)); |
4963 __ j(zero, &runtime); | 4957 __ j(zero, &runtime); |
4964 Condition is_string = masm->IsObjectStringType(rax, rbx, rbx); | 4958 Condition is_string = masm->IsObjectStringType(rax, rbx, rbx); |
4965 __ j(NegateCondition(is_string), &runtime); | 4959 __ j(NegateCondition(is_string), &runtime); |
4966 | 4960 |
4967 // rax: string | 4961 // rax: string |
4968 // rbx: instance type | 4962 // rbx: instance type |
4969 // Calculate length of sub string using the smi values. | 4963 // Calculate length of sub string using the smi values. |
4970 __ movq(rcx, Operand(rsp, kToOffset)); | 4964 __ movq(rcx, args.GetArgumentOperand(2)); |
4971 __ movq(rdx, Operand(rsp, kFromOffset)); | 4965 __ movq(rdx, args.GetArgumentOperand(1)); |
4972 __ JumpUnlessBothNonNegativeSmi(rcx, rdx, &runtime); | 4966 __ JumpUnlessBothNonNegativeSmi(rcx, rdx, &runtime); |
4973 | 4967 |
4974 __ SmiSub(rcx, rcx, rdx); // Overflow doesn't happen. | 4968 __ SmiSub(rcx, rcx, rdx); // Overflow doesn't happen. |
4975 __ cmpq(rcx, FieldOperand(rax, String::kLengthOffset)); | 4969 __ cmpq(rcx, FieldOperand(rax, String::kLengthOffset)); |
4976 Label not_original_string; | 4970 Label not_original_string; |
4977 // Shorter than original string's length: an actual substring. | 4971 // Shorter than original string's length: an actual substring. |
4978 __ j(below, ¬_original_string, Label::kNear); | 4972 __ j(below, ¬_original_string, Label::kNear); |
4979 // Longer than original string's length or negative: unsafe arguments. | 4973 // Longer than original string's length or negative: unsafe arguments. |
4980 __ j(above, &runtime); | 4974 __ j(above, &runtime); |
4981 // Return original string. | 4975 // Return original string. |
4982 Counters* counters = masm->isolate()->counters(); | 4976 Counters* counters = masm->isolate()->counters(); |
4983 __ IncrementCounter(counters->sub_string_native(), 1); | 4977 __ IncrementCounter(counters->sub_string_native(), 1); |
4984 __ ret(kArgumentsSize); | 4978 __ ret(3 * kPointerSize); |
danno
2013/09/18 12:08:42
You can use the argument count instead of a magic
haitao.feng
2013/09/22 08:16:00
Done.
| |
4985 __ bind(¬_original_string); | 4979 __ bind(¬_original_string); |
4986 | 4980 |
4987 Label single_char; | 4981 Label single_char; |
4988 __ SmiCompare(rcx, Smi::FromInt(1)); | 4982 __ SmiCompare(rcx, Smi::FromInt(1)); |
4989 __ j(equal, &single_char); | 4983 __ j(equal, &single_char); |
4990 | 4984 |
4991 __ SmiToInteger32(rcx, rcx); | 4985 __ SmiToInteger32(rcx, rcx); |
4992 | 4986 |
4993 // rax: string | 4987 // rax: string |
4994 // rbx: instance type | 4988 // rbx: instance type |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5057 __ bind(&two_byte_slice); | 5051 __ bind(&two_byte_slice); |
5058 __ AllocateTwoByteSlicedString(rax, rbx, r14, &runtime); | 5052 __ AllocateTwoByteSlicedString(rax, rbx, r14, &runtime); |
5059 __ bind(&set_slice_header); | 5053 __ bind(&set_slice_header); |
5060 __ Integer32ToSmi(rcx, rcx); | 5054 __ Integer32ToSmi(rcx, rcx); |
5061 __ movq(FieldOperand(rax, SlicedString::kLengthOffset), rcx); | 5055 __ movq(FieldOperand(rax, SlicedString::kLengthOffset), rcx); |
5062 __ movq(FieldOperand(rax, SlicedString::kHashFieldOffset), | 5056 __ movq(FieldOperand(rax, SlicedString::kHashFieldOffset), |
5063 Immediate(String::kEmptyHashField)); | 5057 Immediate(String::kEmptyHashField)); |
5064 __ movq(FieldOperand(rax, SlicedString::kParentOffset), rdi); | 5058 __ movq(FieldOperand(rax, SlicedString::kParentOffset), rdi); |
5065 __ movq(FieldOperand(rax, SlicedString::kOffsetOffset), rdx); | 5059 __ movq(FieldOperand(rax, SlicedString::kOffsetOffset), rdx); |
5066 __ IncrementCounter(counters->sub_string_native(), 1); | 5060 __ IncrementCounter(counters->sub_string_native(), 1); |
5067 __ ret(kArgumentsSize); | 5061 __ ret(3 * kPointerSize); |
5068 | 5062 |
5069 __ bind(©_routine); | 5063 __ bind(©_routine); |
5070 } | 5064 } |
5071 | 5065 |
5072 // rdi: underlying subject string | 5066 // rdi: underlying subject string |
5073 // rbx: instance type of underlying subject string | 5067 // rbx: instance type of underlying subject string |
5074 // rdx: adjusted start index (smi) | 5068 // rdx: adjusted start index (smi) |
5075 // rcx: length | 5069 // rcx: length |
5076 // The subject string can only be external or sequential string of either | 5070 // The subject string can only be external or sequential string of either |
5077 // encoding at this point. | 5071 // encoding at this point. |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5111 __ lea(rdi, FieldOperand(rax, SeqOneByteString::kHeaderSize)); | 5105 __ lea(rdi, FieldOperand(rax, SeqOneByteString::kHeaderSize)); |
5112 | 5106 |
5113 // rax: result string | 5107 // rax: result string |
5114 // rcx: result length | 5108 // rcx: result length |
5115 // rdi: first character of result | 5109 // rdi: first character of result |
5116 // rsi: character of sub string start | 5110 // rsi: character of sub string start |
5117 // r14: original value of rsi | 5111 // r14: original value of rsi |
5118 StringHelper::GenerateCopyCharactersREP(masm, rdi, rsi, rcx, true); | 5112 StringHelper::GenerateCopyCharactersREP(masm, rdi, rsi, rcx, true); |
5119 __ movq(rsi, r14); // Restore rsi. | 5113 __ movq(rsi, r14); // Restore rsi. |
5120 __ IncrementCounter(counters->sub_string_native(), 1); | 5114 __ IncrementCounter(counters->sub_string_native(), 1); |
5121 __ ret(kArgumentsSize); | 5115 __ ret(3 * kPointerSize); |
5122 | 5116 |
5123 __ bind(&two_byte_sequential); | 5117 __ bind(&two_byte_sequential); |
5124 // Allocate the result. | 5118 // Allocate the result. |
5125 __ AllocateTwoByteString(rax, rcx, r11, r14, r15, &runtime); | 5119 __ AllocateTwoByteString(rax, rcx, r11, r14, r15, &runtime); |
5126 | 5120 |
5127 // rax: result string | 5121 // rax: result string |
5128 // rcx: result string length | 5122 // rcx: result string length |
5129 __ movq(r14, rsi); // esi used by following code. | 5123 __ movq(r14, rsi); // esi used by following code. |
5130 { // Locate character of sub string start. | 5124 { // Locate character of sub string start. |
5131 SmiIndex smi_as_index = masm->SmiToIndex(rdx, rdx, times_2); | 5125 SmiIndex smi_as_index = masm->SmiToIndex(rdx, rdx, times_2); |
5132 __ lea(rsi, Operand(rdi, smi_as_index.reg, smi_as_index.scale, | 5126 __ lea(rsi, Operand(rdi, smi_as_index.reg, smi_as_index.scale, |
5133 SeqOneByteString::kHeaderSize - kHeapObjectTag)); | 5127 SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
5134 } | 5128 } |
5135 // Locate first character of result. | 5129 // Locate first character of result. |
5136 __ lea(rdi, FieldOperand(rax, SeqTwoByteString::kHeaderSize)); | 5130 __ lea(rdi, FieldOperand(rax, SeqTwoByteString::kHeaderSize)); |
5137 | 5131 |
5138 // rax: result string | 5132 // rax: result string |
5139 // rcx: result length | 5133 // rcx: result length |
5140 // rdi: first character of result | 5134 // rdi: first character of result |
5141 // rsi: character of sub string start | 5135 // rsi: character of sub string start |
5142 // r14: original value of rsi | 5136 // r14: original value of rsi |
5143 StringHelper::GenerateCopyCharactersREP(masm, rdi, rsi, rcx, false); | 5137 StringHelper::GenerateCopyCharactersREP(masm, rdi, rsi, rcx, false); |
5144 __ movq(rsi, r14); // Restore esi. | 5138 __ movq(rsi, r14); // Restore esi. |
5145 __ IncrementCounter(counters->sub_string_native(), 1); | 5139 __ IncrementCounter(counters->sub_string_native(), 1); |
5146 __ ret(kArgumentsSize); | 5140 __ ret(3 * kPointerSize); |
5147 | 5141 |
5148 // Just jump to runtime to create the sub string. | 5142 // Just jump to runtime to create the sub string. |
5149 __ bind(&runtime); | 5143 __ bind(&runtime); |
5150 __ TailCallRuntime(Runtime::kSubString, 3, 1); | 5144 __ TailCallRuntime(Runtime::kSubString, 3, 1); |
5151 | 5145 |
5152 __ bind(&single_char); | 5146 __ bind(&single_char); |
5153 // rax: string | 5147 // rax: string |
5154 // rbx: instance type | 5148 // rbx: instance type |
5155 // rcx: sub string length (smi) | 5149 // rcx: sub string length (smi) |
5156 // rdx: from index (smi) | 5150 // rdx: from index (smi) |
5157 StringCharAtGenerator generator( | 5151 StringCharAtGenerator generator( |
5158 rax, rdx, rcx, rax, &runtime, &runtime, &runtime, STRING_INDEX_IS_NUMBER); | 5152 rax, rdx, rcx, rax, &runtime, &runtime, &runtime, STRING_INDEX_IS_NUMBER); |
5159 generator.GenerateFast(masm); | 5153 generator.GenerateFast(masm); |
5160 __ ret(kArgumentsSize); | 5154 __ ret(3 * kPointerSize); |
5161 generator.SkipSlow(masm, &runtime); | 5155 generator.SkipSlow(masm, &runtime); |
5162 } | 5156 } |
5163 | 5157 |
5164 | 5158 |
5165 void StringCompareStub::GenerateFlatAsciiStringEquals(MacroAssembler* masm, | 5159 void StringCompareStub::GenerateFlatAsciiStringEquals(MacroAssembler* masm, |
5166 Register left, | 5160 Register left, |
5167 Register right, | 5161 Register right, |
5168 Register scratch1, | 5162 Register scratch1, |
5169 Register scratch2) { | 5163 Register scratch2) { |
5170 Register length = scratch1; | 5164 Register length = scratch1; |
(...skipping 1452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6623 __ bind(&fast_elements_case); | 6617 __ bind(&fast_elements_case); |
6624 GenerateCase(masm, FAST_ELEMENTS); | 6618 GenerateCase(masm, FAST_ELEMENTS); |
6625 } | 6619 } |
6626 | 6620 |
6627 | 6621 |
6628 #undef __ | 6622 #undef __ |
6629 | 6623 |
6630 } } // namespace v8::internal | 6624 } } // namespace v8::internal |
6631 | 6625 |
6632 #endif // V8_TARGET_ARCH_X64 | 6626 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |