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

Side by Side Diff: src/ia32/stub-cache-ia32.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/ia32/ic-ia32.cc ('k') | src/ic.h » ('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 359 matching lines...) Expand 10 before | Expand all | Expand 10 after
370 370
371 371
372 // Load a fast property out of a holder object (src). In-object properties 372 // Load a fast property out of a holder object (src). In-object properties
373 // are loaded directly otherwise the property is loaded from the properties 373 // are loaded directly otherwise the property is loaded from the properties
374 // fixed array. 374 // fixed array.
375 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, 375 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
376 Register dst, 376 Register dst,
377 Register src, 377 Register src,
378 Handle<JSObject> holder, 378 Handle<JSObject> holder,
379 PropertyIndex index) { 379 PropertyIndex index) {
380 if (index.is_header_index()) { 380 DoGenerateFastPropertyLoad(
381 int offset = index.header_index() * kPointerSize; 381 masm, dst, src, index.is_inobject(holder), index.translate(holder));
382 __ mov(dst, FieldOperand(src, offset));
383 } else {
384 // Adjust for the number of properties stored in the holder.
385 int slot = index.field_index() - holder->map()->inobject_properties();
386 if (slot < 0) {
387 // Get the property straight out of the holder.
388 int offset = holder->map()->instance_size() + (slot * kPointerSize);
389 __ mov(dst, FieldOperand(src, offset));
390 } else {
391 // Calculate the offset into the properties array.
392 int offset = slot * kPointerSize + FixedArray::kHeaderSize;
393 __ mov(dst, FieldOperand(src, JSObject::kPropertiesOffset));
394 __ mov(dst, FieldOperand(dst, offset));
395 }
396 }
397 } 382 }
398 383
399 384
385 void StubCompiler::DoGenerateFastPropertyLoad(MacroAssembler* masm,
386 Register dst,
387 Register src,
388 bool inobject,
389 int index) {
390 int offset = index * kPointerSize;
391 if (!inobject) {
392 // Calculate the offset into the properties array.
393 offset = offset + FixedArray::kHeaderSize;
394 __ mov(dst, FieldOperand(src, JSObject::kPropertiesOffset));
395 src = dst;
396 }
397 __ mov(dst, FieldOperand(src, offset));
398 }
399
400
400 static void PushInterceptorArguments(MacroAssembler* masm, 401 static void PushInterceptorArguments(MacroAssembler* masm,
401 Register receiver, 402 Register receiver,
402 Register holder, 403 Register holder,
403 Register name, 404 Register name,
404 Handle<JSObject> holder_obj) { 405 Handle<JSObject> holder_obj) {
405 __ push(name); 406 __ push(name);
406 Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor()); 407 Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor());
407 ASSERT(!masm->isolate()->heap()->InNewSpace(*interceptor)); 408 ASSERT(!masm->isolate()->heap()->InNewSpace(*interceptor));
408 Register scratch = name; 409 Register scratch = name;
409 __ mov(scratch, Immediate(interceptor)); 410 __ mov(scratch, Immediate(interceptor));
(...skipping 519 matching lines...) Expand 10 before | Expand all | Expand 10 after
929 miss); 930 miss);
930 } 931 }
931 current = Handle<JSObject>(JSObject::cast(current->GetPrototype())); 932 current = Handle<JSObject>(JSObject::cast(current->GetPrototype()));
932 } 933 }
933 } 934 }
934 935
935 #undef __ 936 #undef __
936 #define __ ACCESS_MASM(masm()) 937 #define __ ACCESS_MASM(masm())
937 938
938 939
940 void StubCompiler::GenerateTailCall(Handle<Code> code) {
941 __ jmp(code, RelocInfo::CODE_TARGET);
942 }
943
944
939 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, 945 Register StubCompiler::CheckPrototypes(Handle<JSObject> object,
940 Register object_reg, 946 Register object_reg,
941 Handle<JSObject> holder, 947 Handle<JSObject> holder,
942 Register holder_reg, 948 Register holder_reg,
943 Register scratch1, 949 Register scratch1,
944 Register scratch2, 950 Register scratch2,
945 Handle<String> name, 951 Handle<String> name,
946 int save_at_depth, 952 int save_at_depth,
947 Label* miss) { 953 Label* miss,
954 PrototypeCheckType check) {
955 Handle<JSObject> first = object;
948 // Make sure there's no overlap between holder and object registers. 956 // Make sure there's no overlap between holder and object registers.
949 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); 957 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
950 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) 958 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg)
951 && !scratch2.is(scratch1)); 959 && !scratch2.is(scratch1));
952 960
953 // Keep track of the current object in register reg. 961 // Keep track of the current object in register reg.
954 Register reg = object_reg; 962 Register reg = object_reg;
955 Handle<JSObject> current = object; 963 Handle<JSObject> current = object;
956 int depth = 0; 964 int depth = 0;
957 965
(...skipping 26 matching lines...) Expand all
984 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); 992 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
985 reg = holder_reg; // From now on the object will be in holder_reg. 993 reg = holder_reg; // From now on the object will be in holder_reg.
986 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); 994 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
987 } else { 995 } else {
988 bool in_new_space = heap()->InNewSpace(*prototype); 996 bool in_new_space = heap()->InNewSpace(*prototype);
989 Handle<Map> current_map(current->map()); 997 Handle<Map> current_map(current->map());
990 if (in_new_space) { 998 if (in_new_space) {
991 // Save the map in scratch1 for later. 999 // Save the map in scratch1 for later.
992 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); 1000 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
993 } 1001 }
994 __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK, 1002 if (!current.is_identical_to(first) || check == CHECK_ALL_MAPS) {
995 ALLOW_ELEMENT_TRANSITION_MAPS); 1003 __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK,
1004 ALLOW_ELEMENT_TRANSITION_MAPS);
1005 }
996 1006
997 // Check access rights to the global object. This has to happen after 1007 // Check access rights to the global object. This has to happen after
998 // the map check so that we know that the object is actually a global 1008 // the map check so that we know that the object is actually a global
999 // object. 1009 // object.
1000 if (current->IsJSGlobalProxy()) { 1010 if (current->IsJSGlobalProxy()) {
1001 __ CheckAccessGlobalProxy(reg, scratch2, miss); 1011 __ CheckAccessGlobalProxy(reg, scratch2, miss);
1002 } 1012 }
1003 reg = holder_reg; // From now on the object will be in holder_reg. 1013 reg = holder_reg; // From now on the object will be in holder_reg.
1004 1014
1005 if (in_new_space) { 1015 if (in_new_space) {
(...skipping 11 matching lines...) Expand all
1017 } 1027 }
1018 1028
1019 // Go to the next object in the prototype chain. 1029 // Go to the next object in the prototype chain.
1020 current = prototype; 1030 current = prototype;
1021 } 1031 }
1022 ASSERT(current.is_identical_to(holder)); 1032 ASSERT(current.is_identical_to(holder));
1023 1033
1024 // Log the check depth. 1034 // Log the check depth.
1025 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); 1035 LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
1026 1036
1027 // Check the holder map. 1037 if (!holder.is_identical_to(first) || check == CHECK_ALL_MAPS) {
1028 __ CheckMap(reg, Handle<Map>(holder->map()), 1038 // Check the holder map.
1029 miss, DONT_DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); 1039 __ CheckMap(reg, Handle<Map>(holder->map()),
1040 miss, DONT_DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
1041 }
1030 1042
1031 // Perform security check for access to the global object. 1043 // Perform security check for access to the global object.
1032 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); 1044 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
1033 if (holder->IsJSGlobalProxy()) { 1045 if (holder->IsJSGlobalProxy()) {
1034 __ CheckAccessGlobalProxy(reg, scratch1, miss); 1046 __ CheckAccessGlobalProxy(reg, scratch1, miss);
1035 } 1047 }
1036 1048
1037 // If we've skipped any global objects, it's not enough to verify that 1049 // If we've skipped any global objects, it's not enough to verify that
1038 // their maps haven't changed. We also need to check that the property 1050 // their maps haven't changed. We also need to check that the property
1039 // cell for the property is still empty. 1051 // cell for the property is still empty.
1040 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); 1052 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss);
1041 1053
1042 // Return the register containing the holder. 1054 // Return the register containing the holder.
1043 return reg; 1055 return reg;
1044 } 1056 }
1045 1057
1046 1058
1047 void BaseLoadStubCompiler::HandlerFrontendFooter(Label* success, 1059 void BaseLoadStubCompiler::HandlerFrontendFooter(Label* success,
1048 Label* miss) { 1060 Label* miss) {
1049 __ jmp(success); 1061 if (!miss->is_unused()) {
1050 __ bind(miss); 1062 __ jmp(success);
1051 GenerateLoadMiss(masm(), kind()); 1063 __ bind(miss);
1064 GenerateLoadMiss(masm(), kind());
1065 }
1052 } 1066 }
1053 1067
1054 1068
1055 Register BaseLoadStubCompiler::CallbackHandlerFrontend( 1069 Register BaseLoadStubCompiler::CallbackHandlerFrontend(
1056 Handle<JSObject> object, 1070 Handle<JSObject> object,
1057 Register object_reg, 1071 Register object_reg,
1058 Handle<JSObject> holder, 1072 Handle<JSObject> holder,
1059 Handle<String> name, 1073 Handle<String> name,
1060 Label* success, 1074 Label* success,
1061 FrontendCheckType check,
1062 Handle<ExecutableAccessorInfo> callback) { 1075 Handle<ExecutableAccessorInfo> callback) {
1063 Label miss; 1076 Label miss;
1064 1077
1065 Register reg = HandlerFrontendHeader( 1078 Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss);
1066 object, object_reg, holder, name, &miss, check);
1067 1079
1068 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { 1080 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) {
1069 ASSERT(!reg.is(scratch2())); 1081 ASSERT(!reg.is(scratch2()));
1070 ASSERT(!reg.is(scratch3())); 1082 ASSERT(!reg.is(scratch3()));
1071 Register dictionary = scratch1(); 1083 Register dictionary = scratch1();
1072 bool must_preserve_dictionary_reg = reg.is(dictionary); 1084 bool must_preserve_dictionary_reg = reg.is(dictionary);
1073 1085
1074 // Load the properties dictionary. 1086 // Load the properties dictionary.
1075 if (must_preserve_dictionary_reg) { 1087 if (must_preserve_dictionary_reg) {
1076 __ push(dictionary); 1088 __ push(dictionary);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1115 1127
1116 1128
1117 void BaseLoadStubCompiler::NonexistentHandlerFrontend( 1129 void BaseLoadStubCompiler::NonexistentHandlerFrontend(
1118 Handle<JSObject> object, 1130 Handle<JSObject> object,
1119 Handle<JSObject> last, 1131 Handle<JSObject> last,
1120 Handle<String> name, 1132 Handle<String> name,
1121 Label* success, 1133 Label* success,
1122 Handle<GlobalObject> global) { 1134 Handle<GlobalObject> global) {
1123 Label miss; 1135 Label miss;
1124 1136
1125 Register reg = HandlerFrontendHeader( 1137 Register reg = HandlerFrontendHeader(object, receiver(), last, name, &miss);
1126 object, receiver(), last, name, &miss, PERFORM_INITIAL_CHECKS);
1127 1138
1128 // If the last object in the prototype chain is a global object, 1139 // If the last object in the prototype chain is a global object,
1129 // check that the global property cell is empty. 1140 // check that the global property cell is empty.
1130 if (!global.is_null()) { 1141 if (!global.is_null()) {
1131 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); 1142 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss);
1132 } 1143 }
1133 1144
1134 if (!last->HasFastProperties()) { 1145 if (!last->HasFastProperties()) {
1135 __ mov(scratch2(), FieldOperand(reg, HeapObject::kMapOffset)); 1146 __ mov(scratch2(), FieldOperand(reg, HeapObject::kMapOffset));
1136 __ mov(scratch2(), FieldOperand(scratch2(), Map::kPrototypeOffset)); 1147 __ mov(scratch2(), FieldOperand(scratch2(), Map::kPrototypeOffset));
(...skipping 18 matching lines...) Expand all
1155 Register reg, 1166 Register reg,
1156 Handle<ExecutableAccessorInfo> callback) { 1167 Handle<ExecutableAccessorInfo> callback) {
1157 // Insert additional parameters into the stack frame above return address. 1168 // Insert additional parameters into the stack frame above return address.
1158 ASSERT(!scratch3().is(reg)); 1169 ASSERT(!scratch3().is(reg));
1159 __ pop(scratch3()); // Get return address to place it below. 1170 __ pop(scratch3()); // Get return address to place it below.
1160 1171
1161 __ push(receiver()); // receiver 1172 __ push(receiver()); // receiver
1162 __ mov(scratch2(), esp); 1173 __ mov(scratch2(), esp);
1163 ASSERT(!scratch2().is(reg)); 1174 ASSERT(!scratch2().is(reg));
1164 __ push(reg); // holder 1175 __ push(reg); // holder
1165 // Push data from AccessorInfo. 1176 // Push data from ExecutableAccessorInfo.
1166 if (isolate()->heap()->InNewSpace(callback->data())) { 1177 if (isolate()->heap()->InNewSpace(callback->data())) {
1167 __ mov(scratch1(), Immediate(callback)); 1178 __ mov(scratch1(), Immediate(callback));
1168 __ push(FieldOperand(scratch1(), ExecutableAccessorInfo::kDataOffset)); 1179 __ push(FieldOperand(scratch1(), ExecutableAccessorInfo::kDataOffset));
1169 } else { 1180 } else {
1170 __ push(Immediate(Handle<Object>(callback->data(), isolate()))); 1181 __ push(Immediate(Handle<Object>(callback->data(), isolate())));
1171 } 1182 }
1172 __ push(Immediate(reinterpret_cast<int>(isolate()))); 1183 __ push(Immediate(reinterpret_cast<int>(isolate())));
1173 1184
1174 // Save a pointer to where we pushed the arguments pointer. 1185 // Save a pointer to where we pushed the arguments pointer. This will be
1175 // This will be passed as the const AccessorInfo& to the C++ callback. 1186 // passed as the const ExecutableAccessorInfo& to the C++ callback.
1176 __ push(scratch2()); 1187 __ push(scratch2());
1177 1188
1178 __ push(name()); // name 1189 __ push(name()); // name
1179 __ mov(ebx, esp); // esp points to reference to name (handler). 1190 __ mov(ebx, esp); // esp points to reference to name (handler).
1180 1191
1181 __ push(scratch3()); // Restore return address. 1192 __ push(scratch3()); // Restore return address.
1182 1193
1183 // 4 elements array for v8::Arguments::values_, handler for name and pointer 1194 // 4 elements array for v8::Arguments::values_, handler for name and pointer
1184 // to the values (it considered as smi in GC). 1195 // to the values (it considered as smi in GC).
1185 const int kStackSpace = 6; 1196 const int kStackSpace = 6;
(...skipping 1740 matching lines...) Expand 10 before | Expand all | Expand 10 after
2926 2937
2927 NonexistentHandlerFrontend(object, last, name, &success, global); 2938 NonexistentHandlerFrontend(object, last, name, &success, global);
2928 2939
2929 __ bind(&success); 2940 __ bind(&success);
2930 // Return undefined if maps of the full prototype chain are still the 2941 // Return undefined if maps of the full prototype chain are still the
2931 // same and no global property with this name contains a value. 2942 // same and no global property with this name contains a value.
2932 __ mov(eax, isolate()->factory()->undefined_value()); 2943 __ mov(eax, isolate()->factory()->undefined_value());
2933 __ ret(0); 2944 __ ret(0);
2934 2945
2935 // Return the generated code. 2946 // Return the generated code.
2936 return GetCode(Code::NONEXISTENT, factory()->empty_string()); 2947 return GetCode(Code::HANDLER_FRAGMENT, Code::NONEXISTENT, name);
2937 } 2948 }
2938 2949
2939 2950
2940 Register* LoadStubCompiler::registers() { 2951 Register* LoadStubCompiler::registers() {
2941 // receiver, name, scratch1, scratch2, scratch3, scratch4. 2952 // receiver, name, scratch1, scratch2, scratch3, scratch4.
2942 static Register registers[] = { edx, ecx, ebx, eax, edi, no_reg }; 2953 static Register registers[] = { edx, ecx, ebx, eax, edi, no_reg };
2943 return registers; 2954 return registers;
2944 } 2955 }
2945 2956
2946 2957
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
2997 3008
2998 3009
2999 Handle<Code> LoadStubCompiler::CompileLoadGlobal( 3010 Handle<Code> LoadStubCompiler::CompileLoadGlobal(
3000 Handle<JSObject> object, 3011 Handle<JSObject> object,
3001 Handle<GlobalObject> global, 3012 Handle<GlobalObject> global,
3002 Handle<JSGlobalPropertyCell> cell, 3013 Handle<JSGlobalPropertyCell> cell,
3003 Handle<String> name, 3014 Handle<String> name,
3004 bool is_dont_delete) { 3015 bool is_dont_delete) {
3005 Label success, miss; 3016 Label success, miss;
3006 3017
3007 HandlerFrontendHeader(object, receiver(), Handle<JSObject>::cast(global), 3018 __ CheckMap(receiver(), Handle<Map>(object->map()), &miss, DO_SMI_CHECK);
3008 name, &miss, PERFORM_INITIAL_CHECKS); 3019 HandlerFrontendHeader(
3020 object, receiver(), Handle<JSObject>::cast(global), name, &miss);
3009 // Get the value from the cell. 3021 // Get the value from the cell.
3010 if (Serializer::enabled()) { 3022 if (Serializer::enabled()) {
3011 __ mov(eax, Immediate(cell)); 3023 __ mov(eax, Immediate(cell));
3012 __ mov(eax, FieldOperand(eax, JSGlobalPropertyCell::kValueOffset)); 3024 __ mov(eax, FieldOperand(eax, JSGlobalPropertyCell::kValueOffset));
3013 } else { 3025 } else {
3014 __ mov(eax, Operand::Cell(cell)); 3026 __ mov(eax, Operand::Cell(cell));
3015 } 3027 }
3016 3028
3017 // Check for deleted property if property can actually be deleted. 3029 // Check for deleted property if property can actually be deleted.
3018 if (!is_dont_delete) { 3030 if (!is_dont_delete) {
3019 __ cmp(eax, factory()->the_hole_value()); 3031 __ cmp(eax, factory()->the_hole_value());
3020 __ j(equal, &miss); 3032 __ j(equal, &miss);
3021 } else if (FLAG_debug_code) { 3033 } else if (FLAG_debug_code) {
3022 __ cmp(eax, factory()->the_hole_value()); 3034 __ cmp(eax, factory()->the_hole_value());
3023 __ Check(not_equal, "DontDelete cells can't contain the hole"); 3035 __ Check(not_equal, "DontDelete cells can't contain the hole");
3024 } 3036 }
3025 3037
3026 HandlerFrontendFooter(&success, &miss); 3038 HandlerFrontendFooter(&success, &miss);
3027 __ bind(&success); 3039 __ bind(&success);
3028 3040
3029 Counters* counters = isolate()->counters(); 3041 Counters* counters = isolate()->counters();
3030 __ IncrementCounter(counters->named_load_global_stub(), 1); 3042 __ IncrementCounter(counters->named_load_global_stub(), 1);
3031 // The code above already loads the result into the return register. 3043 // The code above already loads the result into the return register.
3032 __ ret(0); 3044 __ ret(0);
3033 3045
3034 // Return the generated code. 3046 // Return the generated code.
3035 return GetCode(Code::NORMAL, name); 3047 return GetCode(Code::IC_FRAGMENT, Code::NORMAL, name);
3036 } 3048 }
3037 3049
3038 3050
3039 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement( 3051 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement(
3040 Handle<Map> receiver_map) { 3052 Handle<Map> receiver_map) {
3041 // ----------- S t a t e ------------- 3053 // ----------- S t a t e -------------
3042 // -- ecx : key 3054 // -- ecx : key
3043 // -- edx : receiver 3055 // -- edx : receiver
3044 // -- esp[0] : return address 3056 // -- esp[0] : return address
3045 // ----------------------------------- 3057 // -----------------------------------
3046 3058
3047 ElementsKind elements_kind = receiver_map->elements_kind(); 3059 ElementsKind elements_kind = receiver_map->elements_kind();
3048 if (receiver_map->has_fast_elements() || 3060 if (receiver_map->has_fast_elements() ||
3049 receiver_map->has_external_array_elements()) { 3061 receiver_map->has_external_array_elements()) {
3050 Handle<Code> stub = KeyedLoadFastElementStub( 3062 Handle<Code> stub = KeyedLoadFastElementStub(
3051 receiver_map->instance_type() == JS_ARRAY_TYPE, 3063 receiver_map->instance_type() == JS_ARRAY_TYPE,
3052 elements_kind).GetCode(isolate()); 3064 elements_kind).GetCode(isolate());
3053 __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); 3065 __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK);
3054 } else { 3066 } else {
3055 Handle<Code> stub = 3067 Handle<Code> stub =
3056 KeyedLoadDictionaryElementStub().GetCode(isolate()); 3068 KeyedLoadDictionaryElementStub().GetCode(isolate());
3057 __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); 3069 __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK);
3058 } 3070 }
3059 3071
3060 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 3072 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3061 3073
3062 // Return the generated code. 3074 // Return the generated code.
3063 return GetCode(Code::NORMAL, factory()->empty_string()); 3075 return GetCode(Code::IC_FRAGMENT, Code::NORMAL, factory()->empty_string());
3064 } 3076 }
3065 3077
3066 3078
3067 Handle<Code> KeyedLoadStubCompiler::CompileLoadPolymorphic( 3079 Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC(
3068 MapHandleList* receiver_maps, 3080 MapHandleList* receiver_maps,
3069 CodeHandleList* handler_ics) { 3081 CodeHandleList* handlers,
3070 // ----------- S t a t e ------------- 3082 Handle<String> name,
3071 // -- ecx : key 3083 Code::StubType type,
3072 // -- edx : receiver 3084 IcCheckType check) {
3073 // -- esp[0] : return address
3074 // -----------------------------------
3075 Label miss; 3085 Label miss;
3076 __ JumpIfSmi(edx, &miss);
3077 3086
3078 Register map_reg = ebx; 3087 if (check == PROPERTY) {
3079 __ mov(map_reg, FieldOperand(edx, HeapObject::kMapOffset)); 3088 GenerateNameCheck(name, this->name(), &miss);
3089 }
3090
3091 __ JumpIfSmi(receiver(), &miss);
3092 Register map_reg = scratch1();
3093 __ mov(map_reg, FieldOperand(receiver(), HeapObject::kMapOffset));
3080 int receiver_count = receiver_maps->length(); 3094 int receiver_count = receiver_maps->length();
3081 for (int current = 0; current < receiver_count; ++current) { 3095 for (int current = 0; current < receiver_count; ++current) {
3082 __ cmp(map_reg, receiver_maps->at(current)); 3096 __ cmp(map_reg, receiver_maps->at(current));
3083 __ j(equal, handler_ics->at(current)); 3097 __ j(equal, handlers->at(current));
3084 } 3098 }
3085 3099
3086 __ bind(&miss); 3100 __ bind(&miss);
3087 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 3101 GenerateLoadMiss(masm(), kind());
3088 3102
3089 // Return the generated code. 3103 // Return the generated code.
3090 return GetCode(Code::NORMAL, factory()->empty_string(), POLYMORPHIC); 3104 InlineCacheState state =
3105 receiver_maps->length() > 1 ? POLYMORPHIC : MONOMORPHIC;
3106 return GetCode(Code::IC_FRAGMENT, type, name, state);
3091 } 3107 }
3092 3108
3093 3109
3094 // Specialized stub for constructing objects from functions which only have only 3110 // Specialized stub for constructing objects from functions which only have only
3095 // simple assignments of the form this.x = ...; in their body. 3111 // simple assignments of the form this.x = ...; in their body.
3096 Handle<Code> ConstructStubCompiler::CompileConstructStub( 3112 Handle<Code> ConstructStubCompiler::CompileConstructStub(
3097 Handle<JSFunction> function) { 3113 Handle<JSFunction> function) {
3098 // ----------- S t a t e ------------- 3114 // ----------- S t a t e -------------
3099 // -- eax : argc 3115 // -- eax : argc
3100 // -- edi : constructor 3116 // -- edi : constructor
(...skipping 707 matching lines...) Expand 10 before | Expand all | Expand 10 after
3808 __ jmp(ic_slow, RelocInfo::CODE_TARGET); 3824 __ jmp(ic_slow, RelocInfo::CODE_TARGET);
3809 } 3825 }
3810 } 3826 }
3811 3827
3812 3828
3813 #undef __ 3829 #undef __
3814 3830
3815 } } // namespace v8::internal 3831 } } // namespace v8::internal
3816 3832
3817 #endif // V8_TARGET_ARCH_IA32 3833 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/ic-ia32.cc ('k') | src/ic.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698