| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_X64 | 7 #if V8_TARGET_ARCH_X64 |
| 8 | 8 |
| 9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
| 10 #include "src/ic/ic.h" | 10 #include "src/ic/ic.h" |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 161 | 161 |
| 162 // Check bit field. | 162 // Check bit field. |
| 163 __ testb( | 163 __ testb( |
| 164 FieldOperand(map, Map::kBitFieldOffset), | 164 FieldOperand(map, Map::kBitFieldOffset), |
| 165 Immediate((1 << Map::kIsAccessCheckNeeded) | (1 << interceptor_bit))); | 165 Immediate((1 << Map::kIsAccessCheckNeeded) | (1 << interceptor_bit))); |
| 166 __ j(not_zero, slow); | 166 __ j(not_zero, slow); |
| 167 } | 167 } |
| 168 | 168 |
| 169 | 169 |
| 170 // Loads an indexed element from a fast case array. | 170 // Loads an indexed element from a fast case array. |
| 171 // If not_fast_array is NULL, doesn't perform the elements map check. | |
| 172 static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, | 171 static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, |
| 173 Register key, Register elements, | 172 Register key, Register elements, |
| 174 Register scratch, Register result, | 173 Register scratch, Register result, |
| 175 Label* not_fast_array, Label* out_of_range) { | 174 Label* slow) { |
| 176 // Register use: | 175 // Register use: |
| 177 // | 176 // |
| 178 // receiver - holds the receiver on entry. | 177 // receiver - holds the receiver on entry. |
| 179 // Unchanged unless 'result' is the same register. | 178 // Unchanged unless 'result' is the same register. |
| 180 // | 179 // |
| 181 // key - holds the smi key on entry. | 180 // key - holds the smi key on entry. |
| 182 // Unchanged unless 'result' is the same register. | 181 // Unchanged unless 'result' is the same register. |
| 183 // | 182 // |
| 184 // elements - holds the elements of the receiver on exit. | |
| 185 // | |
| 186 // result - holds the result on exit if the load succeeded. | 183 // result - holds the result on exit if the load succeeded. |
| 187 // Allowed to be the the same as 'receiver' or 'key'. | 184 // Allowed to be the the same as 'receiver' or 'key'. |
| 188 // Unchanged on bailout so 'receiver' and 'key' can be safely | 185 // Unchanged on bailout so 'receiver' and 'key' can be safely |
| 189 // used by further computation. | 186 // used by further computation. |
| 190 // | 187 // |
| 191 // Scratch registers: | 188 // Scratch registers: |
| 192 // | 189 // |
| 193 // scratch - used to hold elements of the receiver and the loaded value. | 190 // elements - holds the elements of the receiver and its prototypes. |
| 191 // |
| 192 // scratch - used to hold maps, prototypes, and the loaded value. |
| 193 Label check_prototypes, check_next_prototype; |
| 194 Label done, in_bounds, return_undefined; |
| 194 | 195 |
| 195 __ movp(elements, FieldOperand(receiver, JSObject::kElementsOffset)); | 196 __ movp(elements, FieldOperand(receiver, JSObject::kElementsOffset)); |
| 196 if (not_fast_array != NULL) { | 197 __ AssertFastElements(elements); |
| 197 // Check that the object is in fast mode and writable. | |
| 198 __ CompareRoot(FieldOperand(elements, HeapObject::kMapOffset), | |
| 199 Heap::kFixedArrayMapRootIndex); | |
| 200 __ j(not_equal, not_fast_array); | |
| 201 } else { | |
| 202 __ AssertFastElements(elements); | |
| 203 } | |
| 204 // Check that the key (index) is within bounds. | 198 // Check that the key (index) is within bounds. |
| 205 __ SmiCompare(key, FieldOperand(elements, FixedArray::kLengthOffset)); | 199 __ SmiCompare(key, FieldOperand(elements, FixedArray::kLengthOffset)); |
| 206 // Unsigned comparison rejects negative indices. | 200 // Unsigned comparison rejects negative indices. |
| 207 __ j(above_equal, out_of_range); | 201 __ j(below, &in_bounds); |
| 202 |
| 203 // Out-of-bounds. Check the prototype chain to see if we can just return |
| 204 // 'undefined'. |
| 205 __ SmiCompare(key, Smi::FromInt(0)); |
| 206 __ j(less, slow); // Negative keys can't take the fast OOB path. |
| 207 __ bind(&check_prototypes); |
| 208 __ movp(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); |
| 209 __ bind(&check_next_prototype); |
| 210 __ movp(scratch, FieldOperand(scratch, Map::kPrototypeOffset)); |
| 211 // scratch: current prototype |
| 212 __ CompareRoot(scratch, Heap::kNullValueRootIndex); |
| 213 __ j(equal, &return_undefined); |
| 214 __ movp(elements, FieldOperand(scratch, JSObject::kElementsOffset)); |
| 215 __ movp(scratch, FieldOperand(scratch, HeapObject::kMapOffset)); |
| 216 // elements: elements of current prototype |
| 217 // scratch: map of current prototype |
| 218 __ CmpInstanceType(scratch, JS_OBJECT_TYPE); |
| 219 __ j(below, slow); |
| 220 __ testb(FieldOperand(scratch, Map::kBitFieldOffset), |
| 221 Immediate((1 << Map::kIsAccessCheckNeeded) | |
| 222 (1 << Map::kHasIndexedInterceptor))); |
| 223 __ j(not_zero, slow); |
| 224 __ CompareRoot(elements, Heap::kEmptyFixedArrayRootIndex); |
| 225 __ j(not_equal, slow); |
| 226 __ jmp(&check_next_prototype); |
| 227 |
| 228 __ bind(&return_undefined); |
| 229 __ LoadRoot(result, Heap::kUndefinedValueRootIndex); |
| 230 __ jmp(&done); |
| 231 |
| 232 __ bind(&in_bounds); |
| 208 // Fast case: Do the load. | 233 // Fast case: Do the load. |
| 209 SmiIndex index = masm->SmiToIndex(scratch, key, kPointerSizeLog2); | 234 SmiIndex index = masm->SmiToIndex(scratch, key, kPointerSizeLog2); |
| 210 __ movp(scratch, FieldOperand(elements, index.reg, index.scale, | 235 __ movp(scratch, FieldOperand(elements, index.reg, index.scale, |
| 211 FixedArray::kHeaderSize)); | 236 FixedArray::kHeaderSize)); |
| 212 __ CompareRoot(scratch, Heap::kTheHoleValueRootIndex); | 237 __ CompareRoot(scratch, Heap::kTheHoleValueRootIndex); |
| 213 // In case the loaded value is the_hole we have to consult GetProperty | 238 // In case the loaded value is the_hole we have to check the prototype chain. |
| 214 // to ensure the prototype chain is searched. | 239 __ j(equal, &check_prototypes); |
| 215 __ j(equal, out_of_range); | 240 __ Move(result, scratch); |
| 216 if (!result.is(scratch)) { | 241 __ bind(&done); |
| 217 __ movp(result, scratch); | |
| 218 } | |
| 219 } | 242 } |
| 220 | 243 |
| 221 | 244 |
| 222 // Checks whether a key is an array index string or a unique name. | 245 // Checks whether a key is an array index string or a unique name. |
| 223 // Falls through if the key is a unique name. | 246 // Falls through if the key is a unique name. |
| 224 static void GenerateKeyNameCheck(MacroAssembler* masm, Register key, | 247 static void GenerateKeyNameCheck(MacroAssembler* masm, Register key, |
| 225 Register map, Register hash, | 248 Register map, Register hash, |
| 226 Label* index_string, Label* not_unique) { | 249 Label* index_string, Label* not_unique) { |
| 227 // Register use: | 250 // Register use: |
| 228 // key - holds the key and is unchanged. Assumed to be non-smi. | 251 // key - holds the key and is unchanged. Assumed to be non-smi. |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 266 __ bind(&index_smi); | 289 __ bind(&index_smi); |
| 267 // Now the key is known to be a smi. This place is also jumped to from below | 290 // Now the key is known to be a smi. This place is also jumped to from below |
| 268 // where a numeric string is converted to a smi. | 291 // where a numeric string is converted to a smi. |
| 269 | 292 |
| 270 GenerateKeyedLoadReceiverCheck(masm, receiver, rax, | 293 GenerateKeyedLoadReceiverCheck(masm, receiver, rax, |
| 271 Map::kHasIndexedInterceptor, &slow); | 294 Map::kHasIndexedInterceptor, &slow); |
| 272 | 295 |
| 273 // Check the receiver's map to see if it has fast elements. | 296 // Check the receiver's map to see if it has fast elements. |
| 274 __ CheckFastElements(rax, &check_number_dictionary); | 297 __ CheckFastElements(rax, &check_number_dictionary); |
| 275 | 298 |
| 276 GenerateFastArrayLoad(masm, receiver, key, rax, rbx, rax, NULL, &slow); | 299 GenerateFastArrayLoad(masm, receiver, key, rax, rbx, rax, &slow); |
| 277 Counters* counters = masm->isolate()->counters(); | 300 Counters* counters = masm->isolate()->counters(); |
| 278 __ IncrementCounter(counters->keyed_load_generic_smi(), 1); | 301 __ IncrementCounter(counters->keyed_load_generic_smi(), 1); |
| 279 __ ret(0); | 302 __ ret(0); |
| 280 | 303 |
| 281 __ bind(&check_number_dictionary); | 304 __ bind(&check_number_dictionary); |
| 282 __ SmiToInteger32(rbx, key); | 305 __ SmiToInteger32(rbx, key); |
| 283 __ movp(rax, FieldOperand(receiver, JSObject::kElementsOffset)); | 306 __ movp(rax, FieldOperand(receiver, JSObject::kElementsOffset)); |
| 284 | 307 |
| 285 // Check whether the elements is a number dictionary. | 308 // Check whether the elements is a number dictionary. |
| 286 // rbx: key as untagged int32 | 309 // rbx: key as untagged int32 |
| (...skipping 703 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 990 Condition cc = | 1013 Condition cc = |
| 991 (check == ENABLE_INLINED_SMI_CHECK) | 1014 (check == ENABLE_INLINED_SMI_CHECK) |
| 992 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) | 1015 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) |
| 993 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); | 1016 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); |
| 994 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); | 1017 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); |
| 995 } | 1018 } |
| 996 } | 1019 } |
| 997 } // namespace v8::internal | 1020 } // namespace v8::internal |
| 998 | 1021 |
| 999 #endif // V8_TARGET_ARCH_X64 | 1022 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |