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 Register object_reg, Handle<JSObject> holder, Register holder_reg, | 728 Register object_reg, Register holder_reg, Register scratch1, |
730 Register scratch1, Register scratch2, Handle<Name> name, Label* miss, | 729 Register scratch2, Handle<Name> name, Label* miss, |
731 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 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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(Register object_reg, | 859 Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg, |
861 Handle<JSObject> holder, | |
862 Handle<Name> name, | 860 Handle<Name> name, |
863 Handle<Object> callback) { | 861 Handle<Object> callback) { |
864 Label miss; | 862 Label miss; |
865 | 863 |
866 Register reg = FrontendHeader(object_reg, holder, name, &miss); | 864 Register reg = FrontendHeader(object_reg, name, &miss); |
867 | 865 |
868 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { | 866 if (!holder()->HasFastProperties()) { |
| 867 ASSERT(!holder()->IsGlobalObject()); |
869 ASSERT(!reg.is(scratch2())); | 868 ASSERT(!reg.is(scratch2())); |
870 ASSERT(!reg.is(scratch3())); | 869 ASSERT(!reg.is(scratch3())); |
871 ASSERT(!reg.is(scratch4())); | 870 ASSERT(!reg.is(scratch4())); |
872 | 871 |
873 // Load the properties dictionary. | 872 // Load the properties dictionary. |
874 Register dictionary = scratch4(); | 873 Register dictionary = scratch4(); |
875 __ ld(dictionary, FieldMemOperand(reg, JSObject::kPropertiesOffset)); | 874 __ ld(dictionary, FieldMemOperand(reg, JSObject::kPropertiesOffset)); |
876 | 875 |
877 // Probe the dictionary. | 876 // Probe the dictionary. |
878 Label probe_done; | 877 Label probe_done; |
(...skipping 15 matching lines...) Expand all Loading... |
894 __ ld(scratch2(), FieldMemOperand(pointer, kValueOffset)); | 893 __ ld(scratch2(), FieldMemOperand(pointer, kValueOffset)); |
895 __ Branch(&miss, ne, scratch2(), Operand(callback)); | 894 __ Branch(&miss, ne, scratch2(), Operand(callback)); |
896 } | 895 } |
897 | 896 |
898 FrontendFooter(name, &miss); | 897 FrontendFooter(name, &miss); |
899 return reg; | 898 return reg; |
900 } | 899 } |
901 | 900 |
902 | 901 |
903 void NamedLoadHandlerCompiler::GenerateLoadField( | 902 void NamedLoadHandlerCompiler::GenerateLoadField( |
904 Register reg, Handle<JSObject> holder, FieldIndex field, | 903 Register reg, FieldIndex field, Representation representation) { |
905 Representation representation) { | |
906 if (!reg.is(receiver())) __ mov(receiver(), reg); | 904 if (!reg.is(receiver())) __ mov(receiver(), reg); |
907 LoadFieldStub stub(isolate(), field); | 905 LoadFieldStub stub(isolate(), field); |
908 GenerateTailCall(masm(), stub.GetCode()); | 906 GenerateTailCall(masm(), stub.GetCode()); |
909 } | 907 } |
910 | 908 |
911 | 909 |
912 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { | 910 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { |
913 // Return the constant value. | 911 // Return the constant value. |
914 __ li(v0, value); | 912 __ li(v0, value); |
915 __ Ret(); | 913 __ Ret(); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
958 ApiFunction fun(getter_address); | 956 ApiFunction fun(getter_address); |
959 ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL; | 957 ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL; |
960 ExternalReference ref = ExternalReference(&fun, type, isolate()); | 958 ExternalReference ref = ExternalReference(&fun, type, isolate()); |
961 __ li(getter_address_reg, Operand(ref)); | 959 __ li(getter_address_reg, Operand(ref)); |
962 | 960 |
963 CallApiGetterStub stub(isolate()); | 961 CallApiGetterStub stub(isolate()); |
964 __ TailCallStub(&stub); | 962 __ TailCallStub(&stub); |
965 } | 963 } |
966 | 964 |
967 | 965 |
968 void NamedLoadHandlerCompiler::GenerateLoadInterceptor( | 966 void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg, |
969 Register holder_reg, Handle<JSObject> interceptor_holder, | 967 LookupResult* lookup, |
970 LookupResult* lookup, Handle<Name> name) { | 968 Handle<Name> name) { |
971 ASSERT(interceptor_holder->HasNamedInterceptor()); | 969 ASSERT(holder()->HasNamedInterceptor()); |
972 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); | 970 ASSERT(!holder()->GetNamedInterceptor()->getter()->IsUndefined()); |
973 | 971 |
974 // 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 |
975 // and CALLBACKS, so inline only them, other cases may be added | 973 // and CALLBACKS, so inline only them, other cases may be added |
976 // later. | 974 // later. |
977 bool compile_followup_inline = false; | 975 bool compile_followup_inline = false; |
978 if (lookup->IsFound() && lookup->IsCacheable()) { | 976 if (lookup->IsFound() && lookup->IsCacheable()) { |
979 if (lookup->IsField()) { | 977 if (lookup->IsField()) { |
980 compile_followup_inline = true; | 978 compile_followup_inline = true; |
981 } else if (lookup->type() == CALLBACKS && | 979 } else if (lookup->type() == CALLBACKS && |
982 lookup->GetCallbackObject()->IsExecutableAccessorInfo()) { | 980 lookup->GetCallbackObject()->IsExecutableAccessorInfo()) { |
983 Handle<ExecutableAccessorInfo> callback( | 981 Handle<ExecutableAccessorInfo> callback( |
984 ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); | 982 ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); |
985 compile_followup_inline = | 983 compile_followup_inline = |
986 callback->getter() != NULL && | 984 callback->getter() != NULL && |
987 ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), callback, | 985 ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), callback, |
988 type()); | 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 = Frontend(receiver(), holder, name); | 1054 Register holder_reg = Frontend(receiver(), name); |
1057 | |
1058 // Stub never generated for non-global objects that require access | |
1059 // checks. | |
1060 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); | |
1061 | 1055 |
1062 __ Push(receiver(), holder_reg); // Receiver. | 1056 __ Push(receiver(), holder_reg); // Receiver. |
1063 __ li(at, Operand(callback)); // Callback info. | 1057 __ li(at, Operand(callback)); // Callback info. |
1064 __ push(at); | 1058 __ push(at); |
1065 __ li(at, Operand(name)); | 1059 __ li(at, Operand(name)); |
1066 __ Push(at, value()); | 1060 __ Push(at, value()); |
1067 | 1061 |
1068 // Do tail-call to the runtime system. | 1062 // Do tail-call to the runtime system. |
1069 ExternalReference store_callback_property = | 1063 ExternalReference store_callback_property = |
1070 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... |
1117 } | 1111 } |
1118 __ Ret(); | 1112 __ Ret(); |
1119 } | 1113 } |
1120 | 1114 |
1121 | 1115 |
1122 #undef __ | 1116 #undef __ |
1123 #define __ ACCESS_MASM(masm()) | 1117 #define __ ACCESS_MASM(masm()) |
1124 | 1118 |
1125 | 1119 |
1126 Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor( | 1120 Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor( |
1127 Handle<JSObject> object, Handle<Name> name) { | 1121 Handle<Name> name) { |
1128 __ Push(receiver(), this->name(), value()); | 1122 __ Push(receiver(), this->name(), value()); |
1129 | 1123 |
1130 // Do tail-call to the runtime system. | 1124 // Do tail-call to the runtime system. |
1131 ExternalReference store_ic_property = ExternalReference( | 1125 ExternalReference store_ic_property = ExternalReference( |
1132 IC_Utility(IC::kStorePropertyWithInterceptor), isolate()); | 1126 IC_Utility(IC::kStorePropertyWithInterceptor), isolate()); |
1133 __ TailCallExternalReference(store_ic_property, 3, 1); | 1127 __ TailCallExternalReference(store_ic_property, 3, 1); |
1134 | 1128 |
1135 // Return the generated code. | 1129 // Return the generated code. |
1136 return GetCode(kind(), Code::FAST, name); | 1130 return GetCode(kind(), Code::FAST, name); |
1137 } | 1131 } |
1138 | 1132 |
1139 | 1133 |
1140 Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( | 1134 Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( |
1141 Handle<JSObject> last, Handle<Name> name) { | 1135 Handle<Name> name) { |
1142 NonexistentFrontend(last, name); | 1136 NonexistentFrontend(name); |
1143 | 1137 |
1144 // 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. |
1145 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); | 1139 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); |
1146 __ Ret(); | 1140 __ Ret(); |
1147 | 1141 |
1148 // Return the generated code. | 1142 // Return the generated code. |
1149 return GetCode(kind(), Code::FAST, name); | 1143 return GetCode(kind(), Code::FAST, name); |
1150 } | 1144 } |
1151 | 1145 |
1152 | 1146 |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1219 } | 1213 } |
1220 __ Ret(); | 1214 __ Ret(); |
1221 } | 1215 } |
1222 | 1216 |
1223 | 1217 |
1224 #undef __ | 1218 #undef __ |
1225 #define __ ACCESS_MASM(masm()) | 1219 #define __ ACCESS_MASM(masm()) |
1226 | 1220 |
1227 | 1221 |
1228 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( | 1222 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( |
1229 Handle<GlobalObject> global, Handle<PropertyCell> cell, Handle<Name> name, | 1223 Handle<PropertyCell> cell, Handle<Name> name, bool is_dont_delete) { |
1230 bool is_dont_delete) { | |
1231 Label miss; | 1224 Label miss; |
1232 | 1225 |
1233 FrontendHeader(receiver(), global, name, &miss); | 1226 FrontendHeader(receiver(), name, &miss); |
1234 | 1227 |
1235 // Get the value from the cell. | 1228 // Get the value from the cell. |
1236 Register result = StoreIC::ValueRegister(); | 1229 Register result = StoreIC::ValueRegister(); |
1237 __ li(result, Operand(cell)); | 1230 __ li(result, Operand(cell)); |
1238 __ ld(result, FieldMemOperand(result, Cell::kValueOffset)); | 1231 __ ld(result, FieldMemOperand(result, Cell::kValueOffset)); |
1239 | 1232 |
1240 // Check for deleted property if property can actually be deleted. | 1233 // Check for deleted property if property can actually be deleted. |
1241 if (!is_dont_delete) { | 1234 if (!is_dont_delete) { |
1242 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 1235 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
1243 __ Branch(&miss, eq, result, Operand(at)); | 1236 __ Branch(&miss, eq, result, Operand(at)); |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1387 | 1380 |
1388 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 1381 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
1389 } | 1382 } |
1390 | 1383 |
1391 | 1384 |
1392 #undef __ | 1385 #undef __ |
1393 | 1386 |
1394 } } // namespace v8::internal | 1387 } } // namespace v8::internal |
1395 | 1388 |
1396 #endif // V8_TARGET_ARCH_MIPS64 | 1389 #endif // V8_TARGET_ARCH_MIPS64 |
OLD | NEW |