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 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
295 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); | 295 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); |
296 } | 296 } |
297 | 297 |
298 | 298 |
299 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { | 299 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { |
300 // ----------- S t a t e ------------- | 300 // ----------- S t a t e ------------- |
301 // -- eax : key | 301 // -- eax : key |
302 // -- edx : receiver | 302 // -- edx : receiver |
303 // -- esp[0] : return address | 303 // -- esp[0] : return address |
304 // ----------------------------------- | 304 // ----------------------------------- |
305 Label slow, check_string, index_int, index_string; | 305 Label slow, check_string, index_smi, index_string; |
306 Label check_pixel_array, probe_dictionary; | 306 Label check_pixel_array, probe_dictionary; |
307 Label check_number_dictionary; | 307 Label check_number_dictionary; |
308 | 308 |
309 // Check that the object isn't a smi. | 309 // Check that the object isn't a smi. |
310 __ test(edx, Immediate(kSmiTagMask)); | 310 __ test(edx, Immediate(kSmiTagMask)); |
311 __ j(zero, &slow, not_taken); | 311 __ j(zero, &slow, not_taken); |
312 | 312 |
313 // Get the map of the receiver. | 313 // Get the map of the receiver. |
314 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); | 314 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); |
315 | 315 |
316 // Check bit field. | 316 // Check bit field. |
317 __ movzx_b(ebx, FieldOperand(ecx, Map::kBitFieldOffset)); | 317 __ movzx_b(ebx, FieldOperand(ecx, Map::kBitFieldOffset)); |
318 __ test(ebx, Immediate(kSlowCaseBitFieldMask)); | 318 __ test(ebx, Immediate(kSlowCaseBitFieldMask)); |
319 __ j(not_zero, &slow, not_taken); | 319 __ j(not_zero, &slow, not_taken); |
320 // Check that the object is some kind of JS object EXCEPT JS Value type. | 320 // Check that the object is some kind of JS object EXCEPT JS Value type. |
321 // In the case that the object is a value-wrapper object, | 321 // In the case that the object is a value-wrapper object, |
322 // we enter the runtime system to make sure that indexing | 322 // we enter the runtime system to make sure that indexing |
323 // into string objects work as intended. | 323 // into string objects work as intended. |
324 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE); | 324 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE); |
325 __ CmpInstanceType(ecx, JS_OBJECT_TYPE); | 325 __ CmpInstanceType(ecx, JS_OBJECT_TYPE); |
326 __ j(below, &slow, not_taken); | 326 __ j(below, &slow, not_taken); |
327 // Check that the key is a smi. | 327 // Check that the key is a smi. |
328 __ test(eax, Immediate(kSmiTagMask)); | 328 __ test(eax, Immediate(kSmiTagMask)); |
329 __ j(not_zero, &check_string, not_taken); | 329 __ j(not_zero, &check_string, not_taken); |
330 __ mov(ebx, eax); | |
331 __ SmiUntag(ebx); | |
332 // Get the elements array of the object. | 330 // Get the elements array of the object. |
333 __ bind(&index_int); | 331 __ bind(&index_smi); |
334 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); | 332 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); |
335 // Check that the object is in fast mode (not dictionary). | 333 // Check that the object is in fast mode (not dictionary). |
336 __ CheckMap(ecx, Factory::fixed_array_map(), &check_pixel_array, true); | 334 __ CheckMap(ecx, Factory::fixed_array_map(), &check_pixel_array, true); |
337 // Check that the key (index) is within bounds. | 335 // Check that the key (index) is within bounds. |
338 __ cmp(ebx, FieldOperand(ecx, FixedArray::kLengthOffset)); | 336 __ cmp(eax, FieldOperand(ecx, FixedArray::kLengthOffset)); |
339 __ j(above_equal, &slow); | 337 __ j(above_equal, &slow); |
340 // Fast case: Do the load. | 338 // Fast case: Do the load. |
341 __ mov(ecx, FieldOperand(ecx, ebx, times_4, FixedArray::kHeaderSize)); | 339 ASSERT((kPointerSize == 4) && (kSmiTagSize == 1) && (kSmiTag == 0)); |
| 340 __ mov(ecx, FieldOperand(ecx, eax, times_2, FixedArray::kHeaderSize)); |
342 __ cmp(Operand(ecx), Immediate(Factory::the_hole_value())); | 341 __ cmp(Operand(ecx), Immediate(Factory::the_hole_value())); |
343 // In case the loaded value is the_hole we have to consult GetProperty | 342 // In case the loaded value is the_hole we have to consult GetProperty |
344 // to ensure the prototype chain is searched. | 343 // to ensure the prototype chain is searched. |
345 __ j(equal, &slow); | 344 __ j(equal, &slow); |
346 __ mov(eax, ecx); | 345 __ mov(eax, ecx); |
347 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1); | 346 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1); |
348 __ ret(0); | 347 __ ret(0); |
349 | 348 |
350 __ bind(&check_pixel_array); | 349 __ bind(&check_pixel_array); |
351 // Check whether the elements is a pixel array. | 350 // Check whether the elements is a pixel array. |
352 // edx: receiver | 351 // edx: receiver |
353 // ebx: untagged index | |
354 // eax: key | 352 // eax: key |
355 // ecx: elements | 353 // ecx: elements |
| 354 __ mov(ebx, eax); |
| 355 __ SmiUntag(ebx); |
356 __ CheckMap(ecx, Factory::pixel_array_map(), &check_number_dictionary, true); | 356 __ CheckMap(ecx, Factory::pixel_array_map(), &check_number_dictionary, true); |
357 __ cmp(ebx, FieldOperand(ecx, PixelArray::kLengthOffset)); | 357 __ cmp(ebx, FieldOperand(ecx, PixelArray::kLengthOffset)); |
358 __ j(above_equal, &slow); | 358 __ j(above_equal, &slow); |
359 __ mov(eax, FieldOperand(ecx, PixelArray::kExternalPointerOffset)); | 359 __ mov(eax, FieldOperand(ecx, PixelArray::kExternalPointerOffset)); |
360 __ movzx_b(eax, Operand(eax, ebx, times_1, 0)); | 360 __ movzx_b(eax, Operand(eax, ebx, times_1, 0)); |
361 __ SmiTag(eax); | 361 __ SmiTag(eax); |
362 __ ret(0); | 362 __ ret(0); |
363 | 363 |
364 __ bind(&check_number_dictionary); | 364 __ bind(&check_number_dictionary); |
365 // Check whether the elements is a number dictionary. | 365 // Check whether the elements is a number dictionary. |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
476 __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1); | 476 __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1); |
477 __ ret(0); | 477 __ ret(0); |
478 | 478 |
479 // If the hash field contains an array index pick it out. The assert checks | 479 // If the hash field contains an array index pick it out. The assert checks |
480 // that the constants for the maximum number of digits for an array index | 480 // that the constants for the maximum number of digits for an array index |
481 // cached in the hash field and the number of bits reserved for it does not | 481 // cached in the hash field and the number of bits reserved for it does not |
482 // conflict. | 482 // conflict. |
483 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) < | 483 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) < |
484 (1 << String::kArrayIndexValueBits)); | 484 (1 << String::kArrayIndexValueBits)); |
485 __ bind(&index_string); | 485 __ bind(&index_string); |
486 __ and_(ebx, String::kArrayIndexHashMask); | 486 // We want the smi-tagged index in eax. kArrayIndexValueMask has zeros in |
487 __ shr(ebx, String::kHashShift); | 487 // the low kHashShift bits. |
488 __ jmp(&index_int); | 488 ASSERT(String::kHashShift >= kSmiTagSize); |
| 489 __ and_(ebx, String::kArrayIndexValueMask); |
| 490 __ shr(ebx, String::kHashShift - kSmiTagSize); |
| 491 __ mov(eax, ebx); |
| 492 __ jmp(&index_smi); |
489 } | 493 } |
490 | 494 |
491 | 495 |
492 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { | 496 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { |
493 // ----------- S t a t e ------------- | 497 // ----------- S t a t e ------------- |
494 // -- eax : key (index) | 498 // -- eax : key (index) |
495 // -- edx : receiver | 499 // -- edx : receiver |
496 // -- esp[0] : return address | 500 // -- esp[0] : return address |
497 // ----------------------------------- | 501 // ----------------------------------- |
498 Label miss; | 502 Label miss; |
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
783 __ CmpInstanceType(edi, FIRST_JS_OBJECT_TYPE); | 787 __ CmpInstanceType(edi, FIRST_JS_OBJECT_TYPE); |
784 __ j(below, &slow, not_taken); | 788 __ j(below, &slow, not_taken); |
785 | 789 |
786 // Object case: Check key against length in the elements array. | 790 // Object case: Check key against length in the elements array. |
787 // eax: value | 791 // eax: value |
788 // edx: JSObject | 792 // edx: JSObject |
789 // ecx: key (a smi) | 793 // ecx: key (a smi) |
790 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); | 794 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); |
791 // Check that the object is in fast mode (not dictionary). | 795 // Check that the object is in fast mode (not dictionary). |
792 __ CheckMap(edi, Factory::fixed_array_map(), &check_pixel_array, true); | 796 __ CheckMap(edi, Factory::fixed_array_map(), &check_pixel_array, true); |
793 __ mov(ebx, Operand(ecx)); | 797 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); |
794 __ SmiUntag(ebx); | |
795 __ cmp(ebx, FieldOperand(edi, Array::kLengthOffset)); | |
796 __ j(below, &fast, taken); | 798 __ j(below, &fast, taken); |
797 | 799 |
798 // Slow case: call runtime. | 800 // Slow case: call runtime. |
799 __ bind(&slow); | 801 __ bind(&slow); |
800 GenerateRuntimeSetProperty(masm); | 802 GenerateRuntimeSetProperty(masm); |
801 | 803 |
802 // Check whether the elements is a pixel array. | 804 // Check whether the elements is a pixel array. |
803 __ bind(&check_pixel_array); | 805 __ bind(&check_pixel_array); |
804 // eax: value | 806 // eax: value |
805 // ecx: key | 807 // ecx: key (a smi) |
806 // edx: receiver | 808 // edx: receiver |
807 // edi: elements array | 809 // edi: elements array |
808 __ CheckMap(edi, Factory::pixel_array_map(), &slow, true); | 810 __ CheckMap(edi, Factory::pixel_array_map(), &slow, true); |
809 // Check that the value is a smi. If a conversion is needed call into the | 811 // Check that the value is a smi. If a conversion is needed call into the |
810 // runtime to convert and clamp. | 812 // runtime to convert and clamp. |
811 __ test(eax, Immediate(kSmiTagMask)); | 813 __ test(eax, Immediate(kSmiTagMask)); |
812 __ j(not_zero, &slow); | 814 __ j(not_zero, &slow); |
813 __ mov(ebx, ecx); | 815 __ mov(ebx, ecx); |
814 __ SmiUntag(ebx); | 816 __ SmiUntag(ebx); |
815 __ cmp(ebx, FieldOperand(edi, PixelArray::kLengthOffset)); | 817 __ cmp(ebx, FieldOperand(edi, PixelArray::kLengthOffset)); |
(...skipping 15 matching lines...) Expand all Loading... |
831 // Extra capacity case: Check if there is extra capacity to | 833 // Extra capacity case: Check if there is extra capacity to |
832 // perform the store and update the length. Used for adding one | 834 // perform the store and update the length. Used for adding one |
833 // element to the array by writing to array[array.length]. | 835 // element to the array by writing to array[array.length]. |
834 __ bind(&extra); | 836 __ bind(&extra); |
835 // eax: value | 837 // eax: value |
836 // edx: receiver, a JSArray | 838 // edx: receiver, a JSArray |
837 // ecx: key, a smi. | 839 // ecx: key, a smi. |
838 // edi: receiver->elements, a FixedArray | 840 // edi: receiver->elements, a FixedArray |
839 // flags: compare (ecx, edx.length()) | 841 // flags: compare (ecx, edx.length()) |
840 __ j(not_equal, &slow, not_taken); // do not leave holes in the array | 842 __ j(not_equal, &slow, not_taken); // do not leave holes in the array |
841 __ mov(ebx, ecx); | 843 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); |
842 __ SmiUntag(ebx); // untag | |
843 __ cmp(ebx, FieldOperand(edi, Array::kLengthOffset)); | |
844 __ j(above_equal, &slow, not_taken); | 844 __ j(above_equal, &slow, not_taken); |
845 // Add 1 to receiver->length, and go to fast array write. | 845 // Add 1 to receiver->length, and go to fast array write. |
846 __ add(FieldOperand(edx, JSArray::kLengthOffset), | 846 __ add(FieldOperand(edx, JSArray::kLengthOffset), |
847 Immediate(1 << kSmiTagSize)); | 847 Immediate(1 << kSmiTagSize)); |
848 __ jmp(&fast); | 848 __ jmp(&fast); |
849 | 849 |
850 // Array case: Get the length and the elements array from the JS | 850 // Array case: Get the length and the elements array from the JS |
851 // array. Check that the array is in fast mode; if it is the | 851 // array. Check that the array is in fast mode; if it is the |
852 // length is always a smi. | 852 // length is always a smi. |
853 __ bind(&array); | 853 __ bind(&array); |
(...skipping 782 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1636 | 1636 |
1637 // Do tail-call to runtime routine. | 1637 // Do tail-call to runtime routine. |
1638 ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss)); | 1638 ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss)); |
1639 __ TailCallExternalReference(ref, 3, 1); | 1639 __ TailCallExternalReference(ref, 3, 1); |
1640 } | 1640 } |
1641 | 1641 |
1642 #undef __ | 1642 #undef __ |
1643 | 1643 |
1644 | 1644 |
1645 } } // namespace v8::internal | 1645 } } // namespace v8::internal |
OLD | NEW |