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_ARM | 7 #if V8_TARGET_ARCH_ARM |
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 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
304 masm, miss, holder_reg, name, scratch1(), scratch2()); | 304 masm, miss, holder_reg, name, scratch1(), scratch2()); |
305 } | 305 } |
306 } | 306 } |
307 | 307 |
308 | 308 |
309 // Generate StoreTransition code, value is passed in r0 register. | 309 // Generate StoreTransition code, value is passed in r0 register. |
310 // When leaving generated code after success, the receiver_reg and name_reg | 310 // When leaving generated code after success, the receiver_reg and name_reg |
311 // may be clobbered. Upon branch to miss_label, the receiver and name | 311 // may be clobbered. Upon branch to miss_label, the receiver and name |
312 // registers have their original values. | 312 // registers have their original values. |
313 void NamedStoreHandlerCompiler::GenerateStoreTransition( | 313 void NamedStoreHandlerCompiler::GenerateStoreTransition( |
314 MacroAssembler* masm, Handle<JSObject> object, LookupResult* lookup, | 314 MacroAssembler* masm, LookupResult* lookup, Handle<Map> transition, |
315 Handle<Map> transition, Handle<Name> name, Register receiver_reg, | 315 Handle<Name> name, Register receiver_reg, Register storage_reg, |
316 Register storage_reg, Register value_reg, Register scratch1, | 316 Register value_reg, Register scratch1, Register scratch2, Register scratch3, |
317 Register scratch2, Register scratch3, Label* miss_label, Label* slow) { | 317 Label* miss_label, Label* slow) { |
318 // r0 : value | 318 // r0 : value |
319 Label exit; | 319 Label exit; |
320 | 320 |
321 int descriptor = transition->LastAdded(); | 321 int descriptor = transition->LastAdded(); |
322 DescriptorArray* descriptors = transition->instance_descriptors(); | 322 DescriptorArray* descriptors = transition->instance_descriptors(); |
323 PropertyDetails details = descriptors->GetDetails(descriptor); | 323 PropertyDetails details = descriptors->GetDetails(descriptor); |
324 Representation representation = details.representation(); | 324 Representation representation = details.representation(); |
325 ASSERT(!representation.IsNone()); | 325 ASSERT(!representation.IsNone()); |
326 | 326 |
327 if (details.type() == CONSTANT) { | 327 if (details.type() == CONSTANT) { |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
363 | 363 |
364 __ bind(&heap_number); | 364 __ bind(&heap_number); |
365 __ CheckMap(value_reg, scratch1, Heap::kHeapNumberMapRootIndex, | 365 __ CheckMap(value_reg, scratch1, Heap::kHeapNumberMapRootIndex, |
366 miss_label, DONT_DO_SMI_CHECK); | 366 miss_label, DONT_DO_SMI_CHECK); |
367 __ vldr(d0, FieldMemOperand(value_reg, HeapNumber::kValueOffset)); | 367 __ vldr(d0, FieldMemOperand(value_reg, HeapNumber::kValueOffset)); |
368 | 368 |
369 __ bind(&do_store); | 369 __ bind(&do_store); |
370 __ vstr(d0, FieldMemOperand(storage_reg, HeapNumber::kValueOffset)); | 370 __ vstr(d0, FieldMemOperand(storage_reg, HeapNumber::kValueOffset)); |
371 } | 371 } |
372 | 372 |
373 // Stub never generated for non-global objects that require access | 373 // Stub never generated for objects that require access checks. |
374 // checks. | 374 ASSERT(!transition->is_access_check_needed()); |
375 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | |
376 | 375 |
377 // Perform map transition for the receiver if necessary. | 376 // Perform map transition for the receiver if necessary. |
378 if (details.type() == FIELD && | 377 if (details.type() == FIELD && |
379 object->map()->unused_property_fields() == 0) { | 378 Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) { |
380 // The properties must be extended before we can store the value. | 379 // The properties must be extended before we can store the value. |
381 // We jump to a runtime call that extends the properties array. | 380 // We jump to a runtime call that extends the properties array. |
382 __ push(receiver_reg); | 381 __ push(receiver_reg); |
383 __ mov(r2, Operand(transition)); | 382 __ mov(r2, Operand(transition)); |
384 __ Push(r2, r0); | 383 __ Push(r2, r0); |
385 __ TailCallExternalReference( | 384 __ TailCallExternalReference( |
386 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), | 385 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), |
387 masm->isolate()), | 386 masm->isolate()), |
388 3, | 387 3, |
389 1); | 388 1); |
(...skipping 19 matching lines...) Expand all Loading... |
409 __ Ret(); | 408 __ Ret(); |
410 return; | 409 return; |
411 } | 410 } |
412 | 411 |
413 int index = transition->instance_descriptors()->GetFieldIndex( | 412 int index = transition->instance_descriptors()->GetFieldIndex( |
414 transition->LastAdded()); | 413 transition->LastAdded()); |
415 | 414 |
416 // Adjust for the number of properties stored in the object. Even in the | 415 // Adjust for the number of properties stored in the object. Even in the |
417 // face of a transition we can use the old map here because the size of the | 416 // face of a transition we can use the old map here because the size of the |
418 // object and the number of in-object properties is not going to change. | 417 // object and the number of in-object properties is not going to change. |
419 index -= object->map()->inobject_properties(); | 418 index -= transition->inobject_properties(); |
420 | 419 |
421 // TODO(verwaest): Share this code as a code stub. | 420 // TODO(verwaest): Share this code as a code stub. |
422 SmiCheck smi_check = representation.IsTagged() | 421 SmiCheck smi_check = representation.IsTagged() |
423 ? INLINE_SMI_CHECK : OMIT_SMI_CHECK; | 422 ? INLINE_SMI_CHECK : OMIT_SMI_CHECK; |
424 if (index < 0) { | 423 if (index < 0) { |
425 // Set the property straight into the object. | 424 // Set the property straight into the object. |
426 int offset = object->map()->instance_size() + (index * kPointerSize); | 425 int offset = transition->instance_size() + (index * kPointerSize); |
427 if (representation.IsDouble()) { | 426 if (representation.IsDouble()) { |
428 __ str(storage_reg, FieldMemOperand(receiver_reg, offset)); | 427 __ str(storage_reg, FieldMemOperand(receiver_reg, offset)); |
429 } else { | 428 } else { |
430 __ str(value_reg, FieldMemOperand(receiver_reg, offset)); | 429 __ str(value_reg, FieldMemOperand(receiver_reg, offset)); |
431 } | 430 } |
432 | 431 |
433 if (!representation.IsSmi()) { | 432 if (!representation.IsSmi()) { |
434 // Update the write barrier for the array address. | 433 // Update the write barrier for the array address. |
435 if (!representation.IsDouble()) { | 434 if (!representation.IsDouble()) { |
436 __ mov(storage_reg, value_reg); | 435 __ mov(storage_reg, value_reg); |
(...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
726 Handle<Code> code) { | 725 Handle<Code> code) { |
727 __ Jump(code, RelocInfo::CODE_TARGET); | 726 __ Jump(code, RelocInfo::CODE_TARGET); |
728 } | 727 } |
729 | 728 |
730 | 729 |
731 #undef __ | 730 #undef __ |
732 #define __ ACCESS_MASM(masm()) | 731 #define __ ACCESS_MASM(masm()) |
733 | 732 |
734 | 733 |
735 Register PropertyHandlerCompiler::CheckPrototypes( | 734 Register PropertyHandlerCompiler::CheckPrototypes( |
736 Register object_reg, Handle<JSObject> holder, Register holder_reg, | 735 Register object_reg, Register holder_reg, Register scratch1, |
737 Register scratch1, Register scratch2, Handle<Name> name, Label* miss, | 736 Register scratch2, Handle<Name> name, Label* miss, |
738 PrototypeCheckType check) { | 737 PrototypeCheckType check) { |
739 Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate())); | 738 Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate())); |
740 | 739 |
741 // Make sure there's no overlap between holder and object registers. | 740 // Make sure there's no overlap between holder and object registers. |
742 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 741 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
743 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | 742 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
744 && !scratch2.is(scratch1)); | 743 && !scratch2.is(scratch1)); |
745 | 744 |
746 // Keep track of the current object in register reg. | 745 // Keep track of the current object in register reg. |
747 Register reg = object_reg; | 746 Register reg = object_reg; |
748 int depth = 0; | 747 int depth = 0; |
749 | 748 |
750 Handle<JSObject> current = Handle<JSObject>::null(); | 749 Handle<JSObject> current = Handle<JSObject>::null(); |
751 if (type()->IsConstant()) { | 750 if (type()->IsConstant()) { |
752 current = Handle<JSObject>::cast(type()->AsConstant()->Value()); | 751 current = Handle<JSObject>::cast(type()->AsConstant()->Value()); |
753 } | 752 } |
754 Handle<JSObject> prototype = Handle<JSObject>::null(); | 753 Handle<JSObject> prototype = Handle<JSObject>::null(); |
755 Handle<Map> current_map = receiver_map; | 754 Handle<Map> current_map = receiver_map; |
756 Handle<Map> holder_map(holder->map()); | 755 Handle<Map> holder_map(holder()->map()); |
757 // Traverse the prototype chain and check the maps in the prototype chain for | 756 // Traverse the prototype chain and check the maps in the prototype chain for |
758 // fast and global objects or do negative lookup for normal objects. | 757 // fast and global objects or do negative lookup for normal objects. |
759 while (!current_map.is_identical_to(holder_map)) { | 758 while (!current_map.is_identical_to(holder_map)) { |
760 ++depth; | 759 ++depth; |
761 | 760 |
762 // Only global objects and objects that do not require access | 761 // Only global objects and objects that do not require access |
763 // checks are allowed in stubs. | 762 // checks are allowed in stubs. |
764 ASSERT(current_map->IsJSGlobalProxyMap() || | 763 ASSERT(current_map->IsJSGlobalProxyMap() || |
765 !current_map->is_access_check_needed()); | 764 !current_map->is_access_check_needed()); |
766 | 765 |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
858 Label success; | 857 Label success; |
859 __ b(&success); | 858 __ b(&success); |
860 GenerateRestoreName(masm(), miss, name); | 859 GenerateRestoreName(masm(), miss, name); |
861 TailCallBuiltin(masm(), MissBuiltin(kind())); | 860 TailCallBuiltin(masm(), MissBuiltin(kind())); |
862 __ bind(&success); | 861 __ bind(&success); |
863 } | 862 } |
864 } | 863 } |
865 | 864 |
866 | 865 |
867 Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg, | 866 Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg, |
868 Handle<JSObject> holder, | |
869 Handle<Name> name, | 867 Handle<Name> name, |
870 Handle<Object> callback) { | 868 Handle<Object> callback) { |
871 Label miss; | 869 Label miss; |
872 | 870 |
873 Register reg = FrontendHeader(object_reg, holder, name, &miss); | 871 Register reg = FrontendHeader(object_reg, name, &miss); |
874 | 872 |
875 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { | 873 if (!holder()->HasFastProperties()) { |
| 874 ASSERT(!holder()->IsGlobalObject()); |
876 ASSERT(!reg.is(scratch2())); | 875 ASSERT(!reg.is(scratch2())); |
877 ASSERT(!reg.is(scratch3())); | 876 ASSERT(!reg.is(scratch3())); |
878 ASSERT(!reg.is(scratch4())); | 877 ASSERT(!reg.is(scratch4())); |
879 | 878 |
880 // Load the properties dictionary. | 879 // Load the properties dictionary. |
881 Register dictionary = scratch4(); | 880 Register dictionary = scratch4(); |
882 __ ldr(dictionary, FieldMemOperand(reg, JSObject::kPropertiesOffset)); | 881 __ ldr(dictionary, FieldMemOperand(reg, JSObject::kPropertiesOffset)); |
883 | 882 |
884 // Probe the dictionary. | 883 // Probe the dictionary. |
885 Label probe_done; | 884 Label probe_done; |
(...skipping 16 matching lines...) Expand all Loading... |
902 __ cmp(scratch2(), Operand(callback)); | 901 __ cmp(scratch2(), Operand(callback)); |
903 __ b(ne, &miss); | 902 __ b(ne, &miss); |
904 } | 903 } |
905 | 904 |
906 FrontendFooter(name, &miss); | 905 FrontendFooter(name, &miss); |
907 return reg; | 906 return reg; |
908 } | 907 } |
909 | 908 |
910 | 909 |
911 void NamedLoadHandlerCompiler::GenerateLoadField( | 910 void NamedLoadHandlerCompiler::GenerateLoadField( |
912 Register reg, Handle<JSObject> holder, FieldIndex field, | 911 Register reg, FieldIndex field, Representation representation) { |
913 Representation representation) { | |
914 if (!reg.is(receiver())) __ mov(receiver(), reg); | 912 if (!reg.is(receiver())) __ mov(receiver(), reg); |
915 LoadFieldStub stub(isolate(), field); | 913 LoadFieldStub stub(isolate(), field); |
916 GenerateTailCall(masm(), stub.GetCode()); | 914 GenerateTailCall(masm(), stub.GetCode()); |
917 } | 915 } |
918 | 916 |
919 | 917 |
920 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { | 918 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { |
921 // Return the constant value. | 919 // Return the constant value. |
922 __ Move(r0, value); | 920 __ Move(r0, value); |
923 __ Ret(); | 921 __ Ret(); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
963 ApiFunction fun(getter_address); | 961 ApiFunction fun(getter_address); |
964 ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL; | 962 ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL; |
965 ExternalReference ref = ExternalReference(&fun, type, isolate()); | 963 ExternalReference ref = ExternalReference(&fun, type, isolate()); |
966 __ mov(getter_address_reg, Operand(ref)); | 964 __ mov(getter_address_reg, Operand(ref)); |
967 | 965 |
968 CallApiGetterStub stub(isolate()); | 966 CallApiGetterStub stub(isolate()); |
969 __ TailCallStub(&stub); | 967 __ TailCallStub(&stub); |
970 } | 968 } |
971 | 969 |
972 | 970 |
973 void NamedLoadHandlerCompiler::GenerateLoadInterceptor( | 971 void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg, |
974 Register holder_reg, Handle<JSObject> interceptor_holder, | 972 LookupResult* lookup, |
975 LookupResult* lookup, Handle<Name> name) { | 973 Handle<Name> name) { |
976 ASSERT(interceptor_holder->HasNamedInterceptor()); | 974 ASSERT(holder()->HasNamedInterceptor()); |
977 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); | 975 ASSERT(!holder()->GetNamedInterceptor()->getter()->IsUndefined()); |
978 | 976 |
979 // So far the most popular follow ups for interceptor loads are FIELD | 977 // So far the most popular follow ups for interceptor loads are FIELD |
980 // and CALLBACKS, so inline only them, other cases may be added | 978 // and CALLBACKS, so inline only them, other cases may be added |
981 // later. | 979 // later. |
982 bool compile_followup_inline = false; | 980 bool compile_followup_inline = false; |
983 if (lookup->IsFound() && lookup->IsCacheable()) { | 981 if (lookup->IsFound() && lookup->IsCacheable()) { |
984 if (lookup->IsField()) { | 982 if (lookup->IsField()) { |
985 compile_followup_inline = true; | 983 compile_followup_inline = true; |
986 } else if (lookup->type() == CALLBACKS && | 984 } else if (lookup->type() == CALLBACKS && |
987 lookup->GetCallbackObject()->IsExecutableAccessorInfo()) { | 985 lookup->GetCallbackObject()->IsExecutableAccessorInfo()) { |
988 Handle<ExecutableAccessorInfo> callback( | 986 Handle<ExecutableAccessorInfo> callback( |
989 ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); | 987 ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); |
990 compile_followup_inline = | 988 compile_followup_inline = |
991 callback->getter() != NULL && | 989 callback->getter() != NULL && |
992 ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), callback, | 990 ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), callback, |
993 type()); | 991 type()); |
994 } | 992 } |
995 } | 993 } |
996 | 994 |
997 if (compile_followup_inline) { | 995 if (compile_followup_inline) { |
998 // Compile the interceptor call, followed by inline code to load the | 996 // Compile the interceptor call, followed by inline code to load the |
999 // property from further up the prototype chain if the call fails. | 997 // property from further up the prototype chain if the call fails. |
1000 // Check that the maps haven't changed. | 998 // Check that the maps haven't changed. |
1001 ASSERT(holder_reg.is(receiver()) || holder_reg.is(scratch1())); | 999 ASSERT(holder_reg.is(receiver()) || holder_reg.is(scratch1())); |
1002 | 1000 |
1003 // Preserve the receiver register explicitly whenever it is different from | 1001 // Preserve the receiver register explicitly whenever it is different from |
1004 // the holder and it is needed should the interceptor return without any | 1002 // the holder and it is needed should the interceptor return without any |
1005 // result. The CALLBACKS case needs the receiver to be passed into C++ code, | 1003 // result. The CALLBACKS case needs the receiver to be passed into C++ code, |
1006 // the FIELD case might cause a miss during the prototype check. | 1004 // the FIELD case might cause a miss during the prototype check. |
1007 bool must_perfrom_prototype_check = *interceptor_holder != lookup->holder(); | 1005 bool must_perfrom_prototype_check = *holder() != lookup->holder(); |
1008 bool must_preserve_receiver_reg = !receiver().is(holder_reg) && | 1006 bool must_preserve_receiver_reg = !receiver().is(holder_reg) && |
1009 (lookup->type() == CALLBACKS || must_perfrom_prototype_check); | 1007 (lookup->type() == CALLBACKS || must_perfrom_prototype_check); |
1010 | 1008 |
1011 // Save necessary data before invoking an interceptor. | 1009 // Save necessary data before invoking an interceptor. |
1012 // Requires a frame to make GC aware of pushed pointers. | 1010 // Requires a frame to make GC aware of pushed pointers. |
1013 { | 1011 { |
1014 FrameAndConstantPoolScope frame_scope(masm(), StackFrame::INTERNAL); | 1012 FrameAndConstantPoolScope frame_scope(masm(), StackFrame::INTERNAL); |
1015 if (must_preserve_receiver_reg) { | 1013 if (must_preserve_receiver_reg) { |
1016 __ Push(receiver(), holder_reg, this->name()); | 1014 __ Push(receiver(), holder_reg, this->name()); |
1017 } else { | 1015 } else { |
1018 __ Push(holder_reg, this->name()); | 1016 __ Push(holder_reg, this->name()); |
1019 } | 1017 } |
1020 // Invoke an interceptor. Note: map checks from receiver to | 1018 // Invoke an interceptor. Note: map checks from receiver to |
1021 // interceptor's holder has been compiled before (see a caller | 1019 // interceptor's holder has been compiled before (see a caller |
1022 // of this method.) | 1020 // of this method.) |
1023 CompileCallLoadPropertyWithInterceptor( | 1021 CompileCallLoadPropertyWithInterceptor( |
1024 masm(), receiver(), holder_reg, this->name(), interceptor_holder, | 1022 masm(), receiver(), holder_reg, this->name(), holder(), |
1025 IC::kLoadPropertyWithInterceptorOnly); | 1023 IC::kLoadPropertyWithInterceptorOnly); |
1026 | 1024 |
1027 // Check if interceptor provided a value for property. If it's | 1025 // Check if interceptor provided a value for property. If it's |
1028 // the case, return immediately. | 1026 // the case, return immediately. |
1029 Label interceptor_failed; | 1027 Label interceptor_failed; |
1030 __ LoadRoot(scratch1(), Heap::kNoInterceptorResultSentinelRootIndex); | 1028 __ LoadRoot(scratch1(), Heap::kNoInterceptorResultSentinelRootIndex); |
1031 __ cmp(r0, scratch1()); | 1029 __ cmp(r0, scratch1()); |
1032 __ b(eq, &interceptor_failed); | 1030 __ b(eq, &interceptor_failed); |
1033 frame_scope.GenerateLeaveFrame(); | 1031 frame_scope.GenerateLeaveFrame(); |
1034 __ Ret(); | 1032 __ Ret(); |
1035 | 1033 |
1036 __ bind(&interceptor_failed); | 1034 __ bind(&interceptor_failed); |
1037 __ pop(this->name()); | 1035 __ pop(this->name()); |
1038 __ pop(holder_reg); | 1036 __ pop(holder_reg); |
1039 if (must_preserve_receiver_reg) { | 1037 if (must_preserve_receiver_reg) { |
1040 __ pop(receiver()); | 1038 __ pop(receiver()); |
1041 } | 1039 } |
1042 // Leave the internal frame. | 1040 // Leave the internal frame. |
1043 } | 1041 } |
1044 | 1042 |
1045 GenerateLoadPostInterceptor(holder_reg, interceptor_holder, name, lookup); | 1043 GenerateLoadPostInterceptor(holder_reg, name, lookup); |
1046 } else { // !compile_followup_inline | 1044 } else { // !compile_followup_inline |
1047 // Call the runtime system to load the interceptor. | 1045 // Call the runtime system to load the interceptor. |
1048 // Check that the maps haven't changed. | 1046 // Check that the maps haven't changed. |
1049 PushInterceptorArguments(masm(), receiver(), holder_reg, | 1047 PushInterceptorArguments(masm(), receiver(), holder_reg, this->name(), |
1050 this->name(), interceptor_holder); | 1048 holder()); |
1051 | 1049 |
1052 ExternalReference ref = | 1050 ExternalReference ref = |
1053 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptor), | 1051 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptor), |
1054 isolate()); | 1052 isolate()); |
1055 __ TailCallExternalReference( | 1053 __ TailCallExternalReference( |
1056 ref, NamedLoadHandlerCompiler::kInterceptorArgsLength, 1); | 1054 ref, NamedLoadHandlerCompiler::kInterceptorArgsLength, 1); |
1057 } | 1055 } |
1058 } | 1056 } |
1059 | 1057 |
1060 | 1058 |
1061 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( | 1059 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( |
1062 Handle<JSObject> object, Handle<JSObject> holder, Handle<Name> name, | 1060 Handle<JSObject> object, Handle<Name> name, |
1063 Handle<ExecutableAccessorInfo> callback) { | 1061 Handle<ExecutableAccessorInfo> callback) { |
1064 Register holder_reg = Frontend(receiver(), holder, name); | 1062 Register holder_reg = Frontend(receiver(), name); |
1065 | |
1066 // Stub never generated for non-global objects that require access checks. | |
1067 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); | |
1068 | 1063 |
1069 __ push(receiver()); // receiver | 1064 __ push(receiver()); // receiver |
1070 __ push(holder_reg); | 1065 __ push(holder_reg); |
1071 __ mov(ip, Operand(callback)); // callback info | 1066 __ mov(ip, Operand(callback)); // callback info |
1072 __ push(ip); | 1067 __ push(ip); |
1073 __ mov(ip, Operand(name)); | 1068 __ mov(ip, Operand(name)); |
1074 __ Push(ip, value()); | 1069 __ Push(ip, value()); |
1075 | 1070 |
1076 // Do tail-call to the runtime system. | 1071 // Do tail-call to the runtime system. |
1077 ExternalReference store_callback_property = | 1072 ExternalReference store_callback_property = |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1125 } | 1120 } |
1126 __ Ret(); | 1121 __ Ret(); |
1127 } | 1122 } |
1128 | 1123 |
1129 | 1124 |
1130 #undef __ | 1125 #undef __ |
1131 #define __ ACCESS_MASM(masm()) | 1126 #define __ ACCESS_MASM(masm()) |
1132 | 1127 |
1133 | 1128 |
1134 Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor( | 1129 Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor( |
1135 Handle<JSObject> object, Handle<Name> name) { | 1130 Handle<Name> name) { |
1136 __ Push(receiver(), this->name(), value()); | 1131 __ Push(receiver(), this->name(), value()); |
1137 | 1132 |
1138 // Do tail-call to the runtime system. | 1133 // Do tail-call to the runtime system. |
1139 ExternalReference store_ic_property = ExternalReference( | 1134 ExternalReference store_ic_property = ExternalReference( |
1140 IC_Utility(IC::kStorePropertyWithInterceptor), isolate()); | 1135 IC_Utility(IC::kStorePropertyWithInterceptor), isolate()); |
1141 __ TailCallExternalReference(store_ic_property, 3, 1); | 1136 __ TailCallExternalReference(store_ic_property, 3, 1); |
1142 | 1137 |
1143 // Return the generated code. | 1138 // Return the generated code. |
1144 return GetCode(kind(), Code::FAST, name); | 1139 return GetCode(kind(), Code::FAST, name); |
1145 } | 1140 } |
1146 | 1141 |
1147 | 1142 |
1148 Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( | 1143 Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( |
1149 Handle<JSObject> last, Handle<Name> name) { | 1144 Handle<Name> name) { |
1150 NonexistentFrontend(last, name); | 1145 NonexistentFrontend(name); |
1151 | 1146 |
1152 // Return undefined if maps of the full prototype chain are still the | 1147 // Return undefined if maps of the full prototype chain are still the |
1153 // same and no global property with this name contains a value. | 1148 // same and no global property with this name contains a value. |
1154 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); | 1149 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); |
1155 __ Ret(); | 1150 __ Ret(); |
1156 | 1151 |
1157 // Return the generated code. | 1152 // Return the generated code. |
1158 return GetCode(kind(), Code::FAST, name); | 1153 return GetCode(kind(), Code::FAST, name); |
1159 } | 1154 } |
1160 | 1155 |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1228 } | 1223 } |
1229 __ Ret(); | 1224 __ Ret(); |
1230 } | 1225 } |
1231 | 1226 |
1232 | 1227 |
1233 #undef __ | 1228 #undef __ |
1234 #define __ ACCESS_MASM(masm()) | 1229 #define __ ACCESS_MASM(masm()) |
1235 | 1230 |
1236 | 1231 |
1237 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( | 1232 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( |
1238 Handle<GlobalObject> global, Handle<PropertyCell> cell, Handle<Name> name, | 1233 Handle<PropertyCell> cell, Handle<Name> name, bool is_dont_delete) { |
1239 bool is_dont_delete) { | |
1240 Label miss; | 1234 Label miss; |
1241 FrontendHeader(receiver(), global, name, &miss); | 1235 FrontendHeader(receiver(), name, &miss); |
1242 | 1236 |
1243 // Get the value from the cell. | 1237 // Get the value from the cell. |
1244 Register result = StoreIC::ValueRegister(); | 1238 Register result = StoreIC::ValueRegister(); |
1245 __ mov(result, Operand(cell)); | 1239 __ mov(result, Operand(cell)); |
1246 __ ldr(result, FieldMemOperand(result, Cell::kValueOffset)); | 1240 __ ldr(result, FieldMemOperand(result, Cell::kValueOffset)); |
1247 | 1241 |
1248 // Check for deleted property if property can actually be deleted. | 1242 // Check for deleted property if property can actually be deleted. |
1249 if (!is_dont_delete) { | 1243 if (!is_dont_delete) { |
1250 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 1244 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
1251 __ cmp(result, ip); | 1245 __ cmp(result, ip); |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1392 | 1386 |
1393 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 1387 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
1394 } | 1388 } |
1395 | 1389 |
1396 | 1390 |
1397 #undef __ | 1391 #undef __ |
1398 | 1392 |
1399 } } // namespace v8::internal | 1393 } } // namespace v8::internal |
1400 | 1394 |
1401 #endif // V8_TARGET_ARCH_ARM | 1395 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |