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

Side by Side Diff: src/x64/codegen-x64.cc

Issue 460109: Perform string add in generated code on X64 platform... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 11 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/x64/codegen-x64.h ('k') | src/x64/macro-assembler-x64.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2009 the V8 project authors. All rights reserved. 1 // Copyright 2009 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 4033 matching lines...) Expand 10 before | Expand all | Expand 10 after
4044 done.Bind(); 4044 done.Bind();
4045 } 4045 }
4046 4046
4047 4047
4048 void CodeGenerator::GenerateStringAdd(ZoneList<Expression*>* args) { 4048 void CodeGenerator::GenerateStringAdd(ZoneList<Expression*>* args) {
4049 ASSERT_EQ(2, args->length()); 4049 ASSERT_EQ(2, args->length());
4050 4050
4051 Load(args->at(0)); 4051 Load(args->at(0));
4052 Load(args->at(1)); 4052 Load(args->at(1));
4053 4053
4054 Result answer = frame_->CallRuntime(Runtime::kStringAdd, 2); 4054 StringAddStub stub(NO_STRING_ADD_FLAGS);
4055 Result answer = frame_->CallStub(&stub, 2);
4055 frame_->Push(&answer); 4056 frame_->Push(&answer);
4056 } 4057 }
4057 4058
4058 4059
4059 void CodeGenerator::GenerateClassOf(ZoneList<Expression*>* args) { 4060 void CodeGenerator::GenerateClassOf(ZoneList<Expression*>* args) {
4060 ASSERT(args->length() == 1); 4061 ASSERT(args->length() == 1);
4061 JumpTarget leave, null, function, non_function_constructor; 4062 JumpTarget leave, null, function, non_function_constructor;
4062 Load(args->at(0)); // Load the object. 4063 Load(args->at(0)); // Load the object.
4063 Result obj = frame_->Pop(); 4064 Result obj = frame_->Pop();
4064 obj.ToRegister(); 4065 obj.ToRegister();
(...skipping 3724 matching lines...) Expand 10 before | Expand all | Expand 10 after
7789 __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, rdx); 7790 __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, rdx);
7790 __ j(above_equal, &not_string1); 7791 __ j(above_equal, &not_string1);
7791 7792
7792 // First argument is a a string, test second. 7793 // First argument is a a string, test second.
7793 is_smi = masm->CheckSmi(rax); 7794 is_smi = masm->CheckSmi(rax);
7794 __ j(is_smi, &string1); 7795 __ j(is_smi, &string1);
7795 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rax); 7796 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rax);
7796 __ j(above_equal, &string1); 7797 __ j(above_equal, &string1);
7797 7798
7798 // First and second argument are strings. 7799 // First and second argument are strings.
7799 Runtime::Function* f = Runtime::FunctionForId(Runtime::kStringAdd); 7800 StringAddStub stub(NO_STRING_CHECK_IN_STUB);
7800 __ TailCallRuntime(ExternalReference(f), 2, f->result_size); 7801 __ TailCallStub(&stub);
7801 7802
7802 // Only first argument is a string. 7803 // Only first argument is a string.
7803 __ bind(&string1); 7804 __ bind(&string1);
7804 __ InvokeBuiltin(Builtins::STRING_ADD_LEFT, JUMP_FUNCTION); 7805 __ InvokeBuiltin(Builtins::STRING_ADD_LEFT, JUMP_FUNCTION);
7805 7806
7806 // First argument was not a string, test second. 7807 // First argument was not a string, test second.
7807 __ bind(&not_string1); 7808 __ bind(&not_string1);
7808 is_smi = masm->CheckSmi(rax); 7809 is_smi = masm->CheckSmi(rax);
7809 __ j(is_smi, &not_strings); 7810 __ j(is_smi, &not_strings);
7810 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rax); 7811 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rax);
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
7873 } 7874 }
7874 } 7875 }
7875 7876
7876 7877
7877 int CompareStub::MinorKey() { 7878 int CompareStub::MinorKey() {
7878 // Encode the two parameters in a unique 16 bit value. 7879 // Encode the two parameters in a unique 16 bit value.
7879 ASSERT(static_cast<unsigned>(cc_) < (1 << 15)); 7880 ASSERT(static_cast<unsigned>(cc_) < (1 << 15));
7880 return (static_cast<unsigned>(cc_) << 1) | (strict_ ? 1 : 0); 7881 return (static_cast<unsigned>(cc_) << 1) | (strict_ ? 1 : 0);
7881 } 7882 }
7882 7883
7884
7885 void StringAddStub::Generate(MacroAssembler* masm) {
7886 Label string_add_runtime;
7887
7888 // Load the two arguments.
7889 __ movq(rax, Operand(rsp, 2 * kPointerSize)); // First argument.
7890 __ movq(rdx, Operand(rsp, 1 * kPointerSize)); // Second argument.
7891
7892 // Make sure that both arguments are strings if not known in advance.
7893 if (string_check_) {
7894 Condition is_smi;
7895 is_smi = masm->CheckSmi(rax);
7896 __ j(is_smi, &string_add_runtime);
7897 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, r8);
7898 __ j(above_equal, &string_add_runtime);
7899
7900 // First argument is a a string, test second.
7901 is_smi = masm->CheckSmi(rdx);
7902 __ j(is_smi, &string_add_runtime);
7903 __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, r9);
7904 __ j(above_equal, &string_add_runtime);
7905 }
7906
7907 // Both arguments are strings.
7908 // rax: first string
7909 // rdx: second string
7910 // Check if either of the strings are empty. In that case return the other.
7911 Label second_not_zero_length, both_not_zero_length;
7912 __ movl(rcx, FieldOperand(rdx, String::kLengthOffset));
7913 __ testl(rcx, rcx);
7914 __ j(not_zero, &second_not_zero_length);
7915 // Second string is empty, result is first string which is already in rax.
7916 __ IncrementCounter(&Counters::string_add_native, 1);
7917 __ ret(2 * kPointerSize);
7918 __ bind(&second_not_zero_length);
7919 __ movl(rbx, FieldOperand(rax, String::kLengthOffset));
7920 __ testl(rbx, rbx);
7921 __ j(not_zero, &both_not_zero_length);
7922 // First string is empty, result is second string which is in rdx.
7923 __ movq(rax, rdx);
7924 __ IncrementCounter(&Counters::string_add_native, 1);
7925 __ ret(2 * kPointerSize);
7926
7927 // Both strings are non-empty.
7928 // rax: first string
7929 // rbx: length of first string
7930 // ecx: length of second string
7931 // edx: second string
7932 // r8: instance type of first string if string check was performed above
7933 // r9: instance type of first string if string check was performed above
7934 Label string_add_flat_result;
7935 __ bind(&both_not_zero_length);
7936 // Look at the length of the result of adding the two strings.
7937 __ addl(rbx, rcx);
7938 // Use the runtime system when adding two one character strings, as it
7939 // contains optimizations for this specific case using the symbol table.
7940 __ cmpl(rbx, Immediate(2));
7941 __ j(equal, &string_add_runtime);
7942 // If arguments where known to be strings, maps are not loaded to r8 and r9
7943 // by the code above.
7944 if (!string_check_) {
7945 __ movq(r8, FieldOperand(rax, HeapObject::kMapOffset));
7946 __ movq(r9, FieldOperand(rdx, HeapObject::kMapOffset));
7947 }
7948 // Get the instance types of the two strings as they will be needed soon.
7949 __ movzxbl(r8, FieldOperand(r8, Map::kInstanceTypeOffset));
7950 __ movzxbl(r9, FieldOperand(r9, Map::kInstanceTypeOffset));
7951 // Check if resulting string will be flat.
7952 __ cmpl(rbx, Immediate(String::kMinNonFlatLength));
7953 __ j(below, &string_add_flat_result);
7954 // Handle exceptionally long strings in the runtime system.
7955 ASSERT((String::kMaxLength & 0x80000000) == 0);
7956 __ cmpl(rbx, Immediate(String::kMaxLength));
7957 __ j(above, &string_add_runtime);
7958
7959 // If result is not supposed to be flat, allocate a cons string object. If
7960 // both strings are ascii the result is an ascii cons string.
7961 // rax: first string
7962 // ebx: length of resulting flat string
7963 // rdx: second string
7964 // r8: instance type of first string
7965 // r9: instance type of second string
7966 Label non_ascii, allocated;
7967 __ movl(rcx, r8);
7968 __ and_(rcx, r9);
7969 ASSERT(kStringEncodingMask == kAsciiStringTag);
7970 __ testl(rcx, Immediate(kAsciiStringTag));
7971 __ j(zero, &non_ascii);
7972 // Allocate an acsii cons string.
7973 __ AllocateAsciiConsString(rcx, rdi, no_reg, &string_add_runtime);
7974 __ bind(&allocated);
7975 // Fill the fields of the cons string.
7976 __ movl(FieldOperand(rcx, ConsString::kLengthOffset), rbx);
7977 __ movl(FieldOperand(rcx, ConsString::kHashFieldOffset),
7978 Immediate(String::kEmptyHashField));
7979 __ movq(FieldOperand(rcx, ConsString::kFirstOffset), rax);
7980 __ movq(FieldOperand(rcx, ConsString::kSecondOffset), rdx);
7981 __ movq(rax, rcx);
7982 __ IncrementCounter(&Counters::string_add_native, 1);
7983 __ ret(2 * kPointerSize);
7984 __ bind(&non_ascii);
7985 // Allocate a two byte cons string.
7986 __ AllocateConsString(rcx, rdi, no_reg, &string_add_runtime);
7987 __ jmp(&allocated);
7988
7989 // Handle creating a flat result. First check that both strings are not
7990 // external strings.
7991 // rax: first string
7992 // ebx: length of resulting flat string
7993 // rdx: second string
7994 // r8: instance type of first string
7995 // r9: instance type of first string
7996 __ bind(&string_add_flat_result);
7997 __ movl(rcx, r8);
7998 __ and_(rcx, Immediate(kStringRepresentationMask));
7999 __ cmpl(rcx, Immediate(kExternalStringTag));
8000 __ j(equal, &string_add_runtime);
8001 __ movl(rcx, r9);
8002 __ and_(rcx, Immediate(kStringRepresentationMask));
8003 __ cmpl(rcx, Immediate(kExternalStringTag));
8004 __ j(equal, &string_add_runtime);
8005 // Now check if both strings are ascii strings.
8006 // rax: first string
8007 // ebx: length of resulting flat string
8008 // rdx: second string
8009 // r8: instance type of first string
8010 // r9: instance type of second string
8011 Label non_ascii_string_add_flat_result;
8012 ASSERT(kStringEncodingMask == kAsciiStringTag);
8013 __ testl(r8, Immediate(kAsciiStringTag));
8014 __ j(zero, &non_ascii_string_add_flat_result);
8015 __ testl(r9, Immediate(kAsciiStringTag));
8016 __ j(zero, &string_add_runtime);
8017 // Both strings are ascii strings. As they are short they are both flat.
8018 __ AllocateAsciiString(rcx, rbx, rdi, r14, r15, &string_add_runtime);
8019 // rcx: result string
8020 __ movq(rbx, rcx);
8021 // Locate first character of result.
8022 __ addq(rcx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
8023 // Locate first character of first argument
8024 __ movl(rdi, FieldOperand(rax, String::kLengthOffset));
8025 __ addq(rax, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
8026 // rax: first char of first argument
8027 // rbx: result string
8028 // rcx: first character of result
8029 // rdx: second string
8030 // rdi: length of first argument
8031 GenerateCopyCharacters(masm, rcx, rax, rdi, true);
8032 // Locate first character of second argument.
8033 __ movl(rdi, FieldOperand(rdx, String::kLengthOffset));
8034 __ addq(rdx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
8035 // rbx: result string
8036 // rcx: next character of result
8037 // rdx: first char of second argument
8038 // rdi: length of second argument
8039 GenerateCopyCharacters(masm, rcx, rdx, rdi, true);
8040 __ movq(rax, rbx);
8041 __ IncrementCounter(&Counters::string_add_native, 1);
8042 __ ret(2 * kPointerSize);
8043
8044 // Handle creating a flat two byte result.
8045 // rax: first string - known to be two byte
8046 // rbx: length of resulting flat string
8047 // rdx: second string
8048 // r8: instance type of first string
8049 // r9: instance type of first string
8050 __ bind(&non_ascii_string_add_flat_result);
8051 __ and_(r9, Immediate(kAsciiStringTag));
8052 __ j(not_zero, &string_add_runtime);
8053 // Both strings are two byte strings. As they are short they are both
8054 // flat.
8055 __ AllocateTwoByteString(rcx, rbx, rdi, r14, r15, &string_add_runtime);
8056 // rcx: result string
8057 __ movq(rbx, rcx);
8058 // Locate first character of result.
8059 __ addq(rcx, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
8060 // Locate first character of first argument.
8061 __ movl(rdi, FieldOperand(rax, String::kLengthOffset));
8062 __ addq(rax, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
8063 // rax: first char of first argument
8064 // rbx: result string
8065 // rcx: first character of result
8066 // rdx: second argument
8067 // rdi: length of first argument
8068 GenerateCopyCharacters(masm, rcx, rax, rdi, false);
8069 // Locate first character of second argument.
8070 __ movl(rdi, FieldOperand(rdx, String::kLengthOffset));
8071 __ addq(rdx, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
8072 // rbx: result string
8073 // rcx: next character of result
8074 // rdx: first char of second argument
8075 // rdi: length of second argument
8076 GenerateCopyCharacters(masm, rcx, rdx, rdi, false);
8077 __ movq(rax, rbx);
8078 __ IncrementCounter(&Counters::string_add_native, 1);
8079 __ ret(2 * kPointerSize);
8080
8081 // Just jump to runtime to add the two strings.
8082 __ bind(&string_add_runtime);
8083 __ TailCallRuntime(ExternalReference(Runtime::kStringAdd), 2, 1);
8084 }
8085
8086
8087 void StringAddStub::GenerateCopyCharacters(MacroAssembler* masm,
8088 Register dest,
8089 Register src,
8090 Register count,
8091 bool ascii) {
8092 Label loop;
8093 __ bind(&loop);
8094 // This loop just copies one character at a time, as it is only used for very
8095 // short strings.
8096 if (ascii) {
8097 __ movb(kScratchRegister, Operand(src, 0));
8098 __ movb(Operand(dest, 0), kScratchRegister);
8099 __ addq(src, Immediate(1));
8100 __ addq(dest, Immediate(1));
8101 } else {
8102 __ movzxwl(kScratchRegister, Operand(src, 0));
8103 __ movw(Operand(dest, 0), kScratchRegister);
8104 __ addq(src, Immediate(2));
8105 __ addq(dest, Immediate(2));
8106 }
8107 __ subl(count, Immediate(1));
8108 __ j(not_zero, &loop);
8109 }
8110
8111
7883 #undef __ 8112 #undef __
7884 8113
7885 #define __ masm. 8114 #define __ masm.
7886 8115
7887 #ifdef _WIN64 8116 #ifdef _WIN64
7888 typedef double (*ModuloFunction)(double, double); 8117 typedef double (*ModuloFunction)(double, double);
7889 // Define custom fmod implementation. 8118 // Define custom fmod implementation.
7890 ModuloFunction CreateModuloFunction() { 8119 ModuloFunction CreateModuloFunction() {
7891 size_t actual_size; 8120 size_t actual_size;
7892 byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, 8121 byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
7969 masm.GetCode(&desc); 8198 masm.GetCode(&desc);
7970 // Call the function from C++. 8199 // Call the function from C++.
7971 return FUNCTION_CAST<ModuloFunction>(buffer); 8200 return FUNCTION_CAST<ModuloFunction>(buffer);
7972 } 8201 }
7973 8202
7974 #endif 8203 #endif
7975 8204
7976 #undef __ 8205 #undef __
7977 8206
7978 } } // namespace v8::internal 8207 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/x64/codegen-x64.h ('k') | src/x64/macro-assembler-x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698