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 1264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2180 const int argc = arguments().immediate(); | 2174 const int argc = arguments().immediate(); |
2181 GenerateGlobalReceiverCheck(object, holder, name, &miss); | 2175 GenerateGlobalReceiverCheck(object, holder, name, &miss); |
2182 GenerateLoadFunctionFromCell(cell, function, &miss); | 2176 GenerateLoadFunctionFromCell(cell, function, &miss); |
2183 | 2177 |
2184 // Patch the receiver on the stack with the global proxy. | 2178 // Patch the receiver on the stack with the global proxy. |
2185 if (object->IsGlobalObject()) { | 2179 if (object->IsGlobalObject()) { |
2186 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); | 2180 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); |
2187 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); | 2181 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); |
2188 } | 2182 } |
2189 | 2183 |
2190 // Setup the context (function already in rdi). | 2184 // Set up the context (function already in rdi). |
2191 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); | 2185 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); |
2192 | 2186 |
2193 // Jump to the cached code (tail call). | 2187 // Jump to the cached code (tail call). |
2194 Counters* counters = isolate()->counters(); | 2188 Counters* counters = isolate()->counters(); |
2195 __ IncrementCounter(counters->call_global_inline(), 1); | 2189 __ IncrementCounter(counters->call_global_inline(), 1); |
2196 ParameterCount expected(function->shared()->formal_parameter_count()); | 2190 ParameterCount expected(function->shared()->formal_parameter_count()); |
2197 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2191 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
2198 ? CALL_AS_FUNCTION | 2192 ? CALL_AS_FUNCTION |
2199 : CALL_AS_METHOD; | 2193 : CALL_AS_METHOD; |
2200 // We call indirectly through the code field in the function to | 2194 // We call indirectly through the code field in the function to |
(...skipping 43 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 |