OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_ARM64 | 7 #if V8_TARGET_ARCH_ARM64 |
8 | 8 |
9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
10 #include "src/ic-inl.h" | 10 #include "src/ic-inl.h" |
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
258 masm, miss, holder_reg, name, scratch1(), scratch2()); | 258 masm, miss, holder_reg, name, scratch1(), scratch2()); |
259 } | 259 } |
260 } | 260 } |
261 | 261 |
262 | 262 |
263 // Generate StoreTransition code, value is passed in x0 register. | 263 // Generate StoreTransition code, value is passed in x0 register. |
264 // When leaving generated code after success, the receiver_reg and storage_reg | 264 // When leaving generated code after success, the receiver_reg and storage_reg |
265 // may be clobbered. Upon branch to miss_label, the receiver and name registers | 265 // may be clobbered. Upon branch to miss_label, the receiver and name registers |
266 // have their original values. | 266 // have their original values. |
267 void NamedStoreHandlerCompiler::GenerateStoreTransition( | 267 void NamedStoreHandlerCompiler::GenerateStoreTransition( |
268 MacroAssembler* masm, Handle<JSObject> object, LookupResult* lookup, | 268 MacroAssembler* masm, LookupResult* lookup, Handle<Map> transition, |
269 Handle<Map> transition, Handle<Name> name, Register receiver_reg, | 269 Handle<Name> name, Register receiver_reg, Register storage_reg, |
270 Register storage_reg, Register value_reg, Register scratch1, | 270 Register value_reg, Register scratch1, Register scratch2, Register scratch3, |
271 Register scratch2, Register scratch3, Label* miss_label, Label* slow) { | 271 Label* miss_label, Label* slow) { |
272 Label exit; | 272 Label exit; |
273 | 273 |
274 ASSERT(!AreAliased(receiver_reg, storage_reg, value_reg, | 274 ASSERT(!AreAliased(receiver_reg, storage_reg, value_reg, |
275 scratch1, scratch2, scratch3)); | 275 scratch1, scratch2, scratch3)); |
276 | 276 |
277 // We don't need scratch3. | 277 // We don't need scratch3. |
278 scratch3 = NoReg; | 278 scratch3 = NoReg; |
279 | 279 |
280 int descriptor = transition->LastAdded(); | 280 int descriptor = transition->LastAdded(); |
281 DescriptorArray* descriptors = transition->instance_descriptors(); | 281 DescriptorArray* descriptors = transition->instance_descriptors(); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
318 | 318 |
319 __ CheckMap(value_reg, scratch1, Heap::kHeapNumberMapRootIndex, | 319 __ CheckMap(value_reg, scratch1, Heap::kHeapNumberMapRootIndex, |
320 miss_label, DONT_DO_SMI_CHECK); | 320 miss_label, DONT_DO_SMI_CHECK); |
321 __ Ldr(temp_double, FieldMemOperand(value_reg, HeapNumber::kValueOffset)); | 321 __ Ldr(temp_double, FieldMemOperand(value_reg, HeapNumber::kValueOffset)); |
322 | 322 |
323 __ Bind(&do_store); | 323 __ Bind(&do_store); |
324 __ AllocateHeapNumber(storage_reg, slow, scratch1, scratch2, temp_double, | 324 __ AllocateHeapNumber(storage_reg, slow, scratch1, scratch2, temp_double, |
325 NoReg, MUTABLE); | 325 NoReg, MUTABLE); |
326 } | 326 } |
327 | 327 |
328 // Stub never generated for non-global objects that require access checks. | 328 // Stub never generated for objects that require access checks. |
329 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 329 ASSERT(!transition->is_access_check_needed()); |
330 | 330 |
331 // Perform map transition for the receiver if necessary. | 331 // Perform map transition for the receiver if necessary. |
332 if ((details.type() == FIELD) && | 332 if (details.type() == FIELD && |
333 (object->map()->unused_property_fields() == 0)) { | 333 Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) { |
334 // The properties must be extended before we can store the value. | 334 // The properties must be extended before we can store the value. |
335 // We jump to a runtime call that extends the properties array. | 335 // We jump to a runtime call that extends the properties array. |
336 __ Mov(scratch1, Operand(transition)); | 336 __ Mov(scratch1, Operand(transition)); |
337 __ Push(receiver_reg, scratch1, value_reg); | 337 __ Push(receiver_reg, scratch1, value_reg); |
338 __ TailCallExternalReference( | 338 __ TailCallExternalReference( |
339 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), | 339 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), |
340 masm->isolate()), | 340 masm->isolate()), |
341 3, | 341 3, |
342 1); | 342 1); |
343 return; | 343 return; |
(...skipping 18 matching lines...) Expand all Loading... |
362 __ Ret(); | 362 __ Ret(); |
363 return; | 363 return; |
364 } | 364 } |
365 | 365 |
366 int index = transition->instance_descriptors()->GetFieldIndex( | 366 int index = transition->instance_descriptors()->GetFieldIndex( |
367 transition->LastAdded()); | 367 transition->LastAdded()); |
368 | 368 |
369 // Adjust for the number of properties stored in the object. Even in the | 369 // Adjust for the number of properties stored in the object. Even in the |
370 // face of a transition we can use the old map here because the size of the | 370 // face of a transition we can use the old map here because the size of the |
371 // object and the number of in-object properties is not going to change. | 371 // object and the number of in-object properties is not going to change. |
372 index -= object->map()->inobject_properties(); | 372 index -= transition->inobject_properties(); |
373 | 373 |
374 // TODO(verwaest): Share this code as a code stub. | 374 // TODO(verwaest): Share this code as a code stub. |
375 SmiCheck smi_check = representation.IsTagged() | 375 SmiCheck smi_check = representation.IsTagged() |
376 ? INLINE_SMI_CHECK : OMIT_SMI_CHECK; | 376 ? INLINE_SMI_CHECK : OMIT_SMI_CHECK; |
377 Register prop_reg = representation.IsDouble() ? storage_reg : value_reg; | 377 Register prop_reg = representation.IsDouble() ? storage_reg : value_reg; |
378 if (index < 0) { | 378 if (index < 0) { |
379 // Set the property straight into the object. | 379 // Set the property straight into the object. |
380 int offset = object->map()->instance_size() + (index * kPointerSize); | 380 int offset = transition->instance_size() + (index * kPointerSize); |
381 __ Str(prop_reg, FieldMemOperand(receiver_reg, offset)); | 381 __ Str(prop_reg, FieldMemOperand(receiver_reg, offset)); |
382 | 382 |
383 if (!representation.IsSmi()) { | 383 if (!representation.IsSmi()) { |
384 // Update the write barrier for the array address. | 384 // Update the write barrier for the array address. |
385 if (!representation.IsDouble()) { | 385 if (!representation.IsDouble()) { |
386 __ Mov(storage_reg, value_reg); | 386 __ Mov(storage_reg, value_reg); |
387 } | 387 } |
388 __ RecordWriteField(receiver_reg, | 388 __ RecordWriteField(receiver_reg, |
389 offset, | 389 offset, |
390 storage_reg, | 390 storage_reg, |
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
675 Handle<Code> code) { | 675 Handle<Code> code) { |
676 __ Jump(code, RelocInfo::CODE_TARGET); | 676 __ Jump(code, RelocInfo::CODE_TARGET); |
677 } | 677 } |
678 | 678 |
679 | 679 |
680 #undef __ | 680 #undef __ |
681 #define __ ACCESS_MASM(masm()) | 681 #define __ ACCESS_MASM(masm()) |
682 | 682 |
683 | 683 |
684 Register PropertyHandlerCompiler::CheckPrototypes( | 684 Register PropertyHandlerCompiler::CheckPrototypes( |
685 Register object_reg, Handle<JSObject> holder, Register holder_reg, | 685 Register object_reg, Register holder_reg, Register scratch1, |
686 Register scratch1, Register scratch2, Handle<Name> name, Label* miss, | 686 Register scratch2, Handle<Name> name, Label* miss, |
687 PrototypeCheckType check) { | 687 PrototypeCheckType check) { |
688 Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate())); | 688 Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate())); |
689 | 689 |
690 // object_reg and holder_reg registers can alias. | 690 // object_reg and holder_reg registers can alias. |
691 ASSERT(!AreAliased(object_reg, scratch1, scratch2)); | 691 ASSERT(!AreAliased(object_reg, scratch1, scratch2)); |
692 ASSERT(!AreAliased(holder_reg, scratch1, scratch2)); | 692 ASSERT(!AreAliased(holder_reg, scratch1, scratch2)); |
693 | 693 |
694 // Keep track of the current object in register reg. | 694 // Keep track of the current object in register reg. |
695 Register reg = object_reg; | 695 Register reg = object_reg; |
696 int depth = 0; | 696 int depth = 0; |
697 | 697 |
698 Handle<JSObject> current = Handle<JSObject>::null(); | 698 Handle<JSObject> current = Handle<JSObject>::null(); |
699 if (type()->IsConstant()) { | 699 if (type()->IsConstant()) { |
700 current = Handle<JSObject>::cast(type()->AsConstant()->Value()); | 700 current = Handle<JSObject>::cast(type()->AsConstant()->Value()); |
701 } | 701 } |
702 Handle<JSObject> prototype = Handle<JSObject>::null(); | 702 Handle<JSObject> prototype = Handle<JSObject>::null(); |
703 Handle<Map> current_map = receiver_map; | 703 Handle<Map> current_map = receiver_map; |
704 Handle<Map> holder_map(holder->map()); | 704 Handle<Map> holder_map(holder()->map()); |
705 // Traverse the prototype chain and check the maps in the prototype chain for | 705 // Traverse the prototype chain and check the maps in the prototype chain for |
706 // fast and global objects or do negative lookup for normal objects. | 706 // fast and global objects or do negative lookup for normal objects. |
707 while (!current_map.is_identical_to(holder_map)) { | 707 while (!current_map.is_identical_to(holder_map)) { |
708 ++depth; | 708 ++depth; |
709 | 709 |
710 // Only global objects and objects that do not require access | 710 // Only global objects and objects that do not require access |
711 // checks are allowed in stubs. | 711 // checks are allowed in stubs. |
712 ASSERT(current_map->IsJSGlobalProxyMap() || | 712 ASSERT(current_map->IsJSGlobalProxyMap() || |
713 !current_map->is_access_check_needed()); | 713 !current_map->is_access_check_needed()); |
714 | 714 |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
811 | 811 |
812 GenerateRestoreName(masm(), miss, name); | 812 GenerateRestoreName(masm(), miss, name); |
813 TailCallBuiltin(masm(), MissBuiltin(kind())); | 813 TailCallBuiltin(masm(), MissBuiltin(kind())); |
814 | 814 |
815 __ Bind(&success); | 815 __ Bind(&success); |
816 } | 816 } |
817 } | 817 } |
818 | 818 |
819 | 819 |
820 Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg, | 820 Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg, |
821 Handle<JSObject> holder, | |
822 Handle<Name> name, | 821 Handle<Name> name, |
823 Handle<Object> callback) { | 822 Handle<Object> callback) { |
824 Label miss; | 823 Label miss; |
825 | 824 |
826 Register reg = FrontendHeader(object_reg, holder, name, &miss); | 825 Register reg = FrontendHeader(object_reg, name, &miss); |
827 // FrontendHeader can return its result into scratch1() so do not | 826 // FrontendHeader can return its result into scratch1() so do not |
828 // use it. | 827 // use it. |
829 Register scratch2 = this->scratch2(); | 828 Register scratch2 = this->scratch2(); |
830 Register scratch3 = this->scratch3(); | 829 Register scratch3 = this->scratch3(); |
831 Register dictionary = this->scratch4(); | 830 Register dictionary = this->scratch4(); |
832 ASSERT(!AreAliased(reg, scratch2, scratch3, dictionary)); | 831 ASSERT(!AreAliased(reg, scratch2, scratch3, dictionary)); |
833 | 832 |
834 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { | 833 if (!holder()->HasFastProperties()) { |
| 834 ASSERT(holder()->IsGlobalObject()); |
835 // Load the properties dictionary. | 835 // Load the properties dictionary. |
836 __ Ldr(dictionary, FieldMemOperand(reg, JSObject::kPropertiesOffset)); | 836 __ Ldr(dictionary, FieldMemOperand(reg, JSObject::kPropertiesOffset)); |
837 | 837 |
838 // Probe the dictionary. | 838 // Probe the dictionary. |
839 Label probe_done; | 839 Label probe_done; |
840 NameDictionaryLookupStub::GeneratePositiveLookup(masm(), | 840 NameDictionaryLookupStub::GeneratePositiveLookup(masm(), |
841 &miss, | 841 &miss, |
842 &probe_done, | 842 &probe_done, |
843 dictionary, | 843 dictionary, |
844 this->name(), | 844 this->name(), |
(...skipping 11 matching lines...) Expand all Loading... |
856 __ Cmp(scratch2, Operand(callback)); | 856 __ Cmp(scratch2, Operand(callback)); |
857 __ B(ne, &miss); | 857 __ B(ne, &miss); |
858 } | 858 } |
859 | 859 |
860 FrontendFooter(name, &miss); | 860 FrontendFooter(name, &miss); |
861 return reg; | 861 return reg; |
862 } | 862 } |
863 | 863 |
864 | 864 |
865 void NamedLoadHandlerCompiler::GenerateLoadField( | 865 void NamedLoadHandlerCompiler::GenerateLoadField( |
866 Register reg, Handle<JSObject> holder, FieldIndex field, | 866 Register reg, FieldIndex field, Representation representation) { |
867 Representation representation) { | |
868 __ Mov(receiver(), reg); | 867 __ Mov(receiver(), reg); |
869 LoadFieldStub stub(isolate(), field); | 868 LoadFieldStub stub(isolate(), field); |
870 GenerateTailCall(masm(), stub.GetCode()); | 869 GenerateTailCall(masm(), stub.GetCode()); |
871 } | 870 } |
872 | 871 |
873 | 872 |
874 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { | 873 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { |
875 // Return the constant value. | 874 // Return the constant value. |
876 __ LoadObject(x0, value); | 875 __ LoadObject(x0, value); |
877 __ Ret(); | 876 __ Ret(); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
925 ApiFunction fun(getter_address); | 924 ApiFunction fun(getter_address); |
926 ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL; | 925 ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL; |
927 ExternalReference ref = ExternalReference(&fun, type, isolate()); | 926 ExternalReference ref = ExternalReference(&fun, type, isolate()); |
928 __ Mov(getter_address_reg, ref); | 927 __ Mov(getter_address_reg, ref); |
929 | 928 |
930 CallApiGetterStub stub(isolate()); | 929 CallApiGetterStub stub(isolate()); |
931 __ TailCallStub(&stub); | 930 __ TailCallStub(&stub); |
932 } | 931 } |
933 | 932 |
934 | 933 |
935 void NamedLoadHandlerCompiler::GenerateLoadInterceptor( | 934 void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg, |
936 Register holder_reg, Handle<JSObject> interceptor_holder, | 935 LookupResult* lookup, |
937 LookupResult* lookup, Handle<Name> name) { | 936 Handle<Name> name) { |
938 ASSERT(!AreAliased(receiver(), this->name(), | 937 ASSERT(!AreAliased(receiver(), this->name(), |
939 scratch1(), scratch2(), scratch3())); | 938 scratch1(), scratch2(), scratch3())); |
940 ASSERT(interceptor_holder->HasNamedInterceptor()); | 939 ASSERT(holder()->HasNamedInterceptor()); |
941 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); | 940 ASSERT(!holder()->GetNamedInterceptor()->getter()->IsUndefined()); |
942 | 941 |
943 // So far the most popular follow ups for interceptor loads are FIELD | 942 // So far the most popular follow ups for interceptor loads are FIELD |
944 // and CALLBACKS, so inline only them, other cases may be added later. | 943 // and CALLBACKS, so inline only them, other cases may be added later. |
945 bool compile_followup_inline = false; | 944 bool compile_followup_inline = false; |
946 if (lookup->IsFound() && lookup->IsCacheable()) { | 945 if (lookup->IsFound() && lookup->IsCacheable()) { |
947 if (lookup->IsField()) { | 946 if (lookup->IsField()) { |
948 compile_followup_inline = true; | 947 compile_followup_inline = true; |
949 } else if (lookup->type() == CALLBACKS && | 948 } else if (lookup->type() == CALLBACKS && |
950 lookup->GetCallbackObject()->IsExecutableAccessorInfo()) { | 949 lookup->GetCallbackObject()->IsExecutableAccessorInfo()) { |
951 Handle<ExecutableAccessorInfo> callback( | 950 Handle<ExecutableAccessorInfo> callback( |
952 ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); | 951 ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); |
953 compile_followup_inline = | 952 compile_followup_inline = |
954 callback->getter() != NULL && | 953 callback->getter() != NULL && |
955 ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), callback, | 954 ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), callback, |
956 type()); | 955 type()); |
957 } | 956 } |
958 } | 957 } |
959 | 958 |
960 if (compile_followup_inline) { | 959 if (compile_followup_inline) { |
961 // Compile the interceptor call, followed by inline code to load the | 960 // Compile the interceptor call, followed by inline code to load the |
962 // property from further up the prototype chain if the call fails. | 961 // property from further up the prototype chain if the call fails. |
963 // Check that the maps haven't changed. | 962 // Check that the maps haven't changed. |
964 ASSERT(holder_reg.is(receiver()) || holder_reg.is(scratch1())); | 963 ASSERT(holder_reg.is(receiver()) || holder_reg.is(scratch1())); |
965 | 964 |
966 // Preserve the receiver register explicitly whenever it is different from | 965 // Preserve the receiver register explicitly whenever it is different from |
967 // the holder and it is needed should the interceptor return without any | 966 // the holder and it is needed should the interceptor return without any |
968 // result. The CALLBACKS case needs the receiver to be passed into C++ code, | 967 // result. The CALLBACKS case needs the receiver to be passed into C++ code, |
969 // the FIELD case might cause a miss during the prototype check. | 968 // the FIELD case might cause a miss during the prototype check. |
970 bool must_perfrom_prototype_check = *interceptor_holder != lookup->holder(); | 969 bool must_perfrom_prototype_check = *holder() != lookup->holder(); |
971 bool must_preserve_receiver_reg = !receiver().Is(holder_reg) && | 970 bool must_preserve_receiver_reg = !receiver().Is(holder_reg) && |
972 (lookup->type() == CALLBACKS || must_perfrom_prototype_check); | 971 (lookup->type() == CALLBACKS || must_perfrom_prototype_check); |
973 | 972 |
974 // Save necessary data before invoking an interceptor. | 973 // Save necessary data before invoking an interceptor. |
975 // Requires a frame to make GC aware of pushed pointers. | 974 // Requires a frame to make GC aware of pushed pointers. |
976 { | 975 { |
977 FrameScope frame_scope(masm(), StackFrame::INTERNAL); | 976 FrameScope frame_scope(masm(), StackFrame::INTERNAL); |
978 if (must_preserve_receiver_reg) { | 977 if (must_preserve_receiver_reg) { |
979 __ Push(receiver(), holder_reg, this->name()); | 978 __ Push(receiver(), holder_reg, this->name()); |
980 } else { | 979 } else { |
981 __ Push(holder_reg, this->name()); | 980 __ Push(holder_reg, this->name()); |
982 } | 981 } |
983 // Invoke an interceptor. Note: map checks from receiver to | 982 // Invoke an interceptor. Note: map checks from receiver to |
984 // interceptor's holder has been compiled before (see a caller | 983 // interceptor's holder has been compiled before (see a caller |
985 // of this method.) | 984 // of this method.) |
986 CompileCallLoadPropertyWithInterceptor( | 985 CompileCallLoadPropertyWithInterceptor( |
987 masm(), receiver(), holder_reg, this->name(), interceptor_holder, | 986 masm(), receiver(), holder_reg, this->name(), holder(), |
988 IC::kLoadPropertyWithInterceptorOnly); | 987 IC::kLoadPropertyWithInterceptorOnly); |
989 | 988 |
990 // Check if interceptor provided a value for property. If it's | 989 // Check if interceptor provided a value for property. If it's |
991 // the case, return immediately. | 990 // the case, return immediately. |
992 Label interceptor_failed; | 991 Label interceptor_failed; |
993 __ JumpIfRoot(x0, | 992 __ JumpIfRoot(x0, |
994 Heap::kNoInterceptorResultSentinelRootIndex, | 993 Heap::kNoInterceptorResultSentinelRootIndex, |
995 &interceptor_failed); | 994 &interceptor_failed); |
996 frame_scope.GenerateLeaveFrame(); | 995 frame_scope.GenerateLeaveFrame(); |
997 __ Ret(); | 996 __ Ret(); |
998 | 997 |
999 __ Bind(&interceptor_failed); | 998 __ Bind(&interceptor_failed); |
1000 if (must_preserve_receiver_reg) { | 999 if (must_preserve_receiver_reg) { |
1001 __ Pop(this->name(), holder_reg, receiver()); | 1000 __ Pop(this->name(), holder_reg, receiver()); |
1002 } else { | 1001 } else { |
1003 __ Pop(this->name(), holder_reg); | 1002 __ Pop(this->name(), holder_reg); |
1004 } | 1003 } |
1005 // Leave the internal frame. | 1004 // Leave the internal frame. |
1006 } | 1005 } |
1007 GenerateLoadPostInterceptor(holder_reg, interceptor_holder, name, lookup); | 1006 GenerateLoadPostInterceptor(holder_reg, name, lookup); |
1008 } else { // !compile_followup_inline | 1007 } else { // !compile_followup_inline |
1009 // Call the runtime system to load the interceptor. | 1008 // Call the runtime system to load the interceptor. |
1010 // Check that the maps haven't changed. | 1009 // Check that the maps haven't changed. |
1011 PushInterceptorArguments( | 1010 PushInterceptorArguments(masm(), receiver(), holder_reg, this->name(), |
1012 masm(), receiver(), holder_reg, this->name(), interceptor_holder); | 1011 holder()); |
1013 | 1012 |
1014 ExternalReference ref = | 1013 ExternalReference ref = |
1015 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptor), | 1014 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptor), |
1016 isolate()); | 1015 isolate()); |
1017 __ TailCallExternalReference( | 1016 __ TailCallExternalReference( |
1018 ref, NamedLoadHandlerCompiler::kInterceptorArgsLength, 1); | 1017 ref, NamedLoadHandlerCompiler::kInterceptorArgsLength, 1); |
1019 } | 1018 } |
1020 } | 1019 } |
1021 | 1020 |
1022 | 1021 |
1023 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( | 1022 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( |
1024 Handle<JSObject> object, Handle<JSObject> holder, Handle<Name> name, | 1023 Handle<JSObject> object, Handle<Name> name, |
1025 Handle<ExecutableAccessorInfo> callback) { | 1024 Handle<ExecutableAccessorInfo> callback) { |
1026 ASM_LOCATION("NamedStoreHandlerCompiler::CompileStoreCallback"); | 1025 ASM_LOCATION("NamedStoreHandlerCompiler::CompileStoreCallback"); |
1027 Register holder_reg = Frontend(receiver(), holder, name); | 1026 Register holder_reg = Frontend(receiver(), name); |
1028 | 1027 |
1029 // Stub never generated for non-global objects that require access checks. | 1028 // Stub never generated for non-global objects that require access checks. |
1030 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); | 1029 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); |
1031 | 1030 |
1032 // receiver() and holder_reg can alias. | 1031 // receiver() and holder_reg can alias. |
1033 ASSERT(!AreAliased(receiver(), scratch1(), scratch2(), value())); | 1032 ASSERT(!AreAliased(receiver(), scratch1(), scratch2(), value())); |
1034 ASSERT(!AreAliased(holder_reg, scratch1(), scratch2(), value())); | 1033 ASSERT(!AreAliased(holder_reg, scratch1(), scratch2(), value())); |
1035 __ Mov(scratch1(), Operand(callback)); | 1034 __ Mov(scratch1(), Operand(callback)); |
1036 __ Mov(scratch2(), Operand(name)); | 1035 __ Mov(scratch2(), Operand(name)); |
1037 __ Push(receiver(), holder_reg, scratch1(), scratch2(), value()); | 1036 __ Push(receiver(), holder_reg, scratch1(), scratch2(), value()); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1090 } | 1089 } |
1091 __ Ret(); | 1090 __ Ret(); |
1092 } | 1091 } |
1093 | 1092 |
1094 | 1093 |
1095 #undef __ | 1094 #undef __ |
1096 #define __ ACCESS_MASM(masm()) | 1095 #define __ ACCESS_MASM(masm()) |
1097 | 1096 |
1098 | 1097 |
1099 Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor( | 1098 Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor( |
1100 Handle<JSObject> object, Handle<Name> name) { | 1099 Handle<Name> name) { |
1101 Label miss; | 1100 Label miss; |
1102 | 1101 |
1103 ASM_LOCATION("NamedStoreHandlerCompiler::CompileStoreInterceptor"); | 1102 ASM_LOCATION("NamedStoreHandlerCompiler::CompileStoreInterceptor"); |
1104 | 1103 |
1105 __ Push(receiver(), this->name(), value()); | 1104 __ Push(receiver(), this->name(), value()); |
1106 | 1105 |
1107 // Do tail-call to the runtime system. | 1106 // Do tail-call to the runtime system. |
1108 ExternalReference store_ic_property = ExternalReference( | 1107 ExternalReference store_ic_property = ExternalReference( |
1109 IC_Utility(IC::kStorePropertyWithInterceptor), isolate()); | 1108 IC_Utility(IC::kStorePropertyWithInterceptor), isolate()); |
1110 __ TailCallExternalReference(store_ic_property, 3, 1); | 1109 __ TailCallExternalReference(store_ic_property, 3, 1); |
1111 | 1110 |
1112 // Return the generated code. | 1111 // Return the generated code. |
1113 return GetCode(kind(), Code::FAST, name); | 1112 return GetCode(kind(), Code::FAST, name); |
1114 } | 1113 } |
1115 | 1114 |
1116 | 1115 |
1117 Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( | 1116 Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( |
1118 Handle<JSObject> last, Handle<Name> name) { | 1117 Handle<Name> name) { |
1119 NonexistentFrontend(last, name); | 1118 NonexistentFrontend(name); |
1120 | 1119 |
1121 // Return undefined if maps of the full prototype chain are still the | 1120 // Return undefined if maps of the full prototype chain are still the |
1122 // same and no global property with this name contains a value. | 1121 // same and no global property with this name contains a value. |
1123 __ LoadRoot(x0, Heap::kUndefinedValueRootIndex); | 1122 __ LoadRoot(x0, Heap::kUndefinedValueRootIndex); |
1124 __ Ret(); | 1123 __ Ret(); |
1125 | 1124 |
1126 // Return the generated code. | 1125 // Return the generated code. |
1127 return GetCode(kind(), Code::FAST, name); | 1126 return GetCode(kind(), Code::FAST, name); |
1128 } | 1127 } |
1129 | 1128 |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1198 } | 1197 } |
1199 __ Ret(); | 1198 __ Ret(); |
1200 } | 1199 } |
1201 | 1200 |
1202 | 1201 |
1203 #undef __ | 1202 #undef __ |
1204 #define __ ACCESS_MASM(masm()) | 1203 #define __ ACCESS_MASM(masm()) |
1205 | 1204 |
1206 | 1205 |
1207 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( | 1206 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( |
1208 Handle<GlobalObject> global, Handle<PropertyCell> cell, Handle<Name> name, | 1207 Handle<PropertyCell> cell, Handle<Name> name, bool is_dont_delete) { |
1209 bool is_dont_delete) { | |
1210 Label miss; | 1208 Label miss; |
1211 FrontendHeader(receiver(), global, name, &miss); | 1209 FrontendHeader(receiver(), name, &miss); |
1212 | 1210 |
1213 // Get the value from the cell. | 1211 // Get the value from the cell. |
1214 Register result = StoreIC::ValueRegister(); | 1212 Register result = StoreIC::ValueRegister(); |
1215 __ Mov(result, Operand(cell)); | 1213 __ Mov(result, Operand(cell)); |
1216 __ Ldr(result, FieldMemOperand(result, Cell::kValueOffset)); | 1214 __ Ldr(result, FieldMemOperand(result, Cell::kValueOffset)); |
1217 | 1215 |
1218 // Check for deleted property if property can actually be deleted. | 1216 // Check for deleted property if property can actually be deleted. |
1219 if (!is_dont_delete) { | 1217 if (!is_dont_delete) { |
1220 __ JumpIfRoot(result, Heap::kTheHoleValueRootIndex, &miss); | 1218 __ JumpIfRoot(result, Heap::kTheHoleValueRootIndex, &miss); |
1221 } | 1219 } |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1357 | 1355 |
1358 // Miss case, call the runtime. | 1356 // Miss case, call the runtime. |
1359 __ Bind(&miss); | 1357 __ Bind(&miss); |
1360 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 1358 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
1361 } | 1359 } |
1362 | 1360 |
1363 | 1361 |
1364 } } // namespace v8::internal | 1362 } } // namespace v8::internal |
1365 | 1363 |
1366 #endif // V8_TARGET_ARCH_ARM64 | 1364 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |