| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 |
| 11 // with the distribution. | 11 // with the distribution. |
| (...skipping 672 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 684 // Both name_reg and receiver_reg are preserved on jumps to miss_label, | 684 // Both name_reg and receiver_reg are preserved on jumps to miss_label, |
| 685 // but may be destroyed if store is successful. | 685 // but may be destroyed if store is successful. |
| 686 void StubCompiler::GenerateStoreField(MacroAssembler* masm, | 686 void StubCompiler::GenerateStoreField(MacroAssembler* masm, |
| 687 Handle<JSObject> object, | 687 Handle<JSObject> object, |
| 688 int index, | 688 int index, |
| 689 Handle<Map> transition, | 689 Handle<Map> transition, |
| 690 Register receiver_reg, | 690 Register receiver_reg, |
| 691 Register name_reg, | 691 Register name_reg, |
| 692 Register scratch, | 692 Register scratch, |
| 693 Label* miss_label) { | 693 Label* miss_label) { |
| 694 // Check that the object isn't a smi. | |
| 695 __ JumpIfSmi(receiver_reg, miss_label); | |
| 696 | |
| 697 // Check that the map of the object hasn't changed. | 694 // Check that the map of the object hasn't changed. |
| 698 __ Cmp(FieldOperand(receiver_reg, HeapObject::kMapOffset), | 695 __ CheckMap(receiver_reg, Handle<Map>(object->map()), |
| 699 Handle<Map>(object->map())); | 696 miss_label, DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); |
| 700 __ j(not_equal, miss_label); | |
| 701 | 697 |
| 702 // Perform global security token check if needed. | 698 // Perform global security token check if needed. |
| 703 if (object->IsJSGlobalProxy()) { | 699 if (object->IsJSGlobalProxy()) { |
| 704 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label); | 700 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label); |
| 705 } | 701 } |
| 706 | 702 |
| 707 // Stub never generated for non-global objects that require access | 703 // Stub never generated for non-global objects that require access |
| 708 // checks. | 704 // checks. |
| 709 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 705 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
| 710 | 706 |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 857 | 853 |
| 858 __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | 854 __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
| 859 reg = holder_reg; // From now on the object will be in holder_reg. | 855 reg = holder_reg; // From now on the object will be in holder_reg. |
| 860 __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); | 856 __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
| 861 } else { | 857 } else { |
| 862 bool in_new_space = heap()->InNewSpace(*prototype); | 858 bool in_new_space = heap()->InNewSpace(*prototype); |
| 863 Handle<Map> current_map(current->map()); | 859 Handle<Map> current_map(current->map()); |
| 864 if (in_new_space) { | 860 if (in_new_space) { |
| 865 // Save the map in scratch1 for later. | 861 // Save the map in scratch1 for later. |
| 866 __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | 862 __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
| 867 __ Cmp(scratch1, current_map); | |
| 868 } else { | |
| 869 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), current_map); | |
| 870 } | 863 } |
| 871 // Branch on the result of the map check. | 864 __ CheckMap(reg, Handle<Map>(current_map), |
| 872 __ j(not_equal, miss); | 865 miss, DONT_DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); |
| 866 |
| 873 // Check access rights to the global object. This has to happen after | 867 // Check access rights to the global object. This has to happen after |
| 874 // the map check so that we know that the object is actually a global | 868 // the map check so that we know that the object is actually a global |
| 875 // object. | 869 // object. |
| 876 if (current->IsJSGlobalProxy()) { | 870 if (current->IsJSGlobalProxy()) { |
| 877 __ CheckAccessGlobalProxy(reg, scratch2, miss); | 871 __ CheckAccessGlobalProxy(reg, scratch2, miss); |
| 878 } | 872 } |
| 879 reg = holder_reg; // From now on the object will be in holder_reg. | 873 reg = holder_reg; // From now on the object will be in holder_reg. |
| 880 | 874 |
| 881 if (in_new_space) { | 875 if (in_new_space) { |
| 882 // The prototype is in new space; we cannot store a reference to it | 876 // The prototype is in new space; we cannot store a reference to it |
| (...skipping 11 matching lines...) Expand all Loading... |
| 894 | 888 |
| 895 // Go to the next object in the prototype chain. | 889 // Go to the next object in the prototype chain. |
| 896 current = prototype; | 890 current = prototype; |
| 897 } | 891 } |
| 898 ASSERT(current.is_identical_to(holder)); | 892 ASSERT(current.is_identical_to(holder)); |
| 899 | 893 |
| 900 // Log the check depth. | 894 // Log the check depth. |
| 901 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); | 895 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); |
| 902 | 896 |
| 903 // Check the holder map. | 897 // Check the holder map. |
| 904 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), Handle<Map>(holder->map())); | 898 __ CheckMap(reg, Handle<Map>(holder->map()), |
| 905 __ j(not_equal, miss); | 899 miss, DONT_DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); |
| 906 | 900 |
| 907 // Perform security check for access to the global object. | 901 // Perform security check for access to the global object. |
| 908 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); | 902 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); |
| 909 if (current->IsJSGlobalProxy()) { | 903 if (current->IsJSGlobalProxy()) { |
| 910 __ CheckAccessGlobalProxy(reg, scratch1, miss); | 904 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
| 911 } | 905 } |
| 912 | 906 |
| 913 // If we've skipped any global objects, it's not enough to verify that | 907 // If we've skipped any global objects, it's not enough to verify that |
| 914 // their maps haven't changed. We also need to check that the property | 908 // their maps haven't changed. We also need to check that the property |
| 915 // cell for the property is still empty. | 909 // cell for the property is still empty. |
| (...skipping 1328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2244 Handle<AccessorInfo> callback, | 2238 Handle<AccessorInfo> callback, |
| 2245 Handle<String> name) { | 2239 Handle<String> name) { |
| 2246 // ----------- S t a t e ------------- | 2240 // ----------- S t a t e ------------- |
| 2247 // -- rax : value | 2241 // -- rax : value |
| 2248 // -- rcx : name | 2242 // -- rcx : name |
| 2249 // -- rdx : receiver | 2243 // -- rdx : receiver |
| 2250 // -- rsp[0] : return address | 2244 // -- rsp[0] : return address |
| 2251 // ----------------------------------- | 2245 // ----------------------------------- |
| 2252 Label miss; | 2246 Label miss; |
| 2253 | 2247 |
| 2254 // Check that the object isn't a smi. | |
| 2255 __ JumpIfSmi(rdx, &miss); | |
| 2256 | |
| 2257 // Check that the map of the object hasn't changed. | 2248 // Check that the map of the object hasn't changed. |
| 2258 __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset), | 2249 __ CheckMap(rdx, Handle<Map>(object->map()), &miss, |
| 2259 Handle<Map>(object->map())); | 2250 DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); |
| 2260 __ j(not_equal, &miss); | |
| 2261 | 2251 |
| 2262 // Perform global security token check if needed. | 2252 // Perform global security token check if needed. |
| 2263 if (object->IsJSGlobalProxy()) { | 2253 if (object->IsJSGlobalProxy()) { |
| 2264 __ CheckAccessGlobalProxy(rdx, rbx, &miss); | 2254 __ CheckAccessGlobalProxy(rdx, rbx, &miss); |
| 2265 } | 2255 } |
| 2266 | 2256 |
| 2267 // Stub never generated for non-global objects that require access | 2257 // Stub never generated for non-global objects that require access |
| 2268 // checks. | 2258 // checks. |
| 2269 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 2259 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
| 2270 | 2260 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 2294 Handle<JSObject> receiver, | 2284 Handle<JSObject> receiver, |
| 2295 Handle<String> name) { | 2285 Handle<String> name) { |
| 2296 // ----------- S t a t e ------------- | 2286 // ----------- S t a t e ------------- |
| 2297 // -- rax : value | 2287 // -- rax : value |
| 2298 // -- rcx : name | 2288 // -- rcx : name |
| 2299 // -- rdx : receiver | 2289 // -- rdx : receiver |
| 2300 // -- rsp[0] : return address | 2290 // -- rsp[0] : return address |
| 2301 // ----------------------------------- | 2291 // ----------------------------------- |
| 2302 Label miss; | 2292 Label miss; |
| 2303 | 2293 |
| 2304 // Check that the object isn't a smi. | |
| 2305 __ JumpIfSmi(rdx, &miss); | |
| 2306 | |
| 2307 // Check that the map of the object hasn't changed. | 2294 // Check that the map of the object hasn't changed. |
| 2308 __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset), | 2295 __ CheckMap(rdx, Handle<Map>(receiver->map()), &miss, |
| 2309 Handle<Map>(receiver->map())); | 2296 DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); |
| 2310 __ j(not_equal, &miss); | |
| 2311 | 2297 |
| 2312 // Perform global security token check if needed. | 2298 // Perform global security token check if needed. |
| 2313 if (receiver->IsJSGlobalProxy()) { | 2299 if (receiver->IsJSGlobalProxy()) { |
| 2314 __ CheckAccessGlobalProxy(rdx, rbx, &miss); | 2300 __ CheckAccessGlobalProxy(rdx, rbx, &miss); |
| 2315 } | 2301 } |
| 2316 | 2302 |
| 2317 // Stub never generated for non-global objects that require access | 2303 // Stub never generated for non-global objects that require access |
| 2318 // checks. | 2304 // checks. |
| 2319 ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded()); | 2305 ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded()); |
| 2320 | 2306 |
| (...skipping 1279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3600 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); | 3586 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); |
| 3601 __ jmp(ic_miss, RelocInfo::CODE_TARGET); | 3587 __ jmp(ic_miss, RelocInfo::CODE_TARGET); |
| 3602 } | 3588 } |
| 3603 | 3589 |
| 3604 | 3590 |
| 3605 #undef __ | 3591 #undef __ |
| 3606 | 3592 |
| 3607 } } // namespace v8::internal | 3593 } } // namespace v8::internal |
| 3608 | 3594 |
| 3609 #endif // V8_TARGET_ARCH_X64 | 3595 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |