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 |