| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 2226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2237 | 2237 |
| 2238 // The displacement is used for skipping the frame pointer on the | 2238 // The displacement is used for skipping the frame pointer on the |
| 2239 // stack. It is the offset of the last parameter (if any) relative | 2239 // stack. It is the offset of the last parameter (if any) relative |
| 2240 // to the frame pointer. | 2240 // to the frame pointer. |
| 2241 static const int kDisplacement = 1 * kPointerSize; | 2241 static const int kDisplacement = 1 * kPointerSize; |
| 2242 | 2242 |
| 2243 // Check that the key is a smi. | 2243 // Check that the key is a smi. |
| 2244 Label slow; | 2244 Label slow; |
| 2245 __ JumpIfNotSmi(rdx, &slow); | 2245 __ JumpIfNotSmi(rdx, &slow); |
| 2246 | 2246 |
| 2247 // Check if the calling frame is an arguments adaptor frame. | 2247 // Check if the calling frame is an arguments adaptor frame. We look at the |
| 2248 // context offset, and if the frame is not a regular one, then we find a |
| 2249 // Smi instead of the context. We can't use SmiCompare here, because that |
| 2250 // only works for comparing two smis. |
| 2248 Label adaptor; | 2251 Label adaptor; |
| 2249 __ movq(rbx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); | 2252 __ movq(rbx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); |
| 2250 __ SmiCompare(Operand(rbx, StandardFrameConstants::kContextOffset), | 2253 __ Cmp(Operand(rbx, StandardFrameConstants::kContextOffset), |
| 2251 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); | 2254 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); |
| 2252 __ j(equal, &adaptor); | 2255 __ j(equal, &adaptor); |
| 2253 | 2256 |
| 2254 // Check index against formal parameters count limit passed in | 2257 // Check index against formal parameters count limit passed in |
| 2255 // through register rax. Use unsigned comparison to get negative | 2258 // through register rax. Use unsigned comparison to get negative |
| 2256 // check for free. | 2259 // check for free. |
| 2257 __ cmpq(rdx, rax); | 2260 __ cmpq(rdx, rax); |
| 2258 __ j(above_equal, &slow); | 2261 __ j(above_equal, &slow); |
| 2259 | 2262 |
| 2260 // Read the argument from the stack and return it. | 2263 // Read the argument from the stack and return it. |
| 2261 SmiIndex index = masm->SmiToIndex(rax, rax, kPointerSizeLog2); | 2264 SmiIndex index = masm->SmiToIndex(rax, rax, kPointerSizeLog2); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2296 // rsp[24] : function | 2299 // rsp[24] : function |
| 2297 | 2300 |
| 2298 // The displacement is used for skipping the return address and the | 2301 // The displacement is used for skipping the return address and the |
| 2299 // frame pointer on the stack. It is the offset of the last | 2302 // frame pointer on the stack. It is the offset of the last |
| 2300 // parameter (if any) relative to the frame pointer. | 2303 // parameter (if any) relative to the frame pointer. |
| 2301 static const int kDisplacement = 2 * kPointerSize; | 2304 static const int kDisplacement = 2 * kPointerSize; |
| 2302 | 2305 |
| 2303 // Check if the calling frame is an arguments adaptor frame. | 2306 // Check if the calling frame is an arguments adaptor frame. |
| 2304 Label adaptor_frame, try_allocate, runtime; | 2307 Label adaptor_frame, try_allocate, runtime; |
| 2305 __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); | 2308 __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); |
| 2306 __ SmiCompare(Operand(rdx, StandardFrameConstants::kContextOffset), | 2309 __ Cmp(Operand(rdx, StandardFrameConstants::kContextOffset), |
| 2307 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); | 2310 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); |
| 2308 __ j(equal, &adaptor_frame); | 2311 __ j(equal, &adaptor_frame); |
| 2309 | 2312 |
| 2310 // Get the length from the frame. | 2313 // Get the length from the frame. |
| 2311 __ SmiToInteger32(rcx, Operand(rsp, 1 * kPointerSize)); | 2314 __ SmiToInteger32(rcx, Operand(rsp, 1 * kPointerSize)); |
| 2312 __ jmp(&try_allocate); | 2315 __ jmp(&try_allocate); |
| 2313 | 2316 |
| 2314 // Patch the arguments.length and the parameters pointer. | 2317 // Patch the arguments.length and the parameters pointer. |
| 2315 __ bind(&adaptor_frame); | 2318 __ bind(&adaptor_frame); |
| 2316 __ SmiToInteger32(rcx, | 2319 __ SmiToInteger32(rcx, |
| 2317 Operand(rdx, | 2320 Operand(rdx, |
| (...skipping 1832 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4150 __ movq(r8, FieldOperand(rax, HeapObject::kMapOffset)); | 4153 __ movq(r8, FieldOperand(rax, HeapObject::kMapOffset)); |
| 4151 __ movq(r9, FieldOperand(rdx, HeapObject::kMapOffset)); | 4154 __ movq(r9, FieldOperand(rdx, HeapObject::kMapOffset)); |
| 4152 } | 4155 } |
| 4153 // Get the instance types of the two strings as they will be needed soon. | 4156 // Get the instance types of the two strings as they will be needed soon. |
| 4154 __ movzxbl(r8, FieldOperand(r8, Map::kInstanceTypeOffset)); | 4157 __ movzxbl(r8, FieldOperand(r8, Map::kInstanceTypeOffset)); |
| 4155 __ movzxbl(r9, FieldOperand(r9, Map::kInstanceTypeOffset)); | 4158 __ movzxbl(r9, FieldOperand(r9, Map::kInstanceTypeOffset)); |
| 4156 | 4159 |
| 4157 // Look at the length of the result of adding the two strings. | 4160 // Look at the length of the result of adding the two strings. |
| 4158 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue / 2); | 4161 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue / 2); |
| 4159 __ SmiAdd(rbx, rbx, rcx); | 4162 __ SmiAdd(rbx, rbx, rcx); |
| 4160 // Use the runtime system when adding two one character strings, as it | 4163 // Use the symbol table when adding two one character strings, as it |
| 4161 // contains optimizations for this specific case using the symbol table. | 4164 // helps later optimizations to return a symbol here. |
| 4162 __ SmiCompare(rbx, Smi::FromInt(2)); | 4165 __ SmiCompare(rbx, Smi::FromInt(2)); |
| 4163 __ j(not_equal, &longer_than_two); | 4166 __ j(not_equal, &longer_than_two); |
| 4164 | 4167 |
| 4165 // Check that both strings are non-external ascii strings. | 4168 // Check that both strings are non-external ascii strings. |
| 4166 __ JumpIfBothInstanceTypesAreNotSequentialAscii(r8, r9, rbx, rcx, | 4169 __ JumpIfBothInstanceTypesAreNotSequentialAscii(r8, r9, rbx, rcx, |
| 4167 &string_add_runtime); | 4170 &string_add_runtime); |
| 4168 | 4171 |
| 4169 // Get the two characters forming the sub string. | 4172 // Get the two characters forming the sub string. |
| 4170 __ movzxbq(rbx, FieldOperand(rax, SeqAsciiString::kHeaderSize)); | 4173 __ movzxbq(rbx, FieldOperand(rax, SeqAsciiString::kHeaderSize)); |
| 4171 __ movzxbq(rcx, FieldOperand(rdx, SeqAsciiString::kHeaderSize)); | 4174 __ movzxbq(rcx, FieldOperand(rdx, SeqAsciiString::kHeaderSize)); |
| (...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4503 // Load the symbol table. | 4506 // Load the symbol table. |
| 4504 Register symbol_table = c2; | 4507 Register symbol_table = c2; |
| 4505 __ LoadRoot(symbol_table, Heap::kSymbolTableRootIndex); | 4508 __ LoadRoot(symbol_table, Heap::kSymbolTableRootIndex); |
| 4506 | 4509 |
| 4507 // Calculate capacity mask from the symbol table capacity. | 4510 // Calculate capacity mask from the symbol table capacity. |
| 4508 Register mask = scratch2; | 4511 Register mask = scratch2; |
| 4509 __ SmiToInteger32(mask, | 4512 __ SmiToInteger32(mask, |
| 4510 FieldOperand(symbol_table, SymbolTable::kCapacityOffset)); | 4513 FieldOperand(symbol_table, SymbolTable::kCapacityOffset)); |
| 4511 __ decl(mask); | 4514 __ decl(mask); |
| 4512 | 4515 |
| 4513 Register undefined = scratch4; | 4516 Register map = scratch4; |
| 4514 __ LoadRoot(undefined, Heap::kUndefinedValueRootIndex); | |
| 4515 | 4517 |
| 4516 // Registers | 4518 // Registers |
| 4517 // chars: two character string, char 1 in byte 0 and char 2 in byte 1. | 4519 // chars: two character string, char 1 in byte 0 and char 2 in byte 1. |
| 4518 // hash: hash of two character string (32-bit int) | 4520 // hash: hash of two character string (32-bit int) |
| 4519 // symbol_table: symbol table | 4521 // symbol_table: symbol table |
| 4520 // mask: capacity mask (32-bit int) | 4522 // mask: capacity mask (32-bit int) |
| 4521 // undefined: undefined value | 4523 // map: - |
| 4522 // scratch: - | 4524 // scratch: - |
| 4523 | 4525 |
| 4524 // Perform a number of probes in the symbol table. | 4526 // Perform a number of probes in the symbol table. |
| 4525 static const int kProbes = 4; | 4527 static const int kProbes = 4; |
| 4526 Label found_in_symbol_table; | 4528 Label found_in_symbol_table; |
| 4527 Label next_probe[kProbes]; | 4529 Label next_probe[kProbes]; |
| 4528 for (int i = 0; i < kProbes; i++) { | 4530 for (int i = 0; i < kProbes; i++) { |
| 4529 // Calculate entry in symbol table. | 4531 // Calculate entry in symbol table. |
| 4530 __ movl(scratch, hash); | 4532 __ movl(scratch, hash); |
| 4531 if (i > 0) { | 4533 if (i > 0) { |
| 4532 __ addl(scratch, Immediate(SymbolTable::GetProbeOffset(i))); | 4534 __ addl(scratch, Immediate(SymbolTable::GetProbeOffset(i))); |
| 4533 } | 4535 } |
| 4534 __ andl(scratch, mask); | 4536 __ andl(scratch, mask); |
| 4535 | 4537 |
| 4536 // Load the entry from the symble table. | 4538 // Load the entry from the symbol table. |
| 4537 Register candidate = scratch; // Scratch register contains candidate. | 4539 Register candidate = scratch; // Scratch register contains candidate. |
| 4538 STATIC_ASSERT(SymbolTable::kEntrySize == 1); | 4540 STATIC_ASSERT(SymbolTable::kEntrySize == 1); |
| 4539 __ movq(candidate, | 4541 __ movq(candidate, |
| 4540 FieldOperand(symbol_table, | 4542 FieldOperand(symbol_table, |
| 4541 scratch, | 4543 scratch, |
| 4542 times_pointer_size, | 4544 times_pointer_size, |
| 4543 SymbolTable::kElementsStartOffset)); | 4545 SymbolTable::kElementsStartOffset)); |
| 4544 | 4546 |
| 4545 // If entry is undefined no string with this hash can be found. | 4547 // If entry is undefined no string with this hash can be found. |
| 4546 __ cmpq(candidate, undefined); | 4548 NearLabel is_string; |
| 4549 __ CmpObjectType(candidate, ODDBALL_TYPE, map); |
| 4550 __ j(not_equal, &is_string); |
| 4551 |
| 4552 __ CompareRoot(candidate, Heap::kUndefinedValueRootIndex); |
| 4547 __ j(equal, not_found); | 4553 __ j(equal, not_found); |
| 4554 // Must be null (deleted entry). |
| 4555 __ jmp(&next_probe[i]); |
| 4556 |
| 4557 __ bind(&is_string); |
| 4548 | 4558 |
| 4549 // If length is not 2 the string is not a candidate. | 4559 // If length is not 2 the string is not a candidate. |
| 4550 __ SmiCompare(FieldOperand(candidate, String::kLengthOffset), | 4560 __ SmiCompare(FieldOperand(candidate, String::kLengthOffset), |
| 4551 Smi::FromInt(2)); | 4561 Smi::FromInt(2)); |
| 4552 __ j(not_equal, &next_probe[i]); | 4562 __ j(not_equal, &next_probe[i]); |
| 4553 | 4563 |
| 4554 // We use kScratchRegister as a temporary register in assumption that | 4564 // We use kScratchRegister as a temporary register in assumption that |
| 4555 // JumpIfInstanceTypeIsNotSequentialAscii does not use it implicitly | 4565 // JumpIfInstanceTypeIsNotSequentialAscii does not use it implicitly |
| 4556 Register temp = kScratchRegister; | 4566 Register temp = kScratchRegister; |
| 4557 | 4567 |
| 4558 // Check that the candidate is a non-external ascii string. | 4568 // Check that the candidate is a non-external ascii string. |
| 4559 __ movq(temp, FieldOperand(candidate, HeapObject::kMapOffset)); | 4569 __ movzxbl(temp, FieldOperand(map, Map::kInstanceTypeOffset)); |
| 4560 __ movzxbl(temp, FieldOperand(temp, Map::kInstanceTypeOffset)); | |
| 4561 __ JumpIfInstanceTypeIsNotSequentialAscii( | 4570 __ JumpIfInstanceTypeIsNotSequentialAscii( |
| 4562 temp, temp, &next_probe[i]); | 4571 temp, temp, &next_probe[i]); |
| 4563 | 4572 |
| 4564 // Check if the two characters match. | 4573 // Check if the two characters match. |
| 4565 __ movl(temp, FieldOperand(candidate, SeqAsciiString::kHeaderSize)); | 4574 __ movl(temp, FieldOperand(candidate, SeqAsciiString::kHeaderSize)); |
| 4566 __ andl(temp, Immediate(0x0000ffff)); | 4575 __ andl(temp, Immediate(0x0000ffff)); |
| 4567 __ cmpl(chars, temp); | 4576 __ cmpl(chars, temp); |
| 4568 __ j(equal, &found_in_symbol_table); | 4577 __ j(equal, &found_in_symbol_table); |
| 4569 __ bind(&next_probe[i]); | 4578 __ bind(&next_probe[i]); |
| 4570 } | 4579 } |
| (...skipping 507 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5078 // Do a tail call to the rewritten stub. | 5087 // Do a tail call to the rewritten stub. |
| 5079 __ jmp(rdi); | 5088 __ jmp(rdi); |
| 5080 } | 5089 } |
| 5081 | 5090 |
| 5082 | 5091 |
| 5083 #undef __ | 5092 #undef __ |
| 5084 | 5093 |
| 5085 } } // namespace v8::internal | 5094 } } // namespace v8::internal |
| 5086 | 5095 |
| 5087 #endif // V8_TARGET_ARCH_X64 | 5096 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |