| 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 |