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_IA32 | 7 #if V8_TARGET_ARCH_IA32 |
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, masm->isolate()->factory()->fixed_array_map(), | |
189 not_fast_array, DONT_DO_SMI_CHECK); | |
190 } else { | |
191 __ AssertFastElements(scratch); | |
192 } | |
193 // Check that the key (index) is within bounds. | 190 // Check that the key (index) is within bounds. |
194 __ cmp(key, FieldOperand(scratch, FixedArray::kLengthOffset)); | 191 __ cmp(key, FieldOperand(scratch, FixedArray::kLengthOffset)); |
195 __ 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); |
196 // Fast case: Do the load. | 223 // Fast case: Do the load. |
197 STATIC_ASSERT((kPointerSize == 4) && (kSmiTagSize == 1) && (kSmiTag == 0)); | 224 STATIC_ASSERT((kPointerSize == 4) && (kSmiTagSize == 1) && (kSmiTag == 0)); |
198 __ mov(scratch, FieldOperand(scratch, key, times_2, FixedArray::kHeaderSize)); | 225 __ mov(scratch, FieldOperand(scratch, key, times_2, FixedArray::kHeaderSize)); |
199 __ cmp(scratch, Immediate(masm->isolate()->factory()->the_hole_value())); | 226 __ cmp(scratch, Immediate(masm->isolate()->factory()->the_hole_value())); |
200 // 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. |
201 // to ensure the prototype chain is searched. | 228 __ j(equal, &check_prototypes); |
202 __ j(equal, out_of_range); | 229 __ Move(result, scratch); |
203 if (!result.is(scratch)) { | 230 __ bind(&done); |
204 __ mov(result, scratch); | |
205 } | |
206 } | 231 } |
207 | 232 |
208 | 233 |
209 // 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. |
210 // Falls through if the key is a unique name. | 235 // Falls through if the key is a unique name. |
211 static void GenerateKeyNameCheck(MacroAssembler* masm, Register key, | 236 static void GenerateKeyNameCheck(MacroAssembler* masm, Register key, |
212 Register map, Register hash, | 237 Register map, Register hash, |
213 Label* index_string, Label* not_unique) { | 238 Label* index_string, Label* not_unique) { |
214 // Register use: | 239 // Register use: |
215 // 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... |
320 __ bind(&index_smi); | 345 __ bind(&index_smi); |
321 // 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 |
322 // where a numeric string is converted to a smi. | 347 // where a numeric string is converted to a smi. |
323 | 348 |
324 GenerateKeyedLoadReceiverCheck(masm, receiver, eax, | 349 GenerateKeyedLoadReceiverCheck(masm, receiver, eax, |
325 Map::kHasIndexedInterceptor, &slow); | 350 Map::kHasIndexedInterceptor, &slow); |
326 | 351 |
327 // 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. |
328 __ CheckFastElements(eax, &check_number_dictionary); | 353 __ CheckFastElements(eax, &check_number_dictionary); |
329 | 354 |
330 GenerateFastArrayLoad(masm, receiver, key, eax, eax, NULL, &slow); | 355 GenerateFastArrayLoad(masm, receiver, key, eax, ebx, eax, &slow); |
331 Isolate* isolate = masm->isolate(); | 356 Isolate* isolate = masm->isolate(); |
332 Counters* counters = isolate->counters(); | 357 Counters* counters = isolate->counters(); |
333 __ IncrementCounter(counters->keyed_load_generic_smi(), 1); | 358 __ IncrementCounter(counters->keyed_load_generic_smi(), 1); |
334 __ ret(0); | 359 __ ret(0); |
335 | 360 |
336 __ bind(&check_number_dictionary); | 361 __ bind(&check_number_dictionary); |
337 __ mov(ebx, key); | 362 __ mov(ebx, key); |
338 __ SmiUntag(ebx); | 363 __ SmiUntag(ebx); |
339 __ mov(eax, FieldOperand(receiver, JSObject::kElementsOffset)); | 364 __ mov(eax, FieldOperand(receiver, JSObject::kElementsOffset)); |
340 | 365 |
(...skipping 652 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
993 Condition cc = | 1018 Condition cc = |
994 (check == ENABLE_INLINED_SMI_CHECK) | 1019 (check == ENABLE_INLINED_SMI_CHECK) |
995 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) | 1020 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) |
996 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); | 1021 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); |
997 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); | 1022 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); |
998 } | 1023 } |
999 } | 1024 } |
1000 } // namespace v8::internal | 1025 } // namespace v8::internal |
1001 | 1026 |
1002 #endif // V8_TARGET_ARCH_IA32 | 1027 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |