OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
227 } | 227 } |
228 #endif | 228 #endif |
229 | 229 |
230 | 230 |
231 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { | 231 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { |
232 // ----------- S t a t e ------------- | 232 // ----------- S t a t e ------------- |
233 // -- esp[0] : return address | 233 // -- esp[0] : return address |
234 // -- esp[4] : name | 234 // -- esp[4] : name |
235 // -- esp[8] : receiver | 235 // -- esp[8] : receiver |
236 // ----------------------------------- | 236 // ----------------------------------- |
237 Label slow, fast, check_string, index_int, index_string; | 237 Label slow, check_string, index_int, index_string, check_pixel_array; |
238 | 238 |
239 // Load name and receiver. | 239 // Load name and receiver. |
240 __ mov(eax, Operand(esp, kPointerSize)); | 240 __ mov(eax, Operand(esp, kPointerSize)); |
241 __ mov(ecx, Operand(esp, 2 * kPointerSize)); | 241 __ mov(ecx, Operand(esp, 2 * kPointerSize)); |
242 | 242 |
243 // Check that the object isn't a smi. | 243 // Check that the object isn't a smi. |
244 __ test(ecx, Immediate(kSmiTagMask)); | 244 __ test(ecx, Immediate(kSmiTagMask)); |
245 __ j(zero, &slow, not_taken); | 245 __ j(zero, &slow, not_taken); |
246 | 246 |
247 // Get the map of the receiver. | 247 // Get the map of the receiver. |
(...skipping 14 matching lines...) Expand all Loading... |
262 __ j(less, &slow, not_taken); | 262 __ j(less, &slow, not_taken); |
263 // Check that the key is a smi. | 263 // Check that the key is a smi. |
264 __ test(eax, Immediate(kSmiTagMask)); | 264 __ test(eax, Immediate(kSmiTagMask)); |
265 __ j(not_zero, &check_string, not_taken); | 265 __ j(not_zero, &check_string, not_taken); |
266 __ sar(eax, kSmiTagSize); | 266 __ sar(eax, kSmiTagSize); |
267 // Get the elements array of the object. | 267 // Get the elements array of the object. |
268 __ bind(&index_int); | 268 __ bind(&index_int); |
269 __ mov(ecx, FieldOperand(ecx, JSObject::kElementsOffset)); | 269 __ mov(ecx, FieldOperand(ecx, JSObject::kElementsOffset)); |
270 // Check that the object is in fast mode (not dictionary). | 270 // Check that the object is in fast mode (not dictionary). |
271 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), | 271 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), |
272 Immediate(Factory::hash_table_map())); | 272 Immediate(Factory::fixed_array_map())); |
273 __ j(equal, &slow, not_taken); | 273 __ j(not_equal, &check_pixel_array); |
274 // Check that the key (index) is within bounds. | 274 // Check that the key (index) is within bounds. |
275 __ cmp(eax, FieldOperand(ecx, FixedArray::kLengthOffset)); | 275 __ cmp(eax, FieldOperand(ecx, FixedArray::kLengthOffset)); |
276 __ j(below, &fast, taken); | 276 __ j(above_equal, &slow); |
| 277 // Fast case: Do the load. |
| 278 __ mov(eax, |
| 279 Operand(ecx, eax, times_4, FixedArray::kHeaderSize - kHeapObjectTag)); |
| 280 __ cmp(Operand(eax), Immediate(Factory::the_hole_value())); |
| 281 // In case the loaded value is the_hole we have to consult GetProperty |
| 282 // to ensure the prototype chain is searched. |
| 283 __ j(equal, &slow); |
| 284 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1); |
| 285 __ ret(0); |
| 286 |
| 287 // Check whether the elements is a pixel array. |
| 288 // eax: untagged index |
| 289 // ecx: elements array |
| 290 __ bind(&check_pixel_array); |
| 291 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), |
| 292 Immediate(Factory::pixel_array_map())); |
| 293 __ j(not_equal, &slow); |
| 294 __ cmp(eax, FieldOperand(ecx, PixelArray::kLengthOffset)); |
| 295 __ j(above_equal, &slow); |
| 296 __ mov(ecx, FieldOperand(ecx, PixelArray::kExternalPointerOffset)); |
| 297 __ movzx_b(eax, Operand(ecx, eax, times_1, 0)); |
| 298 __ shl(eax, kSmiTagSize); |
| 299 __ ret(0); |
| 300 |
| 301 |
277 // Slow case: Load name and receiver from stack and jump to runtime. | 302 // Slow case: Load name and receiver from stack and jump to runtime. |
278 __ bind(&slow); | 303 __ bind(&slow); |
279 __ IncrementCounter(&Counters::keyed_load_generic_slow, 1); | 304 __ IncrementCounter(&Counters::keyed_load_generic_slow, 1); |
280 KeyedLoadIC::Generate(masm, ExternalReference(Runtime::kKeyedGetProperty)); | 305 KeyedLoadIC::Generate(masm, ExternalReference(Runtime::kKeyedGetProperty)); |
281 | 306 |
282 __ bind(&check_string); | 307 __ bind(&check_string); |
283 // The key is not a smi. | 308 // The key is not a smi. |
284 // Is it a string? | 309 // Is it a string? |
285 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edx); | 310 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edx); |
286 __ j(above_equal, &slow); | 311 __ j(above_equal, &slow); |
(...skipping 21 matching lines...) Expand all Loading... |
308 (1 << (String::kShortLengthShift - String::kHashShift))); | 333 (1 << (String::kShortLengthShift - String::kHashShift))); |
309 __ bind(&index_string); | 334 __ bind(&index_string); |
310 const int kLengthFieldLimit = | 335 const int kLengthFieldLimit = |
311 (String::kMaxCachedArrayIndexLength + 1) << String::kShortLengthShift; | 336 (String::kMaxCachedArrayIndexLength + 1) << String::kShortLengthShift; |
312 __ cmp(ebx, kLengthFieldLimit); | 337 __ cmp(ebx, kLengthFieldLimit); |
313 __ j(above_equal, &slow); | 338 __ j(above_equal, &slow); |
314 __ mov(eax, Operand(ebx)); | 339 __ mov(eax, Operand(ebx)); |
315 __ and_(eax, (1 << String::kShortLengthShift) - 1); | 340 __ and_(eax, (1 << String::kShortLengthShift) - 1); |
316 __ shr(eax, String::kLongLengthShift); | 341 __ shr(eax, String::kLongLengthShift); |
317 __ jmp(&index_int); | 342 __ jmp(&index_int); |
318 // Fast case: Do the load. | |
319 __ bind(&fast); | |
320 __ mov(eax, | |
321 Operand(ecx, eax, times_4, FixedArray::kHeaderSize - kHeapObjectTag)); | |
322 __ cmp(Operand(eax), Immediate(Factory::the_hole_value())); | |
323 // In case the loaded value is the_hole we have to consult GetProperty | |
324 // to ensure the prototype chain is searched. | |
325 __ j(equal, &slow, not_taken); | |
326 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1); | |
327 __ ret(0); | |
328 } | 343 } |
329 | 344 |
330 | 345 |
331 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) { | 346 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) { |
332 // ----------- S t a t e ------------- | 347 // ----------- S t a t e ------------- |
333 // -- eax : value | 348 // -- eax : value |
334 // -- esp[0] : return address | 349 // -- esp[0] : return address |
335 // -- esp[4] : key | 350 // -- esp[4] : key |
336 // -- esp[8] : receiver | 351 // -- esp[8] : receiver |
337 // ----------------------------------- | 352 // ----------------------------------- |
338 Label slow, fast, array, extra; | 353 Label slow, fast, array, extra, check_pixel_array; |
339 | 354 |
340 // Get the receiver from the stack. | 355 // Get the receiver from the stack. |
341 __ mov(edx, Operand(esp, 2 * kPointerSize)); // 2 ~ return address, key | 356 __ mov(edx, Operand(esp, 2 * kPointerSize)); // 2 ~ return address, key |
342 // Check that the object isn't a smi. | 357 // Check that the object isn't a smi. |
343 __ test(edx, Immediate(kSmiTagMask)); | 358 __ test(edx, Immediate(kSmiTagMask)); |
344 __ j(zero, &slow, not_taken); | 359 __ j(zero, &slow, not_taken); |
345 // Get the map from the receiver. | 360 // Get the map from the receiver. |
346 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); | 361 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); |
347 // Check that the receiver does not require access checks. We need | 362 // Check that the receiver does not require access checks. We need |
348 // to do this because this generic stub does not perform map checks. | 363 // to do this because this generic stub does not perform map checks. |
(...skipping 14 matching lines...) Expand all Loading... |
363 __ cmp(ecx, FIRST_JS_OBJECT_TYPE); | 378 __ cmp(ecx, FIRST_JS_OBJECT_TYPE); |
364 __ j(less, &slow, not_taken); | 379 __ j(less, &slow, not_taken); |
365 | 380 |
366 // Object case: Check key against length in the elements array. | 381 // Object case: Check key against length in the elements array. |
367 // eax: value | 382 // eax: value |
368 // edx: JSObject | 383 // edx: JSObject |
369 // ebx: index (as a smi) | 384 // ebx: index (as a smi) |
370 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); | 385 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); |
371 // Check that the object is in fast mode (not dictionary). | 386 // Check that the object is in fast mode (not dictionary). |
372 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), | 387 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), |
373 Immediate(Factory::hash_table_map())); | 388 Immediate(Factory::fixed_array_map())); |
374 __ j(equal, &slow, not_taken); | 389 __ j(not_equal, &check_pixel_array, not_taken); |
375 // Untag the key (for checking against untagged length in the fixed array). | 390 // Untag the key (for checking against untagged length in the fixed array). |
376 __ mov(edx, Operand(ebx)); | 391 __ mov(edx, Operand(ebx)); |
377 __ sar(edx, kSmiTagSize); // untag the index and use it for the comparison | 392 __ sar(edx, kSmiTagSize); // untag the index and use it for the comparison |
378 __ cmp(edx, FieldOperand(ecx, Array::kLengthOffset)); | 393 __ cmp(edx, FieldOperand(ecx, Array::kLengthOffset)); |
379 // eax: value | 394 // eax: value |
380 // ecx: FixedArray | 395 // ecx: FixedArray |
381 // ebx: index (as a smi) | 396 // ebx: index (as a smi) |
382 __ j(below, &fast, taken); | 397 __ j(below, &fast, taken); |
383 | 398 |
384 | |
385 // Slow case: Push extra copies of the arguments (3). | 399 // Slow case: Push extra copies of the arguments (3). |
386 __ bind(&slow); | 400 __ bind(&slow); |
387 __ pop(ecx); | 401 __ pop(ecx); |
388 __ push(Operand(esp, 1 * kPointerSize)); | 402 __ push(Operand(esp, 1 * kPointerSize)); |
389 __ push(Operand(esp, 1 * kPointerSize)); | 403 __ push(Operand(esp, 1 * kPointerSize)); |
390 __ push(eax); | 404 __ push(eax); |
391 __ push(ecx); | 405 __ push(ecx); |
392 // Do tail-call to runtime routine. | 406 // Do tail-call to runtime routine. |
393 __ TailCallRuntime(ExternalReference(Runtime::kSetProperty), 3); | 407 __ TailCallRuntime(ExternalReference(Runtime::kSetProperty), 3); |
394 | 408 |
| 409 // Check whether the elements is a pixel array. |
| 410 // eax: value |
| 411 // ecx: elements array |
| 412 // ebx: index (as a smi) |
| 413 __ bind(&check_pixel_array); |
| 414 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), |
| 415 Immediate(Factory::pixel_array_map())); |
| 416 __ j(not_equal, &slow); |
| 417 // Check that the value is a smi. If a conversion is needed call into the |
| 418 // runtime to convert and clamp. |
| 419 __ test(eax, Immediate(kSmiTagMask)); |
| 420 __ j(not_zero, &slow); |
| 421 __ sar(ebx, kSmiTagSize); // Untag the index. |
| 422 __ cmp(ebx, FieldOperand(ecx, PixelArray::kLengthOffset)); |
| 423 __ j(above_equal, &slow); |
| 424 __ sar(eax, kSmiTagSize); // Untag the value. |
| 425 { // Clamp the value to [0..255]. |
| 426 Label done, check_255; |
| 427 __ cmp(eax, 0); |
| 428 __ j(greater_equal, &check_255); |
| 429 __ mov(eax, Immediate(0)); |
| 430 __ jmp(&done); |
| 431 __ bind(&check_255); |
| 432 __ cmp(eax, 255); |
| 433 __ j(less_equal, &done); |
| 434 __ mov(eax, Immediate(255)); |
| 435 __ bind(&done); |
| 436 } |
| 437 __ mov(ecx, FieldOperand(ecx, PixelArray::kExternalPointerOffset)); |
| 438 __ mov_b(Operand(ecx, ebx, times_1, 0), eax); |
| 439 __ ret(0); |
395 | 440 |
396 // Extra capacity case: Check if there is extra capacity to | 441 // Extra capacity case: Check if there is extra capacity to |
397 // perform the store and update the length. Used for adding one | 442 // perform the store and update the length. Used for adding one |
398 // element to the array by writing to array[array.length]. | 443 // element to the array by writing to array[array.length]. |
399 __ bind(&extra); | 444 __ bind(&extra); |
400 // eax: value | 445 // eax: value |
401 // edx: JSArray | 446 // edx: JSArray |
402 // ecx: FixedArray | 447 // ecx: FixedArray |
403 // ebx: index (as a smi) | 448 // ebx: index (as a smi) |
404 // flags: compare (ebx, edx.length()) | 449 // flags: compare (ebx, edx.length()) |
(...skipping 10 matching lines...) Expand all Loading... |
415 | 460 |
416 // Array case: Get the length and the elements array from the JS | 461 // Array case: Get the length and the elements array from the JS |
417 // array. Check that the array is in fast mode; if it is the | 462 // array. Check that the array is in fast mode; if it is the |
418 // length is always a smi. | 463 // length is always a smi. |
419 __ bind(&array); | 464 __ bind(&array); |
420 // eax: value | 465 // eax: value |
421 // edx: JSArray | 466 // edx: JSArray |
422 // ebx: index (as a smi) | 467 // ebx: index (as a smi) |
423 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); | 468 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); |
424 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), | 469 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), |
425 Immediate(Factory::hash_table_map())); | 470 Immediate(Factory::fixed_array_map())); |
426 __ j(equal, &slow, not_taken); | 471 __ j(not_equal, &check_pixel_array); |
427 | 472 |
428 // Check the key against the length in the array, compute the | 473 // Check the key against the length in the array, compute the |
429 // address to store into and fall through to fast case. | 474 // address to store into and fall through to fast case. |
430 __ cmp(ebx, FieldOperand(edx, JSArray::kLengthOffset)); | 475 __ cmp(ebx, FieldOperand(edx, JSArray::kLengthOffset)); |
431 __ j(above_equal, &extra, not_taken); | 476 __ j(above_equal, &extra, not_taken); |
432 | 477 |
433 | |
434 // Fast case: Do the store. | 478 // Fast case: Do the store. |
435 __ bind(&fast); | 479 __ bind(&fast); |
436 // eax: value | 480 // eax: value |
437 // ecx: FixedArray | 481 // ecx: FixedArray |
438 // ebx: index (as a smi) | 482 // ebx: index (as a smi) |
439 __ mov(Operand(ecx, ebx, times_2, FixedArray::kHeaderSize - kHeapObjectTag), | 483 __ mov(Operand(ecx, ebx, times_2, FixedArray::kHeaderSize - kHeapObjectTag), |
440 eax); | 484 eax); |
441 // Update write barrier for the elements array address. | 485 // Update write barrier for the elements array address. |
442 __ mov(edx, Operand(eax)); | 486 __ mov(edx, Operand(eax)); |
443 __ RecordWrite(ecx, 0, edx, ebx); | 487 __ RecordWrite(ecx, 0, edx, ebx); |
(...skipping 542 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
986 | 1030 |
987 // Do tail-call to runtime routine. | 1031 // Do tail-call to runtime routine. |
988 __ TailCallRuntime( | 1032 __ TailCallRuntime( |
989 ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3); | 1033 ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3); |
990 } | 1034 } |
991 | 1035 |
992 #undef __ | 1036 #undef __ |
993 | 1037 |
994 | 1038 |
995 } } // namespace v8::internal | 1039 } } // namespace v8::internal |
OLD | NEW |