OLD | NEW |
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 Loading... |
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 527 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
937 | 938 |
938 | 939 |
939 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, | 940 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, |
940 Register object_reg, | 941 Register object_reg, |
941 Handle<JSObject> holder, | 942 Handle<JSObject> holder, |
942 Register holder_reg, | 943 Register holder_reg, |
943 Register scratch1, | 944 Register scratch1, |
944 Register scratch2, | 945 Register scratch2, |
945 Handle<String> name, | 946 Handle<String> name, |
946 int save_at_depth, | 947 int save_at_depth, |
947 Label* miss) { | 948 Label* miss, |
| 949 PrototypeCheckType check) { |
| 950 Handle<JSObject> first = object; |
948 // Make sure there's no overlap between holder and object registers. | 951 // Make sure there's no overlap between holder and object registers. |
949 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 952 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
950 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | 953 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
951 && !scratch2.is(scratch1)); | 954 && !scratch2.is(scratch1)); |
952 | 955 |
953 // Keep track of the current object in register reg. | 956 // Keep track of the current object in register reg. |
954 Register reg = object_reg; | 957 Register reg = object_reg; |
955 Handle<JSObject> current = object; | 958 Handle<JSObject> current = object; |
956 int depth = 0; | 959 int depth = 0; |
957 | 960 |
(...skipping 26 matching lines...) Expand all Loading... |
984 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | 987 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
985 reg = holder_reg; // From now on the object will be in holder_reg. | 988 reg = holder_reg; // From now on the object will be in holder_reg. |
986 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); | 989 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
987 } else { | 990 } else { |
988 bool in_new_space = heap()->InNewSpace(*prototype); | 991 bool in_new_space = heap()->InNewSpace(*prototype); |
989 Handle<Map> current_map(current->map()); | 992 Handle<Map> current_map(current->map()); |
990 if (in_new_space) { | 993 if (in_new_space) { |
991 // Save the map in scratch1 for later. | 994 // Save the map in scratch1 for later. |
992 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | 995 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
993 } | 996 } |
994 __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK, | 997 if (!current.is_identical_to(first) || check == CHECK_ALL_MAPS) { |
995 ALLOW_ELEMENT_TRANSITION_MAPS); | 998 __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK, |
| 999 ALLOW_ELEMENT_TRANSITION_MAPS); |
| 1000 } |
996 | 1001 |
997 // Check access rights to the global object. This has to happen after | 1002 // 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 | 1003 // the map check so that we know that the object is actually a global |
999 // object. | 1004 // object. |
1000 if (current->IsJSGlobalProxy()) { | 1005 if (current->IsJSGlobalProxy()) { |
1001 __ CheckAccessGlobalProxy(reg, scratch2, miss); | 1006 __ CheckAccessGlobalProxy(reg, scratch2, miss); |
1002 } | 1007 } |
1003 reg = holder_reg; // From now on the object will be in holder_reg. | 1008 reg = holder_reg; // From now on the object will be in holder_reg. |
1004 | 1009 |
1005 if (in_new_space) { | 1010 if (in_new_space) { |
(...skipping 11 matching lines...) Expand all Loading... |
1017 } | 1022 } |
1018 | 1023 |
1019 // Go to the next object in the prototype chain. | 1024 // Go to the next object in the prototype chain. |
1020 current = prototype; | 1025 current = prototype; |
1021 } | 1026 } |
1022 ASSERT(current.is_identical_to(holder)); | 1027 ASSERT(current.is_identical_to(holder)); |
1023 | 1028 |
1024 // Log the check depth. | 1029 // Log the check depth. |
1025 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); | 1030 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); |
1026 | 1031 |
1027 // Check the holder map. | 1032 if (!holder.is_identical_to(first) || check == CHECK_ALL_MAPS) { |
1028 __ CheckMap(reg, Handle<Map>(holder->map()), | 1033 // Check the holder map. |
1029 miss, DONT_DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); | 1034 __ CheckMap(reg, Handle<Map>(holder->map()), |
| 1035 miss, DONT_DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); |
| 1036 } |
1030 | 1037 |
1031 // Perform security check for access to the global object. | 1038 // Perform security check for access to the global object. |
1032 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); | 1039 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); |
1033 if (holder->IsJSGlobalProxy()) { | 1040 if (holder->IsJSGlobalProxy()) { |
1034 __ CheckAccessGlobalProxy(reg, scratch1, miss); | 1041 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
1035 } | 1042 } |
1036 | 1043 |
1037 // If we've skipped any global objects, it's not enough to verify that | 1044 // 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 | 1045 // their maps haven't changed. We also need to check that the property |
1039 // cell for the property is still empty. | 1046 // cell for the property is still empty. |
1040 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); | 1047 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); |
1041 | 1048 |
1042 // Return the register containing the holder. | 1049 // Return the register containing the holder. |
1043 return reg; | 1050 return reg; |
1044 } | 1051 } |
1045 | 1052 |
1046 | 1053 |
1047 void BaseLoadStubCompiler::HandlerFrontendFooter(Label* success, | 1054 void BaseLoadStubCompiler::HandlerFrontendFooter(Label* success, |
1048 Label* miss) { | 1055 Label* miss) { |
1049 __ jmp(success); | 1056 if (!miss->is_unused()) { |
1050 __ bind(miss); | 1057 __ jmp(success); |
1051 GenerateLoadMiss(masm(), kind()); | 1058 __ bind(miss); |
| 1059 GenerateLoadMiss(masm(), kind()); |
| 1060 } |
1052 } | 1061 } |
1053 | 1062 |
1054 | 1063 |
1055 Register BaseLoadStubCompiler::CallbackHandlerFrontend( | 1064 Register BaseLoadStubCompiler::CallbackHandlerFrontend( |
1056 Handle<JSObject> object, | 1065 Handle<JSObject> object, |
1057 Register object_reg, | 1066 Register object_reg, |
1058 Handle<JSObject> holder, | 1067 Handle<JSObject> holder, |
1059 Handle<String> name, | 1068 Handle<String> name, |
1060 Label* success, | 1069 Label* success, |
1061 FrontendCheckType check, | |
1062 Handle<ExecutableAccessorInfo> callback) { | 1070 Handle<ExecutableAccessorInfo> callback) { |
1063 Label miss; | 1071 Label miss; |
1064 | 1072 |
1065 Register reg = HandlerFrontendHeader( | 1073 Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss); |
1066 object, object_reg, holder, name, &miss, check); | |
1067 | 1074 |
1068 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { | 1075 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { |
1069 ASSERT(!reg.is(scratch2())); | 1076 ASSERT(!reg.is(scratch2())); |
1070 ASSERT(!reg.is(scratch3())); | 1077 ASSERT(!reg.is(scratch3())); |
1071 Register dictionary = scratch1(); | 1078 Register dictionary = scratch1(); |
1072 bool must_preserve_dictionary_reg = reg.is(dictionary); | 1079 bool must_preserve_dictionary_reg = reg.is(dictionary); |
1073 | 1080 |
1074 // Load the properties dictionary. | 1081 // Load the properties dictionary. |
1075 if (must_preserve_dictionary_reg) { | 1082 if (must_preserve_dictionary_reg) { |
1076 __ push(dictionary); | 1083 __ push(dictionary); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1115 | 1122 |
1116 | 1123 |
1117 void BaseLoadStubCompiler::NonexistentHandlerFrontend( | 1124 void BaseLoadStubCompiler::NonexistentHandlerFrontend( |
1118 Handle<JSObject> object, | 1125 Handle<JSObject> object, |
1119 Handle<JSObject> last, | 1126 Handle<JSObject> last, |
1120 Handle<String> name, | 1127 Handle<String> name, |
1121 Label* success, | 1128 Label* success, |
1122 Handle<GlobalObject> global) { | 1129 Handle<GlobalObject> global) { |
1123 Label miss; | 1130 Label miss; |
1124 | 1131 |
1125 Register reg = HandlerFrontendHeader( | 1132 Register reg = HandlerFrontendHeader(object, receiver(), last, name, &miss); |
1126 object, receiver(), last, name, &miss, PERFORM_INITIAL_CHECKS); | |
1127 | 1133 |
1128 // If the last object in the prototype chain is a global object, | 1134 // If the last object in the prototype chain is a global object, |
1129 // check that the global property cell is empty. | 1135 // check that the global property cell is empty. |
1130 if (!global.is_null()) { | 1136 if (!global.is_null()) { |
1131 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); | 1137 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); |
1132 } | 1138 } |
1133 | 1139 |
1134 if (!last->HasFastProperties()) { | 1140 if (!last->HasFastProperties()) { |
1135 __ mov(scratch2(), FieldOperand(reg, HeapObject::kMapOffset)); | 1141 __ mov(scratch2(), FieldOperand(reg, HeapObject::kMapOffset)); |
1136 __ mov(scratch2(), FieldOperand(scratch2(), Map::kPrototypeOffset)); | 1142 __ mov(scratch2(), FieldOperand(scratch2(), Map::kPrototypeOffset)); |
(...skipping 18 matching lines...) Expand all Loading... |
1155 Register reg, | 1161 Register reg, |
1156 Handle<ExecutableAccessorInfo> callback) { | 1162 Handle<ExecutableAccessorInfo> callback) { |
1157 // Insert additional parameters into the stack frame above return address. | 1163 // Insert additional parameters into the stack frame above return address. |
1158 ASSERT(!scratch3().is(reg)); | 1164 ASSERT(!scratch3().is(reg)); |
1159 __ pop(scratch3()); // Get return address to place it below. | 1165 __ pop(scratch3()); // Get return address to place it below. |
1160 | 1166 |
1161 __ push(receiver()); // receiver | 1167 __ push(receiver()); // receiver |
1162 __ mov(scratch2(), esp); | 1168 __ mov(scratch2(), esp); |
1163 ASSERT(!scratch2().is(reg)); | 1169 ASSERT(!scratch2().is(reg)); |
1164 __ push(reg); // holder | 1170 __ push(reg); // holder |
1165 // Push data from AccessorInfo. | 1171 // Push data from ExecutableAccessorInfo. |
1166 if (isolate()->heap()->InNewSpace(callback->data())) { | 1172 if (isolate()->heap()->InNewSpace(callback->data())) { |
1167 __ mov(scratch1(), Immediate(callback)); | 1173 __ mov(scratch1(), Immediate(callback)); |
1168 __ push(FieldOperand(scratch1(), ExecutableAccessorInfo::kDataOffset)); | 1174 __ push(FieldOperand(scratch1(), ExecutableAccessorInfo::kDataOffset)); |
1169 } else { | 1175 } else { |
1170 __ push(Immediate(Handle<Object>(callback->data(), isolate()))); | 1176 __ push(Immediate(Handle<Object>(callback->data(), isolate()))); |
1171 } | 1177 } |
1172 __ push(Immediate(reinterpret_cast<int>(isolate()))); | 1178 __ push(Immediate(reinterpret_cast<int>(isolate()))); |
1173 | 1179 |
1174 // Save a pointer to where we pushed the arguments pointer. | 1180 // 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. | 1181 // passed as the const ExecutableAccessorInfo& to the C++ callback. |
1176 __ push(scratch2()); | 1182 __ push(scratch2()); |
1177 | 1183 |
1178 __ push(name()); // name | 1184 __ push(name()); // name |
1179 __ mov(ebx, esp); // esp points to reference to name (handler). | 1185 __ mov(ebx, esp); // esp points to reference to name (handler). |
1180 | 1186 |
1181 __ push(scratch3()); // Restore return address. | 1187 __ push(scratch3()); // Restore return address. |
1182 | 1188 |
1183 // 4 elements array for v8::Arguments::values_, handler for name and pointer | 1189 // 4 elements array for v8::Arguments::values_, handler for name and pointer |
1184 // to the values (it considered as smi in GC). | 1190 // to the values (it considered as smi in GC). |
1185 const int kStackSpace = 6; | 1191 const int kStackSpace = 6; |
(...skipping 1734 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2920 | 2926 |
2921 NonexistentHandlerFrontend(object, last, name, &success, global); | 2927 NonexistentHandlerFrontend(object, last, name, &success, global); |
2922 | 2928 |
2923 __ bind(&success); | 2929 __ bind(&success); |
2924 // Return undefined if maps of the full prototype chain are still the | 2930 // Return undefined if maps of the full prototype chain are still the |
2925 // same and no global property with this name contains a value. | 2931 // same and no global property with this name contains a value. |
2926 __ mov(eax, isolate()->factory()->undefined_value()); | 2932 __ mov(eax, isolate()->factory()->undefined_value()); |
2927 __ ret(0); | 2933 __ ret(0); |
2928 | 2934 |
2929 // Return the generated code. | 2935 // Return the generated code. |
2930 return GetCode(Code::NONEXISTENT, factory()->empty_string()); | 2936 return GetCode(Code::HANDLER_FRAGMENT, Code::NONEXISTENT, name); |
2931 } | 2937 } |
2932 | 2938 |
2933 | 2939 |
2934 Register* LoadStubCompiler::registers() { | 2940 Register* LoadStubCompiler::registers() { |
2935 // receiver, name, scratch1, scratch2, scratch3, scratch4. | 2941 // receiver, name, scratch1, scratch2, scratch3, scratch4. |
2936 static Register registers[] = { edx, ecx, ebx, eax, edi, no_reg }; | 2942 static Register registers[] = { edx, ecx, ebx, eax, edi, no_reg }; |
2937 return registers; | 2943 return registers; |
2938 } | 2944 } |
2939 | 2945 |
2940 | 2946 |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2991 | 2997 |
2992 | 2998 |
2993 Handle<Code> LoadStubCompiler::CompileLoadGlobal( | 2999 Handle<Code> LoadStubCompiler::CompileLoadGlobal( |
2994 Handle<JSObject> object, | 3000 Handle<JSObject> object, |
2995 Handle<GlobalObject> global, | 3001 Handle<GlobalObject> global, |
2996 Handle<JSGlobalPropertyCell> cell, | 3002 Handle<JSGlobalPropertyCell> cell, |
2997 Handle<String> name, | 3003 Handle<String> name, |
2998 bool is_dont_delete) { | 3004 bool is_dont_delete) { |
2999 Label success, miss; | 3005 Label success, miss; |
3000 | 3006 |
3001 HandlerFrontendHeader(object, receiver(), Handle<JSObject>::cast(global), | 3007 __ CheckMap(receiver(), Handle<Map>(object->map()), &miss, DO_SMI_CHECK); |
3002 name, &miss, PERFORM_INITIAL_CHECKS); | 3008 HandlerFrontendHeader( |
| 3009 object, receiver(), Handle<JSObject>::cast(global), name, &miss); |
3003 // Get the value from the cell. | 3010 // Get the value from the cell. |
3004 if (Serializer::enabled()) { | 3011 if (Serializer::enabled()) { |
3005 __ mov(eax, Immediate(cell)); | 3012 __ mov(eax, Immediate(cell)); |
3006 __ mov(eax, FieldOperand(eax, JSGlobalPropertyCell::kValueOffset)); | 3013 __ mov(eax, FieldOperand(eax, JSGlobalPropertyCell::kValueOffset)); |
3007 } else { | 3014 } else { |
3008 __ mov(eax, Operand::Cell(cell)); | 3015 __ mov(eax, Operand::Cell(cell)); |
3009 } | 3016 } |
3010 | 3017 |
3011 // Check for deleted property if property can actually be deleted. | 3018 // Check for deleted property if property can actually be deleted. |
3012 if (!is_dont_delete) { | 3019 if (!is_dont_delete) { |
3013 __ cmp(eax, factory()->the_hole_value()); | 3020 __ cmp(eax, factory()->the_hole_value()); |
3014 __ j(equal, &miss); | 3021 __ j(equal, &miss); |
3015 } else if (FLAG_debug_code) { | 3022 } else if (FLAG_debug_code) { |
3016 __ cmp(eax, factory()->the_hole_value()); | 3023 __ cmp(eax, factory()->the_hole_value()); |
3017 __ Check(not_equal, "DontDelete cells can't contain the hole"); | 3024 __ Check(not_equal, "DontDelete cells can't contain the hole"); |
3018 } | 3025 } |
3019 | 3026 |
3020 HandlerFrontendFooter(&success, &miss); | 3027 HandlerFrontendFooter(&success, &miss); |
3021 __ bind(&success); | 3028 __ bind(&success); |
3022 | 3029 |
3023 Counters* counters = isolate()->counters(); | 3030 Counters* counters = isolate()->counters(); |
3024 __ IncrementCounter(counters->named_load_global_stub(), 1); | 3031 __ IncrementCounter(counters->named_load_global_stub(), 1); |
3025 // The code above already loads the result into the return register. | 3032 // The code above already loads the result into the return register. |
3026 __ ret(0); | 3033 __ ret(0); |
3027 | 3034 |
3028 // Return the generated code. | 3035 // Return the generated code. |
3029 return GetCode(Code::NORMAL, name); | 3036 return GetCode(Code::IC_FRAGMENT, Code::NORMAL, name); |
3030 } | 3037 } |
3031 | 3038 |
3032 | 3039 |
3033 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement( | 3040 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement( |
3034 Handle<Map> receiver_map) { | 3041 Handle<Map> receiver_map) { |
3035 // ----------- S t a t e ------------- | 3042 // ----------- S t a t e ------------- |
3036 // -- ecx : key | 3043 // -- ecx : key |
3037 // -- edx : receiver | 3044 // -- edx : receiver |
3038 // -- esp[0] : return address | 3045 // -- esp[0] : return address |
3039 // ----------------------------------- | 3046 // ----------------------------------- |
3040 | 3047 |
3041 ElementsKind elements_kind = receiver_map->elements_kind(); | 3048 ElementsKind elements_kind = receiver_map->elements_kind(); |
3042 if (receiver_map->has_fast_elements() || | 3049 if (receiver_map->has_fast_elements() || |
3043 receiver_map->has_external_array_elements()) { | 3050 receiver_map->has_external_array_elements()) { |
3044 Handle<Code> stub = KeyedLoadFastElementStub( | 3051 Handle<Code> stub = KeyedLoadFastElementStub( |
3045 receiver_map->instance_type() == JS_ARRAY_TYPE, | 3052 receiver_map->instance_type() == JS_ARRAY_TYPE, |
3046 elements_kind).GetCode(isolate()); | 3053 elements_kind).GetCode(isolate()); |
3047 __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); | 3054 __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); |
3048 } else { | 3055 } else { |
3049 Handle<Code> stub = | 3056 Handle<Code> stub = |
3050 KeyedLoadDictionaryElementStub().GetCode(isolate()); | 3057 KeyedLoadDictionaryElementStub().GetCode(isolate()); |
3051 __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); | 3058 __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); |
3052 } | 3059 } |
3053 | 3060 |
3054 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3061 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
3055 | 3062 |
3056 // Return the generated code. | 3063 // Return the generated code. |
3057 return GetCode(Code::NORMAL, factory()->empty_string()); | 3064 return GetCode(Code::IC_FRAGMENT, Code::NORMAL, factory()->empty_string()); |
3058 } | 3065 } |
3059 | 3066 |
3060 | 3067 |
3061 Handle<Code> KeyedLoadStubCompiler::CompileLoadPolymorphic( | 3068 Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC( |
3062 MapHandleList* receiver_maps, | 3069 MapHandleList* receiver_maps, |
3063 CodeHandleList* handler_ics) { | 3070 CodeHandleList* handlers, |
3064 // ----------- S t a t e ------------- | 3071 Handle<String> name, |
3065 // -- ecx : key | 3072 Code::StubType type, |
3066 // -- edx : receiver | 3073 IcCheckType check) { |
3067 // -- esp[0] : return address | |
3068 // ----------------------------------- | |
3069 Label miss; | 3074 Label miss; |
3070 __ JumpIfSmi(edx, &miss); | |
3071 | 3075 |
3072 Register map_reg = ebx; | 3076 if (check == PROPERTY) { |
3073 __ mov(map_reg, FieldOperand(edx, HeapObject::kMapOffset)); | 3077 GenerateNameCheck(name, this->name(), &miss); |
| 3078 } |
| 3079 |
| 3080 __ JumpIfSmi(receiver(), &miss); |
| 3081 Register map_reg = scratch1(); |
| 3082 __ mov(map_reg, FieldOperand(receiver(), HeapObject::kMapOffset)); |
3074 int receiver_count = receiver_maps->length(); | 3083 int receiver_count = receiver_maps->length(); |
3075 for (int current = 0; current < receiver_count; ++current) { | 3084 for (int current = 0; current < receiver_count; ++current) { |
3076 __ cmp(map_reg, receiver_maps->at(current)); | 3085 __ cmp(map_reg, receiver_maps->at(current)); |
3077 __ j(equal, handler_ics->at(current)); | 3086 __ j(equal, handlers->at(current)); |
3078 } | 3087 } |
3079 | 3088 |
3080 __ bind(&miss); | 3089 __ bind(&miss); |
3081 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3090 GenerateLoadMiss(masm(), kind()); |
3082 | 3091 |
3083 // Return the generated code. | 3092 // Return the generated code. |
3084 return GetCode(Code::NORMAL, factory()->empty_string(), POLYMORPHIC); | 3093 InlineCacheState state = |
| 3094 receiver_maps->length() > 1 ? POLYMORPHIC : MONOMORPHIC; |
| 3095 return GetCode(Code::IC_FRAGMENT, type, name, state); |
3085 } | 3096 } |
3086 | 3097 |
3087 | 3098 |
3088 // Specialized stub for constructing objects from functions which only have only | 3099 // Specialized stub for constructing objects from functions which only have only |
3089 // simple assignments of the form this.x = ...; in their body. | 3100 // simple assignments of the form this.x = ...; in their body. |
3090 Handle<Code> ConstructStubCompiler::CompileConstructStub( | 3101 Handle<Code> ConstructStubCompiler::CompileConstructStub( |
3091 Handle<JSFunction> function) { | 3102 Handle<JSFunction> function) { |
3092 // ----------- S t a t e ------------- | 3103 // ----------- S t a t e ------------- |
3093 // -- eax : argc | 3104 // -- eax : argc |
3094 // -- edi : constructor | 3105 // -- edi : constructor |
(...skipping 707 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3802 __ jmp(ic_slow, RelocInfo::CODE_TARGET); | 3813 __ jmp(ic_slow, RelocInfo::CODE_TARGET); |
3803 } | 3814 } |
3804 } | 3815 } |
3805 | 3816 |
3806 | 3817 |
3807 #undef __ | 3818 #undef __ |
3808 | 3819 |
3809 } } // namespace v8::internal | 3820 } } // namespace v8::internal |
3810 | 3821 |
3811 #endif // V8_TARGET_ARCH_IA32 | 3822 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |