Chromium Code Reviews| 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 |