OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
7037 __ j(zero, ¬_string1); | 7049 __ j(zero, ¬_string1); |
7038 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, eax); | 7050 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, eax); |
7039 __ j(above_equal, ¬_string1); | 7051 __ j(above_equal, ¬_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(¬_string1); | 7068 __ bind(¬_string1); |
7056 __ test(edx, Immediate(kSmiTagMask)); | 7069 __ test(edx, Immediate(kSmiTagMask)); |
7057 __ j(zero, ¬_strings); | 7070 __ j(zero, ¬_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 Loading... | |
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 |
OLD | NEW |