Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(31)

Side by Side Diff: src/x64/stub-cache-x64.cc

Issue 12340112: Polymorphism support for load IC. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Added ARM port, introduced GenerateTailCall Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/x64/ic-x64.cc ('k') | test/cctest/test-heap.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after
344 344
345 345
346 // Load a fast property out of a holder object (src). In-object properties 346 // Load a fast property out of a holder object (src). In-object properties
347 // are loaded directly otherwise the property is loaded from the properties 347 // are loaded directly otherwise the property is loaded from the properties
348 // fixed array. 348 // fixed array.
349 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, 349 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
350 Register dst, 350 Register dst,
351 Register src, 351 Register src,
352 Handle<JSObject> holder, 352 Handle<JSObject> holder,
353 PropertyIndex index) { 353 PropertyIndex index) {
354 if (index.is_header_index()) { 354 DoGenerateFastPropertyLoad(
355 int offset = index.header_index() * kPointerSize; 355 masm, dst, src, index.is_inobject(holder), index.translate(holder));
356 __ movq(dst, FieldOperand(src, offset));
357 } else {
358 // Adjust for the number of properties stored in the holder.
359 int slot = index.field_index() - holder->map()->inobject_properties();
360 if (slot < 0) {
361 // Get the property straight out of the holder.
362 int offset = holder->map()->instance_size() + (slot * kPointerSize);
363 __ movq(dst, FieldOperand(src, offset));
364 } else {
365 // Calculate the offset into the properties array.
366 int offset = slot * kPointerSize + FixedArray::kHeaderSize;
367 __ movq(dst, FieldOperand(src, JSObject::kPropertiesOffset));
368 __ movq(dst, FieldOperand(dst, offset));
369 }
370 }
371 } 356 }
372 357
373 358
359 void StubCompiler::DoGenerateFastPropertyLoad(MacroAssembler* masm,
360 Register dst,
361 Register src,
362 bool inobject,
363 int index) {
364 int offset = index * kPointerSize;
365 if (!inobject) {
366 // Calculate the offset into the properties array.
367 offset = offset + FixedArray::kHeaderSize;
368 __ movq(dst, FieldOperand(src, JSObject::kPropertiesOffset));
369 src = dst;
370 }
371 __ movq(dst, FieldOperand(src, offset));
372 }
373
374
374 static void PushInterceptorArguments(MacroAssembler* masm, 375 static void PushInterceptorArguments(MacroAssembler* masm,
375 Register receiver, 376 Register receiver,
376 Register holder, 377 Register holder,
377 Register name, 378 Register name,
378 Handle<JSObject> holder_obj) { 379 Handle<JSObject> holder_obj) {
379 __ push(name); 380 __ push(name);
380 Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor()); 381 Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor());
381 ASSERT(!masm->isolate()->heap()->InNewSpace(*interceptor)); 382 ASSERT(!masm->isolate()->heap()->InNewSpace(*interceptor));
382 __ Move(kScratchRegister, interceptor); 383 __ Move(kScratchRegister, interceptor);
383 __ push(kScratchRegister); 384 __ push(kScratchRegister);
(...skipping 520 matching lines...) Expand 10 before | Expand all | Expand 10 after
904 miss); 905 miss);
905 } 906 }
906 current = Handle<JSObject>(JSObject::cast(current->GetPrototype())); 907 current = Handle<JSObject>(JSObject::cast(current->GetPrototype()));
907 } 908 }
908 } 909 }
909 910
910 #undef __ 911 #undef __
911 #define __ ACCESS_MASM((masm())) 912 #define __ ACCESS_MASM((masm()))
912 913
913 914
915 void StubCompiler::GenerateTailCall(Handle<Code> code) {
916 __ jmp(code, RelocInfo::CODE_TARGET);
917 }
918
919
914 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, 920 Register StubCompiler::CheckPrototypes(Handle<JSObject> object,
915 Register object_reg, 921 Register object_reg,
916 Handle<JSObject> holder, 922 Handle<JSObject> holder,
917 Register holder_reg, 923 Register holder_reg,
918 Register scratch1, 924 Register scratch1,
919 Register scratch2, 925 Register scratch2,
920 Handle<String> name, 926 Handle<String> name,
921 int save_at_depth, 927 int save_at_depth,
922 Label* miss) { 928 Label* miss,
929 PrototypeCheckType check) {
930 Handle<JSObject> first = object;
923 // Make sure there's no overlap between holder and object registers. 931 // Make sure there's no overlap between holder and object registers.
924 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); 932 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
925 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) 933 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg)
926 && !scratch2.is(scratch1)); 934 && !scratch2.is(scratch1));
927 935
928 // Keep track of the current object in register reg. On the first 936 // Keep track of the current object in register reg. On the first
929 // iteration, reg is an alias for object_reg, on later iterations, 937 // iteration, reg is an alias for object_reg, on later iterations,
930 // it is an alias for holder_reg. 938 // it is an alias for holder_reg.
931 Register reg = object_reg; 939 Register reg = object_reg;
932 int depth = 0; 940 int depth = 0;
(...skipping 28 matching lines...) Expand all
961 __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); 969 __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
962 reg = holder_reg; // From now on the object will be in holder_reg. 970 reg = holder_reg; // From now on the object will be in holder_reg.
963 __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); 971 __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
964 } else { 972 } else {
965 bool in_new_space = heap()->InNewSpace(*prototype); 973 bool in_new_space = heap()->InNewSpace(*prototype);
966 Handle<Map> current_map(current->map()); 974 Handle<Map> current_map(current->map());
967 if (in_new_space) { 975 if (in_new_space) {
968 // Save the map in scratch1 for later. 976 // Save the map in scratch1 for later.
969 __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); 977 __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
970 } 978 }
971 __ CheckMap(reg, Handle<Map>(current_map), 979 if (!current.is_identical_to(first) || check == CHECK_ALL_MAPS) {
972 miss, DONT_DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); 980 __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK,
981 ALLOW_ELEMENT_TRANSITION_MAPS);
982 }
973 983
974 // Check access rights to the global object. This has to happen after 984 // Check access rights to the global object. This has to happen after
975 // the map check so that we know that the object is actually a global 985 // the map check so that we know that the object is actually a global
976 // object. 986 // object.
977 if (current->IsJSGlobalProxy()) { 987 if (current->IsJSGlobalProxy()) {
978 __ CheckAccessGlobalProxy(reg, scratch2, miss); 988 __ CheckAccessGlobalProxy(reg, scratch2, miss);
979 } 989 }
980 reg = holder_reg; // From now on the object will be in holder_reg. 990 reg = holder_reg; // From now on the object will be in holder_reg.
981 991
982 if (in_new_space) { 992 if (in_new_space) {
(...skipping 11 matching lines...) Expand all
994 } 1004 }
995 1005
996 // Go to the next object in the prototype chain. 1006 // Go to the next object in the prototype chain.
997 current = prototype; 1007 current = prototype;
998 } 1008 }
999 ASSERT(current.is_identical_to(holder)); 1009 ASSERT(current.is_identical_to(holder));
1000 1010
1001 // Log the check depth. 1011 // Log the check depth.
1002 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); 1012 LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
1003 1013
1004 // Check the holder map. 1014 if (!holder.is_identical_to(first) || check == CHECK_ALL_MAPS) {
1005 __ CheckMap(reg, Handle<Map>(holder->map()), 1015 // Check the holder map.
1006 miss, DONT_DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); 1016 __ CheckMap(reg, Handle<Map>(holder->map()),
1017 miss, DONT_DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
1018 }
1007 1019
1008 // Perform security check for access to the global object. 1020 // Perform security check for access to the global object.
1009 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); 1021 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded());
1010 if (current->IsJSGlobalProxy()) { 1022 if (current->IsJSGlobalProxy()) {
1011 __ CheckAccessGlobalProxy(reg, scratch1, miss); 1023 __ CheckAccessGlobalProxy(reg, scratch1, miss);
1012 } 1024 }
1013 1025
1014 // If we've skipped any global objects, it's not enough to verify that 1026 // If we've skipped any global objects, it's not enough to verify that
1015 // their maps haven't changed. We also need to check that the property 1027 // their maps haven't changed. We also need to check that the property
1016 // cell for the property is still empty. 1028 // cell for the property is still empty.
1017 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); 1029 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss);
1018 1030
1019 // Return the register containing the holder. 1031 // Return the register containing the holder.
1020 return reg; 1032 return reg;
1021 } 1033 }
1022 1034
1023 1035
1024 void BaseLoadStubCompiler::HandlerFrontendFooter(Label* success, 1036 void BaseLoadStubCompiler::HandlerFrontendFooter(Label* success,
1025 Label* miss) { 1037 Label* miss) {
1026 __ jmp(success); 1038 if (!miss->is_unused()) {
1027 __ bind(miss); 1039 __ jmp(success);
1028 GenerateLoadMiss(masm(), kind()); 1040 __ bind(miss);
1041 GenerateLoadMiss(masm(), kind());
1042 }
1029 } 1043 }
1030 1044
1031 1045
1032 Register BaseLoadStubCompiler::CallbackHandlerFrontend( 1046 Register BaseLoadStubCompiler::CallbackHandlerFrontend(
1033 Handle<JSObject> object, 1047 Handle<JSObject> object,
1034 Register object_reg, 1048 Register object_reg,
1035 Handle<JSObject> holder, 1049 Handle<JSObject> holder,
1036 Handle<String> name, 1050 Handle<String> name,
1037 Label* success, 1051 Label* success,
1038 FrontendCheckType check,
1039 Handle<ExecutableAccessorInfo> callback) { 1052 Handle<ExecutableAccessorInfo> callback) {
1040 Label miss; 1053 Label miss;
1041 1054
1042 Register reg = HandlerFrontendHeader( 1055 Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss);
1043 object, object_reg, holder, name, &miss, check);
1044 1056
1045 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { 1057 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) {
1046 ASSERT(!reg.is(scratch2())); 1058 ASSERT(!reg.is(scratch2()));
1047 ASSERT(!reg.is(scratch3())); 1059 ASSERT(!reg.is(scratch3()));
1048 ASSERT(!reg.is(scratch4())); 1060 ASSERT(!reg.is(scratch4()));
1049 1061
1050 // Load the properties dictionary. 1062 // Load the properties dictionary.
1051 Register dictionary = scratch4(); 1063 Register dictionary = scratch4();
1052 __ movq(dictionary, FieldOperand(reg, JSObject::kPropertiesOffset)); 1064 __ movq(dictionary, FieldOperand(reg, JSObject::kPropertiesOffset));
1053 1065
(...skipping 29 matching lines...) Expand all
1083 1095
1084 1096
1085 void BaseLoadStubCompiler::NonexistentHandlerFrontend( 1097 void BaseLoadStubCompiler::NonexistentHandlerFrontend(
1086 Handle<JSObject> object, 1098 Handle<JSObject> object,
1087 Handle<JSObject> last, 1099 Handle<JSObject> last,
1088 Handle<String> name, 1100 Handle<String> name,
1089 Label* success, 1101 Label* success,
1090 Handle<GlobalObject> global) { 1102 Handle<GlobalObject> global) {
1091 Label miss; 1103 Label miss;
1092 1104
1093 Register reg = HandlerFrontendHeader( 1105 Register reg = HandlerFrontendHeader(object, receiver(), last, name, &miss);
1094 object, receiver(), last, name, &miss, PERFORM_INITIAL_CHECKS);
1095 1106
1096 // If the last object in the prototype chain is a global object, 1107 // If the last object in the prototype chain is a global object,
1097 // check that the global property cell is empty. 1108 // check that the global property cell is empty.
1098 if (!global.is_null()) { 1109 if (!global.is_null()) {
1099 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); 1110 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss);
1100 } 1111 }
1101 1112
1102 if (!last->HasFastProperties()) { 1113 if (!last->HasFastProperties()) {
1103 __ movq(scratch2(), FieldOperand(reg, HeapObject::kMapOffset)); 1114 __ movq(scratch2(), FieldOperand(reg, HeapObject::kMapOffset));
1104 __ movq(scratch2(), FieldOperand(scratch2(), Map::kPrototypeOffset)); 1115 __ movq(scratch2(), FieldOperand(scratch2(), Map::kPrototypeOffset));
(...skipping 25 matching lines...) Expand all
1130 __ push(reg); // holder 1141 __ push(reg); // holder
1131 if (heap()->InNewSpace(callback->data())) { 1142 if (heap()->InNewSpace(callback->data())) {
1132 __ Move(scratch1(), callback); 1143 __ Move(scratch1(), callback);
1133 __ push(FieldOperand(scratch1(), 1144 __ push(FieldOperand(scratch1(),
1134 ExecutableAccessorInfo::kDataOffset)); // data 1145 ExecutableAccessorInfo::kDataOffset)); // data
1135 } else { 1146 } else {
1136 __ Push(Handle<Object>(callback->data(), isolate())); 1147 __ Push(Handle<Object>(callback->data(), isolate()));
1137 } 1148 }
1138 __ PushAddress(ExternalReference::isolate_address()); // isolate 1149 __ PushAddress(ExternalReference::isolate_address()); // isolate
1139 __ push(name()); // name 1150 __ push(name()); // name
1140 // Save a pointer to where we pushed the arguments pointer. 1151 // Save a pointer to where we pushed the arguments pointer. This will be
1141 // This will be passed as the const AccessorInfo& to the C++ callback. 1152 // passed as the const ExecutableAccessorInfo& to the C++ callback.
1142 1153
1143 #if defined(__MINGW64__) 1154 #if defined(__MINGW64__)
1144 Register accessor_info_arg = rdx; 1155 Register accessor_info_arg = rdx;
1145 Register name_arg = rcx; 1156 Register name_arg = rcx;
1146 #elif defined(_WIN64) 1157 #elif defined(_WIN64)
1147 // Win64 uses first register--rcx--for returned value. 1158 // Win64 uses first register--rcx--for returned value.
1148 Register accessor_info_arg = r8; 1159 Register accessor_info_arg = r8;
1149 Register name_arg = rdx; 1160 Register name_arg = rdx;
1150 #else 1161 #else
1151 Register accessor_info_arg = rsi; 1162 Register accessor_info_arg = rsi;
(...skipping 1599 matching lines...) Expand 10 before | Expand all | Expand 10 after
2751 2762
2752 NonexistentHandlerFrontend(object, last, name, &success, global); 2763 NonexistentHandlerFrontend(object, last, name, &success, global);
2753 2764
2754 __ bind(&success); 2765 __ bind(&success);
2755 // Return undefined if maps of the full prototype chain are still the 2766 // Return undefined if maps of the full prototype chain are still the
2756 // same and no global property with this name contains a value. 2767 // same and no global property with this name contains a value.
2757 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 2768 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
2758 __ ret(0); 2769 __ ret(0);
2759 2770
2760 // Return the generated code. 2771 // Return the generated code.
2761 return GetCode(Code::NONEXISTENT, factory()->empty_string()); 2772 return GetCode(Code::HANDLER_FRAGMENT, Code::NONEXISTENT, name);
2762 } 2773 }
2763 2774
2764 2775
2765 Register* LoadStubCompiler::registers() { 2776 Register* LoadStubCompiler::registers() {
2766 // receiver, name, scratch1, scratch2, scratch3, scratch4. 2777 // receiver, name, scratch1, scratch2, scratch3, scratch4.
2767 static Register registers[] = { rax, rcx, rdx, rbx, rdi, r8 }; 2778 static Register registers[] = { rax, rcx, rdx, rbx, rdi, r8 };
2768 return registers; 2779 return registers;
2769 } 2780 }
2770 2781
2771 2782
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
2825 Handle<JSObject> object, 2836 Handle<JSObject> object,
2826 Handle<GlobalObject> global, 2837 Handle<GlobalObject> global,
2827 Handle<JSGlobalPropertyCell> cell, 2838 Handle<JSGlobalPropertyCell> cell,
2828 Handle<String> name, 2839 Handle<String> name,
2829 bool is_dont_delete) { 2840 bool is_dont_delete) {
2830 Label success, miss; 2841 Label success, miss;
2831 // TODO(verwaest): Directly store to rax. Currently we cannot do this, since 2842 // TODO(verwaest): Directly store to rax. Currently we cannot do this, since
2832 // rax is used as receiver(), which we would otherwise clobber before a 2843 // rax is used as receiver(), which we would otherwise clobber before a
2833 // potential miss. 2844 // potential miss.
2834 2845
2835 HandlerFrontendHeader(object, receiver(), Handle<JSObject>::cast(global), 2846 __ CheckMap(receiver(), Handle<Map>(object->map()), &miss, DO_SMI_CHECK);
2836 name, &miss, PERFORM_INITIAL_CHECKS); 2847 HandlerFrontendHeader(
2848 object, receiver(), Handle<JSObject>::cast(global), name, &miss);
2837 2849
2838 // Get the value from the cell. 2850 // Get the value from the cell.
2839 __ Move(rbx, cell); 2851 __ Move(rbx, cell);
2840 __ movq(rbx, FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset)); 2852 __ movq(rbx, FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset));
2841 2853
2842 // Check for deleted property if property can actually be deleted. 2854 // Check for deleted property if property can actually be deleted.
2843 if (!is_dont_delete) { 2855 if (!is_dont_delete) {
2844 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); 2856 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
2845 __ j(equal, &miss); 2857 __ j(equal, &miss);
2846 } else if (FLAG_debug_code) { 2858 } else if (FLAG_debug_code) {
2847 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); 2859 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
2848 __ Check(not_equal, "DontDelete cells can't contain the hole"); 2860 __ Check(not_equal, "DontDelete cells can't contain the hole");
2849 } 2861 }
2850 2862
2851 HandlerFrontendFooter(&success, &miss); 2863 HandlerFrontendFooter(&success, &miss);
2852 __ bind(&success); 2864 __ bind(&success);
2853 2865
2854 Counters* counters = isolate()->counters(); 2866 Counters* counters = isolate()->counters();
2855 __ IncrementCounter(counters->named_load_global_stub(), 1); 2867 __ IncrementCounter(counters->named_load_global_stub(), 1);
2856 __ movq(rax, rbx); 2868 __ movq(rax, rbx);
2857 __ ret(0); 2869 __ ret(0);
2858 2870
2859 // Return the generated code. 2871 // Return the generated code.
2860 return GetCode(Code::NORMAL, name); 2872 return GetCode(Code::IC_FRAGMENT, Code::NORMAL, name);
2861 } 2873 }
2862 2874
2863 2875
2864 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement( 2876 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement(
2865 Handle<Map> receiver_map) { 2877 Handle<Map> receiver_map) {
2866 // ----------- S t a t e ------------- 2878 // ----------- S t a t e -------------
2867 // -- rax : key 2879 // -- rax : key
2868 // -- rdx : receiver 2880 // -- rdx : receiver
2869 // -- rsp[0] : return address 2881 // -- rsp[0] : return address
2870 // ----------------------------------- 2882 // -----------------------------------
2871 ElementsKind elements_kind = receiver_map->elements_kind(); 2883 ElementsKind elements_kind = receiver_map->elements_kind();
2872 if (receiver_map->has_fast_elements() || 2884 if (receiver_map->has_fast_elements() ||
2873 receiver_map->has_external_array_elements()) { 2885 receiver_map->has_external_array_elements()) {
2874 Handle<Code> stub = KeyedLoadFastElementStub( 2886 Handle<Code> stub = KeyedLoadFastElementStub(
2875 receiver_map->instance_type() == JS_ARRAY_TYPE, 2887 receiver_map->instance_type() == JS_ARRAY_TYPE,
2876 elements_kind).GetCode(isolate()); 2888 elements_kind).GetCode(isolate());
2877 __ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK); 2889 __ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK);
2878 } else { 2890 } else {
2879 Handle<Code> stub = 2891 Handle<Code> stub =
2880 KeyedLoadDictionaryElementStub().GetCode(isolate()); 2892 KeyedLoadDictionaryElementStub().GetCode(isolate());
2881 __ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK); 2893 __ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK);
2882 } 2894 }
2883 2895
2884 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2896 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2885 2897
2886 // Return the generated code. 2898 // Return the generated code.
2887 return GetCode(Code::NORMAL, factory()->empty_string()); 2899 return GetCode(Code::IC_FRAGMENT, Code::NORMAL, factory()->empty_string());
2888 } 2900 }
2889 2901
2890 2902
2891 Handle<Code> KeyedLoadStubCompiler::CompileLoadPolymorphic( 2903 Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC(
2892 MapHandleList* receiver_maps, 2904 MapHandleList* receiver_maps,
2893 CodeHandleList* handler_ics) { 2905 CodeHandleList* handlers,
2894 // ----------- S t a t e ------------- 2906 Handle<String> name,
2895 // -- rax : key 2907 Code::StubType type,
2896 // -- rdx : receiver 2908 IcCheckType check) {
2897 // -- rsp[0] : return address
2898 // -----------------------------------
2899 Label miss; 2909 Label miss;
2900 __ JumpIfSmi(rdx, &miss);
2901 2910
2902 Register map_reg = rbx; 2911 if (check == PROPERTY) {
2903 __ movq(map_reg, FieldOperand(rdx, HeapObject::kMapOffset)); 2912 GenerateNameCheck(name, this->name(), &miss);
2913 }
2914
2915 __ JumpIfSmi(receiver(), &miss);
2916 Register map_reg = scratch1();
2917 __ movq(map_reg, FieldOperand(receiver(), HeapObject::kMapOffset));
2904 int receiver_count = receiver_maps->length(); 2918 int receiver_count = receiver_maps->length();
2905 for (int current = 0; current < receiver_count; ++current) { 2919 for (int current = 0; current < receiver_count; ++current) {
2906 // Check map and tail call if there's a match 2920 // Check map and tail call if there's a match
2907 __ Cmp(map_reg, receiver_maps->at(current)); 2921 __ Cmp(map_reg, receiver_maps->at(current));
2908 __ j(equal, handler_ics->at(current), RelocInfo::CODE_TARGET); 2922 __ j(equal, handlers->at(current), RelocInfo::CODE_TARGET);
2909 } 2923 }
2910 2924
2911 __ bind(&miss); 2925 __ bind(&miss);
2912 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2926 GenerateLoadMiss(masm(), kind());
2913 2927
2914 // Return the generated code. 2928 // Return the generated code.
2915 return GetCode(Code::NORMAL, factory()->empty_string(), POLYMORPHIC); 2929 InlineCacheState state =
2930 receiver_maps->length() > 1 ? POLYMORPHIC : MONOMORPHIC;
2931 return GetCode(Code::IC_FRAGMENT, type, name, state);
2916 } 2932 }
2917 2933
2918 2934
2919 // Specialized stub for constructing objects from functions which only have only 2935 // Specialized stub for constructing objects from functions which only have only
2920 // simple assignments of the form this.x = ...; in their body. 2936 // simple assignments of the form this.x = ...; in their body.
2921 Handle<Code> ConstructStubCompiler::CompileConstructStub( 2937 Handle<Code> ConstructStubCompiler::CompileConstructStub(
2922 Handle<JSFunction> function) { 2938 Handle<JSFunction> function) {
2923 // ----------- S t a t e ------------- 2939 // ----------- S t a t e -------------
2924 // -- rax : argc 2940 // -- rax : argc
2925 // -- rdi : constructor 2941 // -- rdi : constructor
(...skipping 662 matching lines...) Expand 10 before | Expand all | Expand 10 after
3588 __ jmp(ic_slow, RelocInfo::CODE_TARGET); 3604 __ jmp(ic_slow, RelocInfo::CODE_TARGET);
3589 } 3605 }
3590 } 3606 }
3591 3607
3592 3608
3593 #undef __ 3609 #undef __
3594 3610
3595 } } // namespace v8::internal 3611 } } // namespace v8::internal
3596 3612
3597 #endif // V8_TARGET_ARCH_X64 3613 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/ic-x64.cc ('k') | test/cctest/test-heap.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698