| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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_MIPS64 | 7 #if V8_TARGET_ARCH_MIPS64 |
| 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 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 291 GenerateDictionaryNegativeLookup( | 291 GenerateDictionaryNegativeLookup( |
| 292 masm, miss, holder_reg, name, scratch1(), scratch2()); | 292 masm, miss, holder_reg, name, scratch1(), scratch2()); |
| 293 } | 293 } |
| 294 } | 294 } |
| 295 | 295 |
| 296 | 296 |
| 297 // Generate StoreTransition code, value is passed in a0 register. | 297 // Generate StoreTransition code, value is passed in a0 register. |
| 298 // After executing generated code, the receiver_reg and name_reg | 298 // After executing generated code, the receiver_reg and name_reg |
| 299 // may be clobbered. | 299 // may be clobbered. |
| 300 void NamedStoreHandlerCompiler::GenerateStoreTransition( | 300 void NamedStoreHandlerCompiler::GenerateStoreTransition( |
| 301 MacroAssembler* masm, Handle<JSObject> object, LookupResult* lookup, | 301 MacroAssembler* masm, LookupResult* lookup, Handle<Map> transition, |
| 302 Handle<Map> transition, Handle<Name> name, Register receiver_reg, | 302 Handle<Name> name, Register receiver_reg, Register storage_reg, |
| 303 Register storage_reg, Register value_reg, Register scratch1, | 303 Register value_reg, Register scratch1, Register scratch2, Register scratch3, |
| 304 Register scratch2, Register scratch3, Label* miss_label, Label* slow) { | 304 Label* miss_label, Label* slow) { |
| 305 // a0 : value. | 305 // a0 : value. |
| 306 Label exit; | 306 Label exit; |
| 307 | 307 |
| 308 int descriptor = transition->LastAdded(); | 308 int descriptor = transition->LastAdded(); |
| 309 DescriptorArray* descriptors = transition->instance_descriptors(); | 309 DescriptorArray* descriptors = transition->instance_descriptors(); |
| 310 PropertyDetails details = descriptors->GetDetails(descriptor); | 310 PropertyDetails details = descriptors->GetDetails(descriptor); |
| 311 Representation representation = details.representation(); | 311 Representation representation = details.representation(); |
| 312 ASSERT(!representation.IsNone()); | 312 ASSERT(!representation.IsNone()); |
| 313 | 313 |
| 314 if (details.type() == CONSTANT) { | 314 if (details.type() == CONSTANT) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 351 | 351 |
| 352 __ bind(&heap_number); | 352 __ bind(&heap_number); |
| 353 __ CheckMap(value_reg, scratch1, Heap::kHeapNumberMapRootIndex, | 353 __ CheckMap(value_reg, scratch1, Heap::kHeapNumberMapRootIndex, |
| 354 miss_label, DONT_DO_SMI_CHECK); | 354 miss_label, DONT_DO_SMI_CHECK); |
| 355 __ ldc1(f4, FieldMemOperand(value_reg, HeapNumber::kValueOffset)); | 355 __ ldc1(f4, FieldMemOperand(value_reg, HeapNumber::kValueOffset)); |
| 356 | 356 |
| 357 __ bind(&do_store); | 357 __ bind(&do_store); |
| 358 __ sdc1(f4, FieldMemOperand(storage_reg, HeapNumber::kValueOffset)); | 358 __ sdc1(f4, FieldMemOperand(storage_reg, HeapNumber::kValueOffset)); |
| 359 } | 359 } |
| 360 | 360 |
| 361 // Stub never generated for non-global objects that require access | 361 // Stub never generated for objects that require access checks. |
| 362 // checks. | 362 ASSERT(!transition->is_access_check_needed()); |
| 363 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | |
| 364 | 363 |
| 365 // Perform map transition for the receiver if necessary. | 364 // Perform map transition for the receiver if necessary. |
| 366 if (details.type() == FIELD && | 365 if (details.type() == FIELD && |
| 367 object->map()->unused_property_fields() == 0) { | 366 Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) { |
| 368 // The properties must be extended before we can store the value. | 367 // The properties must be extended before we can store the value. |
| 369 // We jump to a runtime call that extends the properties array. | 368 // We jump to a runtime call that extends the properties array. |
| 370 __ push(receiver_reg); | 369 __ push(receiver_reg); |
| 371 __ li(a2, Operand(transition)); | 370 __ li(a2, Operand(transition)); |
| 372 __ Push(a2, a0); | 371 __ Push(a2, a0); |
| 373 __ TailCallExternalReference( | 372 __ TailCallExternalReference( |
| 374 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), | 373 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), |
| 375 masm->isolate()), | 374 masm->isolate()), |
| 376 3, 1); | 375 3, 1); |
| 377 return; | 376 return; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 397 __ mov(v0, a0); | 396 __ mov(v0, a0); |
| 398 return; | 397 return; |
| 399 } | 398 } |
| 400 | 399 |
| 401 int index = transition->instance_descriptors()->GetFieldIndex( | 400 int index = transition->instance_descriptors()->GetFieldIndex( |
| 402 transition->LastAdded()); | 401 transition->LastAdded()); |
| 403 | 402 |
| 404 // Adjust for the number of properties stored in the object. Even in the | 403 // Adjust for the number of properties stored in the object. Even in the |
| 405 // face of a transition we can use the old map here because the size of the | 404 // face of a transition we can use the old map here because the size of the |
| 406 // object and the number of in-object properties is not going to change. | 405 // object and the number of in-object properties is not going to change. |
| 407 index -= object->map()->inobject_properties(); | 406 index -= transition->inobject_properties(); |
| 408 | 407 |
| 409 // TODO(verwaest): Share this code as a code stub. | 408 // TODO(verwaest): Share this code as a code stub. |
| 410 SmiCheck smi_check = representation.IsTagged() | 409 SmiCheck smi_check = representation.IsTagged() |
| 411 ? INLINE_SMI_CHECK : OMIT_SMI_CHECK; | 410 ? INLINE_SMI_CHECK : OMIT_SMI_CHECK; |
| 412 if (index < 0) { | 411 if (index < 0) { |
| 413 // Set the property straight into the object. | 412 // Set the property straight into the object. |
| 414 int offset = object->map()->instance_size() + (index * kPointerSize); | 413 int offset = transition->instance_size() + (index * kPointerSize); |
| 415 if (representation.IsDouble()) { | 414 if (representation.IsDouble()) { |
| 416 __ sd(storage_reg, FieldMemOperand(receiver_reg, offset)); | 415 __ sd(storage_reg, FieldMemOperand(receiver_reg, offset)); |
| 417 } else { | 416 } else { |
| 418 __ sd(value_reg, FieldMemOperand(receiver_reg, offset)); | 417 __ sd(value_reg, FieldMemOperand(receiver_reg, offset)); |
| 419 } | 418 } |
| 420 | 419 |
| 421 if (!representation.IsSmi()) { | 420 if (!representation.IsSmi()) { |
| 422 // Update the write barrier for the array address. | 421 // Update the write barrier for the array address. |
| 423 if (!representation.IsDouble()) { | 422 if (!representation.IsDouble()) { |
| 424 __ mov(storage_reg, value_reg); | 423 __ mov(storage_reg, value_reg); |
| (...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 719 Handle<Code> code) { | 718 Handle<Code> code) { |
| 720 __ Jump(code, RelocInfo::CODE_TARGET); | 719 __ Jump(code, RelocInfo::CODE_TARGET); |
| 721 } | 720 } |
| 722 | 721 |
| 723 | 722 |
| 724 #undef __ | 723 #undef __ |
| 725 #define __ ACCESS_MASM(masm()) | 724 #define __ ACCESS_MASM(masm()) |
| 726 | 725 |
| 727 | 726 |
| 728 Register PropertyHandlerCompiler::CheckPrototypes( | 727 Register PropertyHandlerCompiler::CheckPrototypes( |
| 729 Handle<HeapType> type, Register object_reg, Handle<JSObject> holder, | 728 Register object_reg, Register holder_reg, Register scratch1, |
| 730 Register holder_reg, Register scratch1, Register scratch2, | 729 Register scratch2, Handle<Name> name, Label* miss, |
| 731 Handle<Name> name, Label* miss, PrototypeCheckType check) { | 730 PrototypeCheckType check) { |
| 732 Handle<Map> receiver_map(IC::TypeToMap(*type, isolate())); | 731 Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate())); |
| 733 | 732 |
| 734 // Make sure there's no overlap between holder and object registers. | 733 // Make sure there's no overlap between holder and object registers. |
| 735 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 734 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
| 736 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | 735 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
| 737 && !scratch2.is(scratch1)); | 736 && !scratch2.is(scratch1)); |
| 738 | 737 |
| 739 // Keep track of the current object in register reg. | 738 // Keep track of the current object in register reg. |
| 740 Register reg = object_reg; | 739 Register reg = object_reg; |
| 741 int depth = 0; | 740 int depth = 0; |
| 742 | 741 |
| 743 Handle<JSObject> current = Handle<JSObject>::null(); | 742 Handle<JSObject> current = Handle<JSObject>::null(); |
| 744 if (type->IsConstant()) { | 743 if (type()->IsConstant()) { |
| 745 current = Handle<JSObject>::cast(type->AsConstant()->Value()); | 744 current = Handle<JSObject>::cast(type()->AsConstant()->Value()); |
| 746 } | 745 } |
| 747 Handle<JSObject> prototype = Handle<JSObject>::null(); | 746 Handle<JSObject> prototype = Handle<JSObject>::null(); |
| 748 Handle<Map> current_map = receiver_map; | 747 Handle<Map> current_map = receiver_map; |
| 749 Handle<Map> holder_map(holder->map()); | 748 Handle<Map> holder_map(holder()->map()); |
| 750 // Traverse the prototype chain and check the maps in the prototype chain for | 749 // Traverse the prototype chain and check the maps in the prototype chain for |
| 751 // fast and global objects or do negative lookup for normal objects. | 750 // fast and global objects or do negative lookup for normal objects. |
| 752 while (!current_map.is_identical_to(holder_map)) { | 751 while (!current_map.is_identical_to(holder_map)) { |
| 753 ++depth; | 752 ++depth; |
| 754 | 753 |
| 755 // Only global objects and objects that do not require access | 754 // Only global objects and objects that do not require access |
| 756 // checks are allowed in stubs. | 755 // checks are allowed in stubs. |
| 757 ASSERT(current_map->IsJSGlobalProxyMap() || | 756 ASSERT(current_map->IsJSGlobalProxyMap() || |
| 758 !current_map->is_access_check_needed()); | 757 !current_map->is_access_check_needed()); |
| 759 | 758 |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 850 if (!miss->is_unused()) { | 849 if (!miss->is_unused()) { |
| 851 Label success; | 850 Label success; |
| 852 __ Branch(&success); | 851 __ Branch(&success); |
| 853 GenerateRestoreName(masm(), miss, name); | 852 GenerateRestoreName(masm(), miss, name); |
| 854 TailCallBuiltin(masm(), MissBuiltin(kind())); | 853 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 855 __ bind(&success); | 854 __ bind(&success); |
| 856 } | 855 } |
| 857 } | 856 } |
| 858 | 857 |
| 859 | 858 |
| 860 Register NamedLoadHandlerCompiler::CallbackFrontend(Handle<HeapType> type, | 859 Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg, |
| 861 Register object_reg, | |
| 862 Handle<JSObject> holder, | |
| 863 Handle<Name> name, | 860 Handle<Name> name, |
| 864 Handle<Object> callback) { | 861 Handle<Object> callback) { |
| 865 Label miss; | 862 Label miss; |
| 866 | 863 |
| 867 Register reg = FrontendHeader(type, object_reg, holder, name, &miss); | 864 Register reg = FrontendHeader(object_reg, name, &miss); |
| 868 | 865 |
| 869 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { | 866 if (!holder()->HasFastProperties()) { |
| 867 ASSERT(!holder()->IsGlobalObject()); |
| 870 ASSERT(!reg.is(scratch2())); | 868 ASSERT(!reg.is(scratch2())); |
| 871 ASSERT(!reg.is(scratch3())); | 869 ASSERT(!reg.is(scratch3())); |
| 872 ASSERT(!reg.is(scratch4())); | 870 ASSERT(!reg.is(scratch4())); |
| 873 | 871 |
| 874 // Load the properties dictionary. | 872 // Load the properties dictionary. |
| 875 Register dictionary = scratch4(); | 873 Register dictionary = scratch4(); |
| 876 __ ld(dictionary, FieldMemOperand(reg, JSObject::kPropertiesOffset)); | 874 __ ld(dictionary, FieldMemOperand(reg, JSObject::kPropertiesOffset)); |
| 877 | 875 |
| 878 // Probe the dictionary. | 876 // Probe the dictionary. |
| 879 Label probe_done; | 877 Label probe_done; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 895 __ ld(scratch2(), FieldMemOperand(pointer, kValueOffset)); | 893 __ ld(scratch2(), FieldMemOperand(pointer, kValueOffset)); |
| 896 __ Branch(&miss, ne, scratch2(), Operand(callback)); | 894 __ Branch(&miss, ne, scratch2(), Operand(callback)); |
| 897 } | 895 } |
| 898 | 896 |
| 899 FrontendFooter(name, &miss); | 897 FrontendFooter(name, &miss); |
| 900 return reg; | 898 return reg; |
| 901 } | 899 } |
| 902 | 900 |
| 903 | 901 |
| 904 void NamedLoadHandlerCompiler::GenerateLoadField( | 902 void NamedLoadHandlerCompiler::GenerateLoadField( |
| 905 Register reg, Handle<JSObject> holder, FieldIndex field, | 903 Register reg, FieldIndex field, Representation representation) { |
| 906 Representation representation) { | |
| 907 if (!reg.is(receiver())) __ mov(receiver(), reg); | 904 if (!reg.is(receiver())) __ mov(receiver(), reg); |
| 908 LoadFieldStub stub(isolate(), field); | 905 LoadFieldStub stub(isolate(), field); |
| 909 GenerateTailCall(masm(), stub.GetCode()); | 906 GenerateTailCall(masm(), stub.GetCode()); |
| 910 } | 907 } |
| 911 | 908 |
| 912 | 909 |
| 913 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { | 910 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { |
| 914 // Return the constant value. | 911 // Return the constant value. |
| 915 __ li(v0, value); | 912 __ li(v0, value); |
| 916 __ Ret(); | 913 __ Ret(); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 959 ApiFunction fun(getter_address); | 956 ApiFunction fun(getter_address); |
| 960 ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL; | 957 ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL; |
| 961 ExternalReference ref = ExternalReference(&fun, type, isolate()); | 958 ExternalReference ref = ExternalReference(&fun, type, isolate()); |
| 962 __ li(getter_address_reg, Operand(ref)); | 959 __ li(getter_address_reg, Operand(ref)); |
| 963 | 960 |
| 964 CallApiGetterStub stub(isolate()); | 961 CallApiGetterStub stub(isolate()); |
| 965 __ TailCallStub(&stub); | 962 __ TailCallStub(&stub); |
| 966 } | 963 } |
| 967 | 964 |
| 968 | 965 |
| 969 void NamedLoadHandlerCompiler::GenerateLoadInterceptor( | 966 void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg, |
| 970 Register holder_reg, Handle<Object> object, | 967 LookupResult* lookup, |
| 971 Handle<JSObject> interceptor_holder, LookupResult* lookup, | 968 Handle<Name> name) { |
| 972 Handle<Name> name) { | 969 ASSERT(holder()->HasNamedInterceptor()); |
| 973 ASSERT(interceptor_holder->HasNamedInterceptor()); | 970 ASSERT(!holder()->GetNamedInterceptor()->getter()->IsUndefined()); |
| 974 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); | |
| 975 | 971 |
| 976 // So far the most popular follow ups for interceptor loads are FIELD | 972 // So far the most popular follow ups for interceptor loads are FIELD |
| 977 // and CALLBACKS, so inline only them, other cases may be added | 973 // and CALLBACKS, so inline only them, other cases may be added |
| 978 // later. | 974 // later. |
| 979 bool compile_followup_inline = false; | 975 bool compile_followup_inline = false; |
| 980 if (lookup->IsFound() && lookup->IsCacheable()) { | 976 if (lookup->IsFound() && lookup->IsCacheable()) { |
| 981 if (lookup->IsField()) { | 977 if (lookup->IsField()) { |
| 982 compile_followup_inline = true; | 978 compile_followup_inline = true; |
| 983 } else if (lookup->type() == CALLBACKS && | 979 } else if (lookup->type() == CALLBACKS && |
| 984 lookup->GetCallbackObject()->IsExecutableAccessorInfo()) { | 980 lookup->GetCallbackObject()->IsExecutableAccessorInfo()) { |
| 985 ExecutableAccessorInfo* callback = | 981 Handle<ExecutableAccessorInfo> callback( |
| 986 ExecutableAccessorInfo::cast(lookup->GetCallbackObject()); | 982 ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); |
| 987 compile_followup_inline = callback->getter() != NULL && | 983 compile_followup_inline = |
| 988 callback->IsCompatibleReceiver(*object); | 984 callback->getter() != NULL && |
| 985 ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), callback, |
| 986 type()); |
| 989 } | 987 } |
| 990 } | 988 } |
| 991 | 989 |
| 992 if (compile_followup_inline) { | 990 if (compile_followup_inline) { |
| 993 // Compile the interceptor call, followed by inline code to load the | 991 // Compile the interceptor call, followed by inline code to load the |
| 994 // property from further up the prototype chain if the call fails. | 992 // property from further up the prototype chain if the call fails. |
| 995 // Check that the maps haven't changed. | 993 // Check that the maps haven't changed. |
| 996 ASSERT(holder_reg.is(receiver()) || holder_reg.is(scratch1())); | 994 ASSERT(holder_reg.is(receiver()) || holder_reg.is(scratch1())); |
| 997 | 995 |
| 998 // Preserve the receiver register explicitly whenever it is different from | 996 // Preserve the receiver register explicitly whenever it is different from |
| 999 // the holder and it is needed should the interceptor return without any | 997 // the holder and it is needed should the interceptor return without any |
| 1000 // result. The CALLBACKS case needs the receiver to be passed into C++ code, | 998 // result. The CALLBACKS case needs the receiver to be passed into C++ code, |
| 1001 // the FIELD case might cause a miss during the prototype check. | 999 // the FIELD case might cause a miss during the prototype check. |
| 1002 bool must_perfrom_prototype_check = *interceptor_holder != lookup->holder(); | 1000 bool must_perfrom_prototype_check = *holder() != lookup->holder(); |
| 1003 bool must_preserve_receiver_reg = !receiver().is(holder_reg) && | 1001 bool must_preserve_receiver_reg = !receiver().is(holder_reg) && |
| 1004 (lookup->type() == CALLBACKS || must_perfrom_prototype_check); | 1002 (lookup->type() == CALLBACKS || must_perfrom_prototype_check); |
| 1005 | 1003 |
| 1006 // Save necessary data before invoking an interceptor. | 1004 // Save necessary data before invoking an interceptor. |
| 1007 // Requires a frame to make GC aware of pushed pointers. | 1005 // Requires a frame to make GC aware of pushed pointers. |
| 1008 { | 1006 { |
| 1009 FrameScope frame_scope(masm(), StackFrame::INTERNAL); | 1007 FrameScope frame_scope(masm(), StackFrame::INTERNAL); |
| 1010 if (must_preserve_receiver_reg) { | 1008 if (must_preserve_receiver_reg) { |
| 1011 __ Push(receiver(), holder_reg, this->name()); | 1009 __ Push(receiver(), holder_reg, this->name()); |
| 1012 } else { | 1010 } else { |
| 1013 __ Push(holder_reg, this->name()); | 1011 __ Push(holder_reg, this->name()); |
| 1014 } | 1012 } |
| 1015 // Invoke an interceptor. Note: map checks from receiver to | 1013 // Invoke an interceptor. Note: map checks from receiver to |
| 1016 // interceptor's holder has been compiled before (see a caller | 1014 // interceptor's holder has been compiled before (see a caller |
| 1017 // of this method). | 1015 // of this method). |
| 1018 CompileCallLoadPropertyWithInterceptor( | 1016 CompileCallLoadPropertyWithInterceptor( |
| 1019 masm(), receiver(), holder_reg, this->name(), interceptor_holder, | 1017 masm(), receiver(), holder_reg, this->name(), holder(), |
| 1020 IC::kLoadPropertyWithInterceptorOnly); | 1018 IC::kLoadPropertyWithInterceptorOnly); |
| 1021 | 1019 |
| 1022 // Check if interceptor provided a value for property. If it's | 1020 // Check if interceptor provided a value for property. If it's |
| 1023 // the case, return immediately. | 1021 // the case, return immediately. |
| 1024 Label interceptor_failed; | 1022 Label interceptor_failed; |
| 1025 __ LoadRoot(scratch1(), Heap::kNoInterceptorResultSentinelRootIndex); | 1023 __ LoadRoot(scratch1(), Heap::kNoInterceptorResultSentinelRootIndex); |
| 1026 __ Branch(&interceptor_failed, eq, v0, Operand(scratch1())); | 1024 __ Branch(&interceptor_failed, eq, v0, Operand(scratch1())); |
| 1027 frame_scope.GenerateLeaveFrame(); | 1025 frame_scope.GenerateLeaveFrame(); |
| 1028 __ Ret(); | 1026 __ Ret(); |
| 1029 | 1027 |
| 1030 __ bind(&interceptor_failed); | 1028 __ bind(&interceptor_failed); |
| 1031 __ pop(this->name()); | 1029 __ pop(this->name()); |
| 1032 __ pop(holder_reg); | 1030 __ pop(holder_reg); |
| 1033 if (must_preserve_receiver_reg) { | 1031 if (must_preserve_receiver_reg) { |
| 1034 __ pop(receiver()); | 1032 __ pop(receiver()); |
| 1035 } | 1033 } |
| 1036 // Leave the internal frame. | 1034 // Leave the internal frame. |
| 1037 } | 1035 } |
| 1038 GenerateLoadPostInterceptor(holder_reg, interceptor_holder, name, lookup); | 1036 GenerateLoadPostInterceptor(holder_reg, name, lookup); |
| 1039 } else { // !compile_followup_inline | 1037 } else { // !compile_followup_inline |
| 1040 // Call the runtime system to load the interceptor. | 1038 // Call the runtime system to load the interceptor. |
| 1041 // Check that the maps haven't changed. | 1039 // Check that the maps haven't changed. |
| 1042 PushInterceptorArguments(masm(), receiver(), holder_reg, | 1040 PushInterceptorArguments(masm(), receiver(), holder_reg, this->name(), |
| 1043 this->name(), interceptor_holder); | 1041 holder()); |
| 1044 | 1042 |
| 1045 ExternalReference ref = ExternalReference( | 1043 ExternalReference ref = ExternalReference( |
| 1046 IC_Utility(IC::kLoadPropertyWithInterceptor), isolate()); | 1044 IC_Utility(IC::kLoadPropertyWithInterceptor), isolate()); |
| 1047 __ TailCallExternalReference( | 1045 __ TailCallExternalReference( |
| 1048 ref, NamedLoadHandlerCompiler::kInterceptorArgsLength, 1); | 1046 ref, NamedLoadHandlerCompiler::kInterceptorArgsLength, 1); |
| 1049 } | 1047 } |
| 1050 } | 1048 } |
| 1051 | 1049 |
| 1052 | 1050 |
| 1053 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( | 1051 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( |
| 1054 Handle<JSObject> object, Handle<JSObject> holder, Handle<Name> name, | 1052 Handle<JSObject> object, Handle<Name> name, |
| 1055 Handle<ExecutableAccessorInfo> callback) { | 1053 Handle<ExecutableAccessorInfo> callback) { |
| 1056 Register holder_reg = | 1054 Register holder_reg = Frontend(receiver(), name); |
| 1057 Frontend(IC::CurrentTypeOf(object, isolate()), receiver(), holder, name); | |
| 1058 | |
| 1059 // Stub never generated for non-global objects that require access | |
| 1060 // checks. | |
| 1061 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); | |
| 1062 | 1055 |
| 1063 __ Push(receiver(), holder_reg); // Receiver. | 1056 __ Push(receiver(), holder_reg); // Receiver. |
| 1064 __ li(at, Operand(callback)); // Callback info. | 1057 __ li(at, Operand(callback)); // Callback info. |
| 1065 __ push(at); | 1058 __ push(at); |
| 1066 __ li(at, Operand(name)); | 1059 __ li(at, Operand(name)); |
| 1067 __ Push(at, value()); | 1060 __ Push(at, value()); |
| 1068 | 1061 |
| 1069 // Do tail-call to the runtime system. | 1062 // Do tail-call to the runtime system. |
| 1070 ExternalReference store_callback_property = | 1063 ExternalReference store_callback_property = |
| 1071 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); | 1064 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1118 } | 1111 } |
| 1119 __ Ret(); | 1112 __ Ret(); |
| 1120 } | 1113 } |
| 1121 | 1114 |
| 1122 | 1115 |
| 1123 #undef __ | 1116 #undef __ |
| 1124 #define __ ACCESS_MASM(masm()) | 1117 #define __ ACCESS_MASM(masm()) |
| 1125 | 1118 |
| 1126 | 1119 |
| 1127 Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor( | 1120 Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor( |
| 1128 Handle<JSObject> object, Handle<Name> name) { | 1121 Handle<Name> name) { |
| 1129 __ Push(receiver(), this->name(), value()); | 1122 __ Push(receiver(), this->name(), value()); |
| 1130 | 1123 |
| 1131 // Do tail-call to the runtime system. | 1124 // Do tail-call to the runtime system. |
| 1132 ExternalReference store_ic_property = ExternalReference( | 1125 ExternalReference store_ic_property = ExternalReference( |
| 1133 IC_Utility(IC::kStorePropertyWithInterceptor), isolate()); | 1126 IC_Utility(IC::kStorePropertyWithInterceptor), isolate()); |
| 1134 __ TailCallExternalReference(store_ic_property, 3, 1); | 1127 __ TailCallExternalReference(store_ic_property, 3, 1); |
| 1135 | 1128 |
| 1136 // Return the generated code. | 1129 // Return the generated code. |
| 1137 return GetCode(kind(), Code::FAST, name); | 1130 return GetCode(kind(), Code::FAST, name); |
| 1138 } | 1131 } |
| 1139 | 1132 |
| 1140 | 1133 |
| 1141 Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( | 1134 Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( |
| 1142 Handle<HeapType> type, Handle<JSObject> last, Handle<Name> name) { | 1135 Handle<Name> name) { |
| 1143 NonexistentFrontend(type, last, name); | 1136 NonexistentFrontend(name); |
| 1144 | 1137 |
| 1145 // Return undefined if maps of the full prototype chain is still the same. | 1138 // Return undefined if maps of the full prototype chain is still the same. |
| 1146 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); | 1139 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); |
| 1147 __ Ret(); | 1140 __ Ret(); |
| 1148 | 1141 |
| 1149 // Return the generated code. | 1142 // Return the generated code. |
| 1150 return GetCode(kind(), Code::FAST, name); | 1143 return GetCode(kind(), Code::FAST, name); |
| 1151 } | 1144 } |
| 1152 | 1145 |
| 1153 | 1146 |
| 1154 Register* PropertyAccessCompiler::load_calling_convention() { | 1147 Register* PropertyAccessCompiler::load_calling_convention() { |
| 1155 // receiver, name, scratch1, scratch2, scratch3, scratch4. | 1148 // receiver, name, scratch1, scratch2, scratch3, scratch4. |
| 1156 Register receiver = LoadIC::ReceiverRegister(); | 1149 Register receiver = LoadIC::ReceiverRegister(); |
| 1157 Register name = LoadIC::NameRegister(); | 1150 Register name = LoadIC::NameRegister(); |
| 1158 static Register registers[] = { receiver, name, a3, a0, a4, a5 }; | 1151 static Register registers[] = { receiver, name, a3, a0, a4, a5 }; |
| 1159 return registers; | 1152 return registers; |
| 1160 } | 1153 } |
| 1161 | 1154 |
| 1162 | 1155 |
| 1163 Register* PropertyAccessCompiler::store_calling_convention() { | 1156 Register* PropertyAccessCompiler::store_calling_convention() { |
| 1164 // receiver, name, scratch1, scratch2, scratch3. | 1157 // receiver, name, scratch1, scratch2, scratch3. |
| 1165 Register receiver = StoreIC::ReceiverRegister(); | 1158 Register receiver = StoreIC::ReceiverRegister(); |
| 1166 Register name = StoreIC::NameRegister(); | 1159 Register name = StoreIC::NameRegister(); |
| 1160 ASSERT(a3.is(KeyedStoreIC::MapRegister())); |
| 1167 static Register registers[] = { receiver, name, a3, a4, a5 }; | 1161 static Register registers[] = { receiver, name, a3, a4, a5 }; |
| 1168 return registers; | 1162 return registers; |
| 1169 } | 1163 } |
| 1170 | 1164 |
| 1171 | 1165 |
| 1172 Register* PropertyAccessCompiler::keyed_store_calling_convention() { | |
| 1173 // receiver, name, scratch1/map, scratch2, scratch3. | |
| 1174 Register receiver = KeyedStoreIC::ReceiverRegister(); | |
| 1175 Register name = KeyedStoreIC::NameRegister(); | |
| 1176 Register map = KeyedStoreIC::MapRegister(); | |
| 1177 static Register registers[] = { receiver, name, map, a4, a5 }; | |
| 1178 return registers; | |
| 1179 } | |
| 1180 | |
| 1181 | |
| 1182 Register NamedStoreHandlerCompiler::value() { return StoreIC::ValueRegister(); } | 1166 Register NamedStoreHandlerCompiler::value() { return StoreIC::ValueRegister(); } |
| 1183 | 1167 |
| 1184 | 1168 |
| 1185 #undef __ | 1169 #undef __ |
| 1186 #define __ ACCESS_MASM(masm) | 1170 #define __ ACCESS_MASM(masm) |
| 1187 | 1171 |
| 1188 | 1172 |
| 1189 void NamedLoadHandlerCompiler::GenerateLoadViaGetter( | 1173 void NamedLoadHandlerCompiler::GenerateLoadViaGetter( |
| 1190 MacroAssembler* masm, Handle<HeapType> type, Register receiver, | 1174 MacroAssembler* masm, Handle<HeapType> type, Register receiver, |
| 1191 Handle<JSFunction> getter) { | 1175 Handle<JSFunction> getter) { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1220 } | 1204 } |
| 1221 __ Ret(); | 1205 __ Ret(); |
| 1222 } | 1206 } |
| 1223 | 1207 |
| 1224 | 1208 |
| 1225 #undef __ | 1209 #undef __ |
| 1226 #define __ ACCESS_MASM(masm()) | 1210 #define __ ACCESS_MASM(masm()) |
| 1227 | 1211 |
| 1228 | 1212 |
| 1229 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( | 1213 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( |
| 1230 Handle<HeapType> type, Handle<GlobalObject> global, | |
| 1231 Handle<PropertyCell> cell, Handle<Name> name, bool is_dont_delete) { | 1214 Handle<PropertyCell> cell, Handle<Name> name, bool is_dont_delete) { |
| 1232 Label miss; | 1215 Label miss; |
| 1233 | 1216 |
| 1234 FrontendHeader(type, receiver(), global, name, &miss); | 1217 FrontendHeader(receiver(), name, &miss); |
| 1235 | 1218 |
| 1236 // Get the value from the cell. | 1219 // Get the value from the cell. |
| 1237 __ li(a3, Operand(cell)); | 1220 Register result = StoreIC::ValueRegister(); |
| 1238 __ ld(a4, FieldMemOperand(a3, Cell::kValueOffset)); | 1221 __ li(result, Operand(cell)); |
| 1222 __ ld(result, FieldMemOperand(result, Cell::kValueOffset)); |
| 1239 | 1223 |
| 1240 // Check for deleted property if property can actually be deleted. | 1224 // Check for deleted property if property can actually be deleted. |
| 1241 if (!is_dont_delete) { | 1225 if (!is_dont_delete) { |
| 1242 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 1226 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
| 1243 __ Branch(&miss, eq, a4, Operand(at)); | 1227 __ Branch(&miss, eq, result, Operand(at)); |
| 1244 } | 1228 } |
| 1245 | 1229 |
| 1246 Counters* counters = isolate()->counters(); | 1230 Counters* counters = isolate()->counters(); |
| 1247 __ IncrementCounter(counters->named_load_global_stub(), 1, a1, a3); | 1231 __ IncrementCounter(counters->named_load_global_stub(), 1, a1, a3); |
| 1248 __ Ret(USE_DELAY_SLOT); | 1232 __ Ret(USE_DELAY_SLOT); |
| 1249 __ mov(v0, a4); | 1233 __ mov(v0, result); |
| 1250 | 1234 |
| 1251 FrontendFooter(name, &miss); | 1235 FrontendFooter(name, &miss); |
| 1252 | 1236 |
| 1253 // Return the generated code. | 1237 // Return the generated code. |
| 1254 return GetCode(kind(), Code::NORMAL, name); | 1238 return GetCode(kind(), Code::NORMAL, name); |
| 1255 } | 1239 } |
| 1256 | 1240 |
| 1257 | 1241 |
| 1258 Handle<Code> PropertyICCompiler::CompilePolymorphic(TypeHandleList* types, | 1242 Handle<Code> PropertyICCompiler::CompilePolymorphic(TypeHandleList* types, |
| 1259 CodeHandleList* handlers, | 1243 CodeHandleList* handlers, |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1387 | 1371 |
| 1388 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 1372 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
| 1389 } | 1373 } |
| 1390 | 1374 |
| 1391 | 1375 |
| 1392 #undef __ | 1376 #undef __ |
| 1393 | 1377 |
| 1394 } } // namespace v8::internal | 1378 } } // namespace v8::internal |
| 1395 | 1379 |
| 1396 #endif // V8_TARGET_ARCH_MIPS64 | 1380 #endif // V8_TARGET_ARCH_MIPS64 |
| OLD | NEW |