| 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_IA32 | 7 #if V8_TARGET_ARCH_IA32 |
| 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 399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 410 } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) { | 410 } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) { |
| 411 GenerateDictionaryNegativeLookup( | 411 GenerateDictionaryNegativeLookup( |
| 412 masm, miss, holder_reg, name, scratch1(), scratch2()); | 412 masm, miss, holder_reg, name, scratch1(), scratch2()); |
| 413 } | 413 } |
| 414 } | 414 } |
| 415 | 415 |
| 416 | 416 |
| 417 // Receiver_reg is preserved on jumps to miss_label, but may be destroyed if | 417 // Receiver_reg is preserved on jumps to miss_label, but may be destroyed if |
| 418 // store is successful. | 418 // store is successful. |
| 419 void NamedStoreHandlerCompiler::GenerateStoreTransition( | 419 void NamedStoreHandlerCompiler::GenerateStoreTransition( |
| 420 MacroAssembler* masm, Handle<JSObject> object, LookupResult* lookup, | 420 MacroAssembler* masm, LookupResult* lookup, Handle<Map> transition, |
| 421 Handle<Map> transition, Handle<Name> name, Register receiver_reg, | 421 Handle<Name> name, Register receiver_reg, Register storage_reg, |
| 422 Register storage_reg, Register value_reg, Register scratch1, | 422 Register value_reg, Register scratch1, Register scratch2, Register unused, |
| 423 Register scratch2, Register unused, Label* miss_label, Label* slow) { | 423 Label* miss_label, Label* slow) { |
| 424 int descriptor = transition->LastAdded(); | 424 int descriptor = transition->LastAdded(); |
| 425 DescriptorArray* descriptors = transition->instance_descriptors(); | 425 DescriptorArray* descriptors = transition->instance_descriptors(); |
| 426 PropertyDetails details = descriptors->GetDetails(descriptor); | 426 PropertyDetails details = descriptors->GetDetails(descriptor); |
| 427 Representation representation = details.representation(); | 427 Representation representation = details.representation(); |
| 428 ASSERT(!representation.IsNone()); | 428 ASSERT(!representation.IsNone()); |
| 429 | 429 |
| 430 if (details.type() == CONSTANT) { | 430 if (details.type() == CONSTANT) { |
| 431 Handle<Object> constant(descriptors->GetValue(descriptor), masm->isolate()); | 431 Handle<Object> constant(descriptors->GetValue(descriptor), masm->isolate()); |
| 432 __ CmpObject(value_reg, constant); | 432 __ CmpObject(value_reg, constant); |
| 433 __ j(not_equal, miss_label); | 433 __ j(not_equal, miss_label); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 462 | 462 |
| 463 __ bind(&heap_number); | 463 __ bind(&heap_number); |
| 464 __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), | 464 __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), |
| 465 miss_label, DONT_DO_SMI_CHECK); | 465 miss_label, DONT_DO_SMI_CHECK); |
| 466 __ movsd(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset)); | 466 __ movsd(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset)); |
| 467 | 467 |
| 468 __ bind(&do_store); | 468 __ bind(&do_store); |
| 469 __ movsd(FieldOperand(storage_reg, HeapNumber::kValueOffset), xmm0); | 469 __ movsd(FieldOperand(storage_reg, HeapNumber::kValueOffset), xmm0); |
| 470 } | 470 } |
| 471 | 471 |
| 472 // Stub never generated for non-global objects that require access | 472 // Stub never generated for objects that require access checks. |
| 473 // checks. | 473 ASSERT(!transition->is_access_check_needed()); |
| 474 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | |
| 475 | 474 |
| 476 // Perform map transition for the receiver if necessary. | 475 // Perform map transition for the receiver if necessary. |
| 477 if (details.type() == FIELD && | 476 if (details.type() == FIELD && |
| 478 object->map()->unused_property_fields() == 0) { | 477 Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) { |
| 479 // The properties must be extended before we can store the value. | 478 // The properties must be extended before we can store the value. |
| 480 // We jump to a runtime call that extends the properties array. | 479 // We jump to a runtime call that extends the properties array. |
| 481 __ pop(scratch1); // Return address. | 480 __ pop(scratch1); // Return address. |
| 482 __ push(receiver_reg); | 481 __ push(receiver_reg); |
| 483 __ push(Immediate(transition)); | 482 __ push(Immediate(transition)); |
| 484 __ push(value_reg); | 483 __ push(value_reg); |
| 485 __ push(scratch1); | 484 __ push(scratch1); |
| 486 __ TailCallExternalReference( | 485 __ TailCallExternalReference( |
| 487 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), | 486 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), |
| 488 masm->isolate()), | 487 masm->isolate()), |
| (...skipping 20 matching lines...) Expand all Loading... |
| 509 __ ret(0); | 508 __ ret(0); |
| 510 return; | 509 return; |
| 511 } | 510 } |
| 512 | 511 |
| 513 int index = transition->instance_descriptors()->GetFieldIndex( | 512 int index = transition->instance_descriptors()->GetFieldIndex( |
| 514 transition->LastAdded()); | 513 transition->LastAdded()); |
| 515 | 514 |
| 516 // Adjust for the number of properties stored in the object. Even in the | 515 // Adjust for the number of properties stored in the object. Even in the |
| 517 // face of a transition we can use the old map here because the size of the | 516 // face of a transition we can use the old map here because the size of the |
| 518 // object and the number of in-object properties is not going to change. | 517 // object and the number of in-object properties is not going to change. |
| 519 index -= object->map()->inobject_properties(); | 518 index -= transition->inobject_properties(); |
| 520 | 519 |
| 521 SmiCheck smi_check = representation.IsTagged() | 520 SmiCheck smi_check = representation.IsTagged() |
| 522 ? INLINE_SMI_CHECK : OMIT_SMI_CHECK; | 521 ? INLINE_SMI_CHECK : OMIT_SMI_CHECK; |
| 523 // TODO(verwaest): Share this code as a code stub. | 522 // TODO(verwaest): Share this code as a code stub. |
| 524 if (index < 0) { | 523 if (index < 0) { |
| 525 // Set the property straight into the object. | 524 // Set the property straight into the object. |
| 526 int offset = object->map()->instance_size() + (index * kPointerSize); | 525 int offset = transition->instance_size() + (index * kPointerSize); |
| 527 if (representation.IsDouble()) { | 526 if (representation.IsDouble()) { |
| 528 __ mov(FieldOperand(receiver_reg, offset), storage_reg); | 527 __ mov(FieldOperand(receiver_reg, offset), storage_reg); |
| 529 } else { | 528 } else { |
| 530 __ mov(FieldOperand(receiver_reg, offset), value_reg); | 529 __ mov(FieldOperand(receiver_reg, offset), value_reg); |
| 531 } | 530 } |
| 532 | 531 |
| 533 if (!representation.IsSmi()) { | 532 if (!representation.IsSmi()) { |
| 534 // Update the write barrier for the array address. | 533 // Update the write barrier for the array address. |
| 535 if (!representation.IsDouble()) { | 534 if (!representation.IsDouble()) { |
| 536 __ mov(storage_reg, value_reg); | 535 __ mov(storage_reg, value_reg); |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 686 Handle<Code> code) { | 685 Handle<Code> code) { |
| 687 __ jmp(code, RelocInfo::CODE_TARGET); | 686 __ jmp(code, RelocInfo::CODE_TARGET); |
| 688 } | 687 } |
| 689 | 688 |
| 690 | 689 |
| 691 #undef __ | 690 #undef __ |
| 692 #define __ ACCESS_MASM(masm()) | 691 #define __ ACCESS_MASM(masm()) |
| 693 | 692 |
| 694 | 693 |
| 695 Register PropertyHandlerCompiler::CheckPrototypes( | 694 Register PropertyHandlerCompiler::CheckPrototypes( |
| 696 Register object_reg, Handle<JSObject> holder, Register holder_reg, | 695 Register object_reg, Register holder_reg, Register scratch1, |
| 697 Register scratch1, Register scratch2, Handle<Name> name, Label* miss, | 696 Register scratch2, Handle<Name> name, Label* miss, |
| 698 PrototypeCheckType check) { | 697 PrototypeCheckType check) { |
| 699 Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate())); | 698 Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate())); |
| 700 | 699 |
| 701 // Make sure there's no overlap between holder and object registers. | 700 // Make sure there's no overlap between holder and object registers. |
| 702 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 701 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
| 703 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | 702 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
| 704 && !scratch2.is(scratch1)); | 703 && !scratch2.is(scratch1)); |
| 705 | 704 |
| 706 // Keep track of the current object in register reg. | 705 // Keep track of the current object in register reg. |
| 707 Register reg = object_reg; | 706 Register reg = object_reg; |
| 708 int depth = 0; | 707 int depth = 0; |
| 709 | 708 |
| 710 Handle<JSObject> current = Handle<JSObject>::null(); | 709 Handle<JSObject> current = Handle<JSObject>::null(); |
| 711 if (type()->IsConstant()) | 710 if (type()->IsConstant()) |
| 712 current = Handle<JSObject>::cast(type()->AsConstant()->Value()); | 711 current = Handle<JSObject>::cast(type()->AsConstant()->Value()); |
| 713 Handle<JSObject> prototype = Handle<JSObject>::null(); | 712 Handle<JSObject> prototype = Handle<JSObject>::null(); |
| 714 Handle<Map> current_map = receiver_map; | 713 Handle<Map> current_map = receiver_map; |
| 715 Handle<Map> holder_map(holder->map()); | 714 Handle<Map> holder_map(holder()->map()); |
| 716 // Traverse the prototype chain and check the maps in the prototype chain for | 715 // Traverse the prototype chain and check the maps in the prototype chain for |
| 717 // fast and global objects or do negative lookup for normal objects. | 716 // fast and global objects or do negative lookup for normal objects. |
| 718 while (!current_map.is_identical_to(holder_map)) { | 717 while (!current_map.is_identical_to(holder_map)) { |
| 719 ++depth; | 718 ++depth; |
| 720 | 719 |
| 721 // Only global objects and objects that do not require access | 720 // Only global objects and objects that do not require access |
| 722 // checks are allowed in stubs. | 721 // checks are allowed in stubs. |
| 723 ASSERT(current_map->IsJSGlobalProxyMap() || | 722 ASSERT(current_map->IsJSGlobalProxyMap() || |
| 724 !current_map->is_access_check_needed()); | 723 !current_map->is_access_check_needed()); |
| 725 | 724 |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 818 Label success; | 817 Label success; |
| 819 __ jmp(&success); | 818 __ jmp(&success); |
| 820 GenerateRestoreName(masm(), miss, name); | 819 GenerateRestoreName(masm(), miss, name); |
| 821 TailCallBuiltin(masm(), MissBuiltin(kind())); | 820 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 822 __ bind(&success); | 821 __ bind(&success); |
| 823 } | 822 } |
| 824 } | 823 } |
| 825 | 824 |
| 826 | 825 |
| 827 Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg, | 826 Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg, |
| 828 Handle<JSObject> holder, | |
| 829 Handle<Name> name, | 827 Handle<Name> name, |
| 830 Handle<Object> callback) { | 828 Handle<Object> callback) { |
| 831 Label miss; | 829 Label miss; |
| 832 | 830 |
| 833 Register reg = FrontendHeader(object_reg, holder, name, &miss); | 831 Register reg = FrontendHeader(object_reg, name, &miss); |
| 834 | 832 |
| 835 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { | 833 if (!holder()->HasFastProperties()) { |
| 834 ASSERT(!holder()->IsGlobalObject()); |
| 836 ASSERT(!reg.is(scratch2())); | 835 ASSERT(!reg.is(scratch2())); |
| 837 ASSERT(!reg.is(scratch3())); | 836 ASSERT(!reg.is(scratch3())); |
| 838 Register dictionary = scratch1(); | 837 Register dictionary = scratch1(); |
| 839 bool must_preserve_dictionary_reg = reg.is(dictionary); | 838 bool must_preserve_dictionary_reg = reg.is(dictionary); |
| 840 | 839 |
| 841 // Load the properties dictionary. | 840 // Load the properties dictionary. |
| 842 if (must_preserve_dictionary_reg) { | 841 if (must_preserve_dictionary_reg) { |
| 843 __ push(dictionary); | 842 __ push(dictionary); |
| 844 } | 843 } |
| 845 __ mov(dictionary, FieldOperand(reg, JSObject::kPropertiesOffset)); | 844 __ mov(dictionary, FieldOperand(reg, JSObject::kPropertiesOffset)); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 875 __ cmp(scratch3(), callback); | 874 __ cmp(scratch3(), callback); |
| 876 __ j(not_equal, &miss); | 875 __ j(not_equal, &miss); |
| 877 } | 876 } |
| 878 | 877 |
| 879 FrontendFooter(name, &miss); | 878 FrontendFooter(name, &miss); |
| 880 return reg; | 879 return reg; |
| 881 } | 880 } |
| 882 | 881 |
| 883 | 882 |
| 884 void NamedLoadHandlerCompiler::GenerateLoadField( | 883 void NamedLoadHandlerCompiler::GenerateLoadField( |
| 885 Register reg, Handle<JSObject> holder, FieldIndex field, | 884 Register reg, FieldIndex field, Representation representation) { |
| 886 Representation representation) { | |
| 887 if (!reg.is(receiver())) __ mov(receiver(), reg); | 885 if (!reg.is(receiver())) __ mov(receiver(), reg); |
| 888 LoadFieldStub stub(isolate(), field); | 886 LoadFieldStub stub(isolate(), field); |
| 889 GenerateTailCall(masm(), stub.GetCode()); | 887 GenerateTailCall(masm(), stub.GetCode()); |
| 890 } | 888 } |
| 891 | 889 |
| 892 | 890 |
| 893 void NamedLoadHandlerCompiler::GenerateLoadCallback( | 891 void NamedLoadHandlerCompiler::GenerateLoadCallback( |
| 894 Register reg, Handle<ExecutableAccessorInfo> callback) { | 892 Register reg, Handle<ExecutableAccessorInfo> callback) { |
| 895 // Insert additional parameters into the stack frame above return address. | 893 // Insert additional parameters into the stack frame above return address. |
| 896 ASSERT(!scratch3().is(reg)); | 894 ASSERT(!scratch3().is(reg)); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 935 } | 933 } |
| 936 | 934 |
| 937 | 935 |
| 938 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { | 936 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { |
| 939 // Return the constant value. | 937 // Return the constant value. |
| 940 __ LoadObject(eax, value); | 938 __ LoadObject(eax, value); |
| 941 __ ret(0); | 939 __ ret(0); |
| 942 } | 940 } |
| 943 | 941 |
| 944 | 942 |
| 945 void NamedLoadHandlerCompiler::GenerateLoadInterceptor( | 943 void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg, |
| 946 Register holder_reg, Handle<JSObject> interceptor_holder, | 944 LookupResult* lookup, |
| 947 LookupResult* lookup, Handle<Name> name) { | 945 Handle<Name> name) { |
| 948 ASSERT(interceptor_holder->HasNamedInterceptor()); | 946 ASSERT(holder()->HasNamedInterceptor()); |
| 949 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); | 947 ASSERT(!holder()->GetNamedInterceptor()->getter()->IsUndefined()); |
| 950 | 948 |
| 951 // So far the most popular follow ups for interceptor loads are FIELD | 949 // So far the most popular follow ups for interceptor loads are FIELD |
| 952 // and CALLBACKS, so inline only them, other cases may be added | 950 // and CALLBACKS, so inline only them, other cases may be added |
| 953 // later. | 951 // later. |
| 954 bool compile_followup_inline = false; | 952 bool compile_followup_inline = false; |
| 955 if (lookup->IsFound() && lookup->IsCacheable()) { | 953 if (lookup->IsFound() && lookup->IsCacheable()) { |
| 956 if (lookup->IsField()) { | 954 if (lookup->IsField()) { |
| 957 compile_followup_inline = true; | 955 compile_followup_inline = true; |
| 958 } else if (lookup->type() == CALLBACKS && | 956 } else if (lookup->type() == CALLBACKS && |
| 959 lookup->GetCallbackObject()->IsExecutableAccessorInfo()) { | 957 lookup->GetCallbackObject()->IsExecutableAccessorInfo()) { |
| 960 Handle<ExecutableAccessorInfo> callback( | 958 Handle<ExecutableAccessorInfo> callback( |
| 961 ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); | 959 ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); |
| 962 compile_followup_inline = | 960 compile_followup_inline = |
| 963 callback->getter() != NULL && | 961 callback->getter() != NULL && |
| 964 ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), callback, | 962 ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), callback, |
| 965 type()); | 963 type()); |
| 966 } | 964 } |
| 967 } | 965 } |
| 968 | 966 |
| 969 if (compile_followup_inline) { | 967 if (compile_followup_inline) { |
| 970 // Compile the interceptor call, followed by inline code to load the | 968 // Compile the interceptor call, followed by inline code to load the |
| 971 // property from further up the prototype chain if the call fails. | 969 // property from further up the prototype chain if the call fails. |
| 972 // Check that the maps haven't changed. | 970 // Check that the maps haven't changed. |
| 973 ASSERT(holder_reg.is(receiver()) || holder_reg.is(scratch1())); | 971 ASSERT(holder_reg.is(receiver()) || holder_reg.is(scratch1())); |
| 974 | 972 |
| 975 // Preserve the receiver register explicitly whenever it is different from | 973 // Preserve the receiver register explicitly whenever it is different from |
| 976 // the holder and it is needed should the interceptor return without any | 974 // the holder and it is needed should the interceptor return without any |
| 977 // result. The CALLBACKS case needs the receiver to be passed into C++ code, | 975 // result. The CALLBACKS case needs the receiver to be passed into C++ code, |
| 978 // the FIELD case might cause a miss during the prototype check. | 976 // the FIELD case might cause a miss during the prototype check. |
| 979 bool must_perfrom_prototype_check = *interceptor_holder != lookup->holder(); | 977 bool must_perfrom_prototype_check = *holder() != lookup->holder(); |
| 980 bool must_preserve_receiver_reg = !receiver().is(holder_reg) && | 978 bool must_preserve_receiver_reg = !receiver().is(holder_reg) && |
| 981 (lookup->type() == CALLBACKS || must_perfrom_prototype_check); | 979 (lookup->type() == CALLBACKS || must_perfrom_prototype_check); |
| 982 | 980 |
| 983 // Save necessary data before invoking an interceptor. | 981 // Save necessary data before invoking an interceptor. |
| 984 // Requires a frame to make GC aware of pushed pointers. | 982 // Requires a frame to make GC aware of pushed pointers. |
| 985 { | 983 { |
| 986 FrameScope frame_scope(masm(), StackFrame::INTERNAL); | 984 FrameScope frame_scope(masm(), StackFrame::INTERNAL); |
| 987 | 985 |
| 988 if (must_preserve_receiver_reg) { | 986 if (must_preserve_receiver_reg) { |
| 989 __ push(receiver()); | 987 __ push(receiver()); |
| 990 } | 988 } |
| 991 __ push(holder_reg); | 989 __ push(holder_reg); |
| 992 __ push(this->name()); | 990 __ push(this->name()); |
| 993 | 991 |
| 994 // Invoke an interceptor. Note: map checks from receiver to | 992 // Invoke an interceptor. Note: map checks from receiver to |
| 995 // interceptor's holder has been compiled before (see a caller | 993 // interceptor's holder has been compiled before (see a caller |
| 996 // of this method.) | 994 // of this method.) |
| 997 CompileCallLoadPropertyWithInterceptor( | 995 CompileCallLoadPropertyWithInterceptor( |
| 998 masm(), receiver(), holder_reg, this->name(), interceptor_holder, | 996 masm(), receiver(), holder_reg, this->name(), holder(), |
| 999 IC::kLoadPropertyWithInterceptorOnly); | 997 IC::kLoadPropertyWithInterceptorOnly); |
| 1000 | 998 |
| 1001 // Check if interceptor provided a value for property. If it's | 999 // Check if interceptor provided a value for property. If it's |
| 1002 // the case, return immediately. | 1000 // the case, return immediately. |
| 1003 Label interceptor_failed; | 1001 Label interceptor_failed; |
| 1004 __ cmp(eax, factory()->no_interceptor_result_sentinel()); | 1002 __ cmp(eax, factory()->no_interceptor_result_sentinel()); |
| 1005 __ j(equal, &interceptor_failed); | 1003 __ j(equal, &interceptor_failed); |
| 1006 frame_scope.GenerateLeaveFrame(); | 1004 frame_scope.GenerateLeaveFrame(); |
| 1007 __ ret(0); | 1005 __ ret(0); |
| 1008 | 1006 |
| 1009 // Clobber registers when generating debug-code to provoke errors. | 1007 // Clobber registers when generating debug-code to provoke errors. |
| 1010 __ bind(&interceptor_failed); | 1008 __ bind(&interceptor_failed); |
| 1011 if (FLAG_debug_code) { | 1009 if (FLAG_debug_code) { |
| 1012 __ mov(receiver(), Immediate(BitCast<int32_t>(kZapValue))); | 1010 __ mov(receiver(), Immediate(BitCast<int32_t>(kZapValue))); |
| 1013 __ mov(holder_reg, Immediate(BitCast<int32_t>(kZapValue))); | 1011 __ mov(holder_reg, Immediate(BitCast<int32_t>(kZapValue))); |
| 1014 __ mov(this->name(), Immediate(BitCast<int32_t>(kZapValue))); | 1012 __ mov(this->name(), Immediate(BitCast<int32_t>(kZapValue))); |
| 1015 } | 1013 } |
| 1016 | 1014 |
| 1017 __ pop(this->name()); | 1015 __ pop(this->name()); |
| 1018 __ pop(holder_reg); | 1016 __ pop(holder_reg); |
| 1019 if (must_preserve_receiver_reg) { | 1017 if (must_preserve_receiver_reg) { |
| 1020 __ pop(receiver()); | 1018 __ pop(receiver()); |
| 1021 } | 1019 } |
| 1022 | 1020 |
| 1023 // Leave the internal frame. | 1021 // Leave the internal frame. |
| 1024 } | 1022 } |
| 1025 | 1023 |
| 1026 GenerateLoadPostInterceptor(holder_reg, interceptor_holder, name, lookup); | 1024 GenerateLoadPostInterceptor(holder_reg, name, lookup); |
| 1027 } else { // !compile_followup_inline | 1025 } else { // !compile_followup_inline |
| 1028 // Call the runtime system to load the interceptor. | 1026 // Call the runtime system to load the interceptor. |
| 1029 // Check that the maps haven't changed. | 1027 // Check that the maps haven't changed. |
| 1030 __ pop(scratch2()); // save old return address | 1028 __ pop(scratch2()); // save old return address |
| 1031 PushInterceptorArguments(masm(), receiver(), holder_reg, | 1029 PushInterceptorArguments(masm(), receiver(), holder_reg, this->name(), |
| 1032 this->name(), interceptor_holder); | 1030 holder()); |
| 1033 __ push(scratch2()); // restore old return address | 1031 __ push(scratch2()); // restore old return address |
| 1034 | 1032 |
| 1035 ExternalReference ref = | 1033 ExternalReference ref = |
| 1036 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptor), | 1034 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptor), |
| 1037 isolate()); | 1035 isolate()); |
| 1038 __ TailCallExternalReference( | 1036 __ TailCallExternalReference( |
| 1039 ref, NamedLoadHandlerCompiler::kInterceptorArgsLength, 1); | 1037 ref, NamedLoadHandlerCompiler::kInterceptorArgsLength, 1); |
| 1040 } | 1038 } |
| 1041 } | 1039 } |
| 1042 | 1040 |
| 1043 | 1041 |
| 1044 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( | 1042 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( |
| 1045 Handle<JSObject> object, Handle<JSObject> holder, Handle<Name> name, | 1043 Handle<JSObject> object, Handle<Name> name, |
| 1046 Handle<ExecutableAccessorInfo> callback) { | 1044 Handle<ExecutableAccessorInfo> callback) { |
| 1047 Register holder_reg = Frontend(receiver(), holder, name); | 1045 Register holder_reg = Frontend(receiver(), name); |
| 1048 | 1046 |
| 1049 __ pop(scratch1()); // remove the return address | 1047 __ pop(scratch1()); // remove the return address |
| 1050 __ push(receiver()); | 1048 __ push(receiver()); |
| 1051 __ push(holder_reg); | 1049 __ push(holder_reg); |
| 1052 __ Push(callback); | 1050 __ Push(callback); |
| 1053 __ Push(name); | 1051 __ Push(name); |
| 1054 __ push(value()); | 1052 __ push(value()); |
| 1055 __ push(scratch1()); // restore return address | 1053 __ push(scratch1()); // restore return address |
| 1056 | 1054 |
| 1057 // Do tail-call to the runtime system. | 1055 // Do tail-call to the runtime system. |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1107 } | 1105 } |
| 1108 __ ret(0); | 1106 __ ret(0); |
| 1109 } | 1107 } |
| 1110 | 1108 |
| 1111 | 1109 |
| 1112 #undef __ | 1110 #undef __ |
| 1113 #define __ ACCESS_MASM(masm()) | 1111 #define __ ACCESS_MASM(masm()) |
| 1114 | 1112 |
| 1115 | 1113 |
| 1116 Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor( | 1114 Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor( |
| 1117 Handle<JSObject> object, Handle<Name> name) { | 1115 Handle<Name> name) { |
| 1118 __ pop(scratch1()); // remove the return address | 1116 __ pop(scratch1()); // remove the return address |
| 1119 __ push(receiver()); | 1117 __ push(receiver()); |
| 1120 __ push(this->name()); | 1118 __ push(this->name()); |
| 1121 __ push(value()); | 1119 __ push(value()); |
| 1122 __ push(scratch1()); // restore return address | 1120 __ push(scratch1()); // restore return address |
| 1123 | 1121 |
| 1124 // Do tail-call to the runtime system. | 1122 // Do tail-call to the runtime system. |
| 1125 ExternalReference store_ic_property = ExternalReference( | 1123 ExternalReference store_ic_property = ExternalReference( |
| 1126 IC_Utility(IC::kStorePropertyWithInterceptor), isolate()); | 1124 IC_Utility(IC::kStorePropertyWithInterceptor), isolate()); |
| 1127 __ TailCallExternalReference(store_ic_property, 3, 1); | 1125 __ TailCallExternalReference(store_ic_property, 3, 1); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1165 } | 1163 } |
| 1166 __ bind(&miss); | 1164 __ bind(&miss); |
| 1167 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1165 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 1168 | 1166 |
| 1169 // Return the generated code. | 1167 // Return the generated code. |
| 1170 return GetCode(kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); | 1168 return GetCode(kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); |
| 1171 } | 1169 } |
| 1172 | 1170 |
| 1173 | 1171 |
| 1174 Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( | 1172 Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( |
| 1175 Handle<JSObject> last, Handle<Name> name) { | 1173 Handle<Name> name) { |
| 1176 NonexistentFrontend(last, name); | 1174 NonexistentFrontend(name); |
| 1177 | 1175 |
| 1178 // Return undefined if maps of the full prototype chain are still the | 1176 // Return undefined if maps of the full prototype chain are still the |
| 1179 // same and no global property with this name contains a value. | 1177 // same and no global property with this name contains a value. |
| 1180 __ mov(eax, isolate()->factory()->undefined_value()); | 1178 __ mov(eax, isolate()->factory()->undefined_value()); |
| 1181 __ ret(0); | 1179 __ ret(0); |
| 1182 | 1180 |
| 1183 // Return the generated code. | 1181 // Return the generated code. |
| 1184 return GetCode(kind(), Code::FAST, name); | 1182 return GetCode(kind(), Code::FAST, name); |
| 1185 } | 1183 } |
| 1186 | 1184 |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1249 } | 1247 } |
| 1250 __ ret(0); | 1248 __ ret(0); |
| 1251 } | 1249 } |
| 1252 | 1250 |
| 1253 | 1251 |
| 1254 #undef __ | 1252 #undef __ |
| 1255 #define __ ACCESS_MASM(masm()) | 1253 #define __ ACCESS_MASM(masm()) |
| 1256 | 1254 |
| 1257 | 1255 |
| 1258 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( | 1256 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( |
| 1259 Handle<GlobalObject> global, Handle<PropertyCell> cell, Handle<Name> name, | 1257 Handle<PropertyCell> cell, Handle<Name> name, bool is_dont_delete) { |
| 1260 bool is_dont_delete) { | |
| 1261 Label miss; | 1258 Label miss; |
| 1262 | 1259 |
| 1263 FrontendHeader(receiver(), global, name, &miss); | 1260 FrontendHeader(receiver(), name, &miss); |
| 1264 // Get the value from the cell. | 1261 // Get the value from the cell. |
| 1265 Register result = StoreIC::ValueRegister(); | 1262 Register result = StoreIC::ValueRegister(); |
| 1266 if (masm()->serializer_enabled()) { | 1263 if (masm()->serializer_enabled()) { |
| 1267 __ mov(result, Immediate(cell)); | 1264 __ mov(result, Immediate(cell)); |
| 1268 __ mov(result, FieldOperand(result, PropertyCell::kValueOffset)); | 1265 __ mov(result, FieldOperand(result, PropertyCell::kValueOffset)); |
| 1269 } else { | 1266 } else { |
| 1270 __ mov(result, Operand::ForCell(cell)); | 1267 __ mov(result, Operand::ForCell(cell)); |
| 1271 } | 1268 } |
| 1272 | 1269 |
| 1273 // Check for deleted property if property can actually be deleted. | 1270 // Check for deleted property if property can actually be deleted. |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1394 // ----------------------------------- | 1391 // ----------------------------------- |
| 1395 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 1392 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
| 1396 } | 1393 } |
| 1397 | 1394 |
| 1398 | 1395 |
| 1399 #undef __ | 1396 #undef __ |
| 1400 | 1397 |
| 1401 } } // namespace v8::internal | 1398 } } // namespace v8::internal |
| 1402 | 1399 |
| 1403 #endif // V8_TARGET_ARCH_IA32 | 1400 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |