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