| 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_X87 | 7 #if V8_TARGET_ARCH_X87 |
| 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 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 162 // we enter the runtime system to make sure that indexing | 162 // we enter the runtime system to make sure that indexing |
| 163 // into string objects works as intended. | 163 // into string objects works as intended. |
| 164 DCHECK(JS_OBJECT_TYPE > JS_VALUE_TYPE); | 164 DCHECK(JS_OBJECT_TYPE > JS_VALUE_TYPE); |
| 165 | 165 |
| 166 __ CmpInstanceType(map, JS_OBJECT_TYPE); | 166 __ CmpInstanceType(map, JS_OBJECT_TYPE); |
| 167 __ j(below, slow); | 167 __ j(below, slow); |
| 168 } | 168 } |
| 169 | 169 |
| 170 | 170 |
| 171 // Loads an indexed element from a fast case array. | 171 // Loads an indexed element from a fast case array. |
| 172 // If not_fast_array is NULL, doesn't perform the elements map check. | |
| 173 static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, | 172 static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, |
| 174 Register key, Register scratch, | 173 Register key, Register scratch, |
| 175 Register result, Label* not_fast_array, | 174 Register scratch2, Register result, |
| 176 Label* out_of_range) { | 175 Label* slow) { |
| 177 // Register use: | 176 // Register use: |
| 178 // receiver - holds the receiver and is unchanged. | 177 // receiver - holds the receiver and is unchanged. |
| 179 // key - holds the key and is unchanged (must be a smi). | 178 // key - holds the key and is unchanged (must be a smi). |
| 180 // Scratch registers: | 179 // Scratch registers: |
| 181 // scratch - used to hold elements of the receiver and the loaded value. | 180 // scratch - used to hold elements of the receiver and the loaded value. |
| 181 // scratch2 - holds maps and prototypes during prototype chain check. |
| 182 // result - holds the result on exit if the load succeeds and | 182 // result - holds the result on exit if the load succeeds and |
| 183 // we fall through. | 183 // we fall through. |
| 184 Label check_prototypes, check_next_prototype; |
| 185 Label done, in_bounds, return_undefined; |
| 184 | 186 |
| 185 __ mov(scratch, FieldOperand(receiver, JSObject::kElementsOffset)); | 187 __ mov(scratch, FieldOperand(receiver, JSObject::kElementsOffset)); |
| 186 if (not_fast_array != NULL) { | 188 __ AssertFastElements(scratch); |
| 187 // Check that the object is in fast mode and writable. | 189 |
| 188 __ CheckMap(scratch, | |
| 189 masm->isolate()->factory()->fixed_array_map(), | |
| 190 not_fast_array, | |
| 191 DONT_DO_SMI_CHECK); | |
| 192 } else { | |
| 193 __ AssertFastElements(scratch); | |
| 194 } | |
| 195 // Check that the key (index) is within bounds. | 190 // Check that the key (index) is within bounds. |
| 196 __ cmp(key, FieldOperand(scratch, FixedArray::kLengthOffset)); | 191 __ cmp(key, FieldOperand(scratch, FixedArray::kLengthOffset)); |
| 197 __ j(above_equal, out_of_range); | 192 __ j(below, &in_bounds); |
| 193 // Out-of-bounds. Check the prototype chain to see if we can just return |
| 194 // 'undefined'. |
| 195 __ cmp(key, 0); |
| 196 __ j(less, slow); // Negative keys can't take the fast OOB path. |
| 197 __ bind(&check_prototypes); |
| 198 __ mov(scratch2, FieldOperand(receiver, HeapObject::kMapOffset)); |
| 199 __ bind(&check_next_prototype); |
| 200 __ mov(scratch2, FieldOperand(scratch2, Map::kPrototypeOffset)); |
| 201 // scratch2: current prototype |
| 202 __ cmp(scratch2, masm->isolate()->factory()->null_value()); |
| 203 __ j(equal, &return_undefined); |
| 204 __ mov(scratch, FieldOperand(scratch2, JSObject::kElementsOffset)); |
| 205 __ mov(scratch2, FieldOperand(scratch2, HeapObject::kMapOffset)); |
| 206 // scratch: elements of current prototype |
| 207 // scratch2: map of current prototype |
| 208 __ CmpInstanceType(scratch2, JS_OBJECT_TYPE); |
| 209 __ j(below, slow); |
| 210 __ test_b( |
| 211 FieldOperand(scratch2, Map::kBitFieldOffset), |
| 212 (1 << Map::kIsAccessCheckNeeded) | (1 << Map::kHasIndexedInterceptor)); |
| 213 __ j(not_zero, slow); |
| 214 __ cmp(scratch, masm->isolate()->factory()->empty_fixed_array()); |
| 215 __ j(not_equal, slow); |
| 216 __ jmp(&check_next_prototype); |
| 217 |
| 218 __ bind(&return_undefined); |
| 219 __ mov(result, masm->isolate()->factory()->undefined_value()); |
| 220 __ jmp(&done); |
| 221 |
| 222 __ bind(&in_bounds); |
| 198 // Fast case: Do the load. | 223 // Fast case: Do the load. |
| 199 STATIC_ASSERT((kPointerSize == 4) && (kSmiTagSize == 1) && (kSmiTag == 0)); | 224 STATIC_ASSERT((kPointerSize == 4) && (kSmiTagSize == 1) && (kSmiTag == 0)); |
| 200 __ mov(scratch, FieldOperand(scratch, key, times_2, FixedArray::kHeaderSize)); | 225 __ mov(scratch, FieldOperand(scratch, key, times_2, FixedArray::kHeaderSize)); |
| 201 __ cmp(scratch, Immediate(masm->isolate()->factory()->the_hole_value())); | 226 __ cmp(scratch, Immediate(masm->isolate()->factory()->the_hole_value())); |
| 202 // In case the loaded value is the_hole we have to consult GetProperty | 227 // In case the loaded value is the_hole we have to check the prototype chain. |
| 203 // to ensure the prototype chain is searched. | 228 __ j(equal, &check_prototypes); |
| 204 __ j(equal, out_of_range); | 229 __ Move(result, scratch); |
| 205 if (!result.is(scratch)) { | 230 __ bind(&done); |
| 206 __ mov(result, scratch); | |
| 207 } | |
| 208 } | 231 } |
| 209 | 232 |
| 210 | 233 |
| 211 // Checks whether a key is an array index string or a unique name. | 234 // Checks whether a key is an array index string or a unique name. |
| 212 // Falls through if the key is a unique name. | 235 // Falls through if the key is a unique name. |
| 213 static void GenerateKeyNameCheck(MacroAssembler* masm, Register key, | 236 static void GenerateKeyNameCheck(MacroAssembler* masm, Register key, |
| 214 Register map, Register hash, | 237 Register map, Register hash, |
| 215 Label* index_string, Label* not_unique) { | 238 Label* index_string, Label* not_unique) { |
| 216 // Register use: | 239 // Register use: |
| 217 // key - holds the key and is unchanged. Assumed to be non-smi. | 240 // key - holds the key and is unchanged. Assumed to be non-smi. |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 322 __ bind(&index_smi); | 345 __ bind(&index_smi); |
| 323 // Now the key is known to be a smi. This place is also jumped to from | 346 // Now the key is known to be a smi. This place is also jumped to from |
| 324 // where a numeric string is converted to a smi. | 347 // where a numeric string is converted to a smi. |
| 325 | 348 |
| 326 GenerateKeyedLoadReceiverCheck(masm, receiver, eax, | 349 GenerateKeyedLoadReceiverCheck(masm, receiver, eax, |
| 327 Map::kHasIndexedInterceptor, &slow); | 350 Map::kHasIndexedInterceptor, &slow); |
| 328 | 351 |
| 329 // Check the receiver's map to see if it has fast elements. | 352 // Check the receiver's map to see if it has fast elements. |
| 330 __ CheckFastElements(eax, &check_number_dictionary); | 353 __ CheckFastElements(eax, &check_number_dictionary); |
| 331 | 354 |
| 332 GenerateFastArrayLoad(masm, receiver, key, eax, eax, NULL, &slow); | 355 GenerateFastArrayLoad(masm, receiver, key, eax, ebx, eax, &slow); |
| 333 Isolate* isolate = masm->isolate(); | 356 Isolate* isolate = masm->isolate(); |
| 334 Counters* counters = isolate->counters(); | 357 Counters* counters = isolate->counters(); |
| 335 __ IncrementCounter(counters->keyed_load_generic_smi(), 1); | 358 __ IncrementCounter(counters->keyed_load_generic_smi(), 1); |
| 336 __ ret(0); | 359 __ ret(0); |
| 337 | 360 |
| 338 __ bind(&check_number_dictionary); | 361 __ bind(&check_number_dictionary); |
| 339 __ mov(ebx, key); | 362 __ mov(ebx, key); |
| 340 __ SmiUntag(ebx); | 363 __ SmiUntag(ebx); |
| 341 __ mov(eax, FieldOperand(receiver, JSObject::kElementsOffset)); | 364 __ mov(eax, FieldOperand(receiver, JSObject::kElementsOffset)); |
| 342 | 365 |
| (...skipping 652 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 995 Condition cc = | 1018 Condition cc = |
| 996 (check == ENABLE_INLINED_SMI_CHECK) | 1019 (check == ENABLE_INLINED_SMI_CHECK) |
| 997 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) | 1020 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) |
| 998 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); | 1021 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); |
| 999 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); | 1022 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); |
| 1000 } | 1023 } |
| 1001 } | 1024 } |
| 1002 } // namespace v8::internal | 1025 } // namespace v8::internal |
| 1003 | 1026 |
| 1004 #endif // V8_TARGET_ARCH_X87 | 1027 #endif // V8_TARGET_ARCH_X87 |
| OLD | NEW |