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

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

Issue 442024: Perform string add in generated code on IA-32 platforms... (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/ia32/codegen-ia32.h ('k') | src/ia32/macro-assembler-ia32.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 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-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 5194 matching lines...) Expand 10 before | Expand all | Expand 10 after
5205 break; 5205 break;
5206 case COS: 5206 case COS:
5207 answer = frame_->CallRuntime(Runtime::kMath_cos, 1); 5207 answer = frame_->CallRuntime(Runtime::kMath_cos, 1);
5208 break; 5208 break;
5209 } 5209 }
5210 frame_->Push(&answer); 5210 frame_->Push(&answer);
5211 done.Bind(); 5211 done.Bind();
5212 } 5212 }
5213 5213
5214 5214
5215 void CodeGenerator::GenerateStringAdd(ZoneList<Expression*>* args) {
5216 ASSERT_EQ(2, args->length());
5217
5218 Load(args->at(0));
5219 Load(args->at(1));
5220
5221 StringAddStub stub(NO_STRING_ADD_FLAGS);
5222 Result answer = frame_->CallStub(&stub, 2);
5223 frame_->Push(&answer);
5224 }
5225
5226
5215 void CodeGenerator::VisitCallRuntime(CallRuntime* node) { 5227 void CodeGenerator::VisitCallRuntime(CallRuntime* node) {
5216 if (CheckForInlineRuntimeCall(node)) { 5228 if (CheckForInlineRuntimeCall(node)) {
5217 return; 5229 return;
5218 } 5230 }
5219 5231
5220 ZoneList<Expression*>* args = node->arguments(); 5232 ZoneList<Expression*>* args = node->arguments();
5221 Comment cmnt(masm_, "[ CallRuntime"); 5233 Comment cmnt(masm_, "[ CallRuntime");
5222 Runtime::Function* function = node->function(); 5234 Runtime::Function* function = node->function();
5223 5235
5224 if (function == NULL) { 5236 if (function == NULL) {
(...skipping 1812 matching lines...) Expand 10 before | Expand all | Expand 10 after
7037 __ j(zero, &not_string1); 7049 __ j(zero, &not_string1);
7038 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, eax); 7050 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, eax);
7039 __ j(above_equal, &not_string1); 7051 __ j(above_equal, &not_string1);
7040 7052
7041 // First argument is a a string, test second. 7053 // First argument is a a string, test second.
7042 __ test(edx, Immediate(kSmiTagMask)); 7054 __ test(edx, Immediate(kSmiTagMask));
7043 __ j(zero, &string1); 7055 __ j(zero, &string1);
7044 __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, edx); 7056 __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, edx);
7045 __ j(above_equal, &string1); 7057 __ j(above_equal, &string1);
7046 7058
7047 // First and second argument are strings. 7059 // First and second argument are strings. Jump to the string add stub.
7048 __ TailCallRuntime(ExternalReference(Runtime::kStringAdd), 2, 1); 7060 StringAddStub stub(NO_STRING_CHECK_IN_STUB);
7061 __ TailCallStub(&stub);
7049 7062
7050 // Only first argument is a string. 7063 // Only first argument is a string.
7051 __ bind(&string1); 7064 __ bind(&string1);
7052 __ InvokeBuiltin(Builtins::STRING_ADD_LEFT, JUMP_FUNCTION); 7065 __ InvokeBuiltin(Builtins::STRING_ADD_LEFT, JUMP_FUNCTION);
7053 7066
7054 // First argument was not a string, test second. 7067 // First argument was not a string, test second.
7055 __ bind(&not_string1); 7068 __ bind(&not_string1);
7056 __ test(edx, Immediate(kSmiTagMask)); 7069 __ test(edx, Immediate(kSmiTagMask));
7057 __ j(zero, &not_strings); 7070 __ j(zero, &not_strings);
7058 __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, edx); 7071 __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, edx);
(...skipping 1106 matching lines...) Expand 10 before | Expand all | Expand 10 after
8165 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 8178 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
8166 } 8179 }
8167 8180
8168 8181
8169 int CompareStub::MinorKey() { 8182 int CompareStub::MinorKey() {
8170 // Encode the two parameters in a unique 16 bit value. 8183 // Encode the two parameters in a unique 16 bit value.
8171 ASSERT(static_cast<unsigned>(cc_) < (1 << 15)); 8184 ASSERT(static_cast<unsigned>(cc_) < (1 << 15));
8172 return (static_cast<unsigned>(cc_) << 1) | (strict_ ? 1 : 0); 8185 return (static_cast<unsigned>(cc_) << 1) | (strict_ ? 1 : 0);
8173 } 8186 }
8174 8187
8188
8189 void StringAddStub::Generate(MacroAssembler* masm) {
8190 Label string_add_runtime;
8191
8192 // Load the two arguments.
8193 __ mov(eax, Operand(esp, 2 * kPointerSize)); // First argument.
8194 __ mov(edx, Operand(esp, 1 * kPointerSize)); // Second argument.
8195
8196 // Make sure that both arguments are strings if not known in advance.
8197 if (string_check_) {
8198 __ test(eax, Immediate(kSmiTagMask));
8199 __ j(zero, &string_add_runtime);
8200 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, ebx);
8201 __ j(above_equal, &string_add_runtime);
8202
8203 // First argument is a a string, test second.
8204 __ test(edx, Immediate(kSmiTagMask));
8205 __ j(zero, &string_add_runtime);
8206 __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, ebx);
8207 __ j(above_equal, &string_add_runtime);
8208 }
8209
8210 // Both arguments are strings.
8211 // eax: first string
8212 // edx: second string
8213 // Check if either of the strings are empty. In that case return the other.
8214 Label second_not_zero_length, both_not_zero_length;
8215 __ mov(ecx, FieldOperand(edx, String::kLengthOffset));
8216 __ test(ecx, Operand(ecx));
8217 __ j(not_zero, &second_not_zero_length);
8218 // Second string is empty, result is first string which is already in eax.
8219 __ IncrementCounter(&Counters::string_add_native, 1);
8220 __ ret(2 * kPointerSize);
8221 __ bind(&second_not_zero_length);
8222 __ mov(ebx, FieldOperand(eax, String::kLengthOffset));
8223 __ test(ebx, Operand(ebx));
8224 __ j(not_zero, &both_not_zero_length);
8225 // First string is empty, result is second string which is in edx.
8226 __ mov(eax, edx);
8227 __ IncrementCounter(&Counters::string_add_native, 1);
8228 __ ret(2 * kPointerSize);
8229
8230 // Both strings are non-empty.
8231 // eax: first string
8232 // ebx: length of first string
8233 // ecx: length of second string
8234 // edx: second string
8235 // Look at the length of the result of adding the two strings.
8236 Label string_add_flat_result;
8237 __ bind(&both_not_zero_length);
8238 __ add(ebx, Operand(ecx));
8239 // Use the runtime system when adding two one character strings, as it
8240 // contains optimizations for this specific case using the symbol table.
8241 __ cmp(ebx, 2);
8242 __ j(equal, &string_add_runtime);
8243 // Check if resulting string will be flat.
8244 __ cmp(ebx, String::kMinNonFlatLength);
8245 __ j(below, &string_add_flat_result);
8246 // Handle exceptionally long strings in the runtime system.
8247 ASSERT((String::kMaxLength & 0x80000000) == 0);
8248 __ cmp(ebx, String::kMaxLength);
8249 __ j(above, &string_add_runtime);
8250
8251 // If result is not supposed to be flat allocate a cons string object. If both
8252 // strings are ascii the result is an ascii cons string.
8253 Label non_ascii, allocated;
8254 __ mov(edi, FieldOperand(eax, HeapObject::kMapOffset));
8255 __ movzx_b(ecx, FieldOperand(edi, Map::kInstanceTypeOffset));
8256 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
8257 __ movzx_b(edi, FieldOperand(edi, Map::kInstanceTypeOffset));
8258 __ and_(ecx, Operand(edi));
8259 __ test(ecx, Immediate(kAsciiStringTag));
8260 __ j(zero, &non_ascii);
8261 // Allocate an acsii cons string.
8262 __ AllocateAsciiConsString(ecx, edi, no_reg, &string_add_runtime);
8263 __ bind(&allocated);
8264 // Fill the fields of the cons string.
8265 __ mov(FieldOperand(ecx, ConsString::kLengthOffset), ebx);
8266 __ mov(FieldOperand(ecx, ConsString::kHashFieldOffset),
8267 Immediate(String::kEmptyHashField));
8268 __ mov(FieldOperand(ecx, ConsString::kFirstOffset), eax);
8269 __ mov(FieldOperand(ecx, ConsString::kSecondOffset), edx);
8270 __ mov(eax, ecx);
8271 __ IncrementCounter(&Counters::string_add_native, 1);
8272 __ ret(2 * kPointerSize);
8273 __ bind(&non_ascii);
8274 // Allocate a two byte cons string.
8275 __ AllocateConsString(ecx, edi, no_reg, &string_add_runtime);
8276 __ jmp(&allocated);
8277
8278 // Handle creating a flat result. First check that both strings are not
8279 // external strings.
8280 // eax: first string
8281 // ebx: length of resulting flat string
8282 // edx: second string
8283 __ bind(&string_add_flat_result);
8284 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
8285 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
8286 __ and_(ecx, kStringRepresentationMask);
8287 __ cmp(ecx, kExternalStringTag);
8288 __ j(equal, &string_add_runtime);
8289 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
8290 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
8291 __ and_(ecx, kStringRepresentationMask);
8292 __ cmp(ecx, kExternalStringTag);
8293 __ j(equal, &string_add_runtime);
8294 // Now check if both strings are ascii strings.
8295 // eax: first string
8296 // ebx: length of resulting flat string
8297 // edx: second string
8298 Label non_ascii_string_add_flat_result;
8299 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
8300 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
8301 ASSERT(kAsciiStringTag != 0);
8302 __ test(ecx, Immediate(kAsciiStringTag));
8303 __ j(zero, &non_ascii_string_add_flat_result);
8304 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
8305 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
Erik Corry 2009/12/03 08:13:56 Here you load the type fields again that you just
8306 __ test(ecx, Immediate(kAsciiStringTag));
8307 __ j(zero, &string_add_runtime);
8308 // Both strings are ascii strings. As they are short they are both flat.
8309 __ AllocateAsciiString(eax, ebx, ecx, edx, edi, &string_add_runtime);
8310 // eax: result string
8311 __ mov(ecx, eax);
8312 // Locate first character of result.
8313 __ add(Operand(ecx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
8314 // Load first argument and locate first character.
8315 __ mov(edx, Operand(esp, 2 * kPointerSize));
8316 __ mov(edi, FieldOperand(edx, String::kLengthOffset));
8317 __ add(Operand(edx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
8318 // eax: result string
8319 // ecx: first character of result
8320 // edx: first char of first argument
8321 // edi: length of first argument
8322 GenerateCopyCharacters(masm, ecx, edx, edi, ebx, true);
8323 // Load second argument and locate first character.
8324 __ mov(edx, Operand(esp, 1 * kPointerSize));
8325 __ mov(edi, FieldOperand(edx, String::kLengthOffset));
8326 __ add(Operand(edx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
8327 // eax: result string
8328 // ecx: next character of result
8329 // edx: first char of second argument
8330 // edi: length of second argument
8331 GenerateCopyCharacters(masm, ecx, edx, edi, ebx, true);
8332 __ IncrementCounter(&Counters::string_add_native, 1);
8333 __ ret(2 * kPointerSize);
8334
8335 // Handle creating a flat two byte result.
8336 // eax: first string - known to be two byte
8337 // ebx: length of resulting flat string
8338 // edx: second string
8339 __ bind(&non_ascii_string_add_flat_result);
8340 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
8341 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
Erik Corry 2009/12/03 08:13:56 Same issue here.
8342 __ and_(ecx, kAsciiStringTag);
8343 __ j(not_zero, &string_add_runtime);
8344 // Both strings are two byte strings. As they are short they are both
8345 // flat.
8346 __ AllocateTwoByteString(eax, ebx, ecx, edx, edi, &string_add_runtime);
8347 // eax: result string
8348 __ mov(ecx, eax);
8349 // Locate first character of result.
8350 __ add(Operand(ecx),
8351 Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
8352 // Load first argument and locate first character.
8353 __ mov(edx, Operand(esp, 2 * kPointerSize));
8354 __ mov(edi, FieldOperand(edx, String::kLengthOffset));
8355 __ add(Operand(edx),
8356 Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
8357 // eax: result string
8358 // ecx: first character of result
8359 // edx: first char of first argument
8360 // edi: length of first argument
8361 GenerateCopyCharacters(masm, ecx, edx, edi, ebx, false);
8362 // Load second argument and locate first character.
8363 __ mov(edx, Operand(esp, 1 * kPointerSize));
8364 __ mov(edi, FieldOperand(edx, String::kLengthOffset));
8365 __ add(Operand(edx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
8366 // eax: result string
8367 // ecx: next character of result
8368 // edx: first char of second argument
8369 // edi: length of second argument
8370 GenerateCopyCharacters(masm, ecx, edx, edi, ebx, false);
8371 __ IncrementCounter(&Counters::string_add_native, 1);
8372 __ ret(2 * kPointerSize);
8373
8374 // Just jump to runtime to add the two strings.
8375 __ bind(&string_add_runtime);
8376 __ TailCallRuntime(ExternalReference(Runtime::kStringAdd), 2, 1);
8377 }
8378
8379
8380 void StringAddStub::GenerateCopyCharacters(MacroAssembler* masm,
8381 Register dest,
8382 Register src,
8383 Register count,
8384 Register scratch,
8385 bool ascii) {
8386 Label loop;
8387 __ bind(&loop);
8388 // This loop just copies one character at a time, as it is only used for very
8389 // short strings.
8390 if (ascii) {
8391 __ mov_b(scratch, Operand(src, 0));
8392 __ mov_b(Operand(dest, 0), scratch);
8393 __ add(Operand(src), Immediate(1));
8394 __ add(Operand(dest), Immediate(1));
8395 } else {
8396 __ mov_w(scratch, Operand(src, 0));
8397 __ mov_w(Operand(dest, 0), scratch);
8398 __ add(Operand(src), Immediate(2));
8399 __ add(Operand(dest), Immediate(2));
8400 }
8401 __ sub(Operand(count), Immediate(1));
8402 __ j(not_zero, &loop);
8403 }
8404
8405
8175 #undef __ 8406 #undef __
8176 8407
8177 } } // namespace v8::internal 8408 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ia32/codegen-ia32.h ('k') | src/ia32/macro-assembler-ia32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698